# 跨站请求伪造（CSRF）

在本节中，我们将讲解什么是跨站请求伪造，描述一些常见的CSRF漏洞示例，并说明如何防范CSRF攻击。

## 什么是CSRF？

跨站请求伪造（又称为CSRF）是一种Web安全漏洞，允许攻击者诱导用户执行他们并不打算执行的操作。它允许攻击者在一定程度上绕过同源策略，而该策略旨在防止不同网站相互干扰。

![](https://2165487371-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfahSMMYUzmqmE8SfCaax%2Fuploads%2Fgit-blob-f6fe718a422cbdc231035deb0a1ea39cef91e68b%2Fcross-site-request-forgery.svg?alt=media)

> **Labs**
>
> 如果你已经熟悉CSRF漏洞背后的基本概念，并且只想在一些真实的、故意易受攻击的目标上练习利用它们，你可以从下面的链接访问本主题中的所有实验。
>
> * [查看所有CSRF实验](https://portswigger.net/web-security/all-labs#cross-site-request-forgery-csrf)

## CSRF攻击的影响？

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

## CSRF是如何工作的？

要实现CSRF攻击，必须具备三个关键条件：

* **一个相关操作。** 应用程序中存在一个攻击者有理由诱导的操作。可能是特权操作（如修改其他用户的权限）或用户特定数据上的任何操作（如更改用户自己的密码）。
* **基于Cookie的会话处理。** 执行操作涉及到发出一个或多个HTTP请求，应用程序仅依赖会话Cookie来识别发出请求的用户。没有其他机制用于跟踪会话或验证用户请求。
* **没有不可预测的请求参数。** 执行操作的请求不包含攻击者无法确定或猜测其值的任何参数。比如在使用户更改密码时，如果攻击者需要知道现有密码的值，那么该功能就不容易受到攻击。

例如，假设一个应用程序包含一个允许用户更改其账户上电子邮件地址的功能。当用户执行此操作时，他们会发起如下HTTP请求：

```http
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
```

这满足了CSRF所需的条件：

* 攻击者会对更改用户帐户上电子邮件地址的操作感兴趣。执行此操作之后，攻击者通常就能够触发密码重置并完全控制用户的帐户。
* 应用程序使用会话Cookie来识别发起请求的用户。没有其他令牌或机制来跟踪用户会话。
* 攻击者可以轻易确定执行操作所需请求参数的值。

在这些条件存在的情况下，攻击者就可以构建一个包含以下HTML的网页：

```html
<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（假设未使用SameSite Cookie）。
* 易受攻击的网站将以正常方式处理该请求，将其视为由受害用户发起的，并更改他们的电子邮件地址。

> **注意**
>
> 虽然CSRF通常被描述为与基于Cookie的会话处理相关，但它也会出现在应用程序自动将一些用户凭证添加到请求的其他上下文中，如HTTP Basic认证和基于证书的认证。

## 如何构造CSRF攻击？

手动创建用于CSRF利用所需的HTML可能会很麻烦，特别是在所需的请求包含大量参数或请求中存在其他怪异问题的情况下。构造CSRF利用最简单的方法是使用Burp Suite Professional中内置的[`CSRF PoC generator`](https://portswigger.net/burp/documentation/desktop/tools/engagement-tools/generate-csrf-poc)：

* 在Burp Suite Professional中的任意位置选择你要测试或利用的请求。
* 从右键上下文菜单中选择`Engagement tools` - `Generate CSRF PoC`。
* Burp Suite将生成一些HTML，以触发所选请求（不包括由受害者浏览器自动添加的Cookie）。
* 你可以调整`CSRF PoC generator`中的各个选项，以微调攻击的各个方面。在某些不寻常的情况下，可能需要这样做以处理请求的古怪特性。
* 将生成的HTML复制到网页中，在已登录到易受攻击的网站的浏览器中查看它，并测试预期请求是否成功发起以及期望的操作是否发生。

> **LAB**
>
> [无防御的CSRF漏洞](https://portswigger.net/web-security/csrf/lab-no-defenses)

## 如何传递CSRF利用？

跨站请求伪造攻击的传递机制本质上与反射型XSS相同。通常，攻击者会将恶意HTML放置在他们控制的网站上，然后诱导受害者访问该网站。这可以通过电子邮件或社交媒体消息向用户提供一个指向该网站的链接来完成。或者，如果攻击被放入流行网站中（如用户评论中），攻击者可能只需等待用户访问该网站。

请注意，一些简单的CSRF利用使用GET方法，并且可以通过易受攻击的网站上的单个URL完全自包含。在这种情况下，攻击者可能无需使用外部网站，就可以直接向受害者提供易受攻击的域上的恶意URL。在前面的示例中，如果可以使用GET方法执行更改电子邮件地址的请求，那么自包含攻击将如下所示：

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

> **阅读更多**
>
> [XSS与CSRF](https://web-sec.gitbook.io/wsa/client-side/csrf/xss-vs-csrf)

## 针对CSRF的常见防御

如今，要成功发现并利用CSRF漏洞，往往需要绕过目标网站、受害者浏览器或两者均部署的反CSRF措施。你会遇到的最常见的防御如下：

* **CSRF令牌** - CSRF令牌是一个由服务器端应用程序生成并与客户端共享的唯一、保密和不可预测的值。在尝试执行敏感操作（如提交表单）时，客户端必须在请求中包含正确的CSRF令牌。这使得攻击者很难代表受害者构造一个有效的请求。
* **SameSite Cookie** - SameSite是一种浏览器安全机制，用于确定何时将网站的Cookie包含在源自其他网站的请求中。由于执行敏感操作的请求通常需要经过认证的会话Cookie，因此适当的SameSite限制可阻止攻击者跨站触发这些操作。自2021年起，Chrome默认强制执行`Lax` SameSite限制。因为这是拟议的标准，我们预计其他主浏览器在将来也会采用这种行为。
* **基于Referer的验证** - 一些应用程序利用HTTP Referer标头试图防御CSRF攻击，通常是通过验证请求是否来自应用程序自己的域。这种验证通常不如CSRF令牌验证有效。

如需更详细地了解每种防御，以及它们如何被绕过，请查阅以下材料。这些材料包括交互式实验，可让你在现实的、故意易受攻击的目标上练习所学知识。

> **阅读更多**
>
> * [绕过CSRF令牌验证](https://github.com/0xf4n9x/Web_Security_Academy-zh/blob/master/client-side/csrf/bypassing-token-validation.md)
> * [绕过SameSite Cookie限制](https://github.com/0xf4n9x/Web_Security_Academy-zh/blob/master/client-side/csrf/bypassing-samesite-restrictions.md)
> * [绕过基于Referer的CSRF防御](https://github.com/0xf4n9x/Web_Security_Academy-zh/blob/master/client-side/csrf/bypassing-referer-based-defenses.md)

有关如何正确实现这些防御以防止你自己的网站上出现上述问题的详细信息，请参阅[如何防范CSRF漏洞](https://github.com/0xf4n9x/Web_Security_Academy-zh/blob/master/client-side/csrf/preventing.md)。
