DVWA靶场-Command Injection

blog 1.1K
DVWA靶场-Command Injection

0x01 Low级别


<?php
// 判断用户是否提交表单
if( isset( $_POST[ 'Submit' ]  ) ) {
    // 获取表单中提交的目标ip
    $target = $_REQUEST[ 'ip' ];

    // 返回判断PHP运行平台的系统类型 如果是Windows则执行 否则执行else中的
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix   *nix表示Union和Linux操作系统
        // 执行系统命令ping并发送4次ICMP包
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // 将输出结果返回到页面
    echo "<pre>{$cmd}</pre>";
}

?>

通过审计代码发现,并没有对我们传入的ip参数进行过滤,这就导致了命令执行的漏洞。在window中有很多管道符,可以帮我们在一行执行多个语句

0x01.2 Windows 中的管道符

" && " 如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句只能为真。例如:ping 127.0.0.1&&whoami

" & "  如果前面的语句为假则直接执行后面的语句,前面的语句可真可假 如 ping 127.0.0.1&whoami

" || " 只有前面的语句出错 才会执行后面的语句 如 123 || ls

" | " 执行管道符后面语句例如:ping 127.0.0.1|ls

0x01.3 Linux中的管道符

" ; " 执行完分号前面的语句再执行分号后面的语句。如ping -c 1 127.0.0.1;ls

" | " 显示后面语句的执行结果 例如:ping 127.0.0.1|ls

"||" 当前面的语句出错时,执行后面的语句,例如:ping a||ls

" & " 将&前的语句转为后台运行,然后再执行后面的语句 例如 whoami&ls

" && " 如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句只能为真。例如:ping -c 1 127.0.0.1&&whoami

被``包裹起来的英文,可以当做命令进行执行

了解到上述管道符的用法之后,我们尝试在本关应用

以下DVWA靶场基于Macos系统搭建

127.0.0.1 || whoami
DVWA靶场-Command Injection

我们使用到了||或管道符,它的特点就是只有前面的127.0.0.1执行错误,才会执行我们的whoami命令

于是我们看到ping 127.0.0.1 成功执行了,所以不会执行我们的whoami命令。

于是我们尝试让||的语句故意执行出错,从而执行我们的whoami命令

a || whoami

众所周知,一个a字符不管对于ip地址来讲还是对于域名来说格式都是非法的。所以会执行错误,于是我们就成功执行了whoami命令,返回了我们当前计算机登录的用户名

DVWA靶场-Command Injection

对于后端程序员而言,它只是单纯的想让我们传入一个ip地址,之后执行ping命令,判断网络连通性。这个表单本来传的是一个ip地址参数,由于没有经过严格的过滤,被我们利用。假设我们传入的表单数据为a || whoami 经过后端的字符串拼接ping -c 4 a || whoami,由于macos是基于Unix开发的,一般被识别为Unix。所以执行了else中的拼接。之后经过shell_exec()处理,成功执行了我们系统的shell命令。shell_exec是一个可以调用系统命令的函数

它实际执行的语句为

DVWA靶场-Command Injection

我们可以看到ping命令抛出了一个错误 Unknown host。于是就执行了whoami这个命令。

其他的管道符可以自行尝试。这里不再演示。

0x02 Medium 级别


<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // 获取用户输入的值
    $target = $_REQUEST[ 'ip' ];

    // 设置黑名单
    $substitutions = array(
        '&&' => '',
        ';'  => '',
    );

    # 将用户输入的参数拿来校验 如果带有&&和;将会被替换为空 也就是过滤掉
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // 判断操作系统类型
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // 将命令执行的结果输出到页面
    echo "<pre>{$cmd}</pre>";
}

?>

这一关,与上关基本一致。只是本关做了一些过滤,但是过滤的不完整。从而仍旧存在命令注入

我们可以发现,它过滤了&&和; 但是没有过滤其他的管道符,比如|、&、||等等。

于是我们尝试使用 & 进行绕过

127.0.0.1 & whoami
DVWA靶场-Command Injection

刚刚前面有提过,不管&前面的ping命令是否执行成功,都会去执行后面的whoami。也就是说两个都可以被执行

以下是针对不同系统的管道符&讲解:

  • windows系统:刚刚前面有提过,不管&前面的ping命令是否执行成功,都会去执行后面的whoami。也就是说两个都可以被执行
  • *nix系统: 而*nix系统中的&符号是将一个程序以后台的方式运行ping -c 4 127.0.0.1 & whoami 也就是说将ping命令挂后台运行了,于是先执行了我们的whoami命令,之后又执行了ping命令。

0x03 Hight 级别


<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // 获取用户输入的值
    $target = trim($_REQUEST[ 'ip' ]);

    // 设置黑名单
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );

    // 将用户输入的值进行替换 如果存在黑名单中的值,则被替换为空
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // 判断操作系统类型
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // 将命令执行结果输出到页面
    echo "<pre>{$cmd}</pre>";
}

?>

通过审计代码发现,过滤的很严格几乎过滤了我们常用的管道符。但是我们要注意在代码中的第12行。即 | 我们注意到它这里过滤的是| ,注意"| "后面有一个空格。实际上它过滤的是"|+空格",所以我们只需要在传入参数的时候在|后面不加空格就可以绕过了。

127.0.0.1|whoami
DVWA靶场-Command Injection

管道符|不管是在Linux或者windows中都是会执行|管道符前后的命令,但是它只会回显管道符|后面的命令的执行结果,不会回显管道符前面命令的执行结果(但是它可以被执行,只是不会有结果)。

0x03.2 管道符|在*nix中的实验:
DVWA靶场-Command Injection

可以看到管道符|后面的成功被执行了并且返回了结果,那么管道符前面ls命令是否执行成功了呢?

我们再次实验 通过创建文件的方式判断管道符前面的命令是否被执行

我们输入功能为 创建一个名为123.txt文件,并在文件中写入123的命令,然后使用管道符|在后面追加了whoami命令。

前面测试到whoami可以被执行并且有回显

DVWA靶场-Command Injection

通过实验得出,即使管道符前面的没有回显结果,但是它成功的并执行了。我们可以看到创建了123.txt文件,并在里面写了内容123。

0x03.3 管道符|在Windows中的实验:

发现和*nix的结果一致,创建了test.txt文件并且内容为"test"

DVWA靶场-Command Injection
DVWA靶场-Command Injection

0x04 impossible 等级


<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // 检查用户的token值是否与后端一致
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // 获取用户输入的IP值
    $target = $_REQUEST[ 'ip' ];
    
    // 删除用户输入的值中的反斜杠 如 \
    $target = stripslashes( $target );

    // 将用户传入的IP以点分隔为一个数组。
    $octet = explode( ".", $target );

    // 判断用户输入的值是否是一个数字,并且需要是4位。就比如172.16.1.10 以点进行分隔,就可以分隔为四位,这是正常的ip地址
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        // 将打散之后的数组重新拼接成一个字符串
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

        // 检查PHP的运行平台操作系统
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
            // Windows
            $cmd = shell_exec( 'ping  ' . $target );
        }
        else {
            // *nix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }

        // 将执行结果输出到页面
        echo "<pre>{$cmd}</pre>";
    }
    else {
        //如果用户输入的不是一个合法的ip地址 则输出下面这句话
        echo '<pre>ERROR: You have entered an invalid IP.</pre>';
    }
}

// 创建token值
generateSessionToken();

?>

我们引用DVWA-BruteForce文章对token进行简单的描述:

DVWA靶场-Command Injection

也就是说即使用户进行了传参操作,但是如果用户前端页面token和后端的不一致可能就不会执行ping命令

这个token值是隐藏在form表单中的,除了传IP参数的input以外,还有一个传入token的input,只不过这个input隐藏的,其中的value值是通过后端页面生成并传给前端的页面的。当我们点击submit的时候,这个token值会跟随IP参数一并传给后端进行验证

DVWA靶场-Command Injection

除了检查token以外,它还将用户输入的值点进行分隔,一个合法的ip地址,是需要满足点分十进制的。并且IP地址的十进制是一个以点进行分隔的四位数字。那么它分隔之后又将我们传入的ip值进行逐个排查,检查是否是数字类型,并且是一个四位数。只有满足这个条件的时候,我们的ping 命令才会被执行,于是就有效的防止命令注入的风险

0x05 命令注入漏洞原因

当应用需要调用一些外部程序时会用到一些系统命令的函数。应用在调用这些函数执行系统命令的时候,如果将用户传入的值作为系统命令的参数,拼接到字符串中,就很有可能存在命令执行漏洞

0x06 命令注入的危害

1) 继承web服务器的权限,执行系统命令

2) 继承web服务器的权限,读取重要文件

3) 反弹shell

4) 控制整个网站乃至于控制整个服务器

0x07 命令注入的防护

1) 对用户传入的参数进行严格的过滤,过滤一些特殊的符号 若干 &、&&、\、||、|、/、;、等等

2) 结合实际的应用场景,将参数的特征进行反复研究,制造一个针对理想型参数执行的if语句。

3) 尽量不要将命令执行的参数,作为用户可动态控制的参数

4) 判断用户的token值

分享