[TSCTF-J 2021] SimplePHP
这是一道php绕过题
<?php
highlight_file(__FILE__);
if ($_GET["secret"] != hash("md4", $_GET["secret"])) {
die('乐<br>');
}
if (!preg_match('/http/i', $_GET['file'])) {
if (preg_match('/^i_am_bloodhound$/', $_GET['name']) && $_GET['name'] !== 'i_am_bloodhound') {
$file = $_GET["file"];
echo "我是布洛特亨德尔!<br>";
}
} else {
die("?");
}
if ((string)$_GET['s1'] !== (string)$_GET['s2'] && md5($_GET['s1']) === md5($_GET['s2'])) {
echo "众神之父赐予我视野<br>";
} else {
die("众神之父赐予我重伤倒地<br>");
}
if ($_REQUEST) {
foreach ($_REQUEST as $value) {
if (preg_match('/[a-zA-Z]/i', $value))
die('众神之父不喜欢英文<br>');
}
}
if (file_get_contents($file) !== 'phoniex_kit') {
die("我重伤倒地");
}
var_dump(file_get_contents("/flag"));
1.首先第一关:
这是个md4绕过
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,
所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
故我们传一个0e251288019
2.再来第二关
第一个if正则匹配传个file=http就行
第二个if是字符串比较,网上说可以加换行符%0A绕过
3.接着第三关
这是一个md5强碰撞,我们需要找到两个md5值相等的散列
互联网很强大,说来就来
s1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
&s2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
4.终于到第四关,$_REQUEST能获取之前所有传参,但是竟然不能用字母
但是呢,由于这里使用了$REQUEST,根据php中的解释,它可以接受$GET ,$POST 值,并在一定条件下也能接受COOKIE值,
但是它会优先接受$POST传值,所以我们将之前做传的值都用POST传一遍数字。
5.到最后一关了
file_get_contents()是用来将文件的内容读入到一个字符串中的首选方法,并且这个函数是可以绕过的
绕过方式有多种:
使用php://input伪协议绕过
将要GET的参数?xxx=php://input
用post方法传入想要file_get_contents()函数返回的值
用data://伪协议绕过
将url改为:?xxx=data://text/plain;base64,想要file_get_contents()函数返回的值的base64编码
或者将url改为:?xxx=data:text/plain,(url编码的内容)
于是我们开始尝试,发现data://伪协议可行。
最终完整的payload
得到flag