Skip to main content
Create your own
Lesson illustration

XXE for Data Exfiltration and SSRF

Hello! Welcome back to our module on advanced server-side vulnerabilities.

In the last lesson, we established a strong foundation for identifying XML External Entity (XXE) vulnerabilities. You learned to spot them in obvious XML-based requests and in more subtle attack surfaces like file uploads. We focused on the classic attack: making the server read a local file and reflect its contents directly back to us in the HTTP response.

Today, we're going to build directly on that knowledge to tackle more realistic and impactful scenarios. Our goal is to exploit XXE to exfiltrate local files and perform Server-Side Request Forgery (SSRF). We'll cover two major escalations:

  1. Pivoting an XXE vulnerability to perform SSRF, allowing us to scan and interact with the target's internal network.
  2. Exfiltrating data using out-of-band techniques when the application is vulnerable to XXE but doesn't return the data in its response (Blind XXE).

Mastering these techniques is essential, as they often lead to high-severity findings in both penetration tests and bug bounty programs.

1. XXE for File Exfiltration and SSRF: The Payloads

Let's quickly recap the core mechanism. An XXE vulnerability is triggered when the XML parser processes an external entity we've defined. The key is the SYSTEM keyword in our DOCTYPE declaration, which tells the parser to fetch content from an external source.

The source is specified by a URI, which gives us two primary attack paths:

  1. File Exfiltration (Local File Inclusion): Using the file:// protocol wrapper to read local files.
    <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
    
  2. Server-Side Request Forgery (SSRF): Using protocol wrappers like http:// or https:// to make the server initiate web requests.
    <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/"> ]>
    
XXE File Disclosure Attack Flow
This diagram illustrates the basic flow for in-band file disclosure. The attacker sends a malicious XML entity pointing to a local file. The vulnerable server parses the XML, reads the file, and embeds its contents in the response.

Now, let's see these attacks in action.

2. From File Read to Network Scan: XXE-powered SSRF

While reading files like /etc/passwd is a great proof of concept, the real power of XXE is often realized when you pivot to SSRF. By instructing the server to make HTTP requests on your behalf, you can bypass firewalls and access internal resources that are not exposed to the internet.

Common targets for XXE-driven SSRF include:

  • Internal network scanning: Probing internal IP ranges (e.g., 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and ports to discover hidden services.
  • Accessing internal admin panels: Many applications have admin interfaces listening on localhost that are not remotely accessible.
  • Querying cloud provider metadata services: This is a critical target. Cloud platforms like AWS, GCP, and Azure provide a special internal IP address (169.254.169.254 for AWS/GCP) that virtual machines can query to get temporary access credentials and other sensitive data.

The following resources provide a clear explanation and demonstration of these attacks.

XML external entity (XXE) injection

The PortSwigger article you viewed previously has an excellent section that formally explains how to use XXE to trigger SSRF attacks.

Read the section 'Exploiting XXE to perform SSRF attacks'. Focus on how the payload changes from using file:// to using an http:// URL.

Now, let's watch a practical demonstration of using XXE for both file reading and internal port scanning.

Learn XXE by doing hands-on challenges

This video provides a concise, hands-on demonstration of using XXE payloads to first read local files and then pivot to scanning internal ports—a classic SSRF technique.

Watch from 00:49 to 04:19. First, observe the classic file read (00:49 - 02:08). Then, pay close attention to how the payload is modified to perform an SSRF attack to probe an internal port (03:26 - 04:19). Notice how the server's response ('Connection refused') gives a clear signal about the port's status.

Test your understanding!

You have confirmed an XXE vulnerability on a server hosted in AWS. You want to check if you can access the instance metadata service to retrieve temporary credentials. The path to get the IAM security credentials for the attached role is http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE-NAME. You don't know the role name yet, so your first step is to list the available roles by accessing http://169.254.169.254/latest/meta-data/iam/security-credentials/.

Construct the DOCTYPE portion of an XXE payload to perform this initial discovery step.

Show answer

Your payload's DOCTYPE would define an entity that uses the http:// wrapper to query the AWS metadata endpoint.

<!DOCTYPE ssrf [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/"> ]>

If successful, the application's response would contain the name of the IAM role, which you could then use to build your next payload to retrieve the actual credentials.

3. Advanced Exploitation: Blind XXE

So far, we've assumed the application helpfully includes the result of our entity processing in its response. This is called in-band XXE. In many real-world systems, the application may parse the XML and process the entity, but it won't display the result anywhere. This is known as Blind XXE.

How do we confirm the vulnerability and exfiltrate data if we can't see the output? We force the server to send the data to a system we control. This is called out-of-band (OOB) exfiltration.

Method 1: Out-of-Band Exfiltration with an External DTD

This is a powerful technique that involves a two-stage payload.

  1. The Injection Payload: The XML you send to the target application doesn't contain the full exploit. Instead, it contains a reference to a malicious Document Type Definition (DTD) file that you host on your own server (e.g., using Python's http.server or a service like Burp Collaborator).
  2. The Malicious DTD: This file contains the real payload. It defines an entity to read a local file (e.g., /etc/passwd) and then defines another entity that sends the contents of that file as part of an HTTP request back to your server.

This sounds complex, but it's a standard pattern for exploiting blind vulnerabilities. Let's watch it being done.

Learn XXE by doing hands-on challenges

This part of the 'thehackerish' video explains and demonstrates the external DTD technique for blind XXE. Seeing the setup is key to understanding the concept.

Watch from 04:19 to 06:13. Pay close attention to the two parts of the attack: the payload sent to the victim server and the contents of the malicious DTD file hosted on the attacker's server. Notice how the secret file's content arrives as an incoming HTTP request on the attacker's machine.

Method 2: Real-World Bug Bounty - Blind XXE via DNS Exfiltration

What if the server's firewall blocks outgoing HTTP requests, preventing the external DTD technique? This is where top-tier bug hunters get creative. If egress HTTP traffic is blocked, often egress DNS traffic is still allowed. We can exploit this by "smuggling" data out through DNS queries.

In this technique, the exfiltrated data (e.g., the content of /etc/passwd) is Base64-encoded and used as a subdomain in a DNS lookup to a domain you control. For example: cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaA==.your-collaborator-domain.com. Your server logs the incoming DNS query, and you can decode the subdomain to retrieve the file content.

The following video is an excellent war story from bug bounty hunter STÖK, who used this exact technique to find a $7,500 bug.

A $7.500 BUG BOUNTY Bug explained, step by step. (BLIND XXE OOB over DNS) - REDUX

This video is a step-by-step walkthrough of a real bug bounty discovery. It demonstrates finding a blind XXE in a file upload, dealing with firewalls blocking HTTP, and ultimately exfiltrating data over DNS.

Watch this video to see how a professional approaches a challenging target. 01:50 - 03:33: See how the initial blind XXE was found in a PDF file's metadata, triggering a DNS lookup to Burp Collaborator. 03:33 - 05:21: Understand the challenges of egress filtering (no HTTP out) and the clever trick of hosting the malicious DTD on the target application itself. 05:21 - 06:40: Witness the final 'DNS smuggling' technique used to exfiltrate the contents of /etc/passwd over DNS when all other methods failed.

Conclusion

In this lesson, you've moved beyond basic XXE injection and learned how to escalate it into more severe and practical attacks.

Key Takeaways:

  • XXE is a Gateway to SSRF: By changing the protocol in your entity from file:// to http://, you can force the server to make requests, allowing you to scan internal networks and query sensitive cloud metadata services.
  • Blind XXE Requires Out-of-Band Techniques: When the application doesn't reflect the output of your XXE payload, you must exfiltrate the data to a server you control.
  • External DTDs for OOB: A common method for blind XXE involves hosting a malicious DTD file that instructs the server to read a file and send its contents to your listening server via an HTTP request.
  • DNS Exfiltration is a Stealthy Alternative: When egress HTTP traffic is firewalled, you can often still exfiltrate data by encoding it and sending it as part of a DNS query to a domain you control.

Next Lesson Preview:

Today, you saw how XXE can be used to cause SSRF. This link is crucial, but SSRF is a major vulnerability class in its own right and can arise from many other sources. In our next lesson, we will perform a deep dive into Server-Side Request Forgery (SSRF) as a standalone vulnerability. You will learn to identify different types of SSRF, exploit them to access internal systems, and upgrade a basic SSRF to achieve maximum impact, including further attacks on cloud environments.

Can't find a good explanation? Sign up and we'll make it for you

Sign up