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. 安全分析

  1. 黑名单过滤机制

    • 代码使用黑名单过滤特殊字符(&、;、|、-、$、(、)、`、||)
    • 通过str_replace()函数将这些特殊字符替换为转义后的版本
  2. 操作系统检测

    • 使用php_uname('s')检测操作系统类型
    • 根据操作系统类型执行不同的ping命令格式
    • Windows系统:ping 目标IP
    • 非Windows系统:ping -c 4 目标IP
  3. 潜在安全问题

    • 黑名单过滤可能不完整,可能遗漏某些命令连接符
    • 没有对输入进行长度限制
    • 没有对输入进行白名单验证(如只允许IP地址格式)

4. 防御建议

  1. 使用白名单代替黑名单

    • 验证输入是否为合法的IP地址格式
    • 使用正则表达式严格限制输入格式
  2. 使用安全的命令执行函数

    • 考虑使用escapeshellarg()escapeshellcmd()函数
  3. 限制命令执行权限

    • 在服务器配置中限制可执行的命令
    • 使用自定义命令执行函数而非直接调用系统命令
  4. 输入验证增强

    if (!filter_var($target, FILTER_VALIDATE_IP)) {
        die("Invalid IP address format");
    }
    
  5. 使用替代方案

    • 考虑使用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靶场中命令注入高级难度的源码实现,包括:

  1. 完整的源码解析和注释
  2. 涉及的PHP函数详细说明和使用示例
  3. 安全机制分析(黑名单过滤)
  4. 潜在的安全问题和防御建议
  5. 相关函数的实验演示

通过这份文档,读者可以深入理解命令注入漏洞的防御机制实现,以及如何进一步加固Web应用的安全性。

DVWA靶场命令注入高级源码分析详解 1. 源码解析 2. 代码涉及函数详解 isset() 功能:检测变量是否已声明并且其值不为null 语法: bool isset ( mixed $var [, mixed $... ] ) trim() 功能:去除字符串首尾处的空白字符(或者其他字符) 语法: string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] ) 示例: str_ replace() 功能:子字符串替换 语法: mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] ) 说明:该函数返回字符串或者数组。该字符串或数组是将 subject 中全部的 search 都被 replace 替换之后的结果 示例: array_ keys() 功能:返回数组中部分的或所有的键名 语法: array array_keys ( array $array [, mixed $search_value = null [, bool $strict = false ]] ) 示例: stristr() 功能: strstr() 函数的忽略大小写版本,返回第一次出现的位置开始到结尾的字符串 语法: string stristr ( string $haystack , mixed $needle [, bool $before_needle = false ] ) 示例: 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 示例: 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() 函数 限制命令执行权限 : 在服务器配置中限制可执行的命令 使用自定义命令执行函数而非直接调用系统命令 输入验证增强 : 使用替代方案 : 考虑使用PHP原生函数实现ping功能,而非调用系统命令 5. 实验演示 1. trim()函数演示 2. array_ keys()函数演示 3. str_ replace()函数演示 4. php_ uname()函数演示 5. stristr()函数演示 6. 总结 本教程详细分析了DVWA靶场中命令注入高级难度的源码实现,包括: 完整的源码解析和注释 涉及的PHP函数详细说明和使用示例 安全机制分析(黑名单过滤) 潜在的安全问题和防御建议 相关函数的实验演示 通过这份文档,读者可以深入理解命令注入漏洞的防御机制实现,以及如何进一步加固Web应用的安全性。