PortSwigger Labs CSRF靶场通关指南:从原理到实战的12个漏洞利用场景
1. 项目概述为什么PortSwigger Labs的CSRF靶场值得深挖如果你正在学习Web安全尤其是跨站请求伪造CSRF这个听起来有点绕口、但实战中又极其常见的漏洞那么PortSwigger Labs的CSRF靶场绝对是你绕不开的“练功房”。我干了十多年渗透测试带过不少新人发现很多朋友对CSRF的理解停留在“知道概念”的层面一到实战就懵要么是找不到利用点要么是绕不过各种防护机制。PortSwigger Labs也就是开发Burp Suite的那家公司提供的这一系列CSRF实验恰恰填补了从理论到实战的鸿沟。它不是给你一个孤零零的漏洞点而是构建了12个由浅入深、高度模拟真实业务逻辑的场景让你亲手去“攻破”这种学习体验比看十篇理论文章都来得实在。简单来说这个靶场项目就是一套精心设计的CSRF漏洞实战练习题。它模拟了从最简单的无防护表单提交到需要绕过Referer检查、Token验证、甚至利用JSON格式攻击等高级场景。通过它你不仅能彻底搞懂CSRF的攻击原理为什么受害者会在不知情的情况下执行操作更能掌握在真实渗透测试中如何发现、确认并最终利用CSRF漏洞的一整套方法论。无论是安全研究员、渗透测试工程师还是想夯实基础的开发人员这个靶场都能提供极具价值的实操经验。接下来我就结合自己通关的经验为你拆解这里的每一个核心环节和背后那些容易被忽略的细节。2. 核心思路拆解从“是什么”到“怎么利用”在动手之前我们必须把CSRF和这个靶场的核心逻辑吃透。很多新手一上来就急着打开Burp Suite抓包结果往往事倍功半。2.1 CSRF漏洞的本质与攻击模型CSRF的核心就一句话利用受害者的登录状态会话Cookie诱骗其浏览器向目标网站发送一个精心构造的请求。注意攻击者无法直接窃取Cookie而是“借用”了Cookie。这就像你捡到了一把别人家的钥匙Cookie你可以直接用这把钥匙开门发送请求但你并不知道锁芯的结构Cookie的值也无法复制这把钥匙。PortSwigger Labs的靶场正是基于这个模型设计的。每个实验都是一个独立的Web应用你拥有两个角色攻击者账户和受害者账户。你的目标就是以受害者身份登录后通过让受害者访问你攻击者控制的恶意页面来完成诸如修改邮箱、提升权限、转账等敏感操作。靶场巧妙之处在于它把现实中各种常见的防护措施都做成了关卡让你逐一攻克。2.2 靶场环境与工具选型背后的考量工欲善其事必先利其器。为什么大家都用Burp Suite来打这个靶场这不仅仅是因为它和靶场是“一家人”。首先Burp Suite的代理和重放功能是核心。你需要用它拦截浏览器发出的正常请求然后分析这个请求的结构是GET还是POST参数有哪些有没有防护令牌CSRF TokenReferer头是怎样的然后你才能在Burp Suite的Repeater模块里修改并重放这个请求测试你的攻击Payload是否有效。没有这个交互式测试过程纯靠猜是行不通的。其次Burp Suite的Collaborator功能在某些高级实验中是关键。有些实验的防护机制需要让服务器端对外发起网络请求例如通过img标签的src属性触发一个URL访问。Burp Collaborator提供了一个临时的、可由你控制的公网域名和服务器用于接收这些外联请求从而证明“盲打”CSRF的成功。如果你没有Burp专业版也可以使用RequestBin、Interactsh等公开服务替代但稳定性和私密性会差一些。最后浏览器的开发者工具同样重要。你需要用它来查看前端代码寻找可能被利用的JSONP端点、检查Cookie的作用域SameSite属性或者分析复杂的JavaScript逻辑。Burp Suite和浏览器工具的结合构成了CSRF测试的完整工作流。注意整个实验过程必须在同一个浏览器会话中完成并且要清晰地区分攻击者标签页和受害者标签页。我建议使用浏览器的“多用户”或“无痕窗口”功能来隔离两者避免Cookie串扰这是很多新手容易踩的坑。3. 实操全流程解析十二个实验的闯关指南下面我将这12个实验归纳为几个难度阶梯带你一步步通关。每个实验我都会说明核心考点、攻击思路和具体的操作步骤。3.1 基础篇无防护与简单防护的绕过实验1无任何防护的CSRF这是热身。目标是以受害者身份提交一个修改邮箱的请求。用受害者账户登录在修改邮箱页面提交一次用Burp拦截这个POST请求。分析请求你会发现它就是一个简单的POST /my-account/change-email参数是email没有任何token。在攻击者账户下构造一个HTML表单action指向靶场URLmethod为POST包含一个隐藏的email字段值设为攻击者的邮箱。将这段HTML托管在靶场提供的“漏洞利用服务器”上然后让受害者其实就是你自己点击预览链接访问这个恶意页面。表单会自动提交攻击成功。核心技巧这里可以直接用Burp的“Engagement tools” - “Generate CSRF PoC”功能自动生成攻击HTML非常方便。你要理解它生成的代码本质上就是一个自动提交的form。实验2验证Referer头中的令牌Token这个实验引入了初级防护服务器会检查HTTP请求头中的Referer字段看是否包含一个特定的令牌比如referer-token。正常拦截修改邮箱的请求发现请求头里确实有Referer: https://target-domain.net/?referer-tokenxxx。服务器会检查Referer值中是否包含这个令牌。我们的攻击页面在漏洞利用服务器上Referer自然是我们的服务器地址不包含令牌所以直接请求会被拒绝。绕过方法我们可以控制攻击页面的URL。将漏洞利用服务器的页面URL构造为https://exploit-server.net/?referer-tokenxxx其中xxx就是从正常请求的Referer里提取的那个令牌。这样当受害者访问我们的恶意页面时浏览器发出的请求中Referer头就会包含这个令牌从而通过检查。实操心得这种防护非常脆弱因为令牌直接暴露在了URL中。在真实测试中要养成检查所有请求参数和头部的习惯包括URL片段、Referer、Origin等看看有没有可以被我方控制或预测的值。3.2 进阶篇对抗CSRF Token防护CSRF Token是当前最主流的防护机制靶场用了多个实验来模拟其不同实现方式可能存在的缺陷。实验3CSRF Token被绑定到非会话Cookie这是一个经典的逻辑漏洞。场景是应用为每个用户生成了一个CSRF Token但这个Token不是放在会话Session里而是放在了一个单独的Cookie里例如csrf-key。服务器会验证请求体中的csrf参数是否与csrf-key这个Cookie的值匹配。拦截请求发现请求体有csrf参数同时请求头里有一个Cookie: csrf-keyabc123。攻击思路既然Token验证依赖的是Cookiecsrf-key那么只要我们能给受害者的浏览器设置上这个Cookie我们的攻击请求就能通过验证。如何设置Cookie我们可以寻找网站上任何一个能设置csrf-key这个Cookie的端点。通常网站可能有一个独立的API或页面来设置它。在这个靶场中你需要仔细浏览网站可能会发现一个如/set-csrf-cookie这样的路径。访问它会设置csrf-key。构造攻击页面这个页面需要先通过一个img标签或script标签让受害者的浏览器去访问/set-csrf-cookie这个URL从而为其浏览器设置好正确的csrf-keyCookie。然后再自动提交修改邮箱的表单表单中包含从Cookie中获取的csrf值这个值可以通过JavaScript读取document.cookie获得。深度解析这个实验的关键在于理解“同源策略”对Cookie的限制。我们无法从exploit-server.net直接读取target-domain.net的Cookie。但是我们可以通过让浏览器访问target-domain.net下的URL来“帮”它设置Cookie。这就是所谓的“Cookie Tossing”或“Cookie Injection”攻击的一种形式。在真实测试中要关注应用是否将Token存储在了可被第三方网站操纵的位置。实验4CSRF Token绑定到会话但未验证这个实验模拟了另一种开发失误服务器生成了Token并放入了会话也在表单里返回给了用户但在处理请求时却没有去验证这个Token它可能只是检查Token参数是否存在或者格式是否正确而没有与会话中存储的值进行比对。操作很简单正常拦截请求发现请求中有csrf参数。直接使用Burp生成CSRF PoC保留这个csrf参数可以是任意值或者直接删除该参数试试让攻击页面提交。攻击成功。因为服务器端缺少了关键的校验逻辑。排查技巧在实战中如何发现这种漏洞除了常规测试你可以尝试1) 提交一个错误的Token看是否被拒绝2) 提交两次相同的Token如果服务器每次校验后应使Token失效重复提交应失败3) 完全删除Token参数看是否通过。这个实验提醒我们防护机制本身的存在不等于其正确实现。实验5CSRF Token绑定到会话但Token可从其他位置泄露这是非常常见的一类漏洞。Token虽然被正确生成和校验但它可能被泄露到其他可以被攻击者读取的地方。在这个实验场景中你可能发现用户的CSRF Token不仅出现在修改邮箱的表单里还出现在另一个JSON格式的API响应中比如用户个人资料的GET请求。攻击者可以构造一个恶意页面先通过JavaScript可能是利用CORS配置错误或者直接因为同源策略无法读取这里需要具体看去窃取这个包含Token的API响应。从响应中提取Token然后动态地填充到即将提交的CSRF攻击表单中。关键点靶场可能会设计成这个API端点没有正确的CORS策略允许任意来源访问从而让攻击者的恶意脚本可以直接通过XMLHttpRequest或fetch拿到数据。在真实世界里Token泄露的途径五花八门可能出现在日志、分析数据、前端全局变量、甚至其他用户的页面里如果Token生成算法有问题。3.3 高级篇特殊请求格式与复杂交互实验6基于JSON的CSRFContent-Type: application/json传统CSRF攻击依赖于浏览器能自动发送的请求格式主要是application/x-www-form-urlencoded和multipart/form-data。对于application/json浏览器默认不会在跨域请求中发送这曾被认为是一种防护。但靶场展示了如何绕过。拦截请求发现它是一个POST请求Content-Type: application/json body是{email:newattacker.com}。直接使用HTML表单无法发送JSON数据。但是我们可以使用JavaScript来发送。构造攻击页面包含一段脚本使用fetchAPI向目标端点发送一个JSON格式的POST请求。这里有一个关键障碍浏览器的同源策略会阻止这种跨域的、非简单请求特别是带有自定义Content-Type的请求吗答案是如果服务器配置了宽松的CORS策略例如Access-Control-Allow-Origin: *那么预检请求OPTIONS会通过攻击就能成功。在这个实验中靶场服务器通常就配置了这样的策略。你的攻击脚本可以成功发出请求并携带受害者的Cookie。实操要点这告诉我们不能仅仅因为后端接口接收JSON就高枕无忧。必须配合严格的CORS策略、CSRF Token以及校验请求头如X-Requested-With来进行综合防护。实验7基于JSON的CSRF但依赖Content-Type检查这个实验增加了难度服务器会严格检查Content-Type头必须为application/json并且CORS策略是严格的不允许跨域。此时直接用JavaScript的fetch发起跨域请求会被浏览器阻止。绕过方法利用HTML表单可以发送POST请求并且我们可以通过enctypetext/plain来模拟一个“看起来像”JSON的请求体。但这还不够因为Content-Type会是text/plain。更高级的技巧是使用一个可以自动提交的form将其action指向目标URLmethod为POST并在表单中放置一个input其name和value设置为类似{email:attackerevil.com}的字符串。当表单以text/plain编码提交时整个字符串会作为请求体发送。但是服务器检查Content-Type所以这招可能不行。另一个历史漏洞是利用Flash插件现已淘汰或某些浏览器的特性来构造请求。在现代浏览器中一种可能的方法是寻找服务器端的其他解析漏洞比如如果服务器端先尝试解析JSON失败后回退到解析表单数据那么就有可能。这个实验通常设计为有某种特定的绕过方式需要你仔细阅读前端代码或尝试不同的Payload构造技巧。经验之谈面对严格的内容类型检查CSRF攻击确实变得困难。这体现了深度防御的原则。作为攻击方此时应该转向寻找其他更易利用的漏洞点。3.4 综合挑战篇多步骤操作与状态依赖后面的实验如实验8到12复杂度更高可能涉及多步骤操作比如修改邮箱需要先通过邮件验证。攻击需要模拟整个流程可能涉及拦截验证链接、自动点击等。依赖其他用户输入的CSRF攻击Payload需要包含从受害者页面动态获取的信息如当前用户的ID。基于Referer的验证可被绕过利用meta标签或服务器端重定向来篡改或移除Referer头。利用XSS与CSRF结合如果网站存在一个反射型XSS漏洞攻击者可以先注入脚本该脚本在受害者浏览器上下文中运行可以完美地读取CSRF Token并构造请求实现“存储型CSRF”的效果。这在靶场中可能是一个终极挑战。对于这些高级实验通用的思路是彻底分析正常流程用Burp的Proxy记录下受害者完成整个敏感操作如修改邮箱、转账的所有HTTP请求序列。识别状态与依赖找出每个请求依赖哪些参数如上一步返回的令牌、用户ID、会话标识等。这些参数哪些是固定的哪些是动态的哪些可以从攻击页面获取设计攻击链将多个请求按顺序在恶意页面中实现。可能需要使用JavaScript来顺序发送多个fetch请求或者通过隐藏的iframe和表单进行链式提交。处理异步与回调如果操作涉及服务器异步响应攻击页面可能需要监听响应并提取数据用于下一步。4. 核心工具使用技巧与避坑指南光有思路不够工具用不好照样卡壳。下面分享几个在PortSwigger Labs CSRF靶场中使用Burp Suite的关键技巧和常见问题。4.1 Burp Suite高效工作流配置浏览器代理设置确保浏览器正确配置为使用Burp的代理默认127.0.0.1:8080。安装并信任Burp的CA证书否则无法拦截HTTPS流量。这是所有操作的基础但很多新手会在这里出错导致抓不到包。Target作用域设置在Burp的Target-Scope中添加你的靶场域名例如*.web-security-academy.net。这样可以避免Burp拦截和记录大量无关流量让你的工作区更清晰。利用Repeater进行快速测试这是你测试CSRF Payload是否有效的核心工具。拦截到正常请求后右键发送到Repeater。在Repeater中你可以随意修改参数、头部然后发送观察响应。对于CSRF测试关键看修改参数后比如换成攻击者邮箱返回的HTTP状态码和响应内容是否表示成功如302重定向或返回成功消息。4.2 CSRF PoC生成器的正确打开方式Burp的CSRF PoC生成器在拦截的请求上右键 -Engagement tools-Generate CSRF PoC是个神器但别完全依赖它。自动 vs 手动对于无防护或简单Token的实验它生成的HTML表单通常可以直接用。但对于需要复杂JavaScript、多步骤操作或涉及Cookie操作的实验它生成的代码只是基础模板你需要在此基础上进行大量修改。关键修改点表单actionURL确保它是完整的绝对路径指向靶场的目标端点。隐藏字段检查生成的表单是否包含了所有必要的参数特别是那些动态的Token。有时你需要手动添加从其他途径获取的参数。自动提交生成的代码通常包含body onloaddocument.forms[0].submit()。在复杂攻击链中你可能需要移除这个自动提交改为由你自己的JavaScript函数在适当时机触发。测试生成PoC后先在你的攻击者上下文另一个浏览器标签页已登录攻击者账户中用Burp拦截这个PoC页面发出的请求看看它发出的请求是否和你设计的一致。这是一个非常重要的验证步骤。4.3 常见问题与排查实录问题1攻击页面提交后操作没有成功但服务器也没报错。排查首先在Burp中查看攻击页面实际发出的请求Proxy历史记录。对比这个请求和你在Repeater中测试成功的请求逐字逐句地比较URL、方法、每一个请求头尤其是Content-Type、Origin、Referer、请求体。一个多余的空格、一个大小写错误都可能导致失败。可能原因Token过期会话可能已改变Referer头不符合要求请求体格式不对例如应该是JSON却成了表单编码。问题2受害者访问攻击页面后没有任何反应。排查打开浏览器的开发者工具F12切换到“网络(Network)”标签页然后让受害者访问攻击页面。查看是否有请求发出请求的状态码是什么被CORS阻止了会是CORS错误或请求失败查看控制台(Console)是否有JavaScript错误可能原因攻击页面的JavaScript代码有语法错误导致提交函数未执行表单的actionURL写错了靶场环境网络问题。问题3如何模拟“受害者点击链接”这个动作在靶场中你通常需要将构造好的恶意HTML代码粘贴到漏洞利用服务器(Exploit server)上然后点击“View exploit”或“Deliver to victim”。后者会自动模拟一个受害者访问。但请注意这个模拟的受害者会话可能和你当前活跃的受害者浏览器会话不是同一个。最可靠的方法是自己打开一个已登录受害者账户的浏览器或无痕窗口手动输入漏洞利用服务器提供的URL进行访问。这样你能100%确认攻击是在正确的会话上下文中发生的。问题4实验要求使用Burp Collaborator但我没有专业版。对于需要证明“盲”交互的实验如服务器端会对外发起请求你可以使用免费的第三方服务如https://requestbin.com/或https://app.interactsh.com/。在攻击Payload中将需要被访问的URL替换成这些服务为你生成的唯一地址。然后观察这些服务的控制台看是否有请求到来从而证明攻击成功。不过这些公开服务可能被屏蔽或不够稳定仅供学习使用。5. 从靶场到实战CSRF漏洞挖掘思路延伸通关PortSwigger Labs只是第一步。真正的价值在于将这套方法论应用到真实的渗透测试和代码审计中。在黑盒测试中挖掘CSRF功能点枚举列出所有具有状态改变功能的端点登录/注销、修改资料邮箱、密码、地址、增删改数据发布文章、转账、授权、更改设置。请求分析对每个可疑端点用Burp拦截其请求。重点关注方法GET请求的参数可能出现在Referer或日志中更容易被利用。但POST也并非安全。参数是否存在明显的Token参数如csrf_token,authenticity_token,nonce它的值是否随机每次请求是否变化Cookie除了会话Cookie是否有其他用于验证的Cookie它们和Token的关系是什么头部服务器是否检查Origin或Referer头它们的值是否可预测或可绕过Token逻辑测试如果存在Token进行验证删除Token参数再提交。将Token改为一个随机值或空值提交。重复使用同一个Token提交两次。尝试从其他页面如用户主页、API响应寻找泄露的Token。构造PoC对于疑似存在漏洞的端点按照靶场中学到的方法构造攻击页面并在两个不同的浏览器会话模拟攻击者和受害者中进行测试。在白盒/代码审计中识别CSRF缺陷寻找关键控制器查看处理敏感操作的后端代码如changeEmail,updateProfile,transferMoney等方法。检查防护代码寻找是否有对CSRF Token的校验语句。在很多框架中这可能是一个注解如Spring Security的CsrfToken或一个中间件调用如Django的csrf_protect。关键是要看这个校验是否真的被执行了。有时代码里引入了防护库但可能在配置中被全局禁用或者在某些接口上被单独豁免。检查Token的生成与存储Token是否足够随机使用安全的随机数生成器是否与用户会话严格绑定是否在一次使用后立即失效同步令牌模式检查CORS配置对于前后端分离的项目检查后端API的CORS配置。过于宽松的Access-Control-Allow-Origin: *可能会为JSON CSRF打开大门。检查SameSite Cookie属性现代浏览器支持的SameSiteLax或Strict属性能有效缓解CSRF。检查应用中重要的会话Cookie是否设置了此属性。如果设置为None则必须同时设置Secure属性仅限HTTPS。防御措施建议给开发者的提醒首选同步令牌模式在表单中嵌入一个随机、不可预测的Token并在服务器端验证该Token与用户会话中存储的是否匹配。处理成功后应更新Token。使用框架内置功能几乎所有现代Web框架Spring Security, Django, Laravel, Rails等都提供了开箱即用的CSRF防护。不要自己造轮子直接启用并正确配置它们。实施双重Cookie验证对于API等场景可以要求请求头中携带一个自定义头如X-Requested-With: XMLHttpRequest因为浏览器在发起跨域请求时默认不会添加此类头。但这不能作为唯一防护。设置Cookie的SameSite属性将会话Cookie设置为SameSiteLax对大多数网站是平衡的选择或Strict对安全性要求极高的操作。关键操作增加二次确认如修改密码时要求输入旧密码转账时进行短信/邮箱验证。这能从业务逻辑层面增加攻击难度。通关PortSwigger Labs的CSRF靶场就像是完成了一次系统的军事演习。它把理论中枯燥的概念变成了一个个需要你亲手解决的具体问题。当你为绕过一个个防护机制而绞尽脑汁最终成功弹出“Congratulations”页面时你对CSRF的理解就已经远超纸上谈兵了。记住安全是一个攻防对抗的过程今天你学会的攻击手法正是为了明天能写出更坚固的防御代码。保持好奇持续练习这才是通往资深之路的不二法门。