• dvwa-command injection 代码审计(超详细逐行审计)


    dvwa-command injection 代码审计

    low

    
    
    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 "
    {$cmd}
    "
    ; } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    isset( $_POST[ 'Submit' ]此代码判断接受的post参数是否为空

    $target = $_REQUEST[ 'ip' ];request方式接受ip参数

    stristr( php_uname( 's' ), 'Windows NT' 此参数为真时,执行ping命令(意为在windows系统中执行ping命令)

    否则执行ping命令4次(意为在unix或linux中执行ping4次)

    其中的stristr函数如下

    stristr()函数在PHP中用于在字符串中查找子字符串,并返回第一个匹配的子字符串及其后面的部分,而且不区分大小写

    示例

    $str = "Hello, World!";
    $substring = "world";
    $result = stristr($str, $substring);
    echo $result; // 输出 "World!"
    
    • 1
    • 2
    • 3
    • 4

    php_uname()函数如下,此代码中即为查看系统信息是否为Windows NT

    在PHP中,php_uname()函数用于获取操作系统的信息。该函数返回一个包含系统信息的字符串,包括操作系统名称、主机名、内核版本、发布版本等

    • “a”:默认值,返回所有系统信息
    • “s”:返回操作系统名称
    • “n”:返回主机名
    • “r”:返回内核版本
    • “v”:返回发布版本
    • “m”:返回机器类型

    最后则返回执行结果

    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 "
    {$cmd}
    "
    ; } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    该级别代码几乎和low一致,仅添加两个过滤

    关键代码部分

    $substitutions = array( '&&' => '', ';' => '', );

    此代码为使用array函数快速定义一个数组,并将其值赋给substitutions

    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    array_keys( $substitutions )该函数为获取变量中的 键 即key

    
    	$substitutions = array(
    		'&&' => '',
    		';'  => '',
    	);
    	var_dump($substitutions);
    	print("
    "
    ); $a=array_keys($substitutions); var_dump($a); ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出结果

    image-20231121170431441

    然后使用srt_replace()函数进行字符串替换

    该函数如下

    str_replace()函数用于在字符串中替换指定的子字符串。它可以用于执行简单的字符串替换操作,例如将一个子字符串替换为另一个子字符串

    str_replace (mixed $search , mixed $replace , mixed $subject [, int &$count ]) : mixed

    search是要搜索的字符串或字符串数组,replace是要替换为的字符串或字符串数组,subject是被搜索的原始字符串,count是一个可选参数,用于存储替换操作的次数

    示例

    $string = "Hello, World!";
    $new_string = str_replace("World", "PHP", $string);
    echo $new_string;
    
    • 1
    • 2
    • 3

    输出结果即为 Hello, PHP!

    此处即,搜索输入的target的值,将其中substitutions数组中的键替换成substitutions变量中该键所对应的值,从而达成将输入的&&或者;进行置空过滤

    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 );
    
        // 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 "
    {$cmd}
    "
    ; } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    相较上一关,该难度差别在如下代码

    $target = trim($_REQUEST[ 'ip' ]);
    
        // Set blacklist
        $substitutions = array(
            '&'  => '',
            ';'  => '',
            '| ' => '',
            '-'  => '',
            '$'  => '',
            '('  => '',
            ')'  => '',
            '`'  => '',
            '||' => '',
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    增加了过滤项,但是原理不变

    除此之外添加了trim()处理输入的内容

    trim()函数用于删除字符串开头和结尾处的空白字符(空格、制表符、换行符等)或者其它指定字符

    string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] )

    str是要处理的字符串,character_mask是一个可选参数,用于指定要删除的字符。如果不指定$character_mask参数,默认会删除空格、制表符、换行符、回车符、空字符和垂直制表符

    示例

    $str = "   Hello, World!   ";
    $new_str = trim($str);
    echo $new_str;
    
    • 1
    • 2
    • 3

    输出结果为 Hello, World!

    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 the IP 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 "
    {$cmd}
    "
    ; } else { // Ops. Let the user name theres a mistake echo '
    ERROR: You have entered an invalid IP.
    '
    ; } } // Generate Anti-CSRF token generateSessionToken(); ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    将三个参数传递给checktoken函数,checktoken函数一般用于验证匹配用户token和用户session是否匹配,如不匹配则跳转到index.php

    $_REQUEST[ 'user_token' ]:这是一个 PHP 超全局数组,用于获取 HTTP 请求中的参数。在这里,$_REQUEST['user_token'] 用于获取名为 user_token 的参数的值。

    $_SESSION['session_token']:这是 PHP 的会话(Session)变量,用于在用户会话之间存储数据。在这里,$_SESSION['session_token'] 用于获取名为 session_token 的会话变量的值

    index.php:这是一个字符串,表示一个重定向页面的 URL。如果 checkToken 函数判断验证失败,用户将被重定向到这个页面

    $target = stripslashes( $target );该行代码为过滤输出内容

    stripslashes() 函数用于去除由 addslashes() 函数添加的反斜杠。在 PHP 中,addslashes() 用于在特定字符前添加反斜杠,以防止 SQL 注入和其他安全漏洞。而 stripslashes() 则用于将这些反斜杠去除,恢复原始的字符串

    $octet = explode( ".", $target );该行explode函数通过 点 将输入的内容分段,被分割的部分会以数组的形式存储在变量中

    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {该行代码使用is_numeric函数判断该分割后的数组中的每个元素是否为数字,当全部都为数字时判断为真,才会向下执行,is_numric函数会将十六进制也视为数字,可以考虑将代码编程16进制,但是由于有分段组合成ip的这一步,所以该方法也不能实现

    $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];重新将该数组拼接,然后剩下的代码就与之前一样了

    可以说是限制了所有字符和字母

    numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {`该行代码使用is_numeric函数判断该分割后的数组中的每个元素是否为数字,当全部都为数字时判断为真,才会向下执行,is_numric函数会将十六进制也视为数字,可以考虑将代码编程16进制,但是由于有分段组合成ip的这一步,所以该方法也不能实现

    $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];重新将该数组拼接,然后剩下的代码就与之前一样了

    可以说是限制了所有字符和字母

  • 相关阅读:
    Web安全——信息收集上篇
    SSM整合thymeleaf
    [附源码]计算机毕业设计JAVAjsp网上蛋糕订购系统
    九种常见UML图
    C#多线程(三)线程高级篇
    设计模式-代理模式
    嘉为蓝鲸携手广州卷烟厂斩获信通院鼎新杯两大奖项
    Jan 2023-Prioritizing Samples in Reinforcement Learning with Reducible Loss
    继承(一)—— 继承的定义 + 继承方式 和 访问限定符的关系
    备战秋招--mybatis篇
  • 原文地址:https://blog.csdn.net/qq_58683895/article/details/134537349