While this all sounds perfectly innocent, it easily becomes a security vulnerability when you remember that it is often sensitive data that is passed between domains, for example session tokens, and since it is abusing the behavior of the Same Origin Policy there is no built in or standardized security mechanism which may be used to ensure the receiving domain is the intended one.
Depending on the exact usage of JSONP, the vulnerability may result in sensitive information disclosure, Cross Site Scripting, Cross Site Request Forgery, only Reflected File Download. I have most often seen JSONP being used to implement a Single Sign On system, therefore if sufficient validation of the receiving domain is not performed exploitation results in session hijacking or account take over.
In the simplest instance, no validation is performed an exploitation is as simple as including the script from the sending domain within the attacker’s site and persuading a user of the sending application to visit the attacker’s site.
However there are more complex instances where the web developer has attempted to prevent the data being passed to malicious domains. This can take a variety of forms but is often incomplete whether on the client side or the server side.
Anonymous Case Study
The server side validation consisted of a check of the requesting domain against a Regular Expression, however as is often the case the developers overlooked the fact that “.” in Regular Expressions is a wild card. Therefore although the developer only intended to allow “www.somedomain.co.uk” the wild card meant that “wwwXsomedomainXcoXuk” would pass validation (I also identified that any subdomain was allowed i.e “XXXX.wwwXsomedomainXcoXuk”) – however remember it also had to be a valid domain, so the final dot needed to be an actual dot – obviously there were many domains that could be registered to meet these requirements.
The client side validation was significantly more unusual, it consisted of a CRC32 hash of the document.domain and comparing it to a list of approved values. However due to the limited size of the hash (32 bits) it is a mathematical certainty that multiple domains exist that would result in the same hash and therefore pass validation.
In order to exploit this usage of JSONP
I needed to pass both the server and client side validation. To do this I decided to write a Python script to iterate through all the permutations that would pass the Regular Expression in order to identify one that would also pass the CRC32 validation. (Unfortunately this script cannot be released at this time, but I hope to share it in the future as it could be useful to others).
It took over 1.6 billion permutations, but I eventually identified a valid domain and was able register it and exploit the flawed JSONP validation to hijack a user’s session.
JSONP should no longer be used as HTML5 features like CORS and PostMessage are available with well defined security mechanisms, however these also require careful validation of the “origin” to prevent the data being passed to unauthorised domains.
As always, if you have any comments or suggestions please feel free to get in touch.