zoukankan      html  css  js  c++  java
  • 【DVWA】Brute Force(暴力破解)通关教程


    日期:2019-08-01 14:49:47
    更新:
    作者:Bay0net
    介绍:一直以为爆破很简单,直到学习了 Burp 的宏录制和匹配关键词,才发现 burp 能这么玩。。。


    0x01、 漏洞介绍

    利用大量的用户名和字典,去对账号进行暴力破解,人的问题(弱密码)可能是永远都无法防御的一个点吧。

    DVWA 没模拟验证码缺陷的相关漏洞,在实战中,会遇到很多验证码无效的栗子。

    0x02、Low Security Level

    查看源码

    <?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 = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
    
        if( $result && mysql_num_rows( $result ) == 1 ) {
            // Get users details
            $avatar = mysql_result( $result, 0, "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>";
        }
    
        mysql_close();
    }
    
    ?> 
    

    分析源码

    接受 usernamepassword 的值,然后传入数据库做比较,直接使用爆破即可。

    万能密码

    此处也可以使用万能密码进行登录。

    admin'or '1'='1
    admin' -- -
    admin' # 
    

    0x03、Medium Security Level

    查看源码

    <?php
    
    if( isset( $_GET[ 'Login' ] ) ) {
        // Sanitise username input
        $user = $_GET[ 'username' ];
        $user = mysql_real_escape_string( $user );
    
        // Sanitise password input
        $pass = $_GET[ 'password' ];
        $pass = mysql_real_escape_string( $pass );
        $pass = md5( $pass );
    
        // Check the database
        $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
        $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
    
        if( $result && mysql_num_rows( $result ) == 1 ) {
            // Get users details
            $avatar = mysql_result( $result, 0, "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>";
        }
    
        mysql_close();
    }
    
    ?> 
    

    分析源码

    1、对传过来的值,使用了 mysql_real_escape_string() 函数,转义了以下字符:

    x00
    
    
    
    
    '
    "
    x1a
    

    2、使用了 sleep(2) 函数,如果密码错误,则延时两秒响应。

    如果爆破的话,还是可以直接进行爆破的,只不过速度慢了些而已。。

    万能密码

    因为过滤了单引号,我们无法闭合掉前面的单引号,所以此处无法再使用万能密码了。

    0x04、High Security Level

    查看源码

    <?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 = mysql_real_escape_string( $user );
    
        // Sanitise password input
        $pass = $_GET[ 'password' ];
        $pass = stripslashes( $pass );
        $pass = mysql_real_escape_string( $pass );
        $pass = md5( $pass );
    
        // Check database
        $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
        $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
    
        if( $result && mysql_num_rows( $result ) == 1 ) {
            // Get users details
            $avatar = mysql_result( $result, 0, "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>";
        }
    
        mysql_close();
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

    分析源码

    可以发现,每次发送的时候,都带上了一个 user_token,每次发送请求的时候 user_token 都是会变的,而 user_token 是来自于上一个数据包的。

    使用 burp 爆破

    依次选择【Project options】->【Sessions】->【add】-> 【add a Rule Description】-> 【Run a macro(宏)】

    选择新建宏

    添加的时候,选择配置

    爆破成功。。挺费劲的,不如直接写 python 脚本。。

    发现了一个问题,密码为 b 的 user_token,并不是密码 a 响应报文里面的 user_token,推测原理如下:

    每次 burp 都会去访问之前宏里面的页面,然后获取 user_token,再给爆破数据包里面的 user_token 替换上,所以流程不是 a -> b -> c,而是 get_user_token -> a -> get_user_token -> b .....

    0x05、Impossible Security Level

    查看源码

    <?php
    
    if( isset( $_POST[ 'Login' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Sanitise username input
        $user = $_POST[ 'username' ];
        $user = stripslashes( $user );
        $user = mysql_real_escape_string( $user );
    
        // Sanitise password input
        $pass = $_POST[ 'password' ];
        $pass = stripslashes( $pass );
        $pass = mysql_real_escape_string( $pass );
        $pass = md5( $pass );
    
        // Default values
        $total_failed_login = 3;
        $lockout_time       = 15;
        $account_locked     = false;
    
        // Check the database (Check user information)
        $data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR );
        $data->execute();
        $row = $data->fetch();
    
        // Check to see if the user has been locked out.
        if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {
            // User locked out.  Note, using this method would allow for user enumeration!
            //echo "<pre><br />This account has been locked due to too many incorrect logins.</pre>";
    
            // Calculate when the user would be allowed to login again
            $last_login = $row[ 'last_login' ];
            $last_login = strtotime( $last_login );
            $timeout    = strtotime( "{$last_login} +{$lockout_time} minutes" );
            $timenow    = strtotime( "now" );
    
            // Check to see if enough time has passed, if it hasn't locked the account
            if( $timenow > $timeout )
                $account_locked = true;
        }
    
        // Check the database (if username matches the password)
        $data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR);
        $data->bindParam( ':password', $pass, PDO::PARAM_STR );
        $data->execute();
        $row = $data->fetch();
    
        // If its a valid login...
        if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) {
            // Get users details
            $avatar       = $row[ 'avatar' ];
            $failed_login = $row[ 'failed_login' ];
            $last_login   = $row[ 'last_login' ];
    
            // Login successful
            echo "<p>Welcome to the password protected area <em>{$user}</em></p>";
            echo "<img src="{$avatar}" />";
    
            // Had the account been locked out since last login?
            if( $failed_login >= $total_failed_login ) {
                echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
                echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";
            }
    
            // Reset bad login count
            $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' );
            $data->bindParam( ':user', $user, PDO::PARAM_STR );
            $data->execute();
        }
        else {
            // Login failed
            sleep( rand( 2, 4 ) );
    
            // Give the user some feedback
            echo "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";
    
            // Update bad login count
            $data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' );
            $data->bindParam( ':user', $user, PDO::PARAM_STR );
            $data->execute();
        }
    
        // Set the last login time
        $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR );
        $data->execute();
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

    重点在于:

    $total_failed_login = 3;
    $lockout_time       = 15;
    $account_locked     = false;
    

    错误 3 次的话,就锁定 15 分钟,如果在实战中遇到这种情况,可以采用爆破用户名的方法来做。

    0x06、burp 爆破匹配关键词

    设置如下:

    爆破成功会这样显示:

  • 相关阅读:
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    how to use automapper in c#, from cf~
  • 原文地址:https://www.cnblogs.com/v1vvwv/p/DVWA-Brute-Force.html
Copyright © 2011-2022 走看看