Sunday, January 31, 2016

The Magic of Connecting The Dots

Macy's (http://www.macys.com/) calls itself "the magic of macy's" (at least the word magic is mentioned on their main home page logo). It has a global Alexa rank of 241 at the time of writing. It is a high profile web application. I think not from security perspective but from traffic point of view. Let the game begin. Please open the following URL (keyword GET parameter holds our harmless XSS probe string i.e., "xxxxxxxx'yyyyy</img). The following screen-shot shows reflection of our interest and some other cool things.



Lets start connecting few dots ...

The following line (in particular line #1911 in the screen-shot above and I marked it with label "Seems Interesting (3)") of JavaScript code (keywordsearch = kws.replace(/"/g,'\\\"');) replaces the " globally in the input with \\\" i.e., developers try to escape " with the help of three backslashes. Though escaping with three backslashes works fine given developers're using double quotes for holding the input in script context in general. Normally one backslash like \" (for double quotes) or \\ (for backslash) is enough (e.g., see line #21 in the source code in Chrome).


Note: FYI, on YouTube Gaming web site, you will find escaping with single backslash (i.e., \") and escaping with three backslashs (i.e., \\\") on the same page. Please see line #204 and line #200 in the source code in Chrome browser respectively.

So far so good from the application perspective but wait ... What about backslash (\) if injected in the attack payload? Are they escape backslash? Some of you might remember the blog post I did sometime ago and it was related to backslash. At that time I mentioned, my quest for backslash based XSS will continue and I think I am done with it (you will see when you're done reading this post). For example, open the following URL (http://www1.macys.com/shop/search?keyword=\) and if you will look into the source code, backslash is not escaped (see screen-shot below).


The following XSS attack attack payload can do the job for us i.e., \"; confirm(1); //. The URL looks like: www1.macys.com/shop/search?keyword=\";%20confirm(1);%20//. Some of you might be thinking why I started the payload with \. I explain but first look at the screen-shot of injection i.e., \"; confirm(1); //.


The injected XSS payload \"; confirm(1); // becomes \\\\"; confirm(1); // because " is replaced by \\\" in order to make it an escape character and at the same time, \ is not escaped. In short we have four backslashes in the reflection. Further, please remember, we're inside double quotes because developers're using them for keywordsearch variable declaration. The JavaScript code snippet looks like keywordsearch = "\\\\"; confirm(1); //"; How to interpret this code? The number of backslashes as far as one or three or five (i.e., odd number) is concerned, it is fine but if the count is even number i.e., two or four or six ... & so on then it will make the effect of escaping NULL N VOID.

In short, double quote is no more an escaping character because of four backslashes. The browser will consider it a proper closing double quote (in pair) for a variable declaration. In the XSS attack payload, now comes ; which is a statement terminator. It is followed by a proof of concept JavaScript function call i.e, confirm(1);. Last but not the least, we have a single line comment (i.e., //) in order to neutralize the effect of closing ";. It seems all set for an XSS and the following URL will result in an XSS: www1.macys.com/shop/search?keyword=\";%20confirm(1);%20//. Unfortunately NOT... but why? The game is still on ... It is about connecting some dots.

If you look at one line (i.e., line #1949 because line #1950 is a comment ) above the keywordsearch variable declaration that holds our reflection then you will realize that there is a conditional statement and it is not executed. It means that the control never reaches at the reflection or injection point because the conditional statement evaluates to false at the moment. Why false? The conditional statement is:

if(currentPageUrl.indexOf("cm_kws")!= -1) 

while currentPageUrl is a variable i.e., var currentPageUrl = window.location.href.  The window.location.href returns the current location of the document and assigns it to the variable currentPageUrl. The URL at the moment is http://www1.macys.com/shop/search?keyword=\%22;%20confirm(1);%20//. The JavaScript string function indexOf returns the first occurrence of the specified value, otherwise returns -1. The specified value in the indexOf function is "cm_kws". The current URL has no occurrence of "cm_kws". It means inside conditional statement, currentPageUrl.indexOf("cm_kws") evaluates to -1 and we all know that -1 != -1 is false :) The end goal is to make this conditional statement true so that the control reaches at the point of reflection and we will be able to execute JavaScript code of our choice.

I think, it is possible to force conditional statement so that it evaluates to true by appending the specified value i.e., "cm_kws" in the URL given currentPageUrl gets the value from window.location.href as I mentioned earlier and can be seen in the screen-shots. The job can be done by adding a new GET parameter named "cm_kws" like http://www1.macys.com/shop/search?keyword=\%22;%20confirm(1);%20//&cm_kws or by simply padding the string "cm_kws" at the end of URL like http://www1.macys.com/shop/search?keyword=\%22;%20confirm(1);%20//cm_kws.  In case of adding a new GET parameter "cm_kws", the statement currentPageUrl.indexOf("cm_kws") inside if evaluates to 66 and we all know 66 != -1 is true. In case of padding "cm_kws" at the end of URL, the statement inside if evaluates to 65 and we all know that 65 != -1 is true. The screen-shot given below shows the results of evaluation for better understanding.


It seems all set for an XSS i.e., dots have been connected. The following URL shows a confirm box followed by screen-shot.



For the sake of completeness, I wanted to XSS it with </script><script>confirm(1)</script> given in the reflection (see first screen-shot) </ is not filtered or encoded. The URL looks like ...


It has been blocked by some kind of protection layer. I think WAF or any other protection mechanism (e.g., IPS/IDS) stops the payload. The screen-shot shows Access Denied.


I had seen the same screen-shot on Akamai's site. It makes sense to believe or reasonable to believe that Akamai is not using other vendor's security solutions :) Isn't it? Akamai has its own WAF also i.e., Kona. Builtwith also gives some information that site is using Akamai's hosting services. Further, I am still interested if somebody will tell me or confirm which WAF is in place over there. Your feedback is always welcome.


WAF is meant to bypass and this one is not different. As I said earlier that </script> was blocked but </script%0Aanything> was not blocked. The following are quick bypasses and the screen-shot related to the second URL is also given below.




Before conclusion, I noticed that Macy's allowed to have single (') and double quotes (") in the product name (in case if required). I was thinking that it would not be easy for them to handle single (') and double quotes ("). For example, see the following two products ...




A question came to my mind: what will happen if I will do a search query of the product that have single (') and double quotes (") in their name. How site will treat it? Lets make a search query. I query for the following string i.e., a legit product name having both types of quotes ...

Under Armour Men's Raid Performance 10" Shorts

The resulting URL is:


It returns 3 results at the time of writing. Now lets look at the source code and try to figure out any thing interesting. As expected, site starts breaking itself :) The first thing I noticed is a legit search query breaks the attribute context (see screen-shot below).


The second interesting reflection in that case was in script context. It can be seen in the following screen-shot. The screen-shot shows that " from the product name is not escaped or filtered or encoded.


It means that we can leverage the " from the existing product name in constructing the XSS attack string. The XSS payload looks like (please see that the proof of concept JavaScript code does not start with " because we will use the " from the product name):

-confirm(1)-"

Now combine this proof of concept XSS payload with the legit search query we made earlier. The final attack string will be ...

                        Under Armour Men's Raid Performance 10"-confirm(1)-" Shorts

The URL at the time of XSS is given below followed by a screen-shot.



I conclude on a saying: "When You Really Pay Attention, Everything Is Your Teacher." (Ezra Bayda)

Sunday, January 24, 2016

Unusual Reflections

This post is about unusual reflections i.e., when user-supplied input reflects back or ends-up at an unusual place. I will show unusual reflections with the help of four live examples.

-- Reflection in src Attribute of <script> Tag:

This is really unusual when you're getting a reflection as a part of src attribute of <script> tag. The site FAKT.PL has a global Alexa rank of 2296 at the time of writing. Please open the following URL (our harmless probe string ("xxxxxxxx'yyyyy</img) is part of q GET parameter's value):


The screen-shot shows the reflection of our interest.


It can be seen in the screen-shot that developers're using " for holding the value of src attribute and " from the XSS probe string are not filtered. At the same time, </ is not controlled and in my experience, there is a great chance that > is also not controlled. The URL at the time of XSSing is given below followed by a screen-shot.



-- Reflection in SQL Statement:

The title of this heading sounds interesting i.e., when user-supplied input reflects back on the web page as a part of SQL statement. Isn't it? This is happening in the wild. Please open the following URL: http://search.gmw.cn/epaper.jsp. The site GMW.CN has a global Alexa rank of 54 at the time of writing. On the URL, you will find a search bar and lets input our harmless XSS probe string ("xxxxxxxx'yyyyy</img) in the search bar. The screen-shot shows the reflection of our interest. 


The screen-shot above shows our XSS probe string reflects back on the page as a part of where clause of SQL statement. Further <textarea> tag is around the input reflection (HTML context) and its style attribute has been set to "display:none". Furthermore, </ is not filtered or encoded in reflection. Though this is an HTML context and one can assume that the XSS attack payload <img src=x onerror=confirm(1)> will simply work but in-fact it does not because of <textarea> tag around. The </textarea> tag engulfs the contents except its closing counterpart. In order to make the attack payload works, first close the </textarea> tag prematurely and then you can execute the XSS attack payload of your choice. In short, the final attack payload looks like: </textarea><img src=x onerror=confirm(1)> . The screen-shot given below shows the XSS. I was also thinking: WTF SQL statement is doing on the page? Why developers're exposing their database table(s) structure on the web page?


 -- Reflection in alert() Function:

As a part of XSS proof of concept demonstration, we normally use alert() function. I found an exceptional case where user-supplied input ends-up as a part of alert(). Sometime ago, I did a write-up on JavaScript's built-in functions as reflections but alert() is somehow unique because reflections in other functions are common. I can not name the web site in this case but the following screen-shot shows the reflection of XSS probe string ("xxxxxxxx'yyyyy</img) in alert(). The screen-shot also shows " and < from the probe string are filtered but ' is not filtered while at the same time, developers're using single quotes for holding the value.  


For better understanding and XSS this case, first look at the source code of our interest without any injection: <script>alert('For input string: "83845138c47691"');</script>. The numeric value in the alert() function was part of a GET parameter i.e., it might be controlled by the attacker. In order to XSS this case, we have an apparent two choices (given " and < are filtered as can be seen in the screen-shot above).

  1. '-confirm(1)-' 
  2. ');confirm(1);//

In the first case, we break the context with ' and than with the help of JavaScript string operation (minus operator used in this case i.e., In JavaScript, you can subtract anything from anything as long as the syntax is valid), we execute arbitrary JavaScript code (i.e., during string expression evaluation inside alert(), we execute confirm(1).). The second choice lies under the category of "respect the syntax". It means first break the context with ' and than prematurely closes the alert function call with small parenthesis i.e., ) followed by a statement terminator ;. After that proof of concept confirm(1); followed by a single line comments (//) in order to neutralize the affect of closing "');. Here is the screen-shot shows the XSS. I used the second choice from above as a payload.


 -- Reflection in GET parameter name:

This is the case where you will see reflection as a part of GET parameter name along with the value. Normally, the value of a GET parameter is or may be controlled by the attacker but in this special case, an attacker may controlled the name of GET parameter. The BAIDU.COM has a global Alexa rank of 4. Please open the following URL (our harmless probe string ("xxxxxxxx'yyyyy</img) is part of q GET parameter's value):


The screen-shot shows the reflection. It can also be seen that ", ' and / are escaped so it seems no chance to XSS this particular injection point.


So far there is nothing unusual. The interesting thing is if I replace the GET parameter q with probe string ("xxxxxxxx'yyyyy</img) and see the reflection after submission again. I mean now the above URL looks like:


The screen-shot shows the reflection.


The site has recently added protection i.e., escaping of ", ' and / on the Left-Hand-Side (LHS) of =. Sometime ago, they're only doing escaping on the Right-Hand-Side (RHS). I was able to XSS it because of this exceptional reflection on the LHS of =. I conclude on a question: How often during a pen-test you guys try to manipulate a GET parameter name? 

Sunday, January 17, 2016

if --- Reflection Point

In this post, I will discuss with the help of two real examples about `if` reflection point i.e., when user-supplied input reflects back as a part of conditional statement in JavaScript. Please open the following URL (our harmless XSS probe string "xxxxxxxx'yyyyy</img is part of GET parameter q). The screen-shot given below shows the reflection of our interest i.e., part of conditional statement. 



The screen-shot shows that developers're using single quote (') for holding the value of user-supplied input and ' from the probe string ("xxxxxxxx'yyyyy</img) is not filtered or encoded. Further </ is also there in hard-coded form. One potential way to XSSed this case is '-confirm(1)-'. This will execute because at the time of expression evaluation inside `if`, our proof of concept JavaScript is executed. The URL at the time of XSSing is: http://www.pressdemocrat.com/search?q=%27-confirm(1)-%27 and the screen-shot is also given.


For the sake of completeness, I wanted to XSS this case with the help of </script><script>confirm(1)</script> but realized that this does not work even though </ was not filtered or encoded as I mentioned earlier when we're looking at the probe string reflection (see first screen-shot on the page). In short, the URL does not result in an XSS:


I decided to dig deep and found that they have some sort of filtering in place. The screen-shot given below shows the XSS vector </script><script>confirm(1)</script> does not reflect back at all.


If you will come across that type of case, I would suggest try the following valid variations (there are some others ... please figure out and take it as an exercise, now you have a live test-bed from the wild) and have already seen in the wild (at least 3 to 4 different occasions) that they work and bypassed the filtering mechanisms. The valid means: browsers render it.

</script%20><script%20>confirm(1)</script%20> // a space (i.e., %20) before closing > sign
</script%0a><script%0a>confirm(1)</script%0a> // new line (i.e., %0a) before closing > sign

The following URLs result in an XSS (choice is yours) and the screen-shot related to the %0a case is also given. The effect of %0a can also be seen in the screen-shot.



Now lets see another example from the wild. Please open the following URL (our harmless XSS probe string "xxxxxxxx'yyyyy</img is part of GET parameter rgnCd). The screen-shot given below shows the reflection of our interest i.e., part of conditional statement.



The screen-shot shows that developers're using single quote (") for holding the value of user-supplied input and " from the probe string ("xxxxxxxx'yyyyy</img) is encoded. Further < is also in its HTML encoded form. It seems no chance to break the context but the point I wanted to make is `if` is also a reflection point in the wild. Some of you might remember the blog post I did for breaking the SAP's SuccessFactor's XSS filter. In that case, the reflection of our interest was also part of conditional statement.

Wednesday, January 13, 2016

Persistent XSS in Mozilla Add-Ons Site

I do not know how but somehow I ends up on Mozilla's add-ons site. The site provides logged-in user an option or feature to create collections. According to Mozilla, "collections are group of similar add-ons that anyone can create and share". The collections are publicly view-able because site provides a unique URL per collection. The site has a form (available here) having fields like Name, Description and the add-ons for the creation of collection. The Name field of the collection form was vulnerable to a stored XSS. 

I created a collection having a Name "xxxxxxxx'yyyyy</img in order to see the behavior of site regarding special characters in the Name. The collection can be seen here: https://addons.mozilla.org/en-US/firefox/collections/soaj1664/xxxxxxxx-yyyyy-img/. The screen-shot shows the reflection of our interest i.e., as a part of <title> tag. One can see in the screen-shot that < is not encoded or filtered in an HTML context i.e., <title> tag around the reflection of probe string. 


For XSSing, when you're in <title> tag and < is not encoded or filtered then by simply closing the title tag prematurely with the help of </title> does the job for you and after that one can execute JavaScript code of his or her choice.  The payload I used for XSS looks like </title><svg/onload=confirm(document.domain)//. The screen-shot shows the persistent XSS. The URL where it can be seen at that time (before fixed is deployed) is: https://addons.mozilla.org/en-US/firefox/collections/soaj1664/a-img-src-1-gif-onerror-alert/. The stored XSS is now fixed. Isn't it that simple :)


I filed a bug (https://bugzilla.mozilla.org/show_bug.cgi?id=1235190) on 26-12-2015 and it was fixed on 07-01-2016. Mozilla awarded me 2500$ for this persistent XSS that can be used to serve malware, malicious campaign or drive by download. I was informed that soon Mozilla will release a notice/advisory here: https://www.mozilla.org/en-US/security/advisories/.

Further I found two more XSSes (low profile) i.e., one in Mozilla add-on (https://addons.mozilla.org/en-US/firefox/) and one in Mozilla Support site (https://support.mozilla.org/en-US/). The XSSes are not yet fixed and I will update this post once fixed will be deployed for these two XSSes. The XSSes are now fixed.

1) Self-XSS in Edit Review Feature of Mozilla Add-on Site: The bug can be found here: https://bugzilla.mozilla.org/show_bug.cgi?id=1237967 and deployed fix information can be seen here:

2) Self-XSS in Mozilla Support Mobile Site's Main Search Bar: The reported bug is here: https://bugzilla.mozilla.org/show_bug.cgi?id=1238252 and the deployed fix can be seen here: https://github.com/mozilla/kitsune/commit/8eefb30593013e1fb69ed4b4724ef5d457e020bf

Sunday, January 10, 2016

When Reflected Becomes Stored

In this post, I will discuss an interesting case of XSS i.e., when a classical reflected XSS becomes stored XSS. The transition from reflected to stored happens because developers convert user-supplied input into some form of encoding, make it part of a URL and permanently store it in the database. I was thinking why developers do this at first place? The apparent reason, I can think of from the top of my head is tracking or for analytic purpose e.g., popular searches. If you know any other reason, please let me know. At the same time, I think, this type of practice makes the exploitation easy i.e., an attacker may hide the payload as a part of legit URL. Vishal Sharma in his blog-post also points out that cloud-based WAF can be bypassable with the help of this feature of web application because WAF never sees the harmful payload unless decode.    

Lets see this with two real life examples from the wild. On the following URL: http://www.akc.org/, if you will enter a letter `a` in the main search bar and hit enter. The site will give you a URL that looks like: http://www.akc.org/search/YQ/. Now if you will query for the letter `b` in the search feature then site will ends up on a URL like: http://www.akc.org/search/Yg/. You may continue to see the behavior of web application on different inputs and may try to figure out the type of encoding in place. Lets input our harmless probe string "xxxxxxxx'yyyyy</img and as a result the site will give you a URL: http://www.akc.org/search/Inh4eHh4eHh4J3l5eXl5PC9pbWc/. The source code inspection shows the reflection of our interest in the following screen-shot.  


The screen-shot shows the probe string reflects back as a part of JavaScript's built-in function i.e., encodeURIComponent. The developers're using single quote (') for holding the value of function and it can be seen that single quote (') from the probe string ("xxxxxxxx'yyyyy</img) is not filtered or encoded. I already did a write-up on reflections in JavaScript's built-in functions. The XSSing in this case is not difficult. The payload '-confirm(1)-' does the job. The URL at the time of XSSing looks like: http://www.akc.org/search/Jy1jb25maXJtKDEpLSc/ and the screen-shot is also given below.


Now see another example in the wild (sorry for hiding the URL). The screen-shot shows the reflection of probe string but if you will see the value of SysSearch GET parameter, you will find some sort of encoding in the URL instead of hard-coded probe string ("xxxxxxxx'yyyyy</img). The screen-shot also show that < is not encoded in an HTML context. The game is over for them given < is not filtered or encoded in an HTML context.


The next screen-shot shows XSS with the help of simple and popular payload i.e., <img src=x onerror=confirm(1)>. The payload does not start with ' or " quotes because we're in HTML context. Please look at the value of SysSearch GET parameter. It is not hard-coded XSS payload but you will find encoded form.


If as a developer you still wants to use this type of feature then please make sure to follow the basic , well known and million dollar principle of "Filter Input,  Encode Output".
     

Friday, January 1, 2016

A Close Call

Happy New Year

It is not about sugar all the time ... salt is also there. In this blog post, I will discuss a unsuccessful case of XSSing but in the process, I hope some of you may learn something. At the same time, may be some of you're already successful in that particular case and have found that type of XSS earlier in the wild. For me, it is still in the TO DO list ... at least I haven't found it myself in the wild (may be I should browse more sites). In my case, all the time, it was a close call. In short, this is the case where reflection is in script block in general and back-slash (\) is not escaped. The \ is often not escaped in script block and we will see how we can leverage it for our benefit somehow. Further you will see that in live example cases given below " are properly escaped or filtered while < is encoded or filtered. If in script context " or ' or < are not controlled then game is over for the site.

Please open the following URL (the two GET parameters i.e., q & mediatype hold our harmless probe string "xxxxxxxx'yyyyy</img): 
    

The screen-shot given below shows the reflection of our interest i.e., inside script block. Please note that it is not common to control two GET parameters while at the same time getting reflection back in both cases. The screen-shot also shows " and < from the probe string were filtered so we can not use options like "; confirm(1); ", "-confirm(1)-" and </script><script>confirm(1)</script> respectively. 


As I said earlier, in this case, we can control two GET parameters and by keeping this thing in mind lets inject \ in the 1st GET parameter and 2nd GET parameter will have the value ; confirm`1`;//. I explain the injected values later. The screen shot shows injection and has a label of 1 and 2 for 1st and 2nd GET parameters respectively.


The URL looks like: http://foxsports.ramp.com/search?q=\&mediatype=;%20confirm`1`;// and the following screen-shot shows "Uncaught Syntax Error" you will get when you will open the URL. Why Uncaught Syntax Error? I think because of  \, the closing " in the variable declaration becomes special character (or asks for special treatment because it is now an escaped double quotes) and then browser tries to find the matching " which is not their or missing. It results in an Uncaught Syntax Error and for the browsers it becomes unparseable script. Please keep in mind we need " in pair for JavaScript string variable declaration,


This was a close call because we're unable to XSS it BUT what if in the JavaScript source code snippet as shown in the above screen shot, the "mediatype" variable declaration was in the same line (no line break) as "searchedTerm"? I mean something like ...

<script type="text/javascript">

/* other code goes here*/

 var searchedTerm = "reflection-here";   var mediaType = "reflection-here";

</script>

In that case our attack payload as can be seen in the URL http://foxsports.ramp.com/search?q=\&mediatype=;%20confirm`1`;// will work and the culprit will be \ (given " and < are either filtered or encoded as was the case here). Some of you might be thinking how and why? I try to explain it. In the source code, the attack payload looks like ...

<script type="text/javascript">

/* other code goes here*/

 var searchedTerm = "\";   var mediaType = "; confirm`1`;//";

</script>

Why the above JavaScript code works (some of you already have an idea) and why this time there is no Uncaught Syntax Error given everything was same except mediaType variable declaration was not in a new line?  The answer can be seen in the following screen-shot. 1) By injecting \ as a part of variable searchedTerm, we force browser to consider " as a special character or escape character because developers're using " for JavaScript string variable declaration in this case. The browser will digest this " because of  \ and will continue digesting stuff (it also includes ; which is a statement terminator) until it finds the closing ".  The browser will find the plain " after = symbol of variable mediaType. At the end of day, the value of searchedTerm variable will be "; var mediaType =. The next thing is ; which is a statement terminator because this ; is after the matching " and this will close the statement. The ; earlier as a part of variable searchedTerm was not treated as statement terminator because in reality it was enclosed in a pair of double quotes. 2) The next thing is a simple proof of concept JavaScript execution via confirm`1`;. 3) Finally we have single line comments (//) and their job in the attack payload is to neutralizes the effect of at the end. The explanation above shows all stars have been aligned properly and that's why no Uncaught Syntax Error.


The \ is often not escaped or encoded in script context and even Google guys missed it on Google Developers site. The following URL results in an Uncaught Syntax Error: https://developers.google.com/s/results/?q=%5C. In this case, again it was a close call because as an attacker, we can not control the second parameter. When you're testing the web application, the other potential venue where you may leverage \ for XSS would be JSON. My quest for finding this particular XSS in the wild will continue ...

Acknowledgement: I would like to thank Joel Weinberger for some discussion on that.