什么是rce漏洞
rce漏洞又称远程代码执行漏洞,它允许攻击者在目标服务器上远程执行任意代码或操作系统命令。rce漏洞通常出现在 应用程序提供给用户执行命令的接口,例如网页的ping功能也就是网页的url栏,如果不对上传的数据进行严格的管控就可能出现rce漏洞。
许多程序、网站都对用户提供交互功能,利用前端用户提供的代码或命令让后端系统执行一些操作,如果对这些管控不严格就很容易产生rce漏洞。
PHP中执行系统命令的函数
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
执行代码的函数
eval()
assert()
preg_replace()
creat_function()
call_user_func_arry()
call_user_func()
Windows系统命令拼接符
|:将前一个命令的输出作为后一个命令的输入,例如“echo a|b”,将第一个命令输出的结果作为第二个命令输入的结果。
||:运行前一个命令,若失败则运行后一个命令,例如“a||b”,先运行a,如果a运行失败了,则运行b,若成功了则不运行b
&:先运行前一个命令,后运行后一个命令,例如“a&b”,先运行a,然后运行b
&&:先运行前一个命令,如果成功则运行后一个命令,例如“a&&b”,先运行a命令如果成功则运行b,如果失败则不运行b。
;:和&类似
rce绕过类型
这边使用rce-labs靶场来了解
level1(一句话木马,层级关系绕过)
上面有一个包含,下面post传参a参数,看到这里其实第一印象是一句话木马,网页打开的这个php文件一个一句话木马我们用蚁剑链接看看
连接成功可以得到flag,但是我又尝试去传参一些查询函数,例如看一下ls
可以看到回显,里面有一个类似flag的文件,但是通过上面我们知道flag文件的名字就是flag,所以就查一下上层目录,但是不知道为什么查不出来
但是直接抓取上层目录的flag可以抓出来
level2(代码审计)
这关给了三个函数,逐一进行代码审计
function hello_ctf($function, $content){global $flag;$code = $function . "(" . $content . ");";echo "Your Code: $code <br>";eval($code);}
定义一个全局变量flag,将function参数和content参数拼接起来赋值给code参数,回显拼接之后的code参数并执行它,其中.是字符串连接符
整体来看这个函数就是传参两个参数,将这两个参数拼接之后输出出来并执行它
function get_fun(){$func_list = ['eval','assert','call_user_func','create_function','array_map','call_user_func_array','usort','array_filter','array_reduce','preg_replace'];if (!isset($_SESSION['random_func'])) {$_SESSION['random_func'] = $func_list[array_rand($func_list)];}$random_func = $_SESSION['random_func'];$url_fucn = preg_replace('/_/', '-', $_SESSION['random_func']);echo "获得新的函数: $random_func ,去 https://www.php.net/manual/zh/function.".$url_fucn.".php 查看函数详情。<br>";return $_SESSION['random_func'];
}
定义了一个数组里面都是执行函数,定义一个会话变量,检查这个会话变量是否被定义,如果没定义就从上面定义的数组里面抽取一个赋值给它,对抽到的函数进行处理将_变成-这里是为了符合url的解析规则,后面就是将随机抽取到的函数输出到屏幕而已,这里起到一个提示作用
function start($act){$random_func = get_fun();if($act == "r"){ /* 通过发送GET ?action=r 的方式可以重置当前选中的函数 —— 或者你可以自己想办法可控它x */session_unset();session_destroy(); }if ($act == "submit"){$user_content = $_POST['content']; hello_ctf($random_func, $user_content);}
}
这里有一个判断,如果get传参action=r就重置前面随机选取到的执行函数,如果action=submit,就从post传参中获取名为content的参数值
整体看就是要分get传参和post传参
我们先个体传参一下看看
可以看到上面抽取到的函数是assert这个函数,这个函数被赋值给了function变量我们后面用post传参的参数是content,会将这两个函数拼接并执行,那么我们结合assert函数的用法去post传参一个能得到flag的数据即可