新闻详情

新闻详情

首页 / 资讯中心 / 详情

DVWA中等难度暴力破解实战:token绕过与延时防护的局限分析

发布时间:2026/9/17 2:48:48来源:尧图网络
DVWA中等难度暴力破解实战:token绕过与延时防护的局限分析
最近把DVWA的brute force模块从Low一路打到High发现Medium这一档特别有意思。它加了token校验还塞了个sleep(1)的延时乍一看比Low严谨不少但真正动手爆破的时候会发现这种防护只能拦住刚入门的新手拦不住会看报文、会写脚本的人。这篇文章就把我在Medium级别下的完整爆破过程、token处理的几种方案、以及踩过的坑一次说清楚。不管你用的是Burp Suite还是Python脚本都能在这里找到能直接上手的思路。这套操作全部限定在DVWA本地靶场环境内DVWA本来就是拿来练手的别拿这套思路去对着线上系统瞎试这点边界必须清楚。1. DVWA暴力破解模块与实际环境准备1.1 DVWA是什么为什么练手选它DVWADamn Vulnerable Web Application是一个开源的PHPMySQL漏洞靶场它的设计目标就是给安全测试人员和爱好者提供一个合法的练习环境。和真正线上系统最大的区别在于它每个漏洞模块都分成了Low、Medium、High、Impossible四个级别同一款漏洞在不同级别下会有完全不同的防护策略这种渐进式的设计非常适合用来理解漏洞的本质。brute force模块就是经典的登录暴力破解实验。Low级别是直接用GET参数提交用户名和密码服务端没有任何防御只要遍历字典就行。Medium级别加上了user_token和1秒延时High级别把token换成了不可预测的随机值且每次会话绑死Impossible则加上了基于IP的锁定机制。从训练角度来说Medium是理解有防护但防护不彻底的最佳样本。1.2 启动靶场与登录环境细节先说环境。我本地用的是Docker方式部署的DVWA命令很简单docker run -d -p 8080:80 vulnerables/web-dvwa访问http://127.0.0.1:8080就能看到登录页。默认账号是admin密码password。如果用的是本机直接部署的PHP环境注意确认PHP版本和MySQL服务状态DVWA老版本在新版PHP下偶尔会有session警告。登录之后第一次进会显示数据库没初始化点一下页面底部的Create / Reset Database初始化完成后会跳回登录页。这一步容易漏很多人卡在登录成功了但没有数据就是这里的问题。进入后左侧菜单找到Brute Force打开就是登录表单。Level切换入口在DVWA Security页面把安全级别切成Medium再切回Brute Force页面就能看到变化。1.3 Medium和Low的核心差异先说结论Medium比Low多了两个关键变化这两个变化直接决定了爆破方案怎么写表单里多了一个隐藏字段user_token每次刷新页面都会生成一个新的随机值服务端在校验用户名密码之前会先校验这个tokentoken不合法直接拒绝并且不返回登录结果。服务端在处理请求时增加了一个sleep(1)也就是每次都延迟1秒才返回响应目的是拉长爆破时间降低自动化的效率。但是注意Medium级别的token校验只是校验必须存在并且等于当前session的值处理方式比较简单可以通过每次请求前先取一个新token再提交来绕过。而且它没有锁定机制、没有验证码、没有IP封禁这些都是Medium继续可以被爆破的根本原因。明白了这几点后面无论是用Burp还是Python思路都是围绕如何自动获取token展开的。2. Medium级别防护机制拆解2.1 user_token到底是什么它防的是什么先搞清楚token在这里的角色。DVWA的brute force页面返回的HTML里有这样一行input typehidden nameuser_token valuee2a4f3c8... /这个token是服务端在每次请求时生成的随机字符串存到了当前PHP session里同时渲染到表单中。当你提交请求时服务端会把提交的token和session里的token比对一致才继续处理用户名密码。它是为了防CSRF跨站请求伪造设计的不是专门防暴力破解的。攻击者如果想要伪造一个登录请求就必须先拿到当前会话的token这确实提升了一点门槛。但是token就明晃晃地写在页面源码里对于一个能直接访问目标页面的攻击者来说先GET一次页面提取token再提交请求几乎不增加实际成本。这也解释了为什么很多站点的防爆破token形同虚设——只要token能在页面里被正常用户获取到爆破脚本就能模拟正常用户一样拿token关键在于脚本有没有自动化的提取能力。2.2 sleep(1)延时的成本逻辑Medium级别在server端源码里加了sleep(1)每一次请求无论密码对不对服务端都会先睡1秒再返回响应。这个延时的设计思路很简单如果攻击者要跑1000个密码每个请求多1秒总时间就多1000秒接近17分钟。如果字典更大假设是100万条那就是100万秒约11天半。这确实能淘汰掉一批直接拿Burp默认配置暴力跑的初级做法。但要注意几个现实问题这个延时是服务端固定返回的攻击者如果把并发线程拉高比如同时开20个线程那么总时长并不会按单线程的1秒/请求线性增长而是被并发摊薄了。sleep(1)也同时拖慢了正常用户的登录体验如果真拿这个手段防爆破牺牲的是所有用户的可用性。在Medium级别下它带来的最大影响其实是测试时响应变慢需要在工具里适当调整timeout参数否则容易误判为请求失败。我实测下来的感受是sleep(1)对单线程脚本影响明显但对并发方案只能算增加成本不能算阻止攻击。真正有效的防护还是得靠锁定、验证码、速率限制这些更重的手段。2.3 为什么说Medium防护看起来强实则不够把Medium的防护逻辑完整串起来看它的模型是这样的请求进来 - 校验token - 校验用户名密码 - 结果返回整个流程还加上1秒延时。这个模型里面有三个可以利用的薄弱点token获取成本极低GET一次页面就拿到而且token绑定的是session而不是IP没有额外验证码干扰。没有任何失败次数统计和锁定策略可以无限试错。校验逻辑基于用户名和密码同时正确token正确其中用户名和密码是可以穷举的变量token只是每次请求前取一下的前置动作。这就相当于给大门上了一把好锁但钥匙就挂在锁旁边。你只需要写一小段逻辑让程序自动取钥匙-开锁-再取钥匙-再开锁循环往复即可。从学习视角看这就是Medium级别最值得品味的地方它代表了很多真实系统的防护水平——有安全措施但没有把措施落到不可自动化绕过的程度。理解这一点比单纯机械地跑通一个爆破更重要。3. Burp Suite 实操抓包与分析3.1 浏览器代理配置与报文观察Burp Suite是全流程里最高效的图形化工具先从它说起。第一步是配置浏览器代理。我通常用Firefox配合FoxyProxy代理设为127.0.0.1:8080。确认Burp Proxy模块的Intercept处于开启状态然后回到DVWA的Brute Force页面填一个随便的账号密码比如admin/123456点击Login。这时请求会被拦截住能看到请求报文长这样GET /vulnerabilities/brute/?usernameadminpassword123456LoginLoginuser_tokene2a4f3c8... HTTP/1.1 Host: 127.0.0.1:8080 Cookie: PHPSESSIDabc123...; securitymedium这里有个很容易被忽略的点securitymedium这个Cookie是负责指定当前安全级别的。如果在抓包过程中发现请求参数和之前不一样排查一下是不是DVWA Security页面的级别没切换或者是重新登录后Cookie丢了。响应报文里要注意的是HTTP状态码和页面内容。密码错误的情况下状态码仍然是200但页面里会出现Login failed字样。所以爆破结果不能只看状态码必须看响应内容里的关键字。3.2 把登录请求丢给Intruder确认报文结构无误后右键这个请求选择Send to Intruder。在Intruder的Positions标签页里需要标记的攻击位置有两个一是username参数的值二是password参数的值。这里我建议把用户名和密码都设为变量用一个组合字典去跑而不是只爆破密码。虽然很多场景下用户名是已知的但作为攻击者做的完整一点没坏处还能顺便验证admin是不是唯一可用的账号。Payloads设置上简单起见可以只爆破密码用户名保持adminPayload类型选择Simple list从字典文件里加载密码列表。Grep-Match功能强烈建议配置在Options里找到Grep - Match添加Welcome和Login failed两个关键词。这样攻击结束后可以直接通过匹配结果快速定位成功的那一条请求。3.3 token处理的两种现实做法直接把配置好的攻击跑出去你会发现所有请求返回的都是Login failed一个成功的都没有。原因是每次请求里的user_token字段是手工抓包时固定的旧值服务端校验时发现和session当前值对不上直接把请求拒绝了。在Medium级别下要让Intruder跑通有两种现实做法第一种是正则提取每次请求前更新token。Burp在Intruder里不能像脚本那样先GET一下再POST但可以通过Recursive Grep功能把上一个响应里的token提取出来作为下一次请求的参数。具体在Intruder的Extract Grep里配置一个正则比如nameuser_token value([a-f0-9])然后把token位置的Payload类型设为Recursive Grep。这种方案配置起来有点绕而且免费版Burp对Recursive Grep支持有限我通常不推荐新手在这里死磕。第二种是用Python脚本代替Intruder这也是我最推荐的方式。脚本里天然支持先GET页面拿token再POST提交的循环逻辑比在GUI里配Recursive Grep直观太多。Burp在这个场景下更适合做分析报文和手工验证这两个环节真正的高并发爆破交给脚本。3.4 结果分析与性能预期如果按第一种方式把token处理好了Intruder是可以跑出结果的。攻击结束后在Results里看Grep匹配的列如果某一行匹配到了Welcome那这一行对应的就是正确密码。但说实话Burp Community版免费版的Intruder默认是低并发加上Medium级别每个请求要等1秒跑一个几千条的密码字典会非常慢。我试过跑一个5万条的字典用免费版单线程等了将近14个小时。这个体验实在太差所以我后面基本转向了Python脚本。图形化工具适合理解流程、做小规模验证真要大规模跑字典脚本才是效率最优解。还有一个细节Burp的默认HTTP超时时间比较短如果服务端sleep(1)加上网络延迟可能偶尔会出现请求超时或者工具显示Connection reset。遇到这种情况在Intruder的Options里把Request Timeout调大比如10秒能避免误判。4. Python脚本爆破更可控的方案4.1 脚本思路与请求流程Python方案的核心逻辑很清晰就三步循环先用session GET一次页面从响应HTML里提取最新的user_token再带着token、用户名、密码发起登录请求最后根据返回内容判断成功还是失败。用Session对象而不是requests.get直接调是因为爆破全程需要保持同一个会话的Cookie特别是PHPSESSID和securitymedium这两个Cookie一丢token就对不上了。流程里的一个关键点是发完登录请求后服务端会返回一个新的页面这个页面的HTML里会包含一个新的user_token。所以下一次循环时不能直接用上一次请求前拿到的token而是要从最新响应里再提取一次。这也是很多初学脚本时最容易错的地方——复用了旧token导致后续请求全部被拒。4.2 关键代码实现下面是我调通的一个基础版本注释写得很详细直接复制下来改一下URL就能用import requests import re # 目标环境改成你自己的地址 base_url http://127.0.0.1:8080 login_url base_url /login.php brute_url base_url /vulnerabilities/brute/ # 需要登录DVWA先建立会话 session requests.Session() def get_login_token(): 打开登录页提取user_token resp session.get(login_url) token re.search(rnameuser_token value([a-f0-9]), resp.text) if token is None: raise Exception(未获取到登录token请检查登录页HTML结构) return token.group(1) # 第一步登录DVWA login_token get_login_token() login_data { username: admin, password: password, Login: Login, user_token: login_token, } session.post(login_url, datalogin_data) # 切到medium级别 session.get(base_url /security.php, params{ security: medium, seclev_submit: Submit, }) def get_brute_token(): 从brute force页面提取当前token resp session.get(brute_url) token re.search(rnameuser_token value([a-f0-9]), resp.text) if token is None: return None return token.group(1) # 密码字典按需加载 passwords [ 123456, password, admin, admin123, root, 12345678, qwerty, letmein, ] found False for pwd in passwords: token get_brute_token() if token is None: print(token获取失败页面结构可能变了) break params { username: admin, password: pwd, Login: Login, user_token: token, } resp session.get(brute_url, paramsparams) if Welcome in resp.text: print(f[] 爆破成功密码是: {pwd}) found True break else: print(f[-] 尝试密码: {pwd} 失败) if not found: print([-] 字典跑完未找到正确密码)这个脚本跑的时候要注意securitymedium这个Cookie是通过访问security.php设置的如果漏了这一步后续请求会被当成Low级别处理虽然也可能成功但实验就不严谨了。4.3 跑一轮的结果与踩坑记录我实际用上面脚本在Medium级别下跑了一轮用了大约2000条常见的密码列表。由于每次请求前都要先GET一次页面再加上服务端的sleep(1)2000个密码大约耗时40分钟。如果密码对了通常会在命中时很快停下。这个过程中我踩过几个坑整理一下第一个坑是正则写错了。DVWA不同版本里隐藏字段的HTML写法会有细微差异有的是单引号有的是双引号有的是valuexxx有的是valuexxx。如果脚本一直报token获取失败先打开页面源码看一眼实际格式。第二个坑是请求方法。DVWA的brute force模块是GET提交不是POST。我第一次用POST去提交服务端参数没接收到所有请求都返回异常。抓包看清楚再写代码能少走很多弯路。第三个坑是响应判断。判断成功不能只靠状态码因为DVWA对所有登录请求都返回200。要用页面内容里的关键词比如Welcome或Login failed。有些版本的DVWA成功后会显示用户名所以更好的写法是既检查Welcome又检查admin。第四个坑是字典命中后没有及时break。如果循环不停止就算找到密码脚本还会继续跑完整个字典浪费时间。找到后马上break退出。5. 常见问题与避坑经验速查5.1 登录态、token失效类问题爆破半路突然全部失败或者连续返回CSRF token mismatch十有八九是session过期了。DVWA的PHP session默认有效期很短长时间爆破时尤其容易触发。如果遇到这个问题看看是否需要在脚本里定期重新登录或者干脆把session超时时间调长。另一个常见问题是脚本在同一个session里先GET了brute页面拿token然后又用这个token去请求登录但如果中间有另一个请求把session里的token刷新了旧token就失效了。所以脚本里要保证拿token和用token是紧挨着的一对操作中间不要穿插其他请求。多次调试下来把token提取逻辑写在循环开头是最稳妥的。Burp抓包和Python脚本混用时也容易出问题。如果同时开着Burp代理浏览器和脚本的流量全走代理可能因为Burp的session和脚本的session不一致导致token互相覆盖。建议做实验时要么全走Burp要么关掉Burp只跑脚本别两部同时抢同一个session。5.2 字典选择与响应判断字典质量直接决定爆破能不能出结果。DVWA默认的密码是password但如果你改了密码或者换了题目要求字典里没有目标密码就是跑一晚上也跑不出来。建议从小的常见密码集开始试比如rockyou.txt的前几百条确认流程通了再加载大字典。响应判断这一块可以在脚本里加一个debug模式打印最近一次请求的响应前200个字符。这样万一判断逻辑写错了比如把失败当成成功打印出来一眼就能发现问题。我在调试时见过很多人把Login failed写进了成功条件里结果跑出来的成功密码全是错的这就是判断写反了。用Burp的Grep-Match功能时也同理Welcome这个词在DVWA的成功响应里是稳定出现的但它也可能出现在页面的导航或者说明文字里。最好再加上一个用户名关联的匹配比如成功页面里会出现Welcome to the password protected area admin就把Welcome to the password protected area作为匹配关键词更保险。5.3 关于安全测试的边界提醒做这一类实验必须在自建的、授权的靶场环境里进行。DVWA、本地虚拟机、自己搭建的测试服务器都是合法练习的载体。把同样的思路放到别人的系统上哪怕是内网测试机只要没有书面授权都已经越过了法律边界。从技术人的角度讲理解漏洞原理是为了写出更安全的代码、配置更完善的防护不是为了去攻击别人。我在带新人做训练时一直强调这个模块练的不是怎么入侵而是如果攻击者这么想我该怎么防。Brute force模块跑到最后最有价值的产出是你知道要加锁定策略、要上验证码、要做IP限速而不是记住几个爆破命令。如果确实有测试第三方系统的需求务必先确认授权范围拿到授权书或者测试合同再开始任何形式的测试。安全测试这个行当技术能力只是基础职业素养和合规意识才决定你能走多远。6. 从攻击视角反推防护建议6.1 暴力破解为什么难彻底防住跑完Medium级别最有价值的收获其实是站在攻击者的角度理解了为什么防护这么难做。暴力破解的本质是穷举用户名和密码的组合。只要密码空间有限、接口没有限制尝试次数攻击者就可以一直试下去。token在一定程度上防止了直接重放请求但就像前面演示的只要token能从页面里获取攻击者就能自动化地提取和提交。sleep延时增加了时间成本但对并发攻击者来说只是降低了速度并没有从根上堵住暴力破解这条路。这就解释了一个现实单一防护手段几乎都没有绝对效果。token、验证码、延时、锁定、限速每一样都有绕过或削弱的方法只有把多种手段组合起来、配合日常的监控告警才能把风险降到实际可控的范围。6.2 实际工程里推荐的安全措施从DVWA Medium的薄弱点可以映射出一套真实系统的防护基线。按优先级排的话服务端必须有限制登录失败次数的机制比如同一用户名或同一IP连续失败5次后锁定15分钟。这个策略直接否定了无限穷举的前提。登录接口要支持验证码或二次验证。验证码的价值在于增加自动化获取的难度尤其是行为式验证码能让大多数爆破脚本直接失效。登录接口要有速率限制。即使不能完全阻止攻击也要把尝试频率压到用大字典跑不现实的程度。密码策略要合理强制长度和复杂度并且接入常见弱密码黑名单从源头上缩小密码空间。日志和告警要覆盖登录失败事件。如果大量IP在短时间内的失败次数异常增加应该有自动化的告警和封禁动作。这些措施在DVWA的Impossible级别里都有体现比如基于IP的锁定、更严格的token管理。练完Medium再去看Impossible的源码你会立刻明白生产级别的防护和教学级别的防护差距有多大。6.3 一点个人体会把DVWA的brute force模块认真跑一遍比看十篇讲暴力破解的理论文章都有用。我在Medium级别上第一次跑出正确密码的时候印象最深的反而不是爆破成功了这个结果而是意识到一个隐藏的token字段、一行sleep代码确实能挡住大多数人但也仅仅能挡住没有自动化能力的人。安全领域就是这样攻防两端的知识必须同时储备。你只有真正动手写过提取token的脚本、调过正则去分析响应报文才能对token防护的局限有体感。下次自己写登录功能的时候才会条件反射一样地问这里是不是该加个失败锁定这个接口会不会被脚本刷最后说一句心得爆破这种技术本身并不高级真正的高级在于你知道什么时候能用、怎么用才能不逾矩。把DVWA当练习场把这些防护思路带到真实项目中这样的学习才有价值。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Higress MCP 公共实验环境搭建指南:基于 Kind 与 Helm 的一键式可复现环境 2026/9/17 3:24:54

Higress MCP 公共实验环境搭建指南:基于 Kind 与 Helm 的一键式可复现环境

Higress MCP 公共实验环境搭建指南:基于 Kind 与 Helm 的一键式可复现环境 【免费下载链接】higress 🤖 AI Gateway | AI Native API Gateway 项目地址: https://gitcode.com/GitHub_Trending/hi/higress 本文围绕 Higress 仓库中 samples/mcp/env…

阅读更多 →
Cursor+Playwright MCP:UI自动化语义化范式革命 2026/9/17 3:24:54

Cursor+Playwright MCP:UI自动化语义化范式革命

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
告别Postman臃肿体验:轻量API调试工具与Git工作流实践 2026/9/17 3:24:54

告别Postman臃肿体验:轻量API调试工具与Git工作流实践

最近我把用了好几年的 Postman 换掉了。不是它不好,而是它实在越来越重。如果你也经历过打开 Postman 要等好几秒、明明只是调个接口却被强制登录卡住、项目里旧集合越堆越多每次加载都在转圈的场景,那你大概能明白我为什么看到“10MB 安装包、启动不到 …

阅读更多 →
Foundry `forge lint` 规则解析:`require-revert-in-loop`(循环内 require/revert 检测与修复) 2026/9/17 3:24:54

Foundry `forge lint` 规则解析:`require-revert-in-loop`(循环内 require/revert 检测与修复)

Foundry forge lint 规则解析:require-revert-in-loop(循环内 require/revert 检测与修复) 【免费下载链接】foundry Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust. 项…

阅读更多 →
Rerun 中的 SphericalHarmonics3Rgb:3D 高斯溅射视角相关颜色的球谐系数编码解析 2026/9/17 3:24:54

Rerun 中的 SphericalHarmonics3Rgb:3D 高斯溅射视角相关颜色的球谐系数编码解析

Rerun 中的 SphericalHarmonics3Rgb:3D 高斯溅射视角相关颜色的球谐系数编码解析 【免费下载链接】rerun Visualize, query, and stream to train on multimodal robotics data. 项目地址: https://gitcode.com/GitHub_Trending/re/rerun 导读:本文…

阅读更多 →
Simulink风力发电系统建模:开关磁阻、异步电机与直驱并网逆变器仿真 2026/9/17 3:21:54

Simulink风力发电系统建模:开关磁阻、异步电机与直驱并网逆变器仿真

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞