Sunday, November 29, 2015

on* Landing Point

In this post, I will demonstrate different ways of XSSing or how can we XSSed a web application if user-supplied input (or input from any third-party application) reflects back as a part of any eventhandler(s) with the help of a real example(s).  Please open the following URL. The harmless probe string ("xxxxxxxx'yyyyy</img) is part of URL's GET parameter i.e., searchword


The screen-shot given below shows the reflection of our interest i.e., on*. In this particular case, the input reflects back as a part of onblur. At the same time, you will see another reflection of probe string in the screen-shot as a part of value attribute of an <input> tag. This is also a vulnerable end-point (" in use for holding the value of value attribute and " from the probe string are not filtered) but we will not discuss this.  


As I mentioned in the screen-shot that developers're using " (double quote) for holding the value of onblur while (single quote) are in use for holding the probe string or user-supplied input. It is also clear from the screen-shot that " and ' that're part of probe string ("xxxxxxxx'yyyyy</img) are not filtered and can be seen in hard-coded form though developers're filtering everything after < sign. For us it is enough information that " and ' are not filtered.   Lets start XSSing with a simple case i.e., "onmouseover="confirm(1)//. Please keep in mind that " were not filtered and the attack payload starts with " which breaks the context (i.e., two in this case: onblur and value attribute) The URL looks like the following and screen-shot shows XSS ...



Now assume double quotes (") are filtered and we can not break the context with "onmouseover="confirm(1)// so what other options do we have.  Please keep in mind the reflection i.e., onblur="if(this.value=='') this.value='reflection-here';" The first potential way is ...

'; confirm(1); ' or '; confirm(1); //

The first ' from the above mentioned XSS attack payload will break the context then ; will terminate the statement (i.e., this.value). The next part of attack payload is a proof of concept JavaScript code execution via confirm(1);. The payload ends with ' that will take care of the closing ' in order to avoid syntax error or one can use single line comment (//) for neutralizing the affect of  '.  The screen-shot shows XSS.



The second potential way to XSS is by leveraging JavaScript's string operation(s) and the attack payload looks like ...

                                                           '-confirm(1)-' 

The first ' from the above mentioned XSS attack payload will break the context then minus operator followed by a proof of concept function call (confirm(1)). In JavaScript you can subtract anything from anything and it won't care (in worst situation you will get a NaN result but never an exception) given there is a valid syntax. You can also use other operators like +, *, || and ^ etc.  For the reminder, the reflection looks like onblur="if(this.value=='') this.value='reflection-here';". The this.value will carry the final value once expression on the right hand side will be evaluated and during the evaluation of expression, our payload confirm(1) is executed. The screen-shot shows XSS and the URL at this time looks like http://yaandyou.net/index.php/component/search/?searchword=%27-confirm%281%29-%27&ordering=&searchphrase=all.



Now assume both " and ' are filtered. It means that the above mentioned options for XSSing are gone. Do we still have a chance to XSS this case/particular injection point? Yes. The potential payload looks like ...

                                                 &apos;-confirm(1)-&apos; 

Why above XSS payload works? Remember, our reflection was in eventhandler case (i.e., world of JavaScript). The browser will HTML decode the value of onblur as soon as parser reads it before proceeding (It is not only about onblur, browsers do HTML decoding of an attribute(s).). As you can see in the XSS payload, I have used the HTML5 character reference entity for ' i.e., &apos;. The browser decoding operation will convert &apos; to hard-coded ' which then breaks the context (i.e., this.value='reflection-here';) and then with the help JavaScript string operation (explained some paragraphs before), XSS payload is executed. Further the decimal (i.e., &#39;) and hex (&#x00027;) encoding form of ' also works respectively. The screen-shot shows XSS and the URL at this time looks like http://yaandyou.net/index.php/component/search/?searchword=%26apos;-confirm%281%29-%26apos;&ordering=&searchphrase=all


Some of you might be thinking that if &apos; works then why not we use the following: &quot;onmouseover=&quot;confirm(1)// (as an alternate option to the first potential way of XSSed as I described earlier). I leave this up to you to think and figure out but in short &quot;onmouseover=&quot;confirm(1)// does not work.

A quick search on Nerdy Data for the query "onblur="if(this.value=='') this.value=" results in more than 99K pages. Off-course all of them are not vulnerable but it will give you an idea and there is a great chance that some of them're vulnerable (e.g., after spending some time on search results I found one end-point in Alexa top 1000 sites that is vulnerable). At the same time, I found onclick landing point here. The screen-shot shows the reflection of probe string in onclick and I think they're doing good in this case.


The real life examples given above are somehow complicated cases but in the wild one can also see the following simple case related to event handlers. I found the following (see screen-shot below) as a part of WYSIWYG editor somewhere where user-supplied input directly becomes part of event handler (no involvement of any string operation). In this case, the payloads like confirm(1) or alert(1) simply works.



Sunday, November 22, 2015

Watch Out for `$` Based Third-Party Sinks

In the earlier post, I have pointed out how some developers're using JavaScript's built-in functions (by keeping in mind mistakes) in the wild. In this post, I will show some real examples of jQuery based third-party sinks and how we can leverage them for XSS. As I described in the earlier posts that the XSS probe starts with a harmless payload i.e., "xxxxxxxx'yyyyy</img because it gives lot of information. We will continue the same practice here also. 

$.sliLinkTracker


I think, it is a small jQuery plug-in/library for link(s) (or redirect link(s)) tracking. At an abstract level, the function takes three arguments. It looks like: function(links,log_base,keywords) in the JavaScript library. The third argument i.e., keywords is our interest because it holds the user-supplied input. Lets see it in the wild. Please open the following URL ...


The screen-shot given below shows the reflection of probe string. It is clear from the reflection that " from the probe string has been encoded while < sign has been filtered (removed). The single quote ' is there and at the same time, developers're using ' for holding the user-supplied value. This can be easily XSSed via '-confirm(1)-'


The URL at the time of XSS looks like: http://www.dmv.org/search?w=%27-confirm(1)-%27&tz=&section=&asug= (Alexa rank 1357) and the screen-shot is given below.



$("...").highlight



It is a small jQuery based library for text highlighting. Lets see it in the wild. Please open the following URL ...


The screen-shot given below shows the reflection of probe string. It is clear from the reflection that " and < from the probe string have been encoded. The single quote ' is there and at the same time, developers're using ' for holding the user-supplied value. This can be easily XSSed via '-confirm(1)-'


The URL at the time of XSS looks like: http://www.ettoday.net/news_search/doSearch.php?keywords=%27-confirm(1)-%27 (Alexa rank 152) and the screen-shot is given below.


I found one more victim of this highlighting stuff: http://www.buonissimo.org/search/?search=%27-confirm(1)-%27. The screen-shot shows XSS.


Hilite.hiliteElement($("page")


I think, it is another library for highlighting HTML page elements. In the JavaScript code, at a high level, it looks like: function(elm,query) while query is user-supplied input. Lets see it in the wild. Please open the following URL ...


The screen-shot given below shows the reflection of probe string. It is clear from the reflection that " from the probe string has been filtered (removed) (please keep in mind that in this case developers're using double quote for holding the user-supplied input) while developers forgot about </. This can be XSSed now via </script><script>confirm(1)</script>


The URL at the time of XSS looks like: http://www.iteye.com/search?type=all&query=</script><script>confirm(1)</script>  (Alexa rank 3223) and the screen-shot is given below.


I will leave this up to you to figure out on how many sites these third-party jQuery libraries're/potential XSS sinks are in use. For this purpose, you may use NerdyData and MeanPath. If you know any similar case, please feel free to share as a part of comments because sharing is caring. 

Sunday, November 15, 2015

JavaScript's Built-In Function(s) --- A Potential XSS Venue

This post shows how developers (not all of them) are using JavaScript's built-in functions in the wild and how we can leverage them for XSS given user-supplied input reflects as a part of these functions. I will demonstrate XSS by giving four real examples in the wild. Though four examples can never ever be a representative of the whole web but at least it will give an idea. 

decodeURI

According to MDN, decodeURI decodes encoded URI (i.e., URI encoded form). Lets see it on a real site in the wild. Please open the following URL (topic GET parameter holds our probe string i.e., "xxxxxxxx'yyyyy</img): The News.Cn is a popular Chinese site and at the time of writing its global Alexa rank is 3420. 


The reflection that is of our interest (part of decodeURI function) can be seen in the following screen-shot. The developers are using single quote for holding the user-supplied input while single quote as a part of probe string reflects back in its hard coded form. The < from the probe string has been converted into its HTML encoded form i.e., &lt; Isn't decodeURI expects URI encoded form? In this case, this seems missing. 


We have the following potential choices for XSSing in this case.

  • </script><script>confirm(1)</script> 
  • '-confirm(1)-' or '-confirm`1`-'
  • Respect the Syntax 

The case where we prematurely closes the script block (i.e., </script><script>confirm(1)</script>) is no more an option in this particular example because < is converted into &lt; In case of '-confirm(1)-' (In JavaScript you can subtract anything from anything and it won't care), the URL looks like the following at the time of XSS.

http://t.home.news.cn/spIndex.action?ds=all&h=458&pageSize=20&temp=topicRoll&topic='-confirm(1)-'

The respect the syntax case also works and in this case, please make sure to take care of characters like single quote, parenthesis and semi-colon etc by keeping in mind the given syntax. If you remember the reflection in decodeURI, it looks like ...

var topic =  decodeURI('reflection here');

There are potentially two options by looking at the syntax above. I will mark the injections in red for your convenience. In both cases given below, the payloads start with ' to break the context and after ', there is ) which makes sure to properly close the decodeURI function (i.e., it would be a decodeURI function call with an empty string). The next part of XSS payloads is ; which is a statement terminator. This will close the var declarations. The next thing/item is a proof of concept function call of confirm(1) along with statement terminator i.e., confirm(1);. If you will stop here and tries to execute the payloads, you will get an uncaught syntax error on the console because of ');. At this point, again we have two options i.e., (' or // (single line comment) respectively in order to avoid syntax error. The single line comments (//) can neutralizes or normalizes the affect of ');     

var topic =  decodeURI('');confirm(1);(''); 
var topic =  decodeURI('');confirm(1);//');

The URLs look like the following at the time of XSSing by keeping in mind respect the syntax cases.



The screen-shot shows XSS in all potentially possible ways. 



replace (JavaScript String replace Method)

According to MDN, replace method returns a string after a pattern (string or regular expression) or characters' replacement. Lets see it on a real site in the wild. Please open the following URL (including our probe string i.e., "xxxxxxxx'yyyyy</img): The Zaobao is a popular site in Singapore.


The reflection that is of our interest (part of replace function) can be seen in the following screen-shot. The developers are using double quote for holding the user-supplied input in the replace function while double quote as a part of probe string reflects back in its hard coded form. The </ from the probe string can also be seen in its hard-coded form. The game is over here.


The URLs at the time of XSSing look like (choice is yours) ...

http://www.zaobao.com.sg/search/site/");confirm(1);// (does not work because // is filtered)

Here is the screen-shot of XSS.


window.location.replace

According to MDN, location.replace method replaces the location of the current resource or document with the one provided in its argument. Lets see it on a real site in the wild. Please open the following URL (q GET parameter holds our probe string i.e., "xxxxxxxx'yyyyy</img): The global Alexa rank of Bloomberg is 295.


The reflection that is of our interest (part of window.location.replace function) can be seen in the following screen-shot. The developers are using single quote for holding the user-supplied input in the window.location.replace function while single quote as a part of probe string reflects back in its hard coded form. The </ from the probe string can also be seen in its hard-coded form. The game is over here.


I will show only one potential way for XSS but will leave others for you to explore or take as an exercise. The URL at the time of XSSing looks like the following.


Here is the screen-shot.



I found another example in the wild where reflection occurs in window.location.replace. Please open the URL in Firefox browser. You can easily figure out other potential ways of executing arbitrary JavaScript code that work across browsers e.g., '-confirm(1)-'.

http://app.medyanetads.com/redir.a2?URL=</script><script>confirm(1);</script>&ciid=457810&tid=13674

Here is the screen-shot.


Note: In case you have found an XSS in similar cases as given above, please feel free to share. Along with the above mentioned functions, I had also seen parseInt() and document.location.replace() in the wild. Thanks!


Monday, November 9, 2015

The (In)Security of EZDATA

In this post, I will shed light on the (in)security of an analytic and tracking script named "EZDATA". At the time of writing of this post, I do not know who owns EZDATA and a number of web applications are vulnerable. In case you guys have an idea, please let them know about this post. I came across EZDATA by looking at the source code of the Alexa top 500 sites (normally I used to browse and looked at the source code). 

The vulnerable JavaScript code snippet is given below:

<script>
ezQuery(document).ready(function() {
//get here
EZDATA.trackGaEvent('Search','Request','InputReflectsHere');
});
</script>

Lets see EZDATA in the wild.

NFL.COM

The National Football League is a very popular site and at the time of writing of this post, its Alexa's global rank is 261. If you will input the harmless probe string (i.e., "xxxxxxxx'yyyyy</img ) in the search bar of the site then at that time the URL looks like:


This is how our probe string reflects back on the page as a part of EZDATA JavaScript code snippet.


One can easily figure out by looking at the reflection that developers're using single quote for holding the user-supplied input while single quote (part of probe string i.e., "xxxxxxxx'yyyyy</img) reflects back in its hard-coded form. One more thing to notice here is that < (part of probe string i.e., "xxxxxxxx'yyyyy</img) is filtered in the reflection. The < is filtered so the option like </script><script>confirm(1)</script>  (i.e., prematurely closing the script block and than execute code of our choice) is gone and the next attack payload I can think from the top of my head is ...

'-confirm(1)-'

The URL at the time of XSSing looks like ...


I was expecting that it will work like a charm but unfortunately not. The reason can be seen in the following screen-shot.


The above screen-shot shows that the parenthesis (i.e., ()) have been filtered from the XSS payload which makes the attack vector useless. No worries. ECMAScript 6 (ECMA6) provides a feature called multi-line template string and with the help of it, one can execute JavaScript without parenthesis. The back-tick (``) is used instead of parenthesis for JavaScript code execution. The payload now becomes ...

'-confirm`1`-'

Now the URL at the time of XSSing looks like ...


The screen-shot shows XSS in NFL because of EZDATA.


NBC.COM

The National Broadcasting Company is another popular site using EZDATA and the above story holds true for NBC also. The URL looks like http://www.nbc.com/search?q='-confirm`1`-'. The screen-shot shows the XSS in NBC because of EZDATA tracking script.


Other Sites

The next obvious thing one can think of is if EZDATA is in use on popular sites like NFL and NBC respectively then it may be in use on other sites. I do a quick search on NerdyData:

https://search.nerdydata.com/code/?and_code[]=//get+here+EZDATA.trackGaEvent&limit=0,10&rank_min=1&rank_max=1000001

The search returns 61 sites (some may be duplicates) and at least gives an idea that EZDATA is in use on other sites also. Here are the XSSes in 11 different sites as a proof of concept because of buggy EZDATA (first URLs and then screen-shots in one animated GIF).




Note: If you know any site(s) that is using EZDATA, please feel free to add or name it in the comments. 

Monday, November 2, 2015

A Tale of Breaking SAP's SuccessFactors's XSS Filter


TL;DR: 

'-confirm(1)-' was enough to break SAP's SuccessFactors's XSS filter and were able to make hundreds of web applications vulnerable ... 

Earlier this year, SAP invited me for a talk in their SAP Product Security Expert Summit (March 19th & 20th, 2015) held at Walldorf, Germany. It was an invite only conference and security team members of SAP around the world were there. As soon as I got the invitation for a talk, I started thinking that it would be great if I will be able to break something that belongs to SAP in front of their security and research team members. 

I started browsing SAP's main web application and ends up on their Talent Community site. The URL that catches my attention at that time is given below:


The first thing I injected as a value of returnurl GET parameter was a harmless probe string i.e., "xxxxxxxx'yyyyy</img. The URL looks like ...


The probe string reflected back on the page 11 times (one time as a part of action attribute of the <form> tag while 10 times inside the script block). The following screen-shot shows the reflection of harmless probe string inside the script block. 



The reflection shows that our probe string ends up as a part of if condition and a variable loginfromReturnurl inside the script block. In all these cases/sinks (i.e., variable declaration and if condition) inside script block, developers were using single quote and reflection shows single quote that're part of a probe string not filtered or encoded or escaped while </ was also there in hardcoded form. The game is over here because developers were not controlling ' as well as </. The attacker may use ...

  1. </script><script>alert(1)</script> 
  2. '-confirm(1)-' 
Lets start with the first choice. The URL will looks like ...


I was expecting that the payload will work in a neat and clean manner but it was not. The reason can be seen in the following screen-shot. 


I will come to the bypass later (I think most of you can easily figure out at this point) but now lets see how this filter works. I was curious to see how hard it is and how it works because after all it is SAP's SuccessFactors's XSS filter.  The next payload I tested was a commonly used XSS vector <img src=x onerror=alert(1)>. In the following screen-shot, you can see the filter output.



One can observe that the part of above payload i.e., onerror=alert(1) becomes XSS-VIOLATIONXSS-VIOLATION while <img src=x was unfiltered. The next thing, I tested was again the above payload except I changed alert(1) to confirm(1) and now see the output below. This time you will see only one time XSS-VIOLATION and confirm(1) was there in the reflected output. It shows that they're doing black-listing of hard-coded keywords e.g., alert(1) was filtered while confirm(1) was not.


Lets continue to figure out what they're filtering and what they had missed. It was fun playing around. The next payload was <a href=javascript:confirm(1)>click</a>. The screen-shot shows that the keyword javascript was filtered.


Lets see the filter behavior by encoding the letter a of the keyword javascript. I used decimal encoded form of the letter a i.e., &#97. As I mentioned earlier, that we're dealing with GET parameter so the URL encoded form will be %26%2397 and once the payload will land in the DOM it will looks like: <a href=j&#97vascript:confirm(1)>click</a>. This is a valid XSS vector and works in all browsers. The XSS filter missed it and the working payload reflects back. In short, the keyword javascript was filtered but encoded form was not (though I only encoded the letter a of keyword javascript).  In short, the following payloads were not filtered.


All these payloads were able to bypass the filter or have the potential to bypass the filter but under the current situation (by keeping in mind the input reflection) where injected closing script block i.e., </script> becomes XSS-VIOLATIONS (as described earlier and can be seen in one the earlier screen-shot), payloads did not work because once I will be able to close the script block prematurely then I can make use of any of the above mentioned payloads. The problem was that </script> becomes XSS-VIOLATIONS. I tried other valid tricks for closing the script block like ...

/* I have at least 2 examples from very popular sites where the following variations of closing script block works while simple </script> does not */

  • </script%0a> 
  • </script -_->
  • </script anythinggoeshere>    

but failed. But who needs < and > signs/characters when input reflects back in the script block inside the sandbox of single (') or double quotes (") and at the same time single (') or double quotes (") were not filtered or encoded or escaped. Now lets go back and see the reflection of probe string again in the following screen shot.


The developers were using single quote (') as a part of if condition and inside the if condition our probe string reflects back and single quote (') (i.e., part of probe string "xxxxxxxx'yyyyy</img) was there in its hard-coded form. The final attack payload looks like ...

'-confirm(1)-'

The first ' of the payload will break the context and then minus operator followed by a function call followed by a minus operator and payload ends on '. Inside the if condition, it is evaluated as an expression and during expression evaluation a function call (i.e., confirm(1)) is made. In JavaScript you can subtract anything from anything and it won't care. You can also use other operators like +, *, || and ^ etc. So here is an XSS in SAP's web application.


SAP is third largest software maker and if it is SAP's product or SAP is using it then definitely it may be found on other sites. I realized during email conversations with the SAP security team that this XSS filter belongs to SuccessFactors. SuccessFactors is a leader in providing cloud based human resource solutions, according to their website. As per information from the customers and about sections of their web application, they have around 4000 customers. 

I wanted to identify other sites that're using this particular XSS filter and for this purpose I used Google's inurl operator and NerdyData (a source code search engine). In my opinion (you may disagree), Google's inurl operator and NerdyData are a lethal combination for the identification of other vulnerable sites. For example, I queried the following by keeping in mind SAP's URL structure at that time and by looking at the other URL points in the XSS filter client-side JavaScript code. 



The above two queries via Google's inurl operator almost gives back more than 200 unique results (the number may vary). At the same time, on NerdyData I queried the following string that was part of the filter code ...


It resulted in almost 179 entries. After spending sometime on the results of Google's iunrl and NerdyData, I compiled a list of almost 100 popular and unique sites that're using this XSS filter. The list is available here (in case you guys will find something in this XSS filter...). For proof of concept, I prepared a screen-shot that shows XSS in 39 sites. It includes big names like KPMG, CISCO, VISA, Sprint, SunTrust, Ericsson, Johnson & Johnson, Weather, Booz Allen Hamilton, Royal Mail Group and Singtel etc.  The screen-shot is given below.



SAP took almost three months in order to fix it and SAP acknowledged my name as a part of their July 2015 acknowledgement announcement. Once they had informed me about the fix, I thought lets look at the fix and this time found redirect (but it requires user-interaction) in the same returnurl GET parameter. The URL at the time of redirect looks like ...


SAP now had fixed this redirect case. I also found number of bugs in SAP Enterprise Portal and I will later write about it once SAP will fixed them. I will conclude on a saying (pretty much summarizes the state of cloud) by keeping in mind that SuccessFactors provides cloud based solutions ...

"First one bug to rule them all and then one fix to cover them all ..."