In this article, we'll address the subject of Vue XML external entities injection. Our goal is to offer you a solid foundation to understand and mitigate XML external entity injection vulnerabilities in Vue and NodeJS. Additionally, we want to help you prepare to implement solutions in your projects.
It's important to note that we'll be providing mitigation strategies for NodeJS since the bulk of vulnerabilities lie in the back end of applications.
We'll first explain what XML is. Then, we'll give you some basic examples of XML external entity injection vulnerabilities and exploits. Finally, we'll provide you with strategies and mechanisms to prevent this exploit from affecting your application.
It goes without saying, but this article might not be for you if you don't have any experience with Vue. If you just want to know what XML external entity injections are, we recommend you go to our in-depth article about it here. Additionally, if you just want to learn about the basics of Vue, you might want to spend some time here.
Explaining XML
XML (extensible markup language) is a markup language for storing, transmitting, and reconstructing data. This language defines rules for encoding documents in both human-readable and machine-readable formats.
But wait—why does a markup language represent a threat to your systems?
The truth is that we make use of this language everywhere to process data in a convenient and human-readable way. Additionally, most XML processing tools in use allow for the specification of what is known as an external entity.
This entity, commonly a URI, is retrieved and processed during the parsing of the XML file. This prompts the parser to request and include the content inside the XML document. And, as you might've guessed, this is a window into trouble.
XML external entity injections, also known as XXE injections, are attacks that target XML parsing vulnerabilities. And, given that most systems that use XML parsing functionalities that face the user are potentially vulnerable, they can allow a bad actor to access files and resources on the server.
Given that a determined bad actor could use this entity as an avenue to retrieve any resource in the server, this vulnerability could be devastating for our security. All that's needed is a sufficient understanding of server structures and information about the technology stack in use.
Examples of XML External Entity Injection Vulnerabilities
The biggest threat offered by XXE injection is its simplicity.
Most developers won't be able to spot the dangerous code. Many won't even see danger at all, even when it's right in front of them.
So, to prevent that, let's see some common examples.
This XML document contains just one username element.
<?xml version="1.0" encoding="ISO-8859-1"?>
<username>Michael</username>
</xml>
Nothing scary here, right? Well, we haven't added any external entity yet.
OK, how do we add an external entity?
Simple. External entities are simple XML tags that use a system identifier within a DOCTYPE header.
This header works by adding more properties to the XML file structure itself. This would be, for example, a URL referencing another XML file containing additional data—nothing complex.
But what if we take advantage of this feature to retrieve something we shouldn't? For example, the following code containing an external XML entity fetches the content of /privates.txt and displays it.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///privates.txt" >]>
<username>&xxe;</username>
</xml>
Yikes.
It's painfully clear that this is a potentially catastrophic vulnerability since these entities can access local or remote content within our server.
This is particularly awful if you make the mistake of keeping sensitive files on your server. Essentially, this would eventually provide a path to a hostile takeover of your whole platform.
Incidentally, XML external entity injection attacks can also access local resources that may return data in a loop, impacting application availability and leading to a kind of denial of service attack.
Now, if you're paying attention, this is when you should be freaking out and start advocating for disabling XML file processing altogether.
But don't be so hasty. There are still steps that we can take to mitigate this vulnerability.
Mitigating XML External Entity Injection Vulnerabilities
Now that you've calmed yourself a little bit, let's explore how to prevent your systems from falling victim to these attacks so you can keep your job.
First and foremost, mitigating XXE injection attacks is actually quite simple—sorry for the fearmongering.
Assuming that you need the functionality for loading user-provided XML files, as long as you're not deliberately attempting to open a back door for exploits, most libraries do a decent job protecting your application.
The general approach to prevent this exploit is not to use libraries that support entity replacement like LibXML. And, if you have to, disable the feature altogether.
Working on the Code
Now, this mainly concerns the back end of your application. In our case, this is NodeJS, but if you're parsing XML in the front end for any specific purpose, avoid using libraries that support entity replacement.
As we've mentioned in our NodeJS article about the subject, "Sadly, NodeJS does not have a built-in XML parsing engine, so, likely, you might already be using this library in your project. But no fret; entity replacement is disabled by default."
Nevertheless, we recommend that you explicitly disable this feature in your project.
You can do this by simply changing all initializations of the library like so.
const lib = libxmljs.parseXml(xml, {noent: true});
Luckily, the latest versions of LibXML make it tough to allow entity replacement on purpose. Nevertheless, we want you to know that regardless of your approach, you may still be vulnerable to a DoS attack when using LibXML in this way.
Now, if you absolutely have to have this feature, you can still minimize the potential for exploits by safe-listing the external entities you allow.
app.post('/load_xml', upload.single('xml'), async function (req, res) {
if (!req.file) {
res.sendStatus(500); return;
}
try {
const xml = req.file.buffer; const doc = libxmljs.parseXml(xml, {noent: true});
if (doc.text().includes("<!ENTITY")) {
throw new Error("INVALID XML FILE");
}
res.send(doc.text());
} catch (err) {
res.send(err.toString()); res.sendStatus(500);
}
});
By simply checking the XML document before parsing it with our library for any strings containing any "ENTITY" not in our list, we can provide a minimum level of security to our application.
Surefire Solution
The last thing I want to leave you with is that the best approach to security is not to have a door open in the first place.
Do not parse XML unless it's an application requirement. Despite the convenience that it might offer, there are numerous ways to provide equivalent functionalities without opening yourself to these vulnerabilities.
What's Next?
It should go without saying that protecting our platforms against the exploits of bad actors requires an expansive knowledge of the technology and infrastructure in use.
Nevertheless, if you're in charge of a highly productive team with many responsibilities and pressure on your hands, it's essential to do your best to offer them the tools and mechanisms to perform their best. That's not an easy task.
Luckily, we've developed the ideal solution for you.
Our dynamic application security testing solution is a fantastic and powerful solution that empowers teams focused on delivering the best solutions on the web while protecting your users.
You can check it out here.
This post was written by Juan Reyes. Juan is an engineer by profession and a dreamer by heart who crossed the seas to reach Japan following the promise of opportunity and challenge. While trying to find himself and build a meaningful life in the east, Juan borrows wisdom from his experiences as an entrepreneur, artist, hustler, father figure, husband, and friend to start writing about passion, meaning, self-development, leadership, relationships, and mental health. His many years of struggle and self-discovery have inspired him and drive to embark on a journey for wisdom.