diff --git a/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md b/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md index d688bb28609..5d4d806d3fd 100644 --- a/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md +++ b/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md @@ -67,6 +67,40 @@ a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"Guzz I needed to **call this deserialization twice**. In my testing, the first time the `/tmp/a.php` file was created but not loaded, and the second time it was correctly loaded. +## TCPDF `__destruct` POP chain for arbitrary file deletion + +When a real `TCPDF` instance is garbage-collected it calls `_destroy(true)`, iterates over `$this->imagekeys`, and `unlink()`s anything that looks like a cache file under `K_PATH_CACHE`. If an application performs `unserialize($user_data)` while the `TCPDF` class is loaded (e.g. it expects an array with an `html` key), you can supply a serialized object that sets: + +- `file_id` to any integer that is not present in `self::$cleaned_ids` (e.g. `-1`). +- `imagekeys` to paths that begin with `K_PATH_CACHE` or that can be made to look like it (e.g. `/tmp/../tmp/do_not_delete_this_file.txt` when `K_PATH_CACHE` is `/tmp/`). + +Example payload hitting an unsafe `unserialize($_GET['p']); $pdf->writeHTML($payload['html']);` flow: + +```text +a:1:{s:4:"html";O:5:"TCPDF":2:{s:7:"file_id";i:-1;s:9:"imagekeys";a:1:{i:0;s:39:"/tmp/../tmp/do_not_delete_this_file.txt";}}} +``` + +The file is deleted as soon as the object falls out of scope. TCPDF 6.9.3 tightened the check to only remove paths with the `__tcpdf__` prefix inside `K_PATH_CACHE` and introduced `_unlink()` to block non-`file://` schemes, so older `Producer` versions are prime targets. + +### Triggering the gadget via `phar://` in html2pdf `` tags + +`spipu/html2pdf` (≤5.3.0) wraps TCPDF and exposes a custom `` block whose `src`/`privkey` attributes are validated with plain `file_exists()`. On PHP < 8.0 any filesystem function that touches a `phar://` URL causes the Phar metadata to be unserialized. By storing the malicious TCPDF object above inside a Phar archive you gain a reliable POP even if the application never calls `unserialize()` itself. + +1. Craft a Phar with `phar.readonly=0`, set the stub/manifest to look like an image (e.g. rename `archive.phar` to `archive.png`), and store the serialized TCPDF object in the Phar metadata. +2. Upload/place the file somewhere reachable such as `/tmp/user_files/user_1/archive.png`. +3. Submit HTML containing the CERT tag so html2pdf resolves the attacker-controlled path: + +```html + +``` + +The call to `file_exists()` deserializes the metadata, instantiates TCPDF, and its destructor deletes the chosen file, turning html2pdf into a powerful `phar://` entry point. Version 5.3.1 added `Security::checkValidPath()` to block unapproved schemes, so legacy deployments remain attractive. + +## References + +- [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/) + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/file-inclusion/README.md b/src/pentesting-web/file-inclusion/README.md index 499fc7a9e5e..c6045bb956a 100644 --- a/src/pentesting-web/file-inclusion/README.md +++ b/src/pentesting-web/file-inclusion/README.md @@ -88,6 +88,24 @@ http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00 ``` +### HTML-to-PDF SVG/IMG path traversal + +Modern HTML-to-PDF engines (e.g. **TCPDF** or wrappers such as **html2pdf**) happily parse attacker-provided HTML, SVG, CSS, and font URLs, yet they run inside trusted backend networks with filesystem access. Once you can inject HTML into `$pdf->writeHTML()`/`Html2Pdf::writeHTML()`, you can often exfiltrate local files that the web server account can read. + +- **Fingerprint the renderer**: every generated PDF contains a `Producer` field (e.g. `TCPDF 6.8.2`). Knowing the exact build tells you which path filters exist and whether URL decoding occurs before validation. +- **Inline SVG payloads**: `TCPDF::startSVGElementHandler()` reads the `xlink:href` attribute from `` elements before running `urldecode()`. Embedding a malicious SVG inside a data URI makes many HTML sanitizers ignore the payload while TCPDF still parses it: + +``` + +``` + + TCPDF prepends `$_SERVER['DOCUMENT_ROOT']` to paths beginning with `/` and only later resolves `..`, so use either leading `../../..` segments or `/../../..` to escape the root after the prepend. +- **Encoding to bypass naive filters**: Versions ≤6.8.2 only check for the literal substring `../` *before* decoding the URL. Sending `..%2f` (or `..%2F`) in the SVG or in a raw `` attribute bypasses the check, because the traversal dot-dot-slash sequence is recreated only after TCPDF calls `urldecode()`. +- **Double-encoding for multi-stage decoding**: If user input is decoded by the web framework *and* by TCPDF, double-encode the slash (`%252f`). One decode turns it into `%2f`, the second decode in TCPDF turns it into `/`, yielding `/..%252f..` → `/../../../…` without ever showing `../` to the early filter. +- **HTML `` handler**: `TCPDF::openHTMLTagHandler()` contains the same order-of-operations bug, allowing direct HTML payloads such as `src="%2f..%252f..%252ftmp%252fsecret.png"` to read any locally reachable bitmap. + +This technique leaks anything readable by the PDF worker (passport scans, API keys rendered as images, etc.). Hardeners fixed it in 6.9.1 by canonicalising paths (`isRelativePath()`), so during tests prioritise older `Producer` versions. + ### From existent folder Maybe the back-end is checking the folder path: @@ -787,6 +805,7 @@ _Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._ - [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/) - [When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise](https://www.rcesecurity.com/2025/09/when-audits-fail-four-critical-pre-auth-vulnerabilities-in-trufusion-enterprise/) +- [Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?](https://swarm.ptsecurity.com/blind-trust-what-is-hidden-behind-the-process-of-creating-your-pdf-file/) {{#file}} EN-Local-File-Inclusion-1.pdf 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 a3e8733968c..3e75402e8b5 100644 --- a/src/pentesting-web/ssrf-server-side-request-forgery/README.md +++ b/src/pentesting-web/ssrf-server-side-request-forgery/README.md @@ -361,6 +361,25 @@ def start(): Note that this is interesting to leak status codes that you couldn't leak before (like a 200). However, if somehow you could also select the status code of the response (imagine that you can decide that the AWS metadata responds with a 500 status code), **there might be some status codes that directly leak the content of the response.** +### HTML-to-PDF renderers as blind SSRF gadgets + +Libraries such as **TCPDF** (and wrappers like **spipu/html2pdf**) will automatically fetch any URLs present in attacker-controlled HTML while rendering a PDF. Each `` or `` attribute is resolved server-side via cURL, `getimagesize()`, or `file_get_contents()`, so you can drive the PDF worker to probe internal hosts even though no HTTP response is reflected to you. + +``` + + + + + + +``` + +- TCPDF 6.10.0 issues several retrieval attempts for each `` resource, so a single payload can generate multiple requests (helpful for timing-based port scans). +- html2pdf copies TCPDF’s behaviour for `` and adds CSS fetching inside `Css::extractStyle()`, which simply calls `file_get_contents($href)` after a shallow scheme check. Abuse it to hit loopback services, RFC1918 ranges, or cloud metadata endpoints. +- Combine this SSRF primitive with the [HTML-to-PDF path traversal tricks](../file-inclusion/README.md#html-to-pdf-svgimg-path-traversal) to leak both internal HTTP responses and local files rendered into the PDF. + +Hardeners should strip external URLs before rendering or isolate the renderer in a network sandbox; until then, treat PDF generators as blind SSRF proxies. + ## Cloud SSRF Exploitation If you find a SSRF vulnerability in a machine running inside a cloud environment you might be able to obtain interesting information about the cloud environment and even credentials: @@ -421,5 +440,6 @@ https://github.com/incredibleindishell/SSRF_Vulnerable_Lab - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery) - [https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/](https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/) - [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) +- [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/) {{#include ../../banners/hacktricks-training.md}}