• 【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 爆破匹配关键词

    设置如下:

    爆破成功会这样显示:

  • 相关阅读:
    百度echarts插件x轴坐标显示不全决解方法
    Laravel
    Mysql 递归获取多重数组数据
    Laravel 怎么使用资源控制器delete方法
    Laravel 怎么在 blade 视图中将带 HTML 字符原样输出
    laravel sql复杂语句,原生写法----连表分组
    mysql连表分组报错---- sql_mode=only_full_group_by问题解决
    Bootstrap -- 模态框实现拖拽移动
    xcode6模拟器UITextField不能自动弹出键盘
    在Linux系统中使用rpm包安装FTP服务
  • 原文地址:https://www.cnblogs.com/v1vvwv/p/DVWA-Brute-Force.html
Copyright © 2020-2023  润新知