【靶场练习】--DVWA第一关Brute Force(暴力破解)全难度分析

注意,这一关必须要使用Burpsuite来抓包

目录

Low

1.抓包

打开代理,然后在登录框随便输入账号密码

可以拦截抓包:

也可以在历史中找到对应的包:

2.发送到爆破模块

右键

3.选择爆破模式

将Attack type的值设置为Cluster bomb

爆破模式介绍


4.添加载荷

选中需要爆破的地方,点击add(在前后输入§也行)

5.添加字典

可以选择导入字典也可以手动输入

6.爆破查看

果然成功了:

查看源码

php 复制代码
<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // 安全风险:使用GET方法传递用户名和密码,会暴露在URL中并可能被日志记录
    // 建议:使用POST方法处理敏感信息
    
    // Get username
    $user = $_GET[ 'username' ];
    // 安全风险:未对用户名进行任何过滤或转义处理,直接用于SQL查询
    // 存在严重的SQL注入漏洞
    
    // Get password
    $pass = $_GET[ 'password' ];
    // 安全风险:密码通过GET传输,存在泄露风险
    // 安全风险:使用MD5哈希密码,安全性极低,易被彩虹表破解
    // 安全风险:未使用盐值增强密码哈希安全性
    // 建议:使用password_hash()和password_verify()
    $pass = md5( $pass );

    // Check the database
    // 安全风险:直接拼接用户输入构建SQL查询,存在严重SQL注入漏洞
    $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>";
        // 安全风险:直接输出用户可控的$avatar变量,可能存在XSS攻击
        // 示例:如果avatar存储为javascript:alert('xss'),可能执行脚本
        echo "<img src=\"{$avatar}\" />";
        
        // 安全风险:缺少会话管理机制,无法在后续请求中保持登录状态
        // 建议:使用session_start()初始化会话并存储用户认证信息
    }
    else {
        // Login failed
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

可以发现,这个登录框甚至都没有做sql注入防护,那么使用万能密码就可以直接登录...

  • 总的来说,这个只实现了验证账号密码是否匹配的功能,几乎没有安全性可言

Medium

查看源码

php 复制代码
<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // 安全风险:使用GET方法传输用户名和密码,数据会暴露在URL中,可能被日志记录
    // 建议:使用POST方法传输敏感信息
    
    // Sanitise username input
    $user = $_GET[ 'username' ];
    // 安全风险:仅使用mysqli_real_escape_string()不足以完全防止SQL注入
    // 建议:使用参数化查询(prepared statements)
    $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' ];
    // 同样存在SQL注入防护不足的问题
    $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)) ? "" : ""));
    // 安全风险:使用MD5哈希密码,安全性不高,易被破解
    // 安全风险:未使用盐值(salt)增强哈希安全性
    // 建议:使用password_hash()和password_verify()函数
    $pass = md5( $pass );

    // Check the database
    // 安全风险:通过字符串拼接构建SQL查询,存在SQL注入风险
    $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>";
        // 安全风险:直接输出从数据库获取的avatar路径,可能存在XSS攻击风险
        echo "<img src=\"{$avatar}\" />";
        
        // 安全风险:缺少会话管理机制,无法在后续请求中保持身份验证状态
        // 建议:使用session_start()和$_SESSION存储用户认证状态
    }
    else {
        // Login failed
        // 安全风险:登录失败时使用sleep(2),导致响应时间差异,可能被用于暴力破解
        // 建议:移除sleep()或对成功和失败响应使用相同的延迟处理
        sleep( 2 );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

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

?>
  • 不难发现,相比于Low级别的代码,Medium级别的代码主要增加了mysql_real_escape_string函数,这个函数会对字符串中的特殊符号(x00,n,r,,',",x1a)进行转义,把其中的字符串给过滤掉了,勉强能够抵御一般的sql注入攻击,那Low等级时候用到的注入就失效了,需要注意的是中级的暴力破解相对来说较慢是因为有个sleep函数,在破解失败后会使程序停止运行两秒。所以我们直接用爆破方法即可,和low级的一样。

High

1.抓包

发送到爆破模块,发现登陆时有token

要么删除token后发包 ;要么使用同一个token,重放 ;要么使用burp得插件CSRF Token Tracker ,根据规则从reponse报文中找到token并使其他模块发送报文时自动更新新的token

2.在bp的extensions中找到CSRF Token Tracker,并安装


其中host 中的host,name 为token字段名

ps:使用CSRF Token Tracker 插件的原理:你提交用户名密码后,burp捕获这个数据包,然后你将这个数据包send to repeater,send发送给服务端,服务端发送响应包, CSRF Token Tracker 插件捕获响应包中的user_token

3.构造字典

和low一样添加字典

使用单线程

4.成功爆破

查看源码

php 复制代码
<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    // 安全改进:添加了CSRF令牌验证,有助于防止跨站请求伪造攻击
    // 注意:需确认checkToken()实现是否安全,以及令牌生成逻辑是否可靠

    // Sanitise username input
    $user = $_GET[ 'username' ];
    // 安全风险:使用GET方法传输用户名和密码,敏感信息会暴露在URL中
    
    $user = stripslashes( $user );
    // 安全问题:stripslashes()仅移除反斜杠,不能有效防止SQL注入
    // 注意:与mysqli_real_escape_string()配合使用可能产生意外结果
    
    $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)) ? "" : ""));
    // 安全风险:仍依赖字符串拼接构建SQL查询,mysqli_real_escape_string()防护有限
    // 建议:使用参数化查询(prepared statements)彻底防止SQL注入

    // 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)) ? "" : ""));
    // 安全风险:密码哈希使用MD5算法,安全性极低,易被破解
    // 安全风险:未使用盐值(salt)增强密码哈希安全性
    // 建议:使用password_hash()和password_verify()函数
    $pass = md5( $pass );

    // Check database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    // 安全风险:通过字符串拼接构建SQL查询,仍存在SQL注入风险
    // 即使使用了转义函数,在特定编码或场景下仍可能被绕过
    
    $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>";
        // 安全风险:直接输出$user变量,未进行HTML转义,可能存在XSS攻击
        // 建议:使用htmlspecialchars($user, ENT_QUOTES)转义输出
        
        echo "<img src=\"{$avatar}\" />";
        // 安全风险:直接使用数据库中的$avatar路径,若该值用户可控则存在XSS风险
        // 建议:验证路径合法性并使用htmlspecialchars()转义
        
        // 安全风险:缺少会话管理机制,登录状态无法在后续请求中保持
        // 建议:使用session_start()初始化会话并存储用户认证信息
    }
    else {
        // Login failed
        sleep( rand( 0, 3 ) );
        // 安全改进:使用随机延迟替代固定延迟,降低暴力破解效率
        // 仍存在:成功与失败响应时间差异可能被利用的风险
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

    // 代码问题:数据库连接关闭方式过于复杂,可简化为mysqli_close($GLOBALS["___mysqli_ston"])
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

// Generate Anti-CSRF token
generateSessionToken();
// 注意:需确认generateSessionToken()生成的令牌是否足够随机且安全

?>

原理就是 token是前端生成的所以我们可以提前获取他的值(利用的就是token的复用 我们上一次访问失败之后可以把他的token搞到下一次去使用 这样就可以使用这个token去爆破)但是现实场景我们是不知道他的token的 无法提取获取。总的来说就是下面两点:
令牌暴露在前端: 无论后端如何生成,令牌最终会作为 HTML 内容返回给前端(否则前端无法提交),攻击者可通过访问页面直接提取。
复用无限制:代码未实现 "一次有效" 机制,同一令牌可在同一会话中反复使用,无需每次重新获取,失败不失效。

Impossible

查看源码

php 复制代码
<?php

if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) {
    // 安全改进:使用POST方法传输登录数据(用户名、密码)
    // 相比GET方法,POST数据在URL中不可见,避免了浏览器历史、服务器日志泄露敏感信息的风险
    
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    // 保留并延续了CSRF令牌验证机制,有效防御跨站请求伪造攻击
    // 确保登录请求来自当前用户的合法会话,而非第三方伪造
    
    // Sanitise username input
    $user = $_POST[ '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 = $_POST[ '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 );
    // 注:MD5哈希密码仍是安全短板,但本版代码的核心改进在其他维度
    
    // Default values
    $total_failed_login = 3;  // 设定最大失败登录次数(3次)
    $lockout_time       = 15; // 设定账户锁定时长(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();
    // 安全改进:使用PDO参数化查询(prepare + bindParam)
    // 彻底杜绝SQL注入风险!参数化查询将用户输入与SQL语句逻辑分离,输入无法被解析为SQL命令
    
    // Check to see if the user has been locked out.
    if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {
        // 安全改进:实现账户锁定逻辑------当失败次数达到阈值时,触发锁定判断
        // 注:此处虽有用户枚举风险(可通过返回信息判断用户名是否存在),但核心锁定功能已生效
        
        // Calculate when the user would be allowed to login again
        $last_login = strtotime( $row[ 'last_login' ] );
        $timeout    = $last_login + ($lockout_time * 60);
        $timenow    = time();

        // 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();
    // 再次使用PDO参数化查询,确保密码验证环节无SQL注入风险
    // 同时通过LIMIT 1优化查询效率,避免冗余数据返回
    
    // 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();
// 延续令牌生成机制,确保每次页面加载都有有效令牌,维持CSRF防御能力

?>
  1. 彻底防御 SQL 注入:全面采用 PDO 参数化查询,替代字符串拼接,从根源杜绝注入风险;
  2. 强化暴力破解防御:新增 "失败次数累加 + 超时锁定" 机制,大幅提升破解成本,同时保留随机延迟;
  3. 优化敏感数据传输:改用 POST 方法传输用户名 / 密码,避免 URL 泄露;
  4. 降低信息泄露风险:模糊错误提示,减少用户枚举可能;
  5. 增强用户安全感知:登录成功时提示暴力破解预警,同时重置失败次数,平衡安全与体验;
  6. 完善审计与配置:记录登录时间,支持可配置的锁定阈值与时长,便于维护与扩展。

对于制作靶场的作者当时来说md5已经十分牢固,但是随着时代发展,md5变得不那么牢固了,但是这仍然是优秀代码的典范

相关推荐
用户962377954489 小时前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机12 小时前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机12 小时前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户9623779544814 小时前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star14 小时前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户9623779544817 小时前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
cipher2 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
一次旅行5 天前
网络安全总结
安全·web安全
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
red1giant_star5 天前
手把手教你用Vulhub复现ecshop collection_list-sqli漏洞(附完整POC)
安全