DVWA命令注入(Command Injection)漏洞代码审计

DVWA命令注入(Command Injection)漏洞代码审计

 
  代码审计(Code audit)是一种以发现程序错误,安全漏洞和违反程序规范为目标的源代码分析。软件代码审计是对编程项目中源代码的全面分析,旨在发现错误,安全漏洞或违反编程约定。 它是防御性编程范例的一个组成部分,它试图在软件发布之前减少错误。
 
  DVWA是一个基于PHP/MySQL开发的存在糟糕漏洞的web应用,旨在为专业的安全人员提供一个合法的环境,来测试他们的工具和技能。帮助web开发人员理解web应用保护的过程。
 
  下面将以DVWA靶场中的命令注入漏洞练习为例,熟悉人工代码审计的简单流程与方法,从中发现存在的漏洞并加以简单利用。代码中不熟悉的函数,可以通过PHP手册进行查询了解。

工具:PHP手册(下载链接:https://pan.baidu.com/s/1xSH__T1iy7zDD-opgkrw_Q?pwd=e2ht 提取码:e2ht)

 

Low

源代码分析:

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

?> 

 
1.判断是否传入参数,如果是,将传入的参数赋值给$target变量。

if( isset( $_POST[ 'Submit' ]  ) ) {
    $target = $_REQUEST[ 'ip' ];
    ……

isset() — 检测变量是否已声明并且其值不为 null

 
2.判断操作系统类型,若为Windows操作系统,直接执行ping命令,其他操作系统则加入ping4次的限制(Windows默认ping4次)。

    ……
	if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }
	……

stristr() — 查找字符串的首次出现(忽略大小写)。将php_uname返回的操作系统字段与Windows NT进行匹配,若匹配成功,则为Windows操作系统。

php_uname() — 返回运行 PHP 的系统的有关信息。

shell_exec() — 通过 shell 执行命令并将完整的输出以字符串的方式返回。

 
3.将cmd执行ping命令的结果在前端输出。后续出现相同的代码将不再做出解释。

	……
	echo "<pre>{$cmd}</pre>";
}

 

存在漏洞:

  shell_exec()函数是 PHP 中一个强大的功能,允许运行系统命令。然而,如果使用不当,这个函数可能会导致安全问题。在这个例子中,我们看到 shell_exec()被用来执行ping命令,这是一个常见的安全功能,用于检测主机是否在线。但是,问题在于,该脚本并没有对输入进行任何形式的验证和过滤,这可能会导致恶意用户提交的数据被直接用于执行系统命令,从而可能导致安全问题。
 

漏洞利用:

  在输入框输入ip地址 && 系统命令并执行,便可轻松获取想获取的系统信息,例如:

image-20230610192114024
 

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

?> 

 
分析增加的代码,Medium男的从用户输入中移除部分特殊字符,例如 '&&'';'

	……
    $substitutions = array(
        '&&' => '',
        ';'  => '',
    );
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
	……

str_replace() — 子字符串替换。使用该函数将用户输入中的特殊字符替换为空字符串。

array_keys() — 返回数组中部分的或所有的键名。

 

存在漏洞:

  Medium难度的命令注入漏洞源代码中曾加了对某些特殊字符的替换,主要利用了黑名单验证的方式来达到一个过滤的效果,但黑名单的列举是有限的,我们可以从中找到黑名单以外的字符来实现命令注入。
 

漏洞利用:

  将之前输入的 '&&' 改为 '&' 既可轻松实现命令注入。

Snipaste_2023-06-11_16-24-08
 

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

?> 

 
1.当 $_POST['Submit'] 被调用时,变量 $target 将被设置为用户输入的 IP 地址。

if( isset( $_POST[ 'Submit' ]  ) ) {
    $target = trim($_REQUEST[ 'ip' ]);
    ……

trim() — 去除字符串首尾处的空白字符(或者其他字符)

 
2.从用户输入中移除特殊字符,例如 '&'';''|''-''$''('')' 、 和 '||'

	……
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );
	$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
	……

 

存在漏洞:

  High难度的命令注入漏洞源代码中曾加了替换特殊字符的数量,但我们仍能从中找到黑名单以外的字符来实现命令注入。
 

漏洞利用:

   不难发现特殊符号没有对 '|'(无空格) 进行替换,在输入框输入 ip地址|系统命令 并执行,便可轻松获取想获取的系统信息,例如:

image-20230611160926175
 

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

?> 

 
1.检查用户 tokensession token 是否匹配。

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

checkdnsrr() — 给指定的主机(域名)或者IP地址做DNS通信检查,可以防止请求伪造。

 
2.去除 IP 地址中的反斜杠。

	……
    $target = stripslashes( $target );
	……

stripslashes() — 反引用一个引用字符串。将反斜杠 '\' 转换为正斜杠 '/'

 
3.将 IP 地址拆分成四个部分。

	……
    $octet = explode( ".", $target );
	……

explode() — 使用一个字符串分割另一个字符串。这里用 '.' 将 IP 地址进行了分割。

 
4.检查 IP 地址分割后的各部分是否为单纯的数字,如果是,则将拆分的 IP 地址重新拼接,进而继续进行后续操作。

	……
	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];
    ……

is_numeric() — 检测变量是否为数字或数字字符串。

 
  不难看出该方法对输入的 IP 地址做了合法性验证,只有输入符合 IPv4 格式的内容才能被正常执行,排除了一切可以注入其他命令的可能,安全性方面得到大幅提升。
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值