0%

CSRF漏洞学习笔记

bp实验室的CSRF漏洞学习笔记

什么是CSRF(跨站请求伪造)漏洞

攻击者可以利用这漏洞来执行他们不被预期的命令。它允许攻击者部分规避同源策略,该策略旨在防止不同网站相互干扰。

在成功的 CSRF 攻击中,攻击者会导致受害用户无意中执行操作。例如,这可能是更改其帐户上的电子邮件地址、更改其密码或进行资金转账。根据操作的性质,攻击者可能能够完全控制用户的帐户。如果受感染的用户在应用程序中拥有特权角色,那么攻击者可能能够完全控制应用程序的所有数据和功能。

CSRF是如何起效的

想要触发CSRF就要满足下面的三个条件

  • 相关操作。应用程序中存在攻击者有理由诱发的操作。这可能是特权操作(例如修改其他用户的权限)或针对用户特定数据的任何操作(例如更改用户自己的密码)。
  • 基于 Cookie 的会话处理。执行操作涉及发出一个或多个 HTTP 请求,应用程序仅依靠会话 cookie 来识别发出请求的用户。没有其他机制来跟踪会话或验证用户请求。
  • 没有不可预测的请求参数。执行操作的请求不包含任何攻击者无法确定或猜测其值的参数。例如,当导致用户更改密码时,如果攻击者需要知道现有密码的值,则该功能不会受到攻击。

比如某个网页有修改邮箱密码的功能,当用户执行这个操作的时候,他们就会发送下面的请求

1
2
3
4
5
6
7
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE

email=wiener@normal-user.com

这就满足了相关操作 cookie认证 以及参数可以预知的要求,所以存在csrf漏洞。
攻击者可以创建一个html网页

1
2
3
4
5
6
7
8
9
10
<html>
<body>
<form action="https://vulnerable-website.com/email/change" method="POST">
<input type="hidden" name="email" value="pwned@evil-user.net" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>

当用户访问这个网页的时候,攻击者的页面将触发对存在漏洞的网站的 HTTP 请求。如果用户登录之后,他们的浏览器将自动在请求中包含他们的会话 cookie。
存在漏洞的网站将以正常方式处理该请求,将其视为受害者用户发出的请求,并更改其电子邮件地址。

如何构造CSRF

可以使用bp自带的CSRF poc生成器
比如这个网页有一个修改邮箱的功能,在登录自己的账户之后,抓包

在这个页面用bp自带的CSRF poc生成器,然后点击regenerate 把这个poc放在我们的服务器上,
这样子用户在点击这个请求的时候,浏览器就会发送请求给修改邮箱的界面,因为浏览器中存着用户的cookie,就分不清是用户还是攻击者的恶意请求

怎么传播CSRF

上面说了CSRF怎么构建,现在要怎么让用户来触发这个漏洞呢。通常,攻击者会将恶意 HTML 放到他们控制的网站上,然后诱使受害者访问该网站。这可能通过向用户提供该网站的链接(通过电子邮件或社交媒体消息)来实现。

一些简单的CSRF漏洞利用了GET方法,并且可以完全独立于易受攻击的网站上的单个 URL。攻击者可以直接向受害者提供易受攻击的域上的恶意 URL。在前面的示例中,如果可以使用 GET 方法执行更改电子邮件地址的请求,那么自包含攻击将如下所示:

1
<img src="https://vulnerable-website.com/email/change?email=pwned@evil-user.net">

CSRF常见的防护措施

CSRF-tokens

由服务器端应用程序生成并与客户端共享的唯一、秘密且不可预测的值。当尝试执行敏感操作(例如提交表单)时,客户端必须在请求中包含正确的CSRF-tokens.这使得攻击者很难代表受害者构建有效的请求。

与客户端共享 CSRF tokens的常见方法是将它们作为隐藏参数包含在 HTML 表单中,例如:

1
2
3
4
5
6
<form name="change-email-form" action="/my-account/change-email" method="POST">
<label>Email</label>
<input required type="email" name="email" value="example@normal-website.com">
<input required type="hidden" name="csrf" value="50FaWgdOhi9M9wyna8taR1k3ODOR8d6u">
<button class='button' type='submit'> Update email </button>
</form>

常见缺陷:

  • 1、当请求使用 POST 方法时,某些应用程序会正确验证tokens,但使用 GET 方法时则会跳过验证。在这种情况下,攻击者可以切换到 GET 方法来绕过验证并发起 CSRF 攻击:
1
2
3
GET /email/change?email=pwned@evil-user.net HTTP/1.1
Host: vulnerable-website.com
Cookie: session=2yQIDcpia41WrATfjPqvm9tOkDvkMvLm

在bp请求中右键切换请求方式就可以了

  • 2、当tokens存在时,某些应用程序会正确验证tokens,但如果省略tokens,则会跳过验证。

  • 3、一些应用程序确实将 CSRF tokens绑定到 Cookie,但不会绑定到用于跟踪会话的同一 Cookie
    比如我有两个用户,我在a用户的cookie和csrf在b用户上也能用

Cookie 设置行为甚至不需要存在于与 CSRF 漏洞相同的 Web 应用程序中。如果受控 Cookie 具有合适的范围,则同一整体 DNS 域中的任何其他应用程序都可能被利用来在目标应用程序中设置 Cookie。例如,可以利用 staging.demo.normal-website.com 上的 Cookie 设置函数来放置提交给 secure.normal-website.com Cookie。

  • 4、 CSRF token 只是在 cookie 中复制
    在这种情况下,如果网站包含任何 cookie 设置功能,攻击者可以再次执行 CSRF 攻击。此时,攻击者无需获取自己的有效 tokens。他们只需发明一个 tokens(如果经过检查,可能是所需的格式),利用 cookie 设置行为将其 cookie 放入受害者的浏览器中,然后在 CSRF 攻击中将其 tokens提供给受害者。

SameSite 是一种浏览器安全机制,用于确定何时将网站的 Cookie 包含在来自其他网站的请求中。由于执行敏感操作的请求通常需要经过身份验证的会话 Cookie,因此适当的 SameSite 限制可能会阻止攻击者跨站点触发这些操作。

在 SameSite Cookie 环境中,站点是什么?

在 SameSite Cookie 限制的上下文中,站点被定义为顶级域名 (TLD),通常为.com 或.net ,加上域名的附加一级。这通常称为 TLD+1。

在确定请求是否为同站请求时,还会考虑 URL 方案。这意味着从 http://app.example.comhttps://app.example.com 的链接被大多数浏览器视为跨站请求。

另外用两幅图来区分site和oringin

\

Samesite的工作方式
在引入 SameSite 机制之前,浏览器会在每个请求中向发出请求的域发送 Cookie,即使请求是由不相关的第三方网站触发的。SameSite 的工作原理是让浏览器和网站所有者限制哪些跨站点请求(如果有)应包含特定 Cookie。这有助于减少用户受到 CSRF 攻击的风险,这种攻击会诱使受害者的浏览器发出触发易受攻击的网站的有害操作的请求。由于这些请求通常需要与受害者的经过身份验证的会话相关联的 Cookie,因此如果浏览器不包含此 Cookie,攻击就会失败。
所有主流浏览器目前都支持以下 SameSite 限制级别:

Strict
Lax
None

开发人员可以手动配置他们设置的每个 Cookie 的限制级别,从而更好地控制何时使用这些 Cookie。为此,他们只需在 Set-Cookie 响应标头中包含 SameSite 属性及其首选值:

1
Set-Cookie: session=0F8tgdOhi9ynR1M9wa3ODa; SameSite=Strict

如果发布 Cookie 的网站未明确设置 SameSite 属性,Chrome 会默认自动应用 Lax 限制。这意味着 Cookie 仅在符合特定条件的跨站点请求中发送,即使开发人员从未配置此行为。

Strict:
如果 Cookie 设置了 SameSite=Strict 属性,浏览器将不会在任何跨站点请求中发送该 Cookie。简单来说,这意味着如果请求的目标站点与浏览器地址栏中当前显示的站点不匹配,则不会包含该 Cookie。
虽然这是最安全的选择,但在需要跨站点功能的情况下,它可能会对用户体验产生负面影响。

Lac:
Lax SameSite 限制意味着浏览器将在跨站点请求中发送 cookie,但前提是满足以下两个条件:

  • 请求使用 GET 方法。
  • 该请求源自用户的顶级导航,例如单击链接。

这意味着 cookie 不包含在跨站点 POST 请求中。由于 POST 请求通常用于执行修改数据或状态的操作(至少根据最佳实践),因此它们更有可能成为 CSRF 攻击的目标。

当使用 SameSite=None 设置 cookie 时,网站还必须包含 Secure 属性,以确保 cookie 仅通过 HTTPS 以加密消息形式发送。否则,浏览器将拒绝该 cookie 并且不会设置。

1
Set-Cookie: trackingId=0F8tgdOhi9ynR1M9wa3ODa; SameSite=None; Secure

使用 GET 请求绕过 SameSite Lax 限制

实际上,服务器并不总是对它们是否接收对给定端点的 GET 或 POST 请求很挑剔,即使是那些期望表单提交的服务器。如果他们也对其会话 cookie 使用 Lax 限制(无论是明确还是由于浏览器默认), 仍然可以通过从受害者的浏览器引出 GET 请求来执行 CSRF 攻击。
只要请求涉及顶级导航,浏览器仍将包含受害者的会话 cookie。以下是发起此类攻击的最简单方法之一:

1
2
3
<script>
document.location = 'https://vulnerable-website.com/account/transfer-payment?recipient=hacker&amount=1000000';
</script>

即使不允许普通的 GET 请求,某些框架也提供了覆盖请求行中指定的方法。例如,Symfony 在表单中支持_method 参数,该参数在路由方面优先于普通方法:

1
2
3
4
5
<form action="https://vulnerable-website.com/account/transfer-payment" method="POST">
<input type="hidden" name="_method" value="GET">
<input type="hidden" name="recipient" value="hacker">
<input type="hidden" name="amount" value="1000000">
</form>

比如现在goole使用的POST请求会在两分钟内才能成功验证cookie,我们想绕过这个限制,就可以使用_method

1
2
<form action="https://0a04001c0438b910819c76f500230087.web-security-academy.net/my-account/change-email" method="GET">
<input type="hidden" name="_method" value="POST"/>

先发送一个GET请求的表单,但是用_method覆盖成POST

有些时候要注意观察网页一些小脚本,小工具。比如在这个网页用户发送一个评论之后,后重定向到blog界面,观察到是调用了一个js

找到这个js的逻辑只是拼接之后就可以用路径逃逸,像这样/post/comment/confirmation?postId=1/../../my-account
所以可以利用这个界面生成csrf poc,(前提是发现修改邮箱也可以通过get请求实现)

无论 是在测试其他人的网站还是尝试保护 自己的网站,请务必记住,即使是跨源发出的请求仍然可以是同一站点的。

用新发布的cookie绕过 SameSite Lax 限制

具有 Lax SameSite 限制的 Cookie 通常不会在任何跨站点 POST 请求中发送,但也有一些例外。
如果网站在设置 Cookie 时未包含 SameSite 属性,Chrome 会默认自动应用 Lax 限制。但是,为了避免破坏单点登录 (SSO) 机制,它实际上不会在顶级 POST 请求的前 120 秒内强制执行这些限制。因此,在两分钟的时间内,用户可能容易受到跨站点攻击。(此两分钟窗口不适用于使用 SameSite=Lax 属性明确设置的 cookie)
但是尝试将攻击时间安排在这么短的时间范围内有点不切实际。另一方面,如果你能在网站上找到一个可以强制向受害者发出新会话 cookie 的小工具,那么你可以在进行主要攻击之前先刷新他们的 cookie。例如,完成基于 OAuth 的登录流程可能会导致每次都产生新会话,因为 OAuth 服务不一定知道用户是否仍登录到目标网站。
为了触发 cookie 刷新而无需受害者再次手动登录, 需要使用顶级导航,以确保包含与其当前 OAuth 会话相关的 cookie。这带来了额外的挑战,因为 需要将用户重定向回 的网站,以便发起 CSRF 攻击。
或者, 可以从新选项卡触发 cookie 刷新,这样浏览器就不会在 能够发起最终攻击之前离开页面。这种方法的一个小问题是,除非通过手动交互打开弹出选项卡,否则浏览器会阻止它们。例如,以下弹出窗口将默认被浏览器阻止:

1
window.open('https://vulnerable-website.com/login/sso');

为了解决这个问题, 可以将语句包装在 onclick 事件处理程序中,如下所示:

1
2
3
window.onclick = () => {
window.open('https://vulnerable-website.com/login/sso');
}

这样,仅当用户点击页面上的某个位置时,才会调用 window.open() 方法。

基于 Referer 的验证

一些应用程序利用 HTTP Referer 标头来尝试防御 CSRF 攻击,通常是通过验证请求是否来自应用程序自己的域。这通常比 CSRF tokens验证效果差。

HTTP Referer 标头是一个可选的请求标头,其中包含链接到所请求资源的网页的 URL。它通常在用户触发 HTTP 请求时由浏览器自动添加,包括通过点击链接或提交表单。存在各种方法允许链接页面保留或修改 Referer 标头的值。这通常是出于隐私原因。

  • 当请求中存在 Referer 标头时,某些应用程序会验证该标头,但如果省略该标头,则会跳过验证。在这种情况下,攻击者可以精心设计 CSRF 漏洞,让受害用户的浏览器在生成的请求中丢弃 Referer 标头。有多种方法可以实现此目的,但最简单的方法是在承载 CSRF 攻击的 HTML 页面中使用 META 标记:
1
<meta name="referrer" content="never">
  • 某些应用程序以一种可以被绕过的简单方式验证 Referer 标头。例如,如果应用程序验证 Referer 中的域以预期值开头,则攻击者可以将其作为自己域的子域:
1
http://attacker-website.com/csrf-attack?vulnerable-website.com

虽然 可以使用 Burp 识别此行为,但当 在浏览器中测试概念验证时, 经常会发现这种方法不再有效。为了降低以这种方式泄露敏感数据的风险,许多浏览器现在默认从 Referer 标头中删除查询字符串。

因为许多浏览器现在默认从 Referer 标头中删除查询字符串作为安全措施。要覆盖此行为并确保请求中包含完整的 URL,请返回漏洞服务器并将以下标头添加到 “Head” 部分:

1
Referrer-Policy: unsafe-url