What is a JSON Injection?

JSON (JavaScript Object Notation) is an open standard data interchange format used to communicate between applications. JSON is similar to XML but easier to read than XML due to its highly lightweight nature (small file size).

JSON was derived from JavaScript—the programming language of the Web and the world’s most popular. This makes it the preferable data interchange format on the internet. Even though it closely resembles JavaScript object literal syntax, it can be used independently from JavaScript, and many programming environments feature the ability to read (parse) and generate JSON.

JSON exists as a string—useful when you want to transmit data across a network. However, it needs to be converted to a native JavaScript object when you want to access the data. JavaScript provides a global JSON object with methods available for converting a native object to a string (serialization) and converting a string to a native object (deserialization). A JSON string can be stored in its own file—which is basically just a text file with an extension of .json, and a MIME type of application/json—which is basically an extension to the internet email protocol that allows its users to exchange different kinds of data such as images, audio, and video files over the internet.

Many web applications use it to store important information and communicate with each other. JSON is often treated like cached data when used to store data and may potentially contain sensitive information. JSON is often used in conjunction with RESTful APIs and AJAX applications to transmit sensitive information such as authentication credentials when used to send messages.

The widespread use of JSON in web applications makes it a target for malicious activities. JSON alone is not much of a threat. After all, it’s only a data-interchange format. The real security concerns with JSON arise in the way that it is used. If misused, JSON-based applications can become vulnerable to attacks such as  JSON hijacking and JSON injection. This article will discuss everything about JSON injection attacks, including how to detect and prevent them.

JSON object format
Figure 1.0 | A visual representation of JSON object format—an unordered set of name/value pairs | Image Credit: json.org

What is JSON Injection Attack, and How Does it Work?

Injection attacks in web applications are cyber attacks that seek to inject malicious code into an application to alter its normal execution. Injection attacks can lead to loss of data, modification of data, and denial of service. As a result, it is listed as the number one web application security risk in the OWASP Top 10.

JSON injection is a typical example of an injection attack, although it’s not as common and dangerous as the other form of injection attack, such as SQL Injection. The semantics of JSON documents and output messages can be significantly altered if an application constructs JSON from untrusted or unvalidated input. An attacker may take advantage of the loophole to insert malicious codes that can change the program’s normal execution. In some cases, JSON injection can lead to Cross-Site Scripting or Dynamic Code Evaluation.

JSON has traditionally been parsed using an eval() function, but this is an insecure practice. Any code that uses eval() to deserialize the JSON into a JavaScript object is open to JSON injection attacks.

JSON injection occurs when:

  • Data from an untrusted source is not sanitized by the server and written directly to a JSON stream. This is referred to as server-side JSON injection.
  • Data from an untrusted source is not sanitized and parsed directly using the JavaScript eval function. This is referred to as client-side JSON injection.

In order to demonstrate how a server-side JSON injection attack works, let’s consider a web application that accepts username and password input from users without sanitization. The data supplied by the user (username, password and account type) is stored on the server side as a JSON string. The JSON string is formed using simple concatenation as shown in the code below:

$json_string = '{"Account":"user","Username":"'.$_GET['username'].'","Password":"'.$_GET['password'].'"}';

Since the application is not sanitizing the input data, a malicious user decided to append unexpected data to their username: richard%22,%22Account%22:%22administrator%22.

Consequently, the resultant JSON string becomes:

{

"Account":"user",

"Username":"richard",

"Account":"administrator",

"Password":"R1ch@rd24Z"

}

When reading (parsing) the stored string, the JSON parser (json_decode) encounters two account entries (user account and administrator account). So it takes the last one (administrator account), thereby granting Richard administrator privileges on the server. In other words, the user “Richard” has successfully elevated his account privileges to the level of an administrator using a JSON injection attack.

On the other hand, to demonstrate how a client-side JSON injection attack works, let’s consider another web application that displays users’ profiles when their profile picture is clicked. The application allows users to update their highest qualification and grade, but it does not sanitize the user-supplied data.

When the URL: https://userprofile.com/api/users/update/profiledata.json is fetched, the following response is displayed:

{

"qualification": "BSc",

"grade": "First Class."

}

The data is then parsed (read) and inserted using the following JSON eval () function:

var data = eval("(" + resp + ")");

document.getElementById("#qualification").innerText = data.qualification;

document.getElementById("#grade").innerText = data.grade;

Now, if a malicious actor decides to inject a malicious code such as:

Distinction."});alert(1);({"qualification":"MSc","grade":"Distinction”.

This becomes the argument for the eval () function, and when the eval () function executes the code, the following output is displayed:

{

"qualification": "MSc",

"grade": "First Class."});alert(1);({"qualification":"MSc","grade":"Distinction."

}

In other words, the malicious actor successfully manipulated or altered the normal execution of the application using JSON injection. This was possible because input data from users (untrusted source) was not sanitized but parsed directly using the JavaScript eval () function.

What can an Attacker do if Your Application is Vulnerable?

The primary objective of information security efforts is to protect the confidentiality, integrity, and availability of data. Confidentiality means that data is protected from unauthorized viewing or access.  Integrity means that information is protected from unauthorized modification to ensure that it is reliable and accurate. Finally, availability means that authorized users have access to the systems and the resources they need.

Suppose a web application is vulnerable to JSON injection attacks. An attacker can exploit the vulnerability to compromise the application or data’s confidentiality, integrity, and availability. For example, the attacker can compromise the system’s confidentiality by gaining unauthorized access to the application data and stealing sensitive application data. Attackers may also use JSON injection to compromise the integrity of the application and output data by altering the semantics of JSON documents and messages and manipulating business-critical values within the  JSON document or request. Worse yet, an attacker may use JSON injection to gain complete control of the application and make it unavailable to users (denial of service attack).

How Can You Test and Detect JSON Injection Vulnerabilities?

Standard security testing techniques can be utilized to test and detect JSON injection vulnerabilities in web applications. Some of the popular testing techniques that can be used include:

  • Static Application Security Testing (SAST): SAST is used to secure applications by reviewing the source code when it’s not running to identify vulnerabilities or evidence of known insecure practices. SAST tools employ a white-box testing strategy that scans the source code of applications and their components to identify potential security flaws.
  • Dynamic Application Security Testing (DAST): DAST tools communicate with applications through the front-end to identify potential security vulnerabilities. DAST tools do not have access to source codes; instead, they perform actual attacks using the black-box strategy to detect vulnerabilities. With dynamic analysis, security checks are performed while running or executing the code or application under review. A technique known as fuzzing is used in dynamic tests to submit random, malformed data as inputs to the application to determine if it will uncover directory traversal flaws.
  • Interactive Application Security Testing (IAST): IAST combines the best of SAST and DAST. It analyzes code for security vulnerabilities while the app is run by any activity interacting with the application functionality.

With the techniques described above, you can quickly test and detect injection vulnerabilities in your web applications. However, this may require the services of a skilled pen tester. Web vulnerability scanners such as Veracode, Checkmarx, Invicti, Acunetix, and others are an effective way to check whether your website and web applications are vulnerable to JSON injection attacks. They implement most of the web application testing techniques discussed above and allow you to apply those techniques to scan your web application for vulnerabilities. A web vulnerability scanner crawls your entire website or application and automatically checks for injection vulnerabilities and other security issues. It will then generate a report on the vulnerabilities found and attempt to fix them automatically.

How Can You Prevent JSON Injection Attacks?

As with most injection vulnerabilities, the key to securing your web application and preventing JSON injection attacks is to adhere to secure coding practices. For example, a user input scenario to be mindful of in your business-critical applications is one in which your application accepts input from users and uses that input to create output for other users. This is where the golden rules of user input come to play. The first golden rule of user input states that all information is suspicious until proven otherwise. The second golden rule of user input says that data must be validated as it crosses the boundary between untrusted and trusted domains. The moment you neglect these rules, you open the door for all kinds of injection attacks.

By definition, trusted data is data you or an entity you explicitly trust has complete control over; untrusted data refers to everything else. The point here is: never trust user input. If you must accept one, ensure they get sanitized before you allow them. This means checking the type of data you’re receiving and removing unnecessary characters and allowing only those needed. This applies to both server-side and client-side JSON injections.

To prevent server-side JSON injections, sanitize all data before serializing it to JSON. For those using Java, an excellent option to sanitize JSON data is to use the OWASP JSON Sanitizer. The best method to prevent client-side JSON injections is never to use the JavaScript eval function to evaluate JSON data. This can lead to serious security problems when you have malicious code as the argument of eval. If you use the eval function and have malicious JavaScript code as the argument of eval, that code will be executed, creating severe security problems. To avoid this, use JSON.parse. The JSON.parse method won’t parse JSON strings with functions or malicious codes in them.

You can also implement Content Security Policy (CSP)—an added layer of security that helps prevent injection attacks resulting from the execution of malicious content in the trusted web page context. For example, CSP, by default, prevents the use of the eval function in an application. Other ways to avoid JSON injection attacks are as follows:

  • Declare charset when outputting the content type for JSON responses. Most frameworks implement this feature already.
  • Avoid manually reading and writing JSON-based applications; instead, use the framework.
  • Design your application to handle all kinds of exceptions. An unhandled exception may cause unexpected behavior, and an attacker may exploit it. An alternative approach to exception handling is error checking and input validation.
  • Remember to properly escape both ” and \ in user data before putting it in JSON, or just use JSON.parse, so as not to give room to malicious actors.
  • Avoid the use of sequential numbers for resource identifiers. Instead, use UUID/GUID.