RCE(Remote Code Execute)远程代码执行
原理
因为需求设计,后台有时候需要把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。不管是使用了代码执行的函数,还是使用了不安全的反序列化等等。
通过代码注入或远程代码执行(RCE),攻击者可以通过注入攻击执行恶意代码、向网站写webshell、控制整个网站甚至服务器。其实际危害性取决于服务器端解释器的限制(例如,PHP,Python等)。在某些情况下,攻击者可能能够从代码注入升级为命令注入。
通常,代码注入容易发生在应用程序执行却不经过验证代码的情况下。
产生条件(敏感函数)
1 | eval() //把字符串作为PHP代码执行 |
动态函数$a($b)
由于PHP 的特性原因,PHP 的函数支持直接由拼接的方式调用,这直接导致了PHP 在安全上的控制有加大了难度。不少知名程序中也用到了动态函数的写法,这种写法跟使用call_user_func()的初衷一样,用来更加方便地调用函数,但是一旦过滤不严格就会造成代码执行漏洞。
举例:不调用eval()
1 |
|
危害
执行脚本代码如PHP、Java、Python脚本
检测
检测方法
白盒——代码审计
在白盒测试的过程中,我们可以重点关注危险函数出现的位置(上面所总结的那些)。当存在我们能控制的数据,并且能构造出注入攻击的地方,那么漏洞就是存在的。这类测试可以利用自动化工具来进行。
黑盒
- 漏洞扫描工具
- 公开漏洞
- 手工看参数值及功能点,比如提交参数值中出现了echo等PHP函数
检测位置
无
利用
利用过程
此处以php为例,其它语言也存在这类利用。
(1) preg_replace()函数:
1 | mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) |
当$pattern处存在e修饰符时,$replacement 会被当做php代码执行。
(2)mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed $…):
第一个参数为回调函数,第二个参数是回调函数的参数


(3)eval()和assert():
当assert()的参数为字符串时 可执行PHP代码
【区分】:
1 | eval(" phpinfo(); ");【√】 |
RCE(Remote Command Execute)远程命令执行
原理
远程系统命令执行(操作系统命令注入或简称命令注入)是一种注入漏洞。攻击者注入的payload将作为操作系统命令执行。仅当Web应用程序代码包含操作系统调用并且调用中使用了用户输入时,才可能进行OS命令注入攻击。它们不是特定于语言的,命令注入漏洞可能会出现在所有让你调用系统外壳命令的语言中:C,Java,PHP,Perl,Ruby,Python等。
操作系统使用Web服务器的特权执行注入的任意命令。因此,命令注入漏洞本身不会导致整个系统受损。但是,攻击者可能能够使用特权升级和其他漏洞来获得更多访问权限。
产生条件(敏感函数)
1 | system() //执行外部程序,并且显示输出 |
危害
执行系统命令如Windows、Linux命令
检测
检测方法
白盒——代码审计
在白盒测试的过程中,我们可以重点关注危险函数出现的位置(上面所总结的那些)。当存在我们能控制的数据,并且能构造出注入攻击的地方,那么漏洞就是存在的。这类测试可以利用自动化工具来进行。
黑盒
- 漏洞扫描工具
- 公开漏洞
- 手工看参数值及功能点,比如提交参数值中出现了echo等PHP函数
检测位置
无
利用
利用过程
命令执行(注入)常见可控位置情况有下面几种:
system("$arg");//可控点直接是待执行的程序
如果我们能直接控制$arg,那么就能执行执行任意命令了。
system("/bin/prog $arg");//可控点是传入程序的整个参数
我们能够控制的点是程序的整个参数,我们可以直接用&& || 或 | 等等,利用与、或、管道命令来执行其他命令(可以涉及到很多linux命令行技巧)。
system("/bin/prog -p $arg");//可控点是传入程序的某个参数的值(无引号包裹)
我们控制的点是一个参数,我们也同样可以利用与、或、管道来执行其他命令,情境与二无异。
system("/bin/prog --p=\"$arg\"");//可控点是传入程序的某个参数的值(有双引号包裹)
这种情况压力大一点,有双引号包裹。如果引号没有被转义,我们可以先闭合引号,成为第三种情况后按照第三种情况来利用,如果引号被转义(addslashes),我们也不必着急。linux shell 环境下双引号中间的变量也是可以被解析的,我们可以在双引号内利用反引号执行任意命令 id
system("/bin/prog --p='$arg'");//可控点是传入程序的某个参数的值(有单引号包裹)
这是最困难的一种情况,因为单引号内只是一个字符串,我们要先闭合单引号才可以执行命令。如:system(“/bin/prog –p=’aaa’ | id”)
在漏洞检测中,除了有回显的命令注入(比如执行dir 命令或者cat 读取系统文件);还可以使用盲打的方式,比如curl远程机器的某个目录(看access.log),或者通过dns解析的方式获取到漏洞机器发出的请求。
当我们确定了OS命令注入漏洞后,通常可以执行一些初始命令来获取有关受到破坏的系统的信息。以下是在Linux和Windows平台上常用的一些命令的摘要:
| 命令目的 | linux | windows |
|---|---|---|
| 当前用户名 | whoami |
whoami |
| 操作系统 | uname -a |
ver |
| 网络配置 | ifconfig |
ipconfig /all |
| 网络连接 | netstat -an |
netstat -an |
| 运行进程 | ps -ef |
tasklist |
命令分隔符的使用
在Linux上, ; 可以用 |、|| 代替
1 | ;前面的执行完执行后面的 |
在Windows上,不能用 ; 可以用&、&&、|、||代替
1 | &前面的语句为假则直接执行后面的 |
PHP 支持一个执行运算符:反引号(“) PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回
1 | echo `whoami`; |
效果与函数 shell_exec() 相同,都是以字符串的形式返回一个命令的执行结果,可以保存到变量中
RCE防御与安全修复
WAF产品
变量过滤或固定:变量过滤即对提交变量内容进行过滤,变量固定即固定允许提交的变量值,后者更加实用
敏感函数禁用