A Tale Of A DOM Based XSS In Paypal
Introduction
We have already disclosed lots of findings related to DOM Based XSS and this article talks about a pretty interesting DOM Based XSS vulnerability i found long time back inside paypal. A DOM Based xss vulnerability also known as the third type of XSS vulnerability or type 0. This vulnerability occurs due to the fact that developers don't sanitize the input before it reaches a sink. A Sink is defined as anything that generates HTML, not every sink is considered as dangerous, however there are some common sinks that should be avoided and are mentioned at DOM Based XSS wiki .
Current Situation
The situation with DOM Based xss is getting worse now a days, not only because of dynamic JS libraries such as YUI, Jquery, Jquery mobile etc, but also with programming languages such as PHP that are more natively supporting HTML 5 features. One of the aspects of a DOM Based XSS vulnerability that i discovered was with tracking scripts such as Eloqua, Sitestat, Omniture, etc as they often introduce dangerous sinks. Examples are here and here. The same is the case with sharing buttons such as google plus, addthis etc.
A Vulnerable Example from W3schools
The worsed part about DOM Based xss apart from it's complexity is the fact that lots of learning references and guides teach developers to code things in an insecure way i.e. in a way that would introduce vulnerabilities automatically. The following screenshot is taken from the jquery learning section of w3schools. The website needs no introduction, it is the most commonly referred websites for beginners to learn various programming language.
The code uses the html() function inside of jquery to output html, however the problem is that html() is not a safe jquery function and is represented as a dangerous sink as per DOM Based XSS Wiki. In case, where a user controlled input outputted through html() sink without sanitization would lead to a DOM Based xss. The html() function inside of jquery is the equivalent to the innerHTML function inside of javascript. The fundamental problem is that the developers are not advised to use a safe function. Therefore, in my opinion w3schools shall be renamed to w3fools.
The Tale Of Paypal DOM Based XSS
The financing.paypal.com subdomain was a subject of DOM Based xss vulnerability. The subdomain had a feature which triggered my interest, which allowed the users to create ad units of different sizes. The size of the ad was being handled on the client side with the help of jquery.
Example
https://financing.paypal.com/ppfinportal/adGenerator/webCopy?460 * 80
The above input would display "460 * 80" in front of the Selected Size Option, Changing the text with our own input would result in the same text being outputted on to the screen. This means that our input that is taken from a source is being passed through a sink to be displayed upon the screen. So, what happens if we change the input with our XSS payload, for example - <svg/onload=prompt(1)>.
https://financing.paypal.com/ppfinportal/adGenerator/webCopy?<svg/onload=prompt(1)>
Unfortunately, the results were returned URL encoded. Now there could be two possibilities, whether the javascript is encoding our input before rendering it on the screen or it's a general browser behaviour. Turns out that Google Chrome and Firefox browsers encode everything sent after ?, but what about Internet explorer?, Internet explorer returns the characters as URL unencoded and therefore, we inside of internet explorer we are able to render our javascript.
With that being said, as per DOM Based XSS wiki google chrome does not encode certain characters when passed after a hash. Therefore, we could add an additional hash after the ? mark to get our payload executed.
Example
https://financing.paypal.com/ppfinportal/adGenerator/webCopy?#<svg/onload=prompt(1)>
Vulnerable Code
With some debugging i was able to determine the exact cause of the vulnerability. The following screenshot highlights the line of code that was responsible for the cause of this vulnerability.
The line 517 represents the source being document.url, a split function is called which splits everything being sent after the ? mark and saves it inside a variable called url.
Example
The split function would return <svg/onload=prompt(1)> from the url and then is saved inside a variable called url. Next inside the 521 line we can see that html() function is used to output url variable, which in this case contains our xss paylaod. The payload would be outputted to the screen and hence would execute the javascript for us.
Conclusion
DOM Based XSS are growing and would continue to grow as more and more people would start using dynamic javascript libraries and as more people more towards server side javascript i.e. node js, the impact would be much more high. This article demonstrates the importance of sanitizing the user supplied input not only on the server side but also on the client side.