DVWA靶场命令注入高级源码分析详解
字数 1779 2025-08-10 20:35:54
DVWA靶场命令注入高级源码分析详解
1. 源码解析
<?php
if( isset( $_POST[ 'Submit' ] ) ) { //判断前端输入是否有submit变量,且该变量是否为空
$target = trim($_REQUEST[ 'ip' ]); //去除前端输入字符串首尾处的空白字符(或者其它字符)后,将其赋值给$target
$substitutions = array(
'&' => '&',
';' => ';',
'|' => '|',
'-' => '-',
'$' => '$',
'(' => '(',
')' => ')',
'`' => '`',
'||' => '||'
); //将需要转义的字符转义并放入一个数组(黑名单)
$target = str_replace( array_keys( $substitutions ), $substitutions, $target ); //将原变量target中的特殊字符通过str_replace函数的处理,将特殊字符(黑名单)替换为转义后的字符,赋值给$target
if( stristr( php_uname( 's' ), 'Windows NT' ) ) { //php_uname('s')返回运行php服务的操作系统信息,在忽略大小写的情况下,php_uname('s')返回操作系统信息是否包含windowsNT,如果包含,返回true
$cmd = shell_exec( 'ping ' . $target );
} //如果返回的操作系统信息为windows系统,执行ping命令
else { //否则,执行非windows系统的ping命令
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// 输出命令执行结果
echo "<pre>{$cmd}</pre>";
}
?>
2. 代码涉及函数详解
isset()
- 功能:检测变量是否已声明并且其值不为null
- 语法:
bool isset ( mixed $var [, mixed $... ] )
trim()
- 功能:去除字符串首尾处的空白字符(或者其他字符)
- 语法:
string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] ) - 示例:
$a = " abc 123 ";
echo trim($a); // 输出"abc 123"
str_replace()
- 功能:子字符串替换
- 语法:
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] ) - 说明:该函数返回字符串或者数组。该字符串或数组是将
subject中全部的search都被replace替换之后的结果 - 示例:
$substitutions = array(
'ipconfig' => '',
'whoami' => '',
'pwd' => ''
);
$arr1 = array_keys($substitutions);
$a = "whoamiabcipconfig123pwd";
echo $a."<br />";
echo str_replace($arr1, $substitutions, $a); // 输出"abc123"
array_keys()
- 功能:返回数组中部分的或所有的键名
- 语法:
array array_keys ( array $array [, mixed $search_value = null [, bool $strict = false ]] ) - 示例:
$substitutions = array(
'&' => '&',
';' => ';',
'|' => '|'
);
var_dump(array_keys($substitutions));
// 输出array(3) { [0]=> string(1) "&" [1]=> string(1) ";" [2]=> string(1) "|" }
stristr()
- 功能:
strstr()函数的忽略大小写版本,返回第一次出现的位置开始到结尾的字符串 - 语法:
string stristr ( string $haystack , mixed $needle [, bool $before_needle = false ] ) - 示例:
var_dump(stristr("word", "WORD")); // 输出string(4) "word"
php_uname()
- 功能:返回运行PHP的系统的有关信息
- 语法:
string php_uname ([ string $mode = "a" ] ) - 参数说明:
- 'a': 此为默认。包含序列"s n r v m"里的所有模式
- 's': 操作系统名称。例如: FreeBSD
- 'n': 主机名。例如: localhost.example.com
- 'r': 版本名称,例如: 5.1.2-RELEASE
- 'v': 版本信息。操作系统之间有很大的不同
- 'm': 机器类型。例如:i386
- 示例:
echo php_uname('s'); // 输出操作系统名称
shell_exec()
- 功能:通过shell执行命令并将完整的输出以字符串的方式返回
- 语法:
string shell_exec ( string $cmd ) - 注意:该函数与反引号(`)执行操作符效果相同
3. 安全分析
-
黑名单过滤机制:
- 代码使用黑名单过滤特殊字符(&、;、|、-、$、(、)、`、||)
- 通过
str_replace()函数将这些特殊字符替换为转义后的版本
-
操作系统检测:
- 使用
php_uname('s')检测操作系统类型 - 根据操作系统类型执行不同的ping命令格式
- Windows系统:
ping 目标IP - 非Windows系统:
ping -c 4 目标IP
- 使用
-
潜在安全问题:
- 黑名单过滤可能不完整,可能遗漏某些命令连接符
- 没有对输入进行长度限制
- 没有对输入进行白名单验证(如只允许IP地址格式)
4. 防御建议
-
使用白名单代替黑名单:
- 验证输入是否为合法的IP地址格式
- 使用正则表达式严格限制输入格式
-
使用安全的命令执行函数:
- 考虑使用
escapeshellarg()或escapeshellcmd()函数
- 考虑使用
-
限制命令执行权限:
- 在服务器配置中限制可执行的命令
- 使用自定义命令执行函数而非直接调用系统命令
-
输入验证增强:
if (!filter_var($target, FILTER_VALIDATE_IP)) { die("Invalid IP address format"); } -
使用替代方案:
- 考虑使用PHP原生函数实现ping功能,而非调用系统命令
5. 实验演示
1. trim()函数演示
$a = " abc 123 ";
echo trim($a); // 输出"abc 123"
2. array_keys()函数演示
$substitutions = array(
'&' => '&',
';' => ';',
'|' => '|'
);
$arr1 = array_keys($substitutions);
for($a = 0; $a < sizeof($substitutions); $a++) {
echo $arr1[$a]."<br />";
}
// 输出:
// &
// ;
// |
3. str_replace()函数演示
$substitutions = array(
'ipconfig' => '',
'whoami' => '',
'pwd' => ''
);
$arr1 = array_keys($substitutions);
$a = "whoamiabcipconfig123pwd";
echo $a."<br />";
echo str_replace($arr1, $substitutions, $a);
// 输出:
// whoamiabcipconfig123pwd
// abc123
4. php_uname()函数演示
echo php_uname('s'); // 输出操作系统名称,如"Linux"或"Windows NT"
5. stristr()函数演示
var_dump(stristr("word", "WORD")); // 输出string(4) "word"
6. 总结
本教程详细分析了DVWA靶场中命令注入高级难度的源码实现,包括:
- 完整的源码解析和注释
- 涉及的PHP函数详细说明和使用示例
- 安全机制分析(黑名单过滤)
- 潜在的安全问题和防御建议
- 相关函数的实验演示
通过这份文档,读者可以深入理解命令注入漏洞的防御机制实现,以及如何进一步加固Web应用的安全性。