something about DVWA - command injection

DVWA

DVWA => 备份地址

Command Injection(命令注入)

Low

  • 手动注入

    命令参数尾部手动拼接&,&&,|,||,;等,与其它命令。

    • 命令连接符

      1. &

        使得命令在后台运行。

        1
        2
        # 在后台更新软件包索引
        apt update &
      2. ;

        按顺序执行分隔的每条命令。

        1
        2
        # 先更新索引 再更新软件包
        apt update ; apt upgrade
      3. &&

        短路与
        前一条命令执行成功时,执行后一条命令;
        前一条命令执行失败,不会执行后一条命令。

        1
        2
        # 更新软件包索引,成功后更新软件包
        apt update && apt upgrade
      4. ||

        短路或
        前一条命令执行失败时,执行后一条命令;
        前一条命令执行成功,不会执行后一条命令。

        1
        2
        # 更新软件包索引失败时,打印信息
        apt update || echo "update failure"
      5. !

        排除命令执行对象。

        1
        2
        # 删除当前目录下,除html文件的所有文件
        rm -r !(*.html)
      6. &&||

        &&||搭配可以形成if-else选择分支。

        1
        2
        # 先更新软件包索引,成功就更新软件包,失败就打印信息
        apt update && apt upgrade || echo "update failure"
      7. |

        管道运算符,前一条命令的输出作为后一条命令的输入。

        1
        2
        # 列出当前文件夹下所有文件,并筛选文件名包含`example`的内容打印
        ls | grep example
      8. {}

        合并多条命令,使得分隔在一起的命令中,后面的命令依赖于前面的命令。

        1
        2
        # ping web服务器,连接不上,就重启网络服务并打印信息
        ping www.example.com || {service networking restart ; echo "start networking ..."}
      9. ()

        给命令分组,用以改变优先级。

        1
        2
        # 倘若`echo "1"`执行失败,`echo "3" && echo "4"`依然会执行
        (echo "1" && echo "2") || (echo "3" && echo "4")
      10. \

        用以将长命令换行。

        1
        2
        3
        # 打印"hello world"
        echo "hello \
        world"

      Windows下命令连接符不同意义:

      1. &&

        短路与
        前一条命令执行成功时,执行后一条命令;
        前一条命令执行失败,不会执行后一条命令。

      2. &

        真与
        无论情况如何,被分隔的命令都会执行。

      3. ||

        短路或
        前一条命令执行失败时,执行后一条命令;
        前一条命令执行成功,不会执行后一条命令。

      4. |

        真或
        无论情况如何,被分隔的命令都会被执行。

      5. ;

        Windows 不支持 ;分隔符。

  • 源码分析

    • 直接从request中获取参数

      1
      2
      // Get input
      $target = $_REQUEST[ 'ip' ];
    • 直接将参数以字符串的方式拼接入command

      使用shell_exec函数调用函数。

      1
      2
      // *nix
      $cmd = shell_exec( 'ping -c 4 ' . $target );

Medium

  • 手动注入

    不使用黑名单字符,使用其它命令连接符

  • 源码分析

    • 直接从request中获取参数

      Low级别相同。

    • 设置 黑名单

      1
      2
      3
      4
      5
      // Set blacklist
      $substitutions = array(
      '&&' => '',
      ';' => '',
      );
    • 过滤黑名单字符

      使用str_replace函数过滤字符。

      1
      2
      // Remove any of the charactars in the array (blacklist).
      $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
    • 将过滤后的命令以字符串的方式拼接入command

      1
      2
      // *nix
      $cmd = shell_exec( 'ping -c 4 ' . $target );

High

  • 手动注入

    使用|进行注入,注意|后不跟随空格。

  • 源码分析

    • 直接从request中获取参数,过滤首尾空白字符

      1
      2
      // Get input
      $target = trim($_REQUEST[ 'ip' ]);
    • 设置黑名单

      黑名单 不完善

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      // 注意'| ',有 `空格`,因此不完善
      // Set blacklist
      $substitutions = array(
      '&' => '',
      ';' => '',
      '| ' => '',
      '-' => '',
      '$' => '',
      '(' => '',
      ')' => '',
      '`' => '',
      '||' => '',
      );
    • 过滤黑名单字符

      Medium相同。

    • 将过滤后的命令以字符串的方式拼接入command

      Medium相同。

Impossible

针对命令注入:

  1. 首先在获取参数时使用stripslashes函数去除参数中的反斜杠(\)

  2. 其次针对特定命令参数分解判断

    ping ip.ip.ip.ip中针对ip地址,分别判断。

    1
    2
    3
    4
    5
    6
    7
    // 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 ) ) {
    // ...
    }

something about DVWA - brute force

DVWA

DVWA => 备份地址

Brute Force(暴力破解)

Low

  • 选取暴破点

    GET /dvwa/vulnerabilities/brute/?username=admin&password=§p§&Login=Login HTTP/1.1 中,
    password进行暴破。

  • 设置payload

    Attact type选择SniperPayloads选择Runtime file, 既而选择密码 字典文件(2019_top100.txt),暴力破解即可。

  • 源码分析

    • 直接从request中获取参数

      1
      $pass = $_GET[ 'password' ]; 
    • 直接将参数以字符串的方式拼接入sql

      1
      $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';"; 

Medium

  • 选取暴破点

    Low级别相同。

  • 设置payload

    Low级别相同。

  • 源码分析

    request中获取参数后,使用mysqli_real_escape_string函数对参数中可能干扰到sql查询的特殊字符进行删除。

    1
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); 

High

  • 选取暴破点

    由于有token检测,除了password暴破点外,还需要设置user_token暴破点。
    GET /dvwa/vulnerabilities/brute/?username=admin&password=§pa§&Login=Login&user_token=§ad5031ef52b181892a11a845db6807b7§ HTTP/1.1

  • 设置Options

    由于需要绕过token检测,因此需要获取页面请求时返回的token值。

    由于需要先进行页面请求,再进行暴破,因此需要用到重定向Redirections中设置Follow redirections:Always

    Options中,Grep - Extract中添加一条记录,捕获token值。
    Refetch response后,选中tokenvalue值,burpsuite会自动生成对应的捕获正则表达式, 添加即可在每次的页面请求response中捕获对应token值,用于payload中。

    由于绕过token需要对每一次的页面请求responsetoken值进行捕获,因此不可以使用多线程。 Resource Pool中自定义Max concurrent requests1的规则。

  • 设置payload

    Attact type设置为Pitchfork后对每个暴破点设置payload

    password暴破点的payload正常设置。

    tokenpayload设置为Recursive grep,也即使用捕获的token值。

  • 源码分析

    • 检测token

      先进行token的检测检测通过,再进行后续操作。

      1
      checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    • stripslashes函数过滤参数

      request中获取参数后,先使用stripslashes函数去除参数中的\字符。

      1
      $pass = stripslashes( $pass ); 
    • mysqli_real_escape_string函数过滤参数

      再使用mysqli_real_escape_string函数对参数中可能干扰到sql查询的特殊字符进行删除。

      1
      $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); 

Impossible

相比High级别,增加了尝试次数的限定,超过尝试次数后一段时间内禁止尝试。

1
2
3
4
// Default values
$total_failed_login = 3;
$lockout_time = 15;
$account_locked = false;