Sunday, February 28, 2016

Stored, Reflected and DOM XSS in Google for Work Connect (GWC)

Google for Work Connect (GWC) is "a community for system/application administrators and partners". GWC is in scope for Google bug bounty program though Google considers it a low priority application as far as reward amount is concerned. It is not about reward all the time. This blog (i.e., Respect XSS) is about XSS. Some time ago, I found Stored, Reflected and DOM XSS in GWC. 

Stored XSS

In GWC community, application administrators can share their ideas and help each other. The application allows users to create a document/posting/thread/message and among other features (e.g., mark as question, tags and category etc), the posting has a title or name and message body. The title of posting is of our interest in this case. The site was doing good in encoding < character into &lt; (if found in the title) (see screen-shot).


As you can see in the above screen-shot that < is encoded in an HTML context (i.e., <a> tag around reflection), so no need to waste time here. The site has another feature where one can do the same stuff but via Google Drive. The feature is labelled as "Add a file from Google Drive". In that case, at that time (now site has been updated and things may be bit different), the name of Google Drive file becomes the title of the post. The screen-shot shows the site's behavior when a file has been added from Google Drive. Please keep in mind that in Google Drive, I had first created a file named "xxxxxxxx'yyyyy</img>.PNG so that I can used that file here in GWC.


The screen-shot above shows reflection in GWC and and it can be seen that reflection was in script context in general and as a part of var declaration (i.e., object literal) in particular. The developers were using " for holding the title of file and at the same time, " and </ were not controlled or filtered or escaped. The XSS is now pretty straight forward, Please make sure that you have a file in Google Drive named </script><script>confirm(document.domain)</script>


This was an stored XSS because posting on GWC is available for all logged-in users. The root cause of this stored XSS was that GWC application forgot to control/encode/filter input from other application (i.e., Google Drive) though they were doing good on direct user-supplied input.

Reflected XSS

If somehow you're able to cause an error (e.g., file was not properly uploaded from Google Drive) in GWC then application throws an error message in a GET parameter named "googleDriveError". This GET parameter is vulnerable to a classical reflected XSS. Further if you're able to cause an authentication error, then application throws an error message as a part of GET parameter named "error". Both error related GET parameters were vulnerable and both were using the same code base. The screen-shot shows the reflection of our harmless probe string "xxxxxxxx'yyyyy</img as a part of  "googleDriveError" GET parameter.


It can be seen in the screen-shot that < is not filtered in an HTML context. It is enough of information. The next screen-shot shows reflected XSS in "googleDriveError" GET parameter followed by a reflected XSS in "error" GET parameter.



DOM XSS

I also found a DOM XSS in GWC. The culprit for DOM XSS was window.location.hash.substring(1) but the problematic JavaScript code executes only if someone marked/clicked the reply of a posting "Mark as Helpful". The vulnerable dynamic JavaScript code was part of a JavaScript file at that time (site has been updated and you will see a not found message). The vulnerable JavaScript code looks like ...

... {if(window.location.hash){c.scrollTo("a[name='"+window.location.hash.substring(1)+"']")} ...

There are two screen-shots given below. One shows where posting has not been marked "Helpful" and one shows where posting has been marked "Helpful". The DOM XSS payload was part of both cases but executes only in the later case.


GWC received an update recently so there is a great chance that this update has introduced some bugs. Happy Hunting ...  

Sunday, February 14, 2016

Keep An Eye On $.html, $.get and $.ajax Functions

The $.html(), $.get() and $.ajax() are potential XSS venues. Some of you're already aware of this but lets see real life examples from the wild.  Finding a real example from the wild is itself not an easy task but fortunately, I live on the web in general and view-source in particular, so I found one. At the same time, instead of cosmetic bypasses i.e., bypasses based on assumptions or without examples or bypass for the sake of bypass, I am only interested in real cases. It is always good to see how developers use jQuery's features in the wild. Some time ago I did a blog post on third-party jQuery based sinks.

$.html(htmlString)

According to jQuery, $.html(htmlString) sets the HTML contents of each element in the set of matched elements. Please open the following URL.


The screen-shot shows the reflection of our interest i.e., in $.html(htmlString) function. The developers're using single quote for holding the HTML contents inside $.html(htmlString) function and it can be seen that ' from the probe string ( i.e., "xxxxxxxx'yyyyy</img) is not controlled.


The XSS in this case should not be a problem. The URL at the time of XSSing is given below and the screen-shot is also there.




$.get()

According to jQuery, $.get() loads the date from the server via HTTP GET method. Open the following URL (q GET parameter holds our harmless XSS probe string i.e., "xxxxxxxx'yyyyy</img).  The screen-shot shows the reflection of probe string in $.get() function.



It can be seen in the screen-shot that developers're using " for holding the value of first parameter of $.get() function i.e., url and " is not filtered or encoded or escaped. The XSS in this case should not be a problem and it is simple and straight forward. The URL at the time of XSSing is given below and the screen-shot is also there.



$.ajax()

It is used to perform asynchronous HTTP request. The screen-shot shows the reflection of XSS probe string inside $.ajax() function. The developers're using ' for the data section of $.ajax() and it can be seen that ' is not controlled. Further </ is also there in its hard-coded form. I would like to refer you to the article for the detailed syntax of $.ajax().



It is an easy and simple task to XSS this case given ' and </ are not controlled in $.ajax() function. The XSS attack payloads like '-confirm(1)-' and </script><script>confirm(1)</script> work here. I already explained in earlier posts how payloads like '-confirm(1)-' or "-confirm(1)-" work. The screen-shot shows an XSS.


Before conclusion, I would like to say that I am still looking at $.post() and $.load() based XSS in the wild ( both are also potential XSS venue ). If I will find one, I will update this post. I conclude on a saying: "Simplicity is natures first step, and the last of art." Philip James Bailey.

Sunday, February 7, 2016

Find The Root Cause

This time instead of publishing a new blog post, I present two real life XSS example cases from the wild. I already XSSed both cases for you. Your job is to find the root cause and explain it in the comment section or send it to me via Twitter or email. The first best detailed explanation of the following two real life example cases will receive a small token of appreciation from my side. 

1) Open the following URL in Firefox browser:


The screen-shot is also given below.


Your task is to explain how this XSS works to a naive user or beginner. A sort of indirect hint is available in one of my earlier blog posts.

2) Open the following URL in Chrome browser:


Isn't my harmless XSS probe string ("xxxxxxxx'yyyyy</img) part of URL :D The screen-shot is also given below.


Your task is to explain this XSS to a naive user or beginner. In fact the root cause of this XSS is: developers often do not follow the very basic and first principle of security.

I hope it would be fun.

Participants

-- Serious effort by @Zemnmez:

http://pastie.org/private/zgr3xxoj7e6shanmixrlwhttp://pastie.org/private/lpxgyc9iikn9z674pswsqg

-- Attempt by @omeriko_9:

https://twitter.com/omeriko_9/status/696299928717565952