JSONP
JSONP is vulnerable to malicious code being substituted for the innocent function call by the data source. These days, a lot of API providers accept JSONP requests. This is due, in part, to the fact that while utilizing basic Ajax, the majority of web browsers prohibit cross-domain requests.
We will cover the following:
- What is JSONP?
- Implementing JSONP
- Functionality of JSONP
- Script Element Injection
- Security Concerns of JSONP
What is JSONP?
JSONP, often known as JSON-P (JSON with Padding), is a traditional JavaScript method for requesting data by loading an <script> element that is designed to load regular JavaScript.
George Jempty proposed that JSON be given an optional variable assignment in July 2005. Many Web 2.0 applications, including Dojo Toolkit, Google Web Toolkit, and Web services, use JSONP, which appears to have been first proposed by Bob Ippolito in December 2005 and where the padding is a callback function.
JSONP allows sharing data without adhering to the same-origin policy, which forbids JavaScript code from running on a website to read media DOM elements or XMLHttpRequest data acquired from a site other than the page's original. A URI scheme, hostname, and port number combination serve to identify the originating site.
The data can be obtained from the server using the XMLHttpRequest(XHR) method. The browser can use the JSON.parse() method to transform the JSON string that has been received into a JavaScript object once the data has been received. However, XHR has a same-origin security problem.
This implies that if you request a page from ADomain.com, and that page subsequently sends an XMLHttpRequest to get data from BDomain.com, the browser will reject the request.
This is because the request was sent to a different domain than the one that was used to deliver the page. The data from the XMLHttpRequest will only be returned if it is sent to ADomain.com because XHR only functions when the request is sent to the same domain.
Implementing JSONP
- Include the script tag when writing HTML code. This script tag's source will be the URL where the data will be fetched. The callback function can be specified through the web services. Add the callback argument as the final URL component.
- When a script element is encountered, the browser issues an HTTP request to the source URL.
- The server returns the response in the form of JSON enclosed in a function call.
- The browser parses the JSON response, which is a string and transforms it into a JavaScript object. The callback function is then invoked with the generated object.
Functionality of JSONP
The HTML element can typically run JavaScript code that has been downloaded from outside sources. However, before the implementation of CORS (Cross-origin resource sharing), services responding with pure JSON data were unable to communicate data from foreign origins.
For instance, a request to the foreign service http://server.example.com/Users/123 might result in a JSON-formatted record for a person named Joe. The object syntax of JavaScript is the same as that of JSON.
{
"name": "Joe",
"id": 123,
"rank": 9
}
Any attempt to use the data across domains without CORS support ends in a JavaScript error.
<script type="application/javascript" src="https://api.server.com/users/123">
</script>
The browser will download the <script> file, inspect its information, interpret the unprocessed JSON data as a block, and then raise a syntax error.
Even if the data were interpreted as a JavaScript object literal, JavaScript running in the browser would not be able to access it since object literals are unavailable without a variable assignment.
In the JSONP usage pattern, the URL request indicated by the script element's src attribute delivers JSON data that has been wrapped in JavaScript code (often a function call). The browser then decodes this "wrapped payload."
In this manner, the JSON data can be modified by a previously specified function in the JavaScript environment.
The "P" in JSONP—the "padding" or "prefix" that surrounds the pure JSON—is the function call to parseResponse(). A server must respond with a response that contains the JSONP function for JSONP to function. JSON-formatted results cannot be used with JSONP.
The client and the server must agree on the JSONP function invocation sent back and the payload the function receives.
According to tradition, the server that hosts the JSON data offers the website that requests to name the JSONP function, generally using the name jsonp or callback as the named query-string parameter:
The received payload in this instance would be:
parseResponse({"name": "Joe", "id": 123, "rank": 9});
Script Element Injection
Only when combined with a script element does JSONP make sense. The browser must add a new <script> element or reuse an old one for each new JSONP request. Script element injection is the process of inserting a new script element using dynamic DOM modification.
The <script> element is added to the HTML DOM, and its "source" property is set to the URL of the desired JSONP endpoint. A JavaScript utility library often does this dynamic script element injection. There are JSONP helper methods in jQuery and other frameworks, as well as independent choices.
This is an example of how to dynamically inject a script element for a JSONP call using jQuery:
$.getScript("https://api.server.com/users/192.168.73.96?callback=parseResponse");
The element is evaluated by the browser after injection, and the browser then executes an HTTP GET on the src URL to retrieve the content. The reply payload is then assessed by the browser as JavaScript.
Usually, a function invocation looks like this. Using script element injection, JSONP can enable browser sites to circumvent the same-origin restriction.
The script is still subject to cross-domain restrictions about the domain of the including page even though it executes within the scope of the including page.
This means that while a web page might utilize a library located on another site to load it using JSONP and then send XMLHttpRequest queries to that site, it was not possible to do the opposite.
Security Concerns of JSONP
Untrusted Third-party Code
Any content from external servers can be injected into a website by including script components from such remote servers. The page served from the original server is at a higher risk if the remote servers are vulnerable and allow JavaScript injection.
When an attacker injects JavaScript into the original web page, the code can access JavaScript from any domain, circumventing the same-origin requirement. Websites can inform browsers of the domains from which scripts may be inserted by using the Content Security Policy HTTP Header.
Whitespace Differences
JSONP has the same issues as resolving JSON with eval() since they both read JSON content as JavaScript and handle U+2028 (Line Separator) and U+2029 (Paragraph Separator) differently from JSON. As a result, some JSON strings cannot be used in JSONP; to transmit JSONP, these characters must be escaped.
Attack using Reflected File Download and Callback Name Manipulation
As seen in the reflected file download (RFD) attack from 2014, unsanitized callback names can be used to provide malicious content to clients while getting around the limitations imposed by the application/json content type. Malicious data can also be inserted into insecure JSONP endpoints.
Cross-site Request Forgery
JSONP implementations made hastily are vulnerable to cross-site request forgery (CSRF or XSRF) attacks. Because the same-origin principle in web browser implementations is not respected by the HTML script element, a malicious page can request and acquire JSON data that belongs to another website.
If the user is currently signed into the other website, this will enable the JSON-encoded data to be examined in the context of the malicious page, potentially revealing passwords or other sensitive information.
Rosetta Flash
Rosetta Flash is a method of exploitation that enables an attacker to take advantage of servers with weak JSONP endpoints by tricking Adobe Flash Player into thinking that a Flash applet specified by the attacker originated on the vulnerable server.
The same-origin policy is implemented by Flash Player, allowing users to submit requests (using cookies) and receive responses from the hosting website. The data can then be sent back to the attacker through the applet.
Summary
By utilizing the element's nature, JSON with Padding, or JSONP for short, enables developers to get around the same-origin restriction imposed by browsers. The policy forbids reading any responses supplied by websites with a different ancestry than the one being utilized right now. The policy, incidentally, permits sending a request but not reading one.
Explore:
Monitor Your JavaScript Applications with Atatus
Atatus keeps track of your JavaScript application to give you a complete picture of your clients' end-user experience. You can determine the source of delayed load times, route changes, and other issues by identifying frontend performance bottlenecks for each page request.
To make bug fixing easier, every JavaScript error is captured with a full stack trace and the specific line of source code marked. To assist you in resolving the JavaScript error, look at the user activities, console logs, and all JavaScript events that occurred at the moment. Email, Slack, PagerDuty, or webhooks can send error and exception alerts.