Friday, December 25, 2015

A Hardcore XSS

Merry Christmas to you all... 

Tim Willis of Chrome security team called it `hardcore-one` in his talk available here. Alexis Imperial-Legrand (ail) from Google security team already did a good and generalized write-up here. I would call it a `trickier` XSS in both ways i.e., finding and fixing. I have always been interested in finding this XSS in the wild and found many instances of it on popular sites (including a popular proprietary CMS). I will not unveil the name of CMS at the moment but will see later sometime. I also found this hardcore/trickier XSS in SAP Enterprise or NetWeaver Portal. 

Some days ago, I asked a question i.e., Is <a href="javascript:go('a','&quot;xxx&#39;yy&lt;/i');">X</a> it a good XSS protection or not given ', " and <> are encoded? I asked the question on Twitter and poll result shows 30% have given the wrong answer while 70% were correct (total votes casted were 70). This post is intended for the 30% while 70% know everything and they can skip reading this post and continue safe and happy browsing :) Lets see real life example from the wild. Please open the following URL ...


In order to keep it simple for better understanding, I initially used the word "reflection-here". The screen-shot shows the reflection of our interest (i.e., function call within a JavaScript URI).


Now see the same reflection but this time our harmless probe string ("xxxxxxxx'yyyyy</img) will be part of it. It shows that ' from our probe string is not filtered or encoded while " and < are URL encoded.


Lets see different potential ways to XSS this case. The developers're using ' for holding the function parameters and single quote is not filtered. It is enough of information for us. The first method is simple/straight-forward and the XSS attack payload will be '-confirm(1)-'. The URL at the time of XSS is: http://www.nordbayern.de/portalsuche/suchbegriff/'-confirm%281%29-'/sortierung/Datum followed by a screen-shot.


The next potential way to XSS this case is with the help of &apos;-confirm(1)-&apos;. The URL at this time looks like: http://www.nordbayern.de/portalsuche/suchbegriff/&apos;-confirm%281%29-&apos;/sortierung/Datum and the screen-shot is also given.


Why it works? I will come into it later but first lets see another potential way of XSSing this case. I will now use another real life example (inject payload in main search bar on this URL http://www.kyobobook.co.kr/search/SearchCommonMain.jsp) from the wild. It would be great if someone will figure out why I am using new example for this. Please spend sometime on the URL and you will find out why the following attack payload does not work on the URL mentioned earlier. The next attack payload is: %27-confirm(1)-%27 and the screen-shot is also given.


In short, so far we have seen three different ways i.e., '-confirm(1)-', &apos;-confirm(1)-&apos; and %27-confirm(1)-%27. The first way ('-confirm(1)-') is simple and straightforward because single quote was not filtered as can be seen in the probe string reflection while in the second (&apos;-confirm(1)-&apos;) and third (%27-confirm(1)-%27) method, there is an involvement of browsers' decoding as far as XSS is concerned. If you will go through Tim Willis's talk, one of the slide was about browsers' decoding. The slide from Tim Willis's given below shows how browsers' decoding order work ...


As I said earlier that the second potential way to XSS this case was: &apos;-confirm(1)-&apos; and thanks to browser's HTML decoding &apos; becomes hard-coded single quote (') which subsequently breaks the context and via JavaScript string operation, it gets executed. In the third potential way (%27-confirm(1)-%27) for XSSing this case, there is nothing related to HTML decoding but this time URL decoding plays its rule and %27 becomes hard-coded single quote ('). This XSS is more trickier especially if you want to apply a fix. Alexis Imperial-Legrand (ail) had already explained in his post the correct escaping order ...

  • JavaScript Escaping
  • URL Percent Encoding
  • HTML Escaping

Before jump to the conclusion, there is still one more potential way for XSSing this special case. Imagine if " are not filtered or encoded. If you will look at the first screen-shot on this page, you will find that developers're using " for holding the value of href attribute. In case " are not encoded then you can use a payload like "onmouseover="confirm(1). The following screen-shot shows the payload in action. The screen-shot is from another web site because " are encoded in case of earlier mentioned web applications.


In short, we have seen all potential ways to XSS this case and at the same time, now you have some real examples to play with.

Sunday, December 20, 2015

Is Escaping an Option There?

In the real example cases, you will see in this post, escaping SHOULD NOT be the option ... please go for encoding. I found many instances of the following types of reflections in the wild where one SHOULD NOT use escaping but unfortunately it is there. Please open the following URL (Inquirer has a global Alexa rank of 1049 at the time of writing). The GET parameter q holds our probe string "xxxxxxxx'yyyyy</img


The screen-shot shows the reflection in an attribute context (i.e., value attribute of an <input> tag) and you will see that " and ' from the probe string are escaped i.e., \" and \' respectively. At the same time, </ is not controlled. 


In an attribute context, escaping is not a good choice. The developers're using " for the holding the value of value attribute and at the same time, they escaped " i.e., \". The developers think that they are done and it is not possible to break the context. Lets see one potential way (there are many) to XSS this. The XSS attack payload looks like "onmouseover=confirm(1)//. The URL at the time of XSSing is followed by screen-shot:



In the source code, the <input> tag looks like:

<input type="text" name="q" value="\"onmouseover=confirm(1)//" autocomplete="off" />

The more interesting thing is if you look at the innerHTML of the above mentioned <input> tag. This would give better picture why above mentioned XSS attack vector works given " are escaped in an attribute context. I used Live DOM Viewer made by Ian Hixie for this purpose. The innerHTML looks like ...

<input type="text" name="q" value="\" onmouseover="confirm(1)//&quot;" autocomplete="off">

For you to see and test it yourself, the short exercise would be why the following XSS attack payloads do not work? "onmouseover="confirm(1) and "onmouseover="confirm(1)//. Now we see another reflection where escaping SHOULD NOT be there but it is. Please open the following URL (BusinessInsider has a global Alexa rank of 7393 at the time of writing). The GET parameter s holds our probe string "xxxxxxxx'yyyyy</img.


The screen-shot shows the reflection of probe string in an HTML context (<h3> opening and closing tag is around reflection of probe string) and you will see that " and ' from the probe string are escaped i.e., \" and \' respectively. At the same time, </ is not controlled. In an HTML context, if < is not controlled (filtered or encoded) then game is over 99% of the time.


The URL at the time of XSSing looks like http://www.businessinsider.com.au/?s=%3Cimg%20src=x%20onerror=confirm%281%29;%3E followed by a screen-shot. This XSS is now fixed.


I was thinking what could be the reason of escaping " and ' in an attribute and HTML context? I think because of single XSS protection applied on a web application in general or they're using one XSS protection for all cases (escaping is good in script context e.g., JavaScript String Literal Case). The sad thing is that I found many instances of escaping in an attribute and HTML context in the wild. It is a common mistake. The context-specific case(s) was not in the mind.  If you can think of any other reason(s), please feel free to share as part of comment section below. At the same time, if you have a reason or justification that escaping can be applied in above mentioned cases (i.e., attribute and HTML context), then I would be very happy to see the real example(s) where it is working fine.

Update: Ouch ... Forward Slash for Escaping

Recently, I found a real life case where developers're using forward slash (/) for escaping double (") and single quotes (') respectively in an HTML context. As I said earlier in the post that escaping is not an option in an HTML and attribute context and at the same time, developers're using instead of \. The can be used as an escaper in an script context. Please open the following URL http://www.autos.ca/ and input XSS probe string "xxxxxxxx'yyyyy</img in the main search bar. The screen-shot given below shows the reflection.


The URL at the time of XSSing is given below followed by a screen-shot. The XSS in this case is very simple because </ is not filtered or encoded in an HTML context.





Sunday, December 13, 2015

No Quotes At All

In this post, I will describe a rare variation of common reflection points. We all know and have seen reflection in JavaScript string literal case and <input> tag's having type attribute set to hidden i.e.,

<script>
var any-variable-name="reflection here"; // double quoted case
var any-variable-name='reflection here'; // single quoted case
</script> 

and

<input type="hidden" value="reflection here"> // double quoted case
<input type='hidden' value='reflection here'// single quoted case

In the wild, developers either use single (') or double (") quote for JavaScript string literals and the same holds true for <input> tag. But how often you see a reflection without any quotes at all in the wild (though as per W3C specification it is allowed)? I mean something like that ...

<script>
var any-variable-name=reflection here; // no quotes at all
</script>

and

<input type=hidden value=reflection here// no quotes at all


I think it is a needle in a haystack. I found real examples (one I am sharing here and one I can't) of such reflection without any quotes so I thought it would be interesting to share. Please open the following URL (GET parameter rp holds our harmless XSS probe string "xxxxxxxx'yyyyy</img). The site NEWS.CN has an Alexa rank of 3573 at the time of writing.


The screen-shot shows the reflection of our interest. In the screen-shot you can see the probe string ("xxxxxxxx'yyyyy</img) reflects back as a part of rp JavaScript variable and the developers're not using any quotes. 


So how to XSS this case? It would be very simple. The proof of concept XSS payloads like confirm(1), alert(1) and prompt(1) etc simply works. The URL at the time of XSS looks like the following and the screen-shot is also given.



The same page has another reflection (without quotes) as a part of <input> tag's hidden value and it is shown in the following screen-shot.


It can be easily XSSed and there are many ways. The URL at the time of XSS looks like the following and the screen-shot is also given. The XSS payload starts with a space character (i.e., %20). Why? I leave this up to you to figure out. It's easy.



Sunday, December 6, 2015

The Dark Side of Comments

Comments are good. We all know and have a general consensus on that. The developers should make use of comments in a useful manner. One more aspect of comment that normally we see in the wild is: developers often comment out unwanted or unused code. This may be because the functionality (code) is no more needed or there can be any other reason. This is where the problem starts. Lets elaborate it with the help of real examples from Alexa top sites. Please open the following URL (our harmless probe string "xxxxxxxx'yyyyy</img is part of URL's GET parameter slowo) and the following screen-shot shows the reflection of our interest (i.e., inside an HTML comment block). The site GAZETA has an Alexa rank of 589 at the time of writing.



It can be seen in the screen-shot above that our XSS probe string (i.e., "xxxxxxxx'yyyyy</img) lands as a part of value of <input> tag's value attribute in particular while there're HTML comments  (<!-- -->) around the <input> tag. Further " from the probe string has been encoded into &quot; while < is not filtered. In my experience, if < is not filtered than 99.9% of the time > is also not controlled but will get back to it later. Now for the moment, imagine that HTML comments are not there around the <input> tag then is it possible to break the context (i.e., attribute context)? In order to break the attribute context (i.e., value attribute of an <input> tag), we need hard-coded " because developers're using it. The " are properly encoded into &quot; so no chance to break the context in modern browsers.

Now lets see how we can leverage HTML comments that're around <input> tag and < is not filtered as can be seen in the screen-shot above. The implicit assumption is that > is also not filtered. Lets inject the following XSS attack payload -->anyxssattackvectorhere. The goal is to prematurely closes the HTML comment block and then execute JavaScript with the help of any XSS attack vector. The browsers are good guys and as soon as the parser detects the syntax/token -->, it will try its level best to close the HTML comment even though reflection was part of quoted attribute (i.e., value attribute of an <input> tag). Please remember for the browser's parser, HTML comment has already been started (i.e., <!--) before the <input> tag. The URL at the time of XSS looks like the following and screen-shot is also given below:


    

The next example related to HTML comments is from one of the Alexa top 500 sites. Please open the following URL (YAOLAN's Alexa rank at the time of writing is 399). The probe string "xxxxxxxx'yyyyy</img is part of URL's GET parameter searchWord.


The following screen-shot shows the reflection in HTML comments which is of our interest. There are other reflections (can be XSSed) also on the page but we will not consider them.


It is clear from the reflection of XSS probe string that " has been filtered (removed) while < is there in its hard-coded form. The developers are using " for the value attribute of <input> tag and " has been filtered so it means that in this particular reflection or case, we can not break the context (i.e., attribute context) in modern browsers. Further, reflection shows that < is not filtered so the assumption that > is also not filtered should work while at the same time please keep in mind that we want to prematurely close the HTML comment block. The attack payload will be looks like -->anyxssattackvectorhere. The URL at the time of XSS should looks like the following.


I was expecting a confirm box having 1 but got the following Chinese message (available in the form of screen-shot). I think some sort of malicious code detection mechanism (may be some WAF) was in place on their site (I translated the message and realized).


Now this would be interesting :) After spending few minutes on their detection, I realized the following (go and test yourself for fun):
  • <iframe>, <object>, <meta>, <style> and <script> tags are part of their black-list
  • <svg>, <img>, <details> and <p> tags works
  • onerror=confirm(1) does not work and it has been detected
  • onerror%0a=%0aconfirm(1) becomes onerror%0a=%0aconfirm1 (small parenthesis are removed) // It means not detected ... but () has been removed
  • ontoggle=confirm(1) becomes ontoggle=confirm1
  • javascript: has been detected but javascript&colon; works
  • `` was not removed so we can use confirm`1` instead of confirm(1)
  • many more .... 
I think it is enough. Lets XSSed it. The URL at the time of XSS looks like the following and the screen-shot is also given below.

http://search.yaolan.com/all.do?searchWord=--><p/id=1%0Aonmousemove%0A=%0Aconfirm`1`>


I deliberately picked a XSS vector that needs user-interaction so that you can identify and see yourself the vulnerable end-point i.e., inside comment block. On the page, there are other vulnerable end-points also. I found some real examples related to JavaScript comments and how can we leverage them for XSS but I will write about JavaScript comments later sometime. I will conclude on ... Why not delete the unwanted or unused code instead of commenting out? 

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 ..."