The JSON vs. XML wars are brutal like trying to till a rough patch of land that returns no gain. Understanding the security considerations of both is like a green pasture providing a fruitful harvest of knowledge.

The age-old question of which is better between XML and JSON has been a hot topic on the Internet as JSON has risen in prevalence. JSON has been relevant since its adoption in popular web services in the mid-2000s. XML, is older, having been around since 1998 when the World Wide Web Consortium (W3C) officially recommended it.

XML and JSON are both universal formats for arbitrary data sharing between computer architectures and programs, but there are a number of differences between them. These differences have motivated blog posts and other documents on the Internet comparing the two, and a compilation of even a couple of these resources would cover most of their functional advantages and disadvantages. However, in my research I haven’t seen a comprehensive comparison of the two standards that addresses the security considerations of using one or the other, and these are important for any developer trying to minimize a web API’s attack surface. Hence, the purpose of this blog is to gather this information into one place so XML or JSON developers can understand the functional reasons to choose one over the other in addition to the security precautions that they should take with either choice.

Before I dive into the security aspects, it’s important to know the functional differences between XML and JSON. If you’re already familiar with these, it may be useful to skip to the Security section.

Similarities

Before diving into their differences, it’s important to first summarize what XML and JSON have in common:

1. Both are widely used data sharing standards with publicly available documentation.

https://tools.ietf.org/html/rfc4825 (XML)

https://tools.ietf.org/html/rfc7159 (JSON)

2. Both are self-describing and human-readable: self-describing in that they are represented as a hierarchical tree of metadata, and human-readable in that the data itself is ASCII and Unicode characters.

3. Libraries for working with both exist for many programming languages, including JavaScript, Python, Perl, Ruby, and more.

4. Client JavaScript code may access responses in both languages through asynchronous requests with the XMLHttpRequest object, despite its name.

Simplicity and Parsing

In terms of simplicity and parsing speed, JSON has the advantage in most cases. Its syntax is usually less verbose because XML requires beginning and end tags for each branch of the data tree while JSON represents data in arrays with name/value pairs. Examples of both representations of the same data are shown below.

XML (174 characters)

<document id="1" name="test">

<dimensions>

<width>10</width>

<height>15</height>

</dimensions>

<objects>

<object id="1">

<object id="2">

</objects>

<window onclick="openDoc()" />

</document>

JSON (155 characters)

{"document": {

"id": "1",

"name": "test",

"dimensions": {

"width": "10",

"height": "15"

}

"objects": {

"object": [

{"id"= "1"},

{"id"= "2"}

]

}

"window": {

"onclick":"openDoc()"

}

}}

Due to syntax differences, programs can usually parse JSON faster than XML. This is not only because JSON generally uses fewer characters, but because its syntax better matches object-oriented languages’ data structures, especially JavaScript. These languages have libraries for parsing both JSON and XML, but generally there’s a standard minimal JSON parser that’s more intuitive than the XML counterpart(s). The official JSON site summarizes JSON’s advantages. Some other resources that favor JSON are a Cloud Elements blog and a w3schools page.

Extensibility

The reason JSON is usually simpler and faster is because it has limited support for data types, i.e., only strings and numbers that can be organized into arrays. This standardizes how it can be parsed, but it also restricts the flexibility of what types of documents the receiving program can parse. There are number of advantages to XML’s complexity:

1. XML’s user-defined elements make it a better option for more complicated documents that include images, charts, or other non-primitive types.

2. XML gives the ability for the user to set metadata within a specific data’s tag in the form of attributes, for example, <document id="1" name="test"> in the code above, and this could help a developer better organize the information.

3. XML allows resolving name collisions through namespaces, which may be useful for client programs that need two variables of the same name in different scopes. w3schools provides a summary of namespaces and how to implement them.

4. XML documents can be validated using a Schema document that the XML document references as it is transferred from server to server. The parser uses the schema to validate the structure of the XML data to make sure it maintains a specific syntax. An example can found here.

5. There are some powerful tools for reading and writing to XML documents, including XPath for querying nodes or values and XSL for modifying and displaying documents.

Here is a blog defending XML that summarizes these advantages.

Security

As shown in the previous sections, many blogs and articles address the XML vs. JSON debate, and the opinions vary from favoring one over the other to a neutral stance. I, too, would take a neutral stance because, in terms of functionality, one is not necessarily better than the other; they both are a better fit for different data transfers.

However, the security aspects of using one or the other is often ignored, but they are incredibly important because, unlike functional inefficiencies, insecure implementations can lead to the exploitation of a system. Both XML and JSON parsers have security considerations of which developers should be aware.

XML

There are a number of security issues involved in the configuration of XML parsers and how they interact with the document structure, and these need to be addressed in order to properly secure an application that is utilizing XML.

XML External Entity Injection (XXE)

XXE arises when an application resolves arbitrary external entities defined in an XML document. External entities are like macros that expand to a local or remote resource through a system identifier. This identifier is assumed to be a URL that the XML parser processes, and then all instances of the external entity within the XML document are replaced with the contents of the external resource. An attacker can exploit this to obtain sensitive data on the application’s machine or perform remote code execution. Here’s a classic XXE example:

<?xml version="1.0" ?>

<!DOCTYPE foo [

<!ELEMENT foo ANY>

<!ENTITY xxe SYSTEM "file:///etc/passwd" >]

<credentials>

<user>&xxe;</user>

<pass>somevalue</pass>

</credentials>

Here the attacker has modified the XML document to include an external entity referencing the local machine’s /etc/passwd file. If the server allows unrestricted external entity expansion, the contents of this file could be reflected any server response derived from the XML input, and the attacker would obtain user information from the server.

The external entity could also reference URLs as a way to bypass firewall restrictions that permit access from the exploited server but not from an outside address. The attacker could then potentially access privileged information through HTTP GET responses that are reflected in the webpage UI. OWASP gives a more in-depth explanation of XXE with more attack examples.

Another area of XXE attacks is resource exhaustion, which can utilize a couple different payloads, including generic and recursive entity expansion. In these attack payloads, a large number of external entities are declared that reference each other, and when the server is forced to evaluate all of them, it runs out of memory and crashes. This attack is also called an “XML Bomb”. A ws-attacks wiki article summarizes these attacks.

Similarly, the attacker may be able to carry out a remote code execution using the PHP expect module, but the server must have this module loaded, and this type of XXE occurs rarely. The OWASP vulnerability page mentioned above also includes an example for this attack.

Remediation: XXE attacks can be prevented by simply disabling external entity substitution or expansion. The terminology can vary with each XML parser, and further, disabling DTDs entirely is the safest option. The problem is external entity expansion is often enabled by default, but is rarely necessary for legitimate functionality. OWASP provides a guide for XXE prevention.

XML DTD Validation

Another vulnerability that can be exploited in the default configuration of XML parsers is the validation against untrusted external DTD (Document Type Declaration) files. The DTD of an XML document is one way to define the valid structure of the document, i.e., rules for what elements and values are allowed. These rules can be implemented internally within the document’s DTD, or can be loaded externally by referencing a file or URL. An example external declaration would look like this:

<!DOCTYPE foo SYSTEM "http://www.example.com/schema.dtd">

<foo>

...

</foo>

A security problem arises if the server’s XML parser accepts an arbitrary external DTD URL and attempts to download the DTD and validate the XML document against it. In this case, an attacker could input any URL and execute a Server Side Request Forgery (SSRF) attack where the attacker forces the server to make a request to the target URL. The server may have privileges to access certain resources that the attacker doesn’t, and the attacker can leverage this to scan and attack services behind the server’s firewall. A summary of SSRF can be found here.

Remediation: Disabling DTDs completely (i.e., as in a non-validating XML parser) would mitigate this vulnerability.

JSON

As a simple data format with no document-based configurations, merely parsing a JSON document is not open to security misconfiguration. However, given that JSON is designed to be a subset of JavaScript, it is tempting to parse a JSON document by simply passing it to a JavaScript engine (e.g., the eval method). Certain implementations of JSON exchanges in JavaScript work this way and can open up an application to vulnerabilities, e.g., through JSONP.

JSONP

JSONP was developed as a way for developers to exchange JSON data across different domains outside the restrictions of the Same-Origin Policy. It’s simply a modified version of a JSON data exchange where the target URL is stored in a src attribute within <script> tags, and the JSON data being accessed is passed to a JavaScript callback function. Because browsers evaluate JavaScript in the context of where it is embedded, the JSONP request that is downloaded and executed by the client is not restricted from interacting with the calling page by the Same-Origin Policy. For information on the Same-Origin Policy, there are many resources on the Internet, e.g., here.

The following illustrates a JSONP exchange.

A webpage could use the following to make a JSONP request to a resource on another server, example.com:

<script

type="application/javascript"

src="http://example.com/someFile?callback=someFunc">

</script>

The client visiting this page would receive a response with a JSON-wrapped function like the one shown below. The function then executes with the JSON data as input. For the exchange to function properly, the receiving server must be configured with a JSONP API to send this response.

someFunc({"name": "foo", "id": 1});

JSONP is dangerous because it allows cross-origin exchanges of data. If “example.com” were compromised, the attacker could send arbitrary JavaScript code to execute in the context of the page holding the <script> tag, rather than a callback function and JSON document.

Another exploit would be a Cross-Site Request Forgery (CSRF) attack. An attacker could trick a victim into visiting a malicious webpage that creates a JSONP request to a third-party site utilizing a JSONP API. Depending on the request and the requested data, the server may respond with sensitive JSON data (e.g., usernames, passwords, credit card information, etc.) that would be disclosed to the attacker. For this CSRF attack to succeed, the JSONP server endpoint would need to use cookies for authentication and not implement CSRF protection (e.g., CSRF tokens).

It’s important to note that JSONP is a security risk that developers must choose to take by implementing its functionality. Unlike the XML issues, this is not the default behavior of JSON web exchanges.

TL;DR

In terms of functionality, XML and JSON are similar in a lot of ways, and their differences provide advantages depending on the context of the application’s data types. Overall, one is not better than the other. In regard to security, processing untrusted Internet-facing requests is one of the most basic functions of an XML or JSON parser. Unfortunately, common XML parsers are not suitable for this purpose in their default configuration; only with hardening to disable external entity expansion and external DTD validation are they safe. Conversely, JSON parsing is almost always safe, so long as the programmer uses modern techniques rather than JSONP. As long as web developers are aware of these security risks and take the steps to defend against them, either option is completely viable in the current web environment.