用户
搜索
  • TA的每日心情
    开心
    2019-4-25 18:23
  • 签到天数: 115 天

    连续签到: 1 天

    [LV.6]常住居民II

    i春秋作家

    春秋认证√作家团颜值担当

    Rank: 7Rank: 7Rank: 7

    17

    主题

    377

    帖子

    4374

    魔法币
    收听
    1
    粉丝
    82
    注册时间
    2017-6-5

    i春秋认证秦春秋文阁i春秋签约作者

    onls辜釉 i春秋作家 春秋认证√作家团颜值担当 i春秋认证 秦 春秋文阁 i春秋签约作者 楼主
    发表于 2018-5-22 17:50:31 1717536
    本帖最后由 onls辜釉 于 2018-5-22 09:50 编辑

    @风在指尖 一波XSS绕过之后,下载源码一看只是简单用了个360的用户输入参数过滤规则,本身代码全是注入。
    本想来篇简单分析,怎料@Ashe以迅雷不及掩耳盗铃之势捷足先登。



    这鱼站的注入很简单,就是一个无返回的Cookie时间注入,直接拿他跑出密码的那个鱼站帐号登录一波发现已经提示密码错误,接着我直接拷下源码想玩一波。



    发现不管是username还是password都只能跑出两位程序便停止运行,就像这样:


    1.png

    表哥那篇帖子对细节讲得不是很详细,估计有一部分人看得不是很明白,所以我干脆顺水推舟来一波详解。

    首先鱼站代码存在SQL是显而易见的,我就直接对表哥的Python代码做一波解释。

    贴出来的源代码中,sendHead()以及myHeaders()函数部分我们可以不用去管它,作用是用来向目标URL发起http get请求,并且对请求头做设置和对请求做错误处理,你可以当作固定公式。我们来看这个SQL注入脚本的关键函数 getPass() :

    2.png


    我们先找到下列带SQL的语句,
    [Python] 纯文本查看 复制代码
    poc="' or substr({0},{1},1)='{2}' and sleep(6) #".format(option,x,chr(i))


    format是python里面用来格式化字符串的函数,这里是基于位置的格式化,前面{0}{1}{2}类似占位符,代表这里将被替换为format()函数对应0,1,2位置传参代表的字符串。option是getPass()函数接受的传参,值为username或者password,代表你想要碰撞的是用户名还是密码,这个值是根据鱼站数据库里的字段对应的。 又由代码可以看到,x的取值为1~32,是外循环,代表的是此时碰撞的是用户名(或密码)的第x位字符(当然这里是假设了用户名最大不超过32位字符),i是内循环,取值为48~90,chr(i)是得到十进制数i所对应的ASCII 码所表示的字符,奉上ascii字符对照表可能更直观:

    3.png

    图中我用红框框出来了,可以看到48~90包括了数字0~9 ,大写英文A~Z和一些标点符号,也就是作者本来是想对数据库中用户名(或密码)的每一位字符和这些字符做对照,如果相同则保存在tmp中用来拼接出最终结果,但是这样有一点不好的是范围太窄了,别说万一用户名密码中带有小写字母,光是“@#*!”这些字符都有可能出现在常用密码中(当然,因为阅读了源码,此鱼站数据库保存的是MD5值所以不带这些特殊符号),但是如果鱼站数据库是区分大小写的话,这里可能就会无法跑出正确的用户名。所以取值范围最好改为48~122。

    现在理解了这条python语句,我们来看看是怎么sql注入的,首先substr(columns,opt1,opt2)函数是mysql数据库中用来做字符串截断的,代表的是对查找出来的数据,columns字段的字符串进行截断,获取第opt1位置开始,长度为opt2的字符串,此处opt2恒为1也就是只取第opt1位上的那个字符。

    现在我们对比鱼站源码拼凑起进行SQL注入后执行的完整SQL语句:


    [Python] 纯文本查看 复制代码
    SELECT * FROM fish_admin WHERE username='' or substr(username,第X位字符,1)='十进制i代表的字符' and sleep(6) #' limit 1


    首先开头的单引号闭合掉了原语句的单引号,最后的#注释掉了原语句后面的单引号,使整个语句能保持语法正确,这是基础就不多解释了,中间的语句会先判断:

    [Python] 纯文本查看 复制代码
    substr(username,x,1)='chr(i)' and sleep(6) 
    ,因为sleep()返回的是1,所以整个and连接的真假取决于从数据库中取值截断的字符和在ascii表中遍历的字符是否相同,相同则为真,否则为假,而这句前面是or,所以整句的真假取决于and语句的真假,也就是说当遍历到相同字符的的时候,整句为真,sql执行将延迟6秒,但是这里 有一个问题,如果username字段存在很多个值(也就是存在N个用户),那么这样执行将会延迟N*6秒,甚至导致语句执行被挂起,所以我觉得修改为:

    [Python] 纯文本查看 复制代码
    SELECT * FROM fish_admin WHERE username='' or substr(username,第X位字符,1)='十进制i代表的字符' and sleep(6) limit 1 #' limit 1



    比较合适。


    其他代码就比较好理解了,主要就是判断字段username值中,当前x位置的字符是否和i对应的ascii字符匹配,若匹配则拼接在变量tmp中准备作为最后结果输出,那么我们看看为啥只能跑出两位就退出程序了呢?




    4.png

    原因就出在我箭头标出来的位置,作者本意是想通过变量xxoo来判断是否遍历完了整个username字符串,当连续两次遍历ascii表都找不到匹配时,就判断已经对用户名碰撞完成,可是他此处用了continue,它代表的是不执行本次循环中在continue后面的语句,但是并没有退出这个内循环,也就是当找到对应的字符后,程序仍然会继续寻找,此时strNone必定会被置为True,所以在进行两次外循环之后就一定会执行exit()从而退出程序,解决办法很简单,修改continue为break。

    此时我们重新运行修改后的程序,得到该鱼站的新密码:

    md5 : 552E6A97297C53E592208CF97FBB3B60
    解密后:aaaaaaaaa


    5.png

    登陆成功,这么多登录记录,目测已被老哥们玩坏。

    既然这鱼站是个普遍的模版,那干脆将注入脚本改为带参数的通用exp,支持-u url注入其他网站的形式(不带参数则默认为这个鱼站):

    6.png

    这样可能对小白学习起来友好些,好了,愉快的玩耍去吧!

    修改后的代码:

    sql.zip

    1.39 KB, 下载次数: 50, 下载积分: 魔法币 -5

    售价: 3 魔法币  [记录]

    评分

    参与人数 1魔法币 +1 收起 理由
    AShe + 1 表哥616!

    查看全部评分

    本帖被以下淘专辑推荐:

    • · 实例|主题: 14, 订阅: 3
    信息安全菜鸟/社会主义接班人
    发表于 2018-5-22 22:22:55
    @onls辜釉   补充下至于表哥为什么执行后暂停了!因为我脚本那里有问题
    [Python] 纯文本查看 复制代码
        except requests.HTTPError as e:
            if errNum>maxErr:
                print(e)
                return None
            else:
                errNum=errNum+1
                sendHead(url,header,cookie,errNum)

    sendHead(url,header,cookie,errNum)这里报错后进行二次调用但是结果没有进行赋值所以报错后没有进行赋值导致result=None然后停止了后面的查询
    只需要把全部的except下的sendHead(url,header,cookie,errNum)改成result=sendHead(url,header,cookie,errNum)
    就好了。
    然后强行辩论一波!本来想偷偷补上无奈每次编辑提交都被拦截为攻击行为。
    所以沉默了。。。。。。
    用代码将梦想照进现实!Qq:2047797039
    使用道具 举报 回复
    AShe 发表于 2018-5-22 22:22
    @onls辜釉   补充下至于表哥为什么执行后暂停了!因为我脚本那里有问题
    [mw_shl_code=python,true]    exce ...

    sendHead方法中区分不同异常做处理,可是不同异常的处理都一样,是不是可以直接捕获Exception做统一处理?还有只有发生异常才会进入到二次调用处理,可是发生异常毕竟占少数,所以这个地方虽然也有问题会造成运行终止,可是真正的原因应该不在这里吧?其他语言歪楼过来对python不是很了解,错了轻喷
    使用道具 举报 回复
    onls辜釉 i春秋作家 春秋认证√作家团颜值担当 i春秋认证 秦 春秋文阁 i春秋签约作者
    推荐
    发表于 2018-5-23 09:16:31
    AShe 发表于 2018-5-22 14:22
    @onls辜釉   补充下至于表哥为什么执行后暂停了!因为我脚本那里有问题
    [mw_shl_code=python,true]    exce ...

    哈哈哈
    信息安全菜鸟/社会主义接班人
    使用道具 举报 回复
    吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼,这就需要一个良好的代码逻辑
    使用道具 举报 回复
    @onls辜釉 不知道能不能教一下我  纯属小白看不明白
    使用道具 举报 回复

    回帖是中华传统美德,嗯,一定要发扬光大
    使用道具 举报 回复
    我好像看懂了,因为continue悔终生
    使用道具 举报 回复
    虽然看不懂,但是我要抢波沙发
    使用道具 举报 回复
    发表于 2018-5-22 21:14:16
    666 666这样是清晰多了
    使用道具 举报 回复
    发表于 2018-5-23 09:29:43
    厉害厉害
    小白~~~
    使用道具 举报 回复
    使用道具 举报 回复
    发表于 2018-5-24 06:39:13
    不错不错。
    使用道具 举报 回复
    发表于 2018-5-27 08:57:05
    有黑市吗
    使用道具 举报 回复
    发表于 2018-9-10 15:34:01
    老哥666666
    使用道具 举报 回复
    发表于 2018-10-7 00:55:28
    学习一下~
    使用道具 举报 回复
    发表于 2018-12-26 13:27:30
    学习了!
    使用道具 举报 回复
    12下一页
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册