rce漏洞学习
什么是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的数据即可
level3(命令执行函数)
这关就是执行我们传参的参数a,直接看列表再抓取即可
level4(拼接符运用)
定义一个函数,这关函数接受一个参数,参数是一个地址,这关函数会连接这个地址,get传参接受一个参数ip,后面执行上面定义的函数,我们ping一下本地地址
连接成功显示了一些信息,那么我们使用连接符在后面加上查询函数,也可以执行
level5(黑名单绕过)
定义一个函数,匹配参数和flag这个字符串,如果有则输出waf,没有则执行这个参数,get传参获得参数,将参数传入定义的函数,可以直接反斜杠绕过,\是在php中是转义字符,会转义字符的意义位为特殊含义
也可以正则匹配绕过,使用通配符*匹配改层级里面0或一个或多个字符直接搜索所有f开头的文件,或用?匹配单个字符
单双引号绕过,单双引号可以用来定义一个空字符串或保护包含空格或特殊字符的字符串
取反中括号绕过,匹配不在中括号内的字符
中括号绕过,匹配中括号内的任意一个字符
level6(黑名单绕过+通配符绕过)
这关就是上一关的加强版,禁用了一系列绕过的字符,还是get传参字符并执行,可以看到禁用字符不完全其中a和?和/没禁用,我们可以尝试用?替代禁用的字符,传参?a? /??a?没反应……
就像我们平时用小皮搭建网站一样,一些简单的网站,除去数据库啊一些其他的东西,一个网站所有的文件都存在一个文件夹内,而一个网页通常就是一个html文件,然后在html文件中通过一些语句,在用户执行命令之后网页会有特定的回显,例如我们像查看这个网站中的一个文件,有一个简单的办法就是知道这个文件的路径,在url中直接搜索查看,或者通过网页提供的途径去直接跳到对应文件的路径,但是归根结底就是查文件路径,而我们想要的flag就藏在这个网站的文件夹中的某个文件,我们执行的查询函数其实就是查看对应路径里面的文件中的内容而已。而rce-labs这关靶场时搭建在kali操作系统里面的,那么到这里我们就需要了解一些?这个通配符的使用条件了。?通配符在路径、正则表达式、一些对比的情境下都适用,绕过我们正常用?通配符去替代cat显然不是上述说到的类型,既让如此我们传参的字符串就要是以上类型中的一种,显而易见是路径,这时候又遇到一个问题就是我们要怎么去确定这个路径,如果*没有被禁用那么可以用一个或若干个*直接去替代,但是用?就要大致的确定对应路径名称的字符串的字符数量,因为?只能代表0或1个字符,而且还要确定这个路径有几层,这要操作还有一个问题就是使用多个?去通配一个字符串,使用几个?也就说明了字符串有几个字符,在文件夹中相同字符数量的字符串肯定是有的,所有查出来的内容就会很多很繁琐,这时候如果在加上一些确定的字符就可以大大缩小范围,所以也可以使用base64来将内容查出。
说了这么多重要的还是要知道路径是什么,有几层。
直接用cat查
能查到flag,但是其他内容也很多,假设我们查的东西不是那么明显,或者它的文件格式不是文本,是图片啊什么的者显然就很不好用
用base64查
结果很精简,解码过来就是flag
level7(空格过滤)
这关同时过滤了flag和空格,直接用< 、>、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等替代空格都可以,这边就不一一演示了
level8(文件描述和重定向)
这关的代码通过定向输出结果到/dev/null
屏蔽输出结果,/dev/null
是类unix系统中的一个特殊文件,丢到这关文件中的数据都会被丢弃掉,kali就是类unix系统,2>&1
表示将标准错误输出(文件描述符为 2 )重定向到标准输出(文件描述符为 1 )的位置,也就是也导向 /dev/null
,这样命令执行过程中的错误信息也不会显示
这样的话我们即使我们执行了正确的指令,把flag查出来了也没有回显,我们要做的就是执行完查询语句之后截断将他发送到/dev/null
中,只要理解到一个点就很简单,代码是先执行完查询语句之后再进行定向的,也就是说我们在查询语句和定向的代码中间加一个;或其他拼接符不就可以了,因为定向的语句是固定加在后面的