尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

DVWA暴力破解实战:从Low到Impossible的攻防演进与防御策略

DVWA暴力破解实战:从Low到Impossible的攻防演进与防御策略
📅 发布时间:2026/7/7 0:40:53

1. 项目概述:从“暴力”到“优雅”的攻防博弈

在网络安全的学习和实践道路上,DVWA(Damn Vulnerable Web Application)靶场几乎是每个初学者的必经之地。它就像一个精心设计的“漏洞博物馆”,将Web应用中最常见的安全问题,按照从易到难的防御等级(Low, Medium, High, Impossible)一一陈列出来。而“暴力破解”(Brute Force)作为最古老、最直接,却也最考验防御策略的攻击方式,往往是很多人上手实战的第一个关卡。今天,我们不谈空泛的理论,就从一个渗透测试工程师的视角,手把手地带你通关DVWA的Brute Force模块所有级别。这不仅仅是一个“点击下一步”的教程,我会深入每个级别的代码逻辑,拆解防御者的思路,并分享在实际攻防演练中,如何绕过这些防御、以及如何真正有效地加固你的登录接口。无论你是刚接触安全的新手,还是想巩固Web安全基础的老兵,这篇基于实战经验的深度剖析,都能让你对认证安全有更立体的认识。

2. 环境准备与基础认知:你的“手术刀”和“战场”

在开始“手术”前,我们必须准备好“手术刀”并了解“病人”的构造。DVWA靶场通常部署在如XAMPP、PHPStudy或Metasploitable这样的集成环境中。确保你的DVWA可以正常访问,并将安全级别设置为“Low”,这是我们一切的起点。工欲善其事,必先利其器,除了靶场,我们还需要几件核心工具:

  1. Burp Suite Community/Professional版:这是我们的主武器。它不仅仅是一个代理,更是一个强大的Web漏洞扫描和攻击平台。我们将主要使用它的Proxy(代理拦截)、Repeater(重放测试)和Intruder(暴力破解/模糊测试)模块。
  2. 浏览器与代理配置:将浏览器(如Chrome、Firefox)的HTTP/HTTPS代理设置为Burp Suite监听的地址(通常是127.0.0.1:8080),并安装Burp签发的CA证书,以便拦截和修改HTTPS流量。
  3. 密码字典:暴力破解的灵魂。你可以使用Kali Linux自带的rockyou.txt、SecLists项目中的字典,或者根据目标情况自己生成针对性字典(如公司名、常见弱口令组合)。一个高质量的字典能极大提升成功率。

注意:所有操作务必在你自己搭建的本地或授权测试环境中进行。未经授权的攻击是违法行为。我们的目的是学习防御,而非破坏。

在开始攻击前,我们先理解一下暴力破解的本质:它通过系统性地尝试大量用户名和密码组合,来寻找正确的认证凭证。防御的核心,就是通过各种手段提高这种尝试的成本(时间成本、计算成本),使其变得不可行。

3. Low级别通关:毫无防备的“门户大开”

将DVWA安全级别调到Low,访问Brute Force模块。你会看到一个极其简单的登录表单。我们首先按正常流程输入任意账号密码(如admin/123)并提交,同时用Burp Suite拦截这个请求。

3.1 源码分析与攻击面审视

查看Low级别的后端PHP源码(在DVWA中可直接点击“View Source”),其逻辑清晰得令人“感动”:

$user = $_GET[ 'username' ]; $pass = $_GET[ 'password' ]; $pass = md5( $pass ); $query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
  • 无任何过滤:用户名($user)和密码($pass)直接从$_GET获取,未经任何处理就直接拼接进SQL语句。这里虽然主要演示暴力破解,但同时也存在严重的SQL注入漏洞。
  • 密码处理:仅对密码进行MD5哈希后比对。MD5早已被证明可快速碰撞,但在单纯的暴力破解场景下,我们直接针对哈希前的明文进行尝试。
  • 无失败处理:登录成功或失败,服务器立即返回结果,没有任何延迟、锁定或尝试次数记录。

这相当于你家大门不仅没锁,门上还贴着一张纸条:“钥匙就在地毯下”。攻击起来毫无技术含量。

3.2 Burp Suite Intruder实战爆破

拦截到的HTTP请求大概长这样:

GET /dvwa/vulnerabilities/brute/?username=admin&password=123&Login=Login HTTP/1.1

接下来,我们使用Burp Suite的Intruder模块进行自动化攻击。

  1. 发送到Intruder:在Proxy的拦截历史或Repeater中,右键请求,选择“Send to Intruder”。
  2. 设置攻击点位(Positions):
    • 在Intruder的Positions标签页,点击“Clear §”清空所有默认标记。
    • 分别选中username参数的值(如admin)和password参数的值(如123),点击“Add §”进行标记。最终,username=§admin§&password=§123§。
    • 攻击类型(Attack type)选择“Cluster bomb”。这是最常用的暴力破解类型,适用于用户名和密码来自两个不同字典的情况,它会尝试所有可能的组合。
  3. 配置载荷(Payloads):
    • 在Payloads标签页,为Payload set 1(对应username)加载你的用户名字典。DVWA默认常用用户名为admin、gordonb、1337、pablo、smithy等。
    • 为Payload set 2(对应password)加载你的密码字典。可以从简单字典开始,如password,123456,admin,letmein等。
  4. 开始攻击(Start attack):Intruder会发起大量请求。攻击完成后,我们需要在结果中找出成功的那个。
  5. 结果分析:成功的登录请求,其HTTP响应状态码可能依然是200,但响应体长度(Length)或内容会与其他失败的请求显著不同。在结果列表中,点击“Length”列进行排序,通常成功登录的响应页面会包含“Welcome to the password protected area”字样,其长度会远大于显示“Username and/or password incorrect.”的失败响应。找到这个独特长度的请求,查看响应详情即可确认破解出的账号密码。

实操心得:在Low级别,由于毫无防护,攻击速度可以非常快。在Burp Intruder的“Options”标签中,你可以适当增加线程数(如20-30)以提升速度。但要注意,对真实目标(即使是授权测试)也需谨慎使用高线程,可能触发运维监控告警。

4. Medium级别通关:增加了“减速带”

将安全级别调至Medium,再次查看源码,发现了两处关键变化:

$user = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ); $pass = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ); // ... if( $result && mysqli_num_rows( $result ) == 1 ) { // ... 成功 } else { sleep( 2 ); // 关键! echo "<pre><br />Username and/or password incorrect.</pre>"; }
  • 输入过滤:使用了mysqli_real_escape_string函数对输入进行转义,这基本封堵了SQL注入的可能性,迫使攻击者回归到纯粹的暴力破解路径上。
  • 失败延迟:在登录失败后,程序会执行sleep(2),即强制等待2秒再返回错误信息。

这个sleep(2)是一个典型的“减速带”防御。它不会阻止攻击,但会将攻击时间成本线性放大。假设你有1000个密码要尝试,那么至少需要2000秒(超过30分钟)。这对于手动攻击或缺乏耐心的自动化脚本是一个心理威慑。

4.1 攻击策略调整与执行

尽管有延迟,但攻击流程和Low级别完全一致。因为防御机制并不检查请求来源、频率或历史记录,只是单纯地让每次失败的请求都变慢。

  1. 沿用Cluster bomb攻击:在Burp Intruder中,设置与Low级别完全一致。
  2. 心理准备与时间管理:发起攻击后,你会明显感觉到进度条走得慢了很多。这是正常的。你需要做的就是等待。对于Medium级别,使用大型字典(几十万条)变得不切实际,但针对性的小字典(几百上千条)仍然可以在可接受的时间内完成。
  3. 结果鉴别:鉴别成功请求的方法不变,依然是寻找响应长度或内容不同的那个请求。

注意事项:在实际渗透测试中,遇到登录失败有延迟的情况,需要评估延迟时间与字典大小。如果延迟很长(如5秒、10秒),通常意味着需要更精准的用户名枚举和更小的密码字典,或者寻找其他绕过认证的漏洞(如密码重置、会话漏洞),而非一味蛮力。

5. High级别通关:挑战动态令牌(Token)防御

High级别的源码引入了更强的防御机制:

if( isset( $_GET[ 'Login' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // ... 后续过滤和查询逻辑与Medium类似 sleep( rand( 0, 3 ) ); // 随机延迟 } // Generate Anti-CSRF token generateSessionToken();

查看页面HTML源码,会发现一个隐藏的表单字段:

<input type="hidden" name="user_token" value="a1b2c3d4e5f6g7h8i9j0...">
  • Anti-CSRF Token:每次页面加载或刷新,都会生成一个随机的、不可预测的user_token,并嵌入表单。提交登录请求时,必须携带这个有效的token,服务器会校验其与会话中存储的是否一致。这主要用于防御跨站请求伪造(CSRF),但同时也给传统的暴力破解带来了麻烦,因为每次尝试都需要一个全新的、有效的token。
  • 随机延迟:失败延迟从固定的2秒变成了sleep( rand( 0, 3 ) ),在0到3秒间随机,使基于响应时间的旁路攻击(Timing Attack)变得更加困难。

此时,如果我们直接用Low/Medium的方法,只把username和password设为变量,攻击会立刻失败,因为第一次尝试后服务器端的session token就失效了,后续请求携带的仍是旧的token,会导致checkToken失败。

5.1 方法一:Burp Suite的Pitchfork模式与递归提取(Grep-Extract)

这是最经典、最优雅的绕过方法,完全在Burp Suite内完成。

  1. 抓取首次请求,设置攻击点位:拦截一个正常的登录请求,发送到Intruder。你会发现请求中包含了user_token参数。我们将三个参数标记为变量:username、password和user_token。
    username=§admin§&password=§123§&Login=Login&user_token=§abc123def456§
  2. 选择攻击类型:选择“Pitchfork”(草叉模式)。该模式会并行使用多个Payload集,并且每个Payload集只遍历一次,然后停止。它要求各Payload列表长度一致,并按顺序一一对应。这正适合我们:我们需要为每一次尝试,提供一组对应的username、password和实时获取的user_token。
  3. 配置Payload集:
    • Payload Set 1 (username):加载用户名字典。假设我们已知或猜测用户名为admin,可以只放一个admin,或者放几个常见用户名。
    • Payload Set 2 (password):加载密码字典。
    • Payload Set 3 (user_token):这是关键。我们不能使用静态字典。需要设置Payload类型为“Recursive grep”。
  4. 设置Recursive Grep:
    • 首先,我们需要告诉Intruder如何从服务器的响应中提取新的user_token。
    • 在Intruder的“Options”标签页,找到“Grep - Extract”区域。
    • 点击“Add”,Burp会弹出一个窗口让你从样本响应中提取数据。我们需要一个包含user_token的响应页面(比如登录失败后的页面,或者直接刷新Brute Force页面获取的源码)。
    • 在样本响应中,找到user_token的input标签,类似<input type='hidden' name='user_token' value='a1b2c3d4e5...' />。用鼠标精确选中value='和'之间的那串令牌值。
    • Burp会自动生成一个提取规则(通常基于前缀value='和后缀')。点击“OK”保存。
    • 然后,在“Payloads”标签页,为Payload Set 3选择类型为“Recursive grep”,并选择刚才创建的那个提取项。
  5. 关键配置:
    • 在“Options”标签页,必须将“Request Engine”中的线程(Number of threads)设置为1。因为Recursive Grep模式是串行的:它需要先发送一个请求,从响应中提取token,再将这个token用于下一个请求。多线程会导致token混乱。
    • 将“Redirections”设置为“Always”,确保能跟随跳转获取完整响应。
  6. 发起攻击:点击“Start attack”。Burp会执行如下循环: a. 使用Payload Set 1的第一个用户名、Payload Set 2的第一个密码,以及Payload Set 3的初始值(来自我们标记的请求中的token)发起第一次请求。 b. 从第一次请求的响应中,提取出新的user_token。 c. 使用Payload Set 1的第一个用户名、Payload Set 2的第二个密码,以及上一步提取的新user_token发起第二次请求。 d. 如此循环,直到密码字典耗尽。如果用户名列表有多个,则会切换到下一个用户名,并重新开始获取token和尝试密码的过程。

通过这种方式,我们实现了token的自动更新,完美绕过了High级别的Token验证。攻击速度虽然受限于单线程和随机延迟,但依然是完全可行的。

5.2 方法二:编写Python脚本实现自动化

对于喜欢编码或需要更灵活控制的情况,编写脚本是更好的选择。思路同样是模拟“获取token -> 携带token尝试登录”的循环。

import requests import re import time from bs4 import BeautifulSoup # 目标URL和会话管理 target_url = "http://your-dvwa-ip/dvwa/vulnerabilities/brute/" login_url = "http://your-dvwa-ip/dvwa/login.php" dvwa_session = requests.Session() # 1. 首先登录DVWA,获取有效会话 (DVWA默认账号密码 admin/password) login_data = { 'username': 'admin', 'password': 'password', 'Login': 'Login', 'user_token': '' # 先留空,第一次需要从登录页面获取 } # 获取登录页面的token resp = dvwa_session.get(login_url) soup = BeautifulSoup(resp.text, 'html.parser') user_token = soup.find('input', {'name': 'user_token'}).get('value') login_data['user_token'] = user_token # 提交登录 dvwa_session.post(login_url, data=login_data) print("[+] DVWA登录成功") # 2. 设置安全级别为High (需要先知道你的DVWA安全级别设置页面的URL和参数) # 这里省略,假设你已经手动将Brute Force模块安全级别设为High # 3. 准备字典 username = "admin" passwords = ["password", "123456", "admin", "letmein", "12345", "root"] # 示例字典 # 4. 暴力破解主循环 for password in passwords: # 步骤A: 访问Brute Force页面,获取最新的user_token resp = dvwa_session.get(target_url) soup = BeautifulSoup(resp.text, 'html.parser') user_token = soup.find('input', {'name': 'user_token'}).get('value') # 步骤B: 构造登录请求数据 brute_data = { 'username': username, 'password': password, 'Login': 'Login', 'user_token': user_token } # 步骤C: 发送登录请求 resp = dvwa_session.get(target_url, params=brute_data) # 步骤D: 检查响应是否成功 if "Welcome to the password protected area" in resp.text: print(f"[+] 破解成功! 用户名: {username}, 密码: {password}") break else: print(f"[-] 尝试失败: {username}:{password}") # High级别有随机延迟,脚本中可以不额外sleep,因为每次循环都包含一次网络请求和页面解析,本身就有时间间隔。 print("[*] 破解完成。")

这个脚本清晰地展示了攻击链:维持一个会话(requests.Session),每次尝试前先GET页面获取新鲜token,然后用这个token组合用户名密码发起登录GET请求,最后检查响应内容。它比Burp的Pitchfork模式更透明,也便于添加代理、异常处理等复杂逻辑。

实操心得:High级别的Token防御在自动化脚本面前形同虚设,因为它只是增加了攻击的复杂性,而非不可逾越的障碍。这告诉我们,Token是防御CSRF的利器,但绝非抵御暴力破解的银弹。真正的防御需要多层措施叠加。

6. Impossible级别解析:为何“不可能”?

Impossible级别的源码展示了近乎完美的防御姿态:

// 1. 使用PDO预处理语句,彻底杜绝SQL注入 $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(); // 2. 检查是否找到用户 if( $data->rowCount() == 1 ) { // 3. 获取用户信息 $row = $data->fetch(); // 4. 密码验证使用password_hash()和password_verify(),即使数据库泄露,也无法直接破解哈希值 if ( password_verify( $pass, $row[ 'password' ] ) ) { // 登录成功... } else { // 5. 登录失败:增加延迟并记录日志(模拟) sleep( 3 ); // 记录失败尝试到数据库或文件,可用于后续分析或锁定 } } else { sleep( 3 ); }
  • SQL注入免疫:采用参数化查询(PDO预处理),将用户输入与SQL指令分离,从根本上消灭了注入漏洞。
  • 强密码哈希:使用password_hash()(通常采用bcrypt算法)存储密码,并用password_verify()验证。bcrypt算法设计缓慢且可调整成本因子,使得即使攻击者拿到了数据库的密码哈希值,进行离线暴力破解或彩虹表攻击的成本也极高。
  • 一致的失败响应:无论用户是否存在、密码是否正确,失败时都返回相同的消息和相同的3秒延迟。这防止了攻击者通过响应差异来枚举有效用户名(用户名枚举漏洞)。
  • 失败记录与账户锁定(潜在):虽然代码中未直接实现锁定,但注释提示会记录失败尝试。在实际应用中,可以基于此实现账户锁定或IP地址限制策略。

在这个级别,传统的Web请求暴力破解已经基本失效。原因如下:

  1. 无法绕过认证逻辑:密码哈希验证是密码学安全的,无法从哈希反推密码。
  2. 时间成本不可接受:每次尝试固定延迟3秒,且无法通过响应差异获取信息。尝试1000个密码需要50分钟,且成功率极低。
  3. 可能触发警报:如果实现了失败尝试记录,多次失败会很快引起管理员注意。

那么,Impossible级别就真的无懈可击了吗?从纯Web应用层暴力破解的角度看,是的。但安全是一个整体,攻击者可能会转向其他弱点:

  • 社会工程学:通过钓鱼邮件、电话等方式骗取凭证。
  • 密码重置漏洞:攻击密码重置功能,而非直接登录。
  • 横向移动:如果已有一个低权限账户,尝试利用其他漏洞提权。
  • 离线攻击:如果通过其他漏洞(如SQL注入、文件包含)窃取了数据库中的密码哈希,则可以在本地进行高强度的离线破解。虽然bcrypt很难破,但面对弱密码(如password123)和强大的GPU/ASIC算力,仍有风险。这强调了使用强密码的重要性。

7. 防御方案总结与进阶思考

通关四个级别,我们实际上经历了一场生动的防御演进史。下面我们来系统性地总结和拓展暴力破解的防御方案:

防御层级具体措施对应DVWA级别优点局限性/绕过方法
无防御无任何过滤、延迟、限制Low无可被高速自动化工具瞬间破解
基础加固输入过滤、固定延迟Medium增加时间成本,阻止简单脚本无法阻止有耐心的自动化攻击(如Burp Intruder)
增强交互动态Anti-CSRF Token、随机延迟High增加攻击复杂性,阻止简单重放可通过自动化工具(递归提取)或脚本绕过
密码学安全参数化查询、强密码哈希(bcrypt)Impossible根本性防止SQL注入,极大增加离线破解成本Web层攻击基本无效,但依赖其他环节(如密钥管理)安全
行为层面验证码(尤其是行为验证码)(DVWA未包含)有效区分人与机器可能影响用户体验;存在OCR、打码平台绕过风险
策略层面账户锁定(n次失败后锁定一段时间)(DVWA未包含)直接阻断自动化枚举可能被用于DoS攻击(锁定合法用户);需平衡安全与可用性
策略层面IP速率限制(同一IP单位时间请求次数)(DVWA未包含)限制攻击源效率攻击者可使用代理池、僵尸网络(Botnet)分散攻击
策略层面设备指纹/行为分析(DVWA未包含)识别异常登录行为模式实现复杂,可能存在误判

进阶思考与实操建议:

  1. 多层防御(Defense in Depth):不要依赖单一措施。“强密码哈希 + 账户锁定/IP限制 + 验证码”的组合拳能提供强大的防御。例如,前5次失败仅记录,第6次开始要求验证码,连续10次失败则锁定账户1小时。
  2. 用户体验平衡:安全措施不能过度妨碍合法用户。可以考虑“智能锁定”,例如对来自常用设备和地理位置的失败尝试更宽容,而对异常来源则更严格。
  3. 监控与告警:所有失败的登录尝试都应被记录并分析。短时间内来自大量不同IP对同一账户的失败尝试,是明显的暴力破解攻击信号,应触发实时告警。
  4. 面向未来的密码:鼓励或强制用户使用密码管理器生成的随机、长密码(如12位以上,包含大小写字母、数字、符号)。对于高敏感系统,推行双因素认证(2FA)。
  5. 渗透测试中的暴力破解:在实际授权测试中,进行暴力破解前务必确认测试范围是否允许。即使允许,也应使用可控的、低频率的测试,并优先使用从信息收集阶段获得的针对性字典(如公司名、产品名、员工姓名组合),而非盲目使用超大通用字典。

从Low级别的“门户大开”到Impossible级别的“铜墙铁壁”,DVWA的Brute Force模块生动地展示了安全是一个持续对抗和演进的过程。作为开发者,理解每一层防御的原理和局限,才能构建出真正稳健的系统。作为安全研究者或渗透测试员,理解这些防御机制,才能更有效地发现和验证漏洞。希望这篇结合实战工具和代码分析的教程,能让你下次面对登录框时,不仅有攻击的思路,更有防御的智慧。

相关新闻

  • Kindle Comic Converter终极指南:将漫画完美适配电子墨水屏的免费工具
  • 【深度学习】PyTorch 图像分类进阶:从本地脚本到 Flask Web 服务部署
  • PIC18F8520驱动WS2812:硬件SPI与DMA的精准控制

最新新闻

  • 欧文·亚隆的《当尼采哭泣》(When Nietzsche Wept)精简总结
  • 第 5 篇:节点重启自愈——两阶段模块恢复机制
  • 城市生命线智慧管网建设落地指南|北京益豪时代一站式解决地下管网安全管控难题
  • 财务报销终端怎么做审计留痕:附件目录、浏览器后台和远程维护三条线
  • 153、LangChain Chain:LLMChain、SequentialChain、RouterChain 的链式编排
  • 3 种点云补全网络对比:PF-Net vs PCN vs TopNet,在 ShapeNet 上的 F-Score 评测

日新闻

  • Android逆向分析全能助手:集成化工具链与自动化工作流设计
  • 面搜索(Faceted Search)原理与工程实践指南
  • 神经网络调参避坑指南:从5个常见Loss曲线形态定位超参数问题

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号