DVWA全级别通关笔记(一)--Brute Force(暴力破解)

引言

结合DVWA(Damn Vulberable Web Application)提供的各种漏洞环境,对各类漏洞进行一下攻击,并且记录一下怎么防范,其实在DVWA各个漏洞安全级别的不断提升过程中,已经告诉我们一些防范各类漏洞的防范技巧,只要我们从源码中分析,就可以得到我们想要的答案。模块其中主要包括:Brute Force(暴力破解)、Command Injection(命令注入)、CSRF(Cross-site request forgery)、File Inclusion(文件包含)、File Upload(文件上传)、Insecure CAPTCHA(不安全的验证码)、SQL Injection(SQL注入)、SQL Injection(Blind)(SQL盲注)、XSS(Reflected)(反射型跨站脚本)、XSS(Stored)(存储型跨站脚本)。

环境

metasploitable2(虚拟机)

phpstudy

burpsuit

Brute Force(暴力破解)

low

对于某些需要进行用户登录的情况我们可以使用暴力破解的方法找到用户名以及密码。首先我们看一下源码:

<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // Get username
    $user = $_GET[ 'username' ];

    // Get password
    $pass = $_GET[ 'password' ];
    $pass = md5( $pass );

    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];

        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?> 

  low级别的暴力破解漏洞源码比较简单,就是GET传参$user和$pass,后面直接执行Mysql语句查询数据库,验证账号密码是否正确,如果正确,则直接登陆成功。我们直接上burp,抓包,进行暴力破解,找一个常规的字典就可以。线程数可以调整,数量越大,速度越快。

burp四种暴力破解类型:

sniper   一个字典,两个参数,先匹配第一项再匹配第二项

Battering ram  一个字典,两个参数,同用户名同密码

Pitchfork    两个字典,两个参数,同行匹配,短的截至

Cluster bomb 两个字典,两个参数,交叉匹配,所有可能 

 

 

攻击之后按照长度对响应包进行排列,查看异常的报文,如果攻击成功就可以找到用户名admin的密码。

 

 medium

首先我们看一下源码和low级别的有什么变化:

<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // Sanitise username input
    $user = $_GET[ 'username' ];
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitise password input
    $pass = $_GET[ 'password' ];
    $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)) ? "" : ""));
    $pass = md5( $pass );

    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];

        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        sleep( 2 );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>

  分析源码可以看到,用mysql_real_escape_string函数对参数进行过滤, 转义在 SQL 语句中使用的字符串中的特殊字符(简单防止SQL注入),而且如果登录失败,代码将延迟执行2秒(sleep(2))。这时暴力破解的时间可能比较长,但是依然能够破解成功。采用和low级别一样的方法即可。

high

同样的先看一下源码:

<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Sanitise username input
    $user = $_GET[ 'username' ];
    $user = stripslashes( $user );
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitise password input
    $pass = $_GET[ 'password' ];
    $pass = stripslashes( $pass );
    $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)) ? "" : ""));
    $pass = md5( $pass );

    // Check database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];

        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        sleep( rand( 0, 3 ) );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

  high级别的暴力破解源码中加入了一个user_token验证,每次请求报文时,都需要加上user_token参数,而且每次这个user_token参数都是会变化的。在HTML代码里面可以看到一个生成user_token值的表单。

我们来看一下token的原理和作用机制。

什么是Token?

Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。如果这个 Token 在服务端持久化(比如存入数据库),那它就是一个永久的身份令牌。

Token可以用来干什么?

  1. Token完全有应用管理,它可以避开同源策略。
  2. Token可以避免CSRF攻击。
  3. Token是无状态的,可以在多个应用间共享。

下面我们来对题目进行破解。破解步骤可以参考https://blog.csdn.net/liweibin812/article/details/86287645

1、首先可以对password和user_token两个参数进行暴力破解,选用burp的intruder模块,设置两个参数 password和user_token为变量,攻击类型选择pitchfork,意思是草叉模式(Pitchfork )——它可以使用多组Payload集合,在每一个不同的Payload标志位置上(最多20个),遍历所有的Payload。举例来说,如果有两个Payload标志位置,第一个Payload值为A和B,第二个Payload值为C和D,则发起攻击时,将共发起两次攻击,第一次使用的Payload分别为A和C,第二次使用的Payload分别为B和D。

2、设置参数,在option选项卡中将攻击线程thread设置为1,因为Recursive_Grep模式不支持多线程攻击,然后选择Grep-Extract,意思是用于提取响应消息中的有用信息,点击Add,如下图进行设置,最后将Redirections设置为Always。

 

 

3、设置payload,第一个参数就是常规设置,导入字典即可,第二个参数为user_token设置如图:

4、之后start attack就可以进行常规检查,找到真实用户名和密码。

从该方法我们就可以知道,增加token验证机制并不能防止暴力破解攻击,因为token可以在前端获取,这样防范措施就无效了,照样可以传参进行暴力破解。

除了使用上述burp绕过token验证的方法,还可以编写脚本,每次登陆前先获取user_token然后进行登录验证,这样也能实现暴力破解。

 暴力破解的防范

结合前面不同级别源码以及其他知识,我们可以总结一下防范暴力破解的方法。

  1. 对登陆失败的情况做一些处理,比如失败次数超过一定数量,则锁定账号或者ip一段时间。
  2. 设置安全的验证码
  3. 使用Token+验证码一起使用,这样可以防止csrf攻击。
  4. 限制登录之间的时间限制(例如两次登录之间必须间隔10秒),当然这样也会在一定程度上降低用户体验。
posted @ 2020-11-12 10:06  s1awwhy  阅读(2937)  评论(0编辑  收藏  举报