欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DVWA学习日记——命令注入(Command Injection)

程序员文章站 2022-07-16 12:37:49
...

命令注入(Command Injection),是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。DVWA学习日记——命令注入(Command Injection)

Low级别

window和linux系统都可以用&&来执行多条命令
127.0.0.1 && net user

<?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>";
}

?> 
相关函数:

stristr(string,search,before_search)
查找“search”在“string”中的第一次出现并返回字符串的剩余部分
before_search默认为“false”,如果设置为 “true”,它将返回 “search”第一次出现之前的字符串部分
php_uname (mode)
mode为单个字符
‘a’:此为默认。包含序列 “s n r v m” 里的所有模式。
‘s’:操作系统名称。
‘n’:主机名。
‘r’:版本名称。
‘v’:版本信息。
‘m’:机器类型。

Medium级别

127.0.0.1 & net user
127.0.0.1 &;& net user

<?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>";
}

?> 
相关函数:

str_replace(find,replace,string,count)
在被查找字符串string中用replace替换find。

可以看到相比Low级别,服务器端对传入的ip参数进行了一定过滤,把“&&” “;”删除。即采用了黑名单的方式,因此仍存在安全问题
过滤“&&”但“&”仍可用,由于使用str_replace会把“&&” “;”替换为空字符所以还有一种绕过黑名单的方式“&;&”

High级别

127.0.0.1|net user

<?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 "<pre>{$cmd}</pre>";
}

?> 

可以看到相比Medium级别完善了黑名单过滤了更多的字符但是’| ’ => ''增加了一个字符所以‘|’成为漏网之鱼
A|B
|”是管道符,表示将A的输出作为B的输入,并且只打印B执行的结果

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 "<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();

?> 
相关函数:

stripslashes(string)
删除字符串中’'并返回已剥离反斜杠的字符串
explode(separator,string,limit)
此函数返回由字符串组成的数组separator规定在哪分割字符串,string需要分割的字符串
limit(可选)
大于 0 - 返回包含最多 limit 个元素的数组
小于 0 - 返回包含除了最后的 -limit 个元素以外的所有元素的数组
0 - 返回包含一个元素的数组

可以看到Impossible级别的代码加入了Anti-CSRF token,同时用白名单的方式对ip进行了限制,只有如数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。

总结

Command Injection

条件
  1. 是否调用系统命令
  2. 函数或函数的参数是否可控
  3. 是否拼接命令注入
Windows下常用拼接命令符号
命令 描述
A&B 简单的拼接,AB之间无制约关系
A&&B A执行成功后才会执行B
A|B A的输出作为B的输入
A||B A执行失败后才会执行B
没有回显怎么办
  1. 延时注入
    Windows ping 127.0.0.1 -n 5 >nul
    Linux sleep 5

  2. 远程请求
    Windows ping,telnet等
    Linux wget,curl等

修复

黑名单×
黑名单可以绕过如:用"“绕过
whoami——who”“am”"i
白名单√

相关标签: web