Pages

Showing posts with label Cross site Scripting. Show all posts
Showing posts with label Cross site Scripting. Show all posts

Friday, August 14, 2020

Leveraging JSONP to SOME via HTTP Parameter Pollution


Introduction


When you see a callback control in a JSONP endpoint doesn't that make you want to execute XSS? But, there's always this "text/javascript" (or similar) content-type that stands in the way.

During BlackHat 2014 I presented Same Origin Method Execution (SOME) attack. This talk explains how to abuse callback endpoints to execute javascript methods in a vulnerable domain.

Nowadays, finding vulnerable callback endpoints got harder as passive content-types dominate the web. While the vulnerable, active content-types like "text/html", "Adobe Flash" or "ActiveX plugins" are less common. In the second SOME talk during HackInTheBox 2017, I shared the hint of my ongoing research:



"JSONP is NOT vulnerable without a chain"
(slide 16, under "What are the vulnerable endpoints?")


As I was always "too busy", on Jun 7, 2020, @kinugawamasato released the following tweet:
His callback challenge was similar and inspired me to share my research in the form of a my own XSS challenge.


The Challenge


The challenge goal was: chaining HPP to SOME, then bypass a strict CSP policy and get arbitrary cross-site scripting.

For almost 2 months (Jun 18, 2020 - Aug 14, 2020) only 4 players solved it. Even though, on July 1th, Masato released the solution to his challenge.

The following is a the original tweet:



Challenge Structure


The challenge was consisted of 3 pages:
  1. index.html - Static Page
  2. connect.php - JSONP endpoint 
  3. purify.js - Cure53's DOMPurify

Entry points

index.html:
  • "client_id" - URL parameter
connect.php:
  • client_id - URL parameter - Limited control of up to 38 characters (<= 38)
  • callback - URL parameter:
    • Limited to classic callback characters:[a-z0-9.]+/i
    • Blocked the string "write" to avoid using "document.write"

CSP Policy


The script-src directive only allow scripts with a valid nonce (I did not use a random nonce but players were instructed to assume it's dynamic for every page load).

The Challenge Workflow


On page load the index.html page:
  1. Calls "init();" to insert items from the rules array which is defined on the global scope. 
  2. Calls "connect(client_id)" to trigger the JSONP endpoint at "connect.php" while appending client_id as a parameter.
  3. Listen to JSONP which calls back with "callback(response, status)".
  4. Render the response as HTML safely using Purify's sanitize function.

Unintended Solution

Slightly after I uploaded the challenge it was possible to skip the harder steps of the challenge as I forgot to include "base-uri 'none'" - that was quickly fixed.





The Solution



To solve the challenge one had to complete several steps:

  1. Control the method execution using a callback (SOME attack).
  2. Abuse the lack of X-Frame-Options to obtain multiple method execution. 
  3. Inject arbitrary HTML limited to 38 characters.
  4. Bypass CSP to execute XSS while abusing "strict-dynamic".
  5. Navigating the DOM tree to overcome character limits.

During my talk in 2017, I already published the instructions for solving steps 1-2 and step 5 (slide 34-43) as part of SOME white paper and slides.

Before we dig into the details the following is the challenge solution:


Run the Solution

Here is a simplified version of the solution:

top.frame.rules.push("Error: '<iframe srcdoc='<script></script>'>'","406: Not Acceptable")
top.frame.init("Error: 'x'","406: Not Acceptable")
top.frame.itemsList.lastElementChild.previousSibling.previousSibling.previousSibling.firstElementChild.contentWindow.document.head.firstElementChild.append("Error: '';parent.x=parent.document.scripts//'","406: Not Acceptable")
top.frame.itemsList.lastElementChild.previousSibling.lastElementChild.contentWindow.document.head.firstElementChild.append("Error: '';alert(parent.x[0].nonce)//'","406: Not Acceptable")


Solvers🎉

Thankfully 4 of the players were above all others and solved this challenge relatively fast! All with the intended solution, though some used shorter and cleaner code to solve.
The first to solve was @kinugawamasato the great, followed by 3 other fantastic players: Roman Shafigullin (@shafigullin), terjanq (@terjanq) and Luan Herrera (@lbherrera_)


Deep Dive


Method Execution via HTTP Parameter Pollution

☑️  Method execution can quite simply be controlled by abusing HPP.

Reviewing the javascript code of the main challange page (Specifically the 'DOMContentLoaded' event listener) reveals that it accepts the search parameter: 'client_id'. This parameter is later used by the 'connect' function to append a script to the page.

Injecting "%26callback=alert" to this 'client_id' parameter allows us to overwrite the appended script url ("connect.php" endpoint) callback parameter and therefore get control over the method to execute.




This however will only execute an alert, which will not allow stealing the CSP nonce or executing arbitrary XSS.

Multiple Method Execution

Multiple Method Execution is all about constructing a gadget and reusing existing code.

  1. Setting up 5-6 windows (iframes) based on the amount of methods we want to execute on the challenge page.
  2. Abusing the JSONP endpoint with designated callback parameter by navigating each window context.
  3. Controlling the execution order.

I've described the impact of executing multiple methods using SOME and how it can be as bad or nearly as bad as XSS throughout the SOME white-paper.

Pushing 38 Bytes of Arbitrary HTML

The first real step of the challenge was to "plant" HTML code into a globally defined array named "rules". This could be achieved using the native Array.push function:

	top.frame.rules.push("Error: '<iframe srcdoc='<script></script>'>'","406: Not Acceptable")
	

Once we have arbitrary HTML in "rules", it is possible to use the JSONP endpoint again, this time to execute the "init()" method defined in a whitelisted script. The code at "init" uses innerHTML to inject the rules array items along with the smuggled 38 bytes of HTML payload!

Injecting the HTML:
top.frame.init("Error: 'x'","406: Not Acceptable")
We now finally have arbitrary HTML injection!

☑️ HTML injection (of 38 bytes)

Bypassing Content Security Policy

The server was setup to block anything but allowed scripts using the following CSP directives:

Reading the policy, one can spot a bold hint I left there, that is the strict-dynamic directive.

This step made quite some players struggle, as it was about abusing strict-dynamic to make a non-"parser-inserted" script element execute javascript code.


What is strict-dynamic?

A simple explanation can be found in content-security-policy.com:

The key super power of strict-dynamic is that it will allow whitelisted scripts to load additional scripts via non-"parser-inserted" script elements.

So how do you create a non-"parser-inserted" script element? Here's an example:
			var s = document.createElement('script');
s.src = "https://cdn.example.com/some-script-you-need.min.js";
document.body.appendChild(s);
		

That is a great, but at this point in the challenge executing such code is impossible.

Yet, is that the only way we can create non-parser inserted scripts?


Empty Script Nodes


If we carefully read the HTML5 spec we can notice the following:

"A script element has a parser document, which is either null or a Document. Initially, its value must be null. It is set by the HTML parser and the XML parser on script elements they insert, and affects the processing of those elements. script elements with non-null parser documents are known as "parser-inserted"."

So if the script tag has content, it’s already considered as “parser inserted”.


Creating Scripts with null parser documents


The key point players had to figure out is that script tags's parser documents are initially null ("Initially, its value must be null") and therefore, an empty script has a null parser document and will not be executed by the html parser.

Here how to abuse this for solving the challenge:

<iframe srcdoc='<script></script>'></iframe>

Notice this payload is 44 bytes (>38) and is blocked by "connect.php" length limit. Luckily, we can drop the "</iframe>" and the browser will "guess" it needs to close the tag for us. Once we have a non-parser inserted script it is now finally possible to abuse strict-dynamic.


☑️ non-parser inserted scripts

XSS via Node.append

The final part in the challenge can be broken down into 2 main steps

  • Navigate the DOM to obtain a reference to the empty script, and
  • Find a method that allows adding content into the empty non-"parser inserted" script tag.

All there's left to do is to construct a valid javascript code and append it to the script node:

top.frame.itemsList.lastElementChild.previousSibling.previousSibling.previousSibling.firstElementChild.contentWindow.document.head.firstElementChild
// Returns a refernce to the injected <script> Node
scriptNode.append("Error: '';alert(1337)//'","...")
// Adds content to the script tag and executes

☑️ Bypassing CSP for arbitrary XSS

Run the Solution

This writeup took longer than expected but I hope you enjoy it as much as I enjoyed writing it.

Thanks you all who played!

Monday, May 25, 2015

Stealing Private Photo Albums from Google - Same Origin Method Execution


It has been a long time since I updated this blog since I focused on company blogs and Black Hat presentations for the last couple of years. It is time to kick in with details about the vulnerable Google instance I was demonstrating during my Black Hat EU presentation – Same Origin Method Execution. Using that instance and a payload of only alphanumeric characters and a dot I was able to hijack web functionality and thereby delete or steal private photo albums from Google Plus. A white paper is currently in review stages and will be released next week in my next post! 



Same Origin Policy and OAuth overview:

From time to time and for numerous reasons web applications interact with external third-party services. Some of these reasons may be importing information (e.g. import contact list), notifying events, getting delegated access to resources such providing a "Login with" systems and etc. 


Since an external service often (if not always) means a different security context, interacting with it will require overcoming Same Origin Policy (SOP). One of the most common interfaces for such third-party interaction these days is using OAuthentication dialogs. OAuth dialogs are hosted on third-party resource providers and are designed to ask the resource owner (the user) to allow/deny access from the website to the user's (resource owner) private resources. Once an answer is given the dialog will redirect (call) the user back to a callback page hosted on the website which asked for access, this page is called the “callback endpoint”. The purpose of the callback endpoint is to receive a token from the third-party and notify the requesting website. Although, since no best practice was created for building callback endpoints, the technique web developers use to save the token and notify the initiating page (call it back) is based entirely on developers’ habit and experience. Therefore many times callback endpoints end up prone to “Same Origin Method Execution”.


The vulnerable instance:

How many times have you noticed a "Login with", import contacts or friend lists from third-party service? 



As in many other websites Google Plus provides an option to import external contacts information from third-party resource providers such as Yahoo and Microsoft, Prior to the responsible disclosure the authorization process occurred as follows:

  1. Google Plus opened a pop-up for the OAuth dialog asking secure delegated access to the user’s external contact-list on Yahoo/Microsoft, to avoid losing the currently open document content.  
  2. After the user allows/denies the access, the dialog window document is redirected to a Google Plus callback endpoint consisting a callback URL parameter.
  3. The endpoint page uses the value provided by the parameter to notify the opener and deliver the access token (JSONP style).
Callback endpoint URL:

https://plus.google.com/c/u/0/auth?src=connectedaccounts&callback=callback_function_name&dest=microsoft2&[...snip...]
Accessing the callback endpoint URL directly responded with the following markup:

<html><body><script type="text/javascript">
window.opener.callback_function_name({"status":0,"token":"ItHumYWI[...snip..]","oauthstate":"1234","tokenid":"ToKeN1234","tokenexp":"0","gid":"401223423..","siteid":6,"displayname":"Ben Hayak","profileurl":"http://profile-url.com"});
</script></body></html>



Is that Cross-site scripting?

Of course the first thing to try here was Cross-site Scripting, although fortunately ;) in similarity to most callback endpoint implementations only a specific set of characters were allowed as a callback value specifically alphanumeric a dot and underscore [A-Za-z0-9_\.]. We can however use tricks like document.write, eval, etc, though as aforementioned in the markup above no user controlled input got inside the parenthesis so XSS is out of the question.


“NULL means no!?”

When accessing the callback endpoint directly the window.opener property is null, so it appears that the instance is not vulnerable. However there is a technique to control the opener window. The first idea that came to mind was to create a bug chain, by finding another page in google plus that will force opening a window with an arbitrary URL and combine that with the callback endpoint. Although finding such a page is a little too rare and will weaken the attack.


Window Objects in memory:

So let’s try different approach, I wanted to entirely control a window and set its document to whatever page in Google Plus and then tell the Google Plus callback endpoint “This is your opener window deal with it”. That’s exactly what you can acheive in “Same Origin Method Execution” all you need is a page that opens another window and a set of redirection and you can designated any window as the opener and start hijacking methods! The key element that makes this a successful approach is the nature of user agents. When a window document is being redirected its window object remains at the original allocated memory space, therefore any other window/s that holds a reference to it as “opener” can still use the reference to access the opener window even after the document changed/redirected.

If window A opens window B, the user agent will create a reference to window A as window.opener property of window B, when window A’s document would change (redirect) the reference won’t be cleared/deleted and window B can still use the opener property to reference it.

So the answer is pretty clear, all there’s left is to make a malicious html that will open another window via “window.open(‘/step1.html’)” , then redirect the first window to a designated document on Google Plus, and redirected the pop-up window to the callback endpoint. This way you can set any page as the opener of the callback endpoint.



Stealing Private Photo Albums with SOME:

I covered how to control an opener and abuse a vulnerable callback endpoint to execute any DOM/Javascript function at the context of the opener window. All there’s left is to choose a page containing an interesting web functionality and use only alphanumeric and a dot to assemble a payload that will hijack this web functionality (Similar to the impact of CSRF but we don’t mind CSRFTokens or other protective mechanisms).

The target document I used:

Google Plus can automatically backup private cell photos to Google servers in case G+ is installed as a mobile application on your phone. Fortunately Google created a service called “Google Picker” which allows users to share their photos, videos and documents stored in Google servers with third-party websites.

Now that I've designated a target document (Google Picker) I setup the attack page as follows:
  1. Set a page that opens two pop-up windows to control their opener.
  2. Redirect the page to Google Plus instance of Picker.
  3. Wait for the DOM to complete loading.
  4. Redirect the first pop-up to the vulnerable callback endpoint with a callback parameter set to: document.activeElement.parentElement.parentElement.parentElement.previousSibling.lastChild.click
  5. Redirect the second pop-up to the vulnerable callback endpoint with a callback parameter set to: pickerApp.V.Fa.PA which made the service send all the selected photos to my own domain.
  6. Send the malicious setup to a chosen victim (In my case Google Bug bounty responsible disclosure :)
The exploit resulted in hijacking the following JavaScript functions:
  1. window.opener.document.activeElement.parentElement.parentElement.parentElement.previousSibling.lastChild.click({JSONDATA});
  2. window.opener.pickerApp.V.Fa.PA({JSONDATA});


This flow could make any user send every single photo from his/her private album to my server.

BlackHat EU Video:




Additional use cases: 
I exploited the same instance to delete Google Plus timeline posts. 



Note: The issue is now fixed as it has been reported to Google bug bounty program.



Hope you enjoyed reading!





Wednesday, June 27, 2012

Google Mail Hacking - Gmail Stored XSS - 2012!

Gmail Accounts Hacking Risk 2012! 

Millions of users use Gmail as their information center to perform actions such as Business, Chat, Place Orders, Payment confirmation, main password recovery mail for different web services and so on...
many people - including myself use Gmail to store and save important and personal data, none of us want our data to be at risk of steal, manipulation, and obviously not considering the Gmail account being completely hacked!
I found a possibility to do all that!


Fortunate enough for us, Google is taking a lot of efforts securing their services. mostly by doing a great job, which integrates supporting a vulnerability reward program.


I made a quick research and reported this vulnerability along with all the related details. 
I must say Google's response was very quick and so as their fix. (it is Fixed)


as it appears here :Vulnerability Reward Program even after the bounty raise:
Google's Reward for this bug: $1337 (mail.google.com)
PoC Picture:


Technical Details: 

I am quite busy at work and personal life at these days so I placed a side the reward programs of Google, Facebook And others.


I was just checking my mail the other day and I noticed something different.
Google made this nice change in Gmail , apparently around December 2011 - Google Adds circles to Gmail 
"Users can now Filter their Mails based on their Circles"


Trusting your Google+ Friends?

When I clicked this Gmail Circles feature, I saw my Google+ connections: profile pictures, nicknames and some other circles related data 
Do they Control this data?! - Yes!
I had to spend some time back in the business, Gmail Stored XSS is a serious finding!

So I imminently researched that feature's JavaScript code.
It appeared that data that comes from Google+ was not sanitized by Gmail!

    zk.prototype.Ca = function $pn(a, c, d) {
        this.xa = 0;
        if (!this.ea) {
            //Shorten/removed
            var e = this.Bb.zb().body, g = this.ea.va();
            //Shorten/removed
            e.wa = h
        }
        a: {
            if (d)
                switch (d.toLowerCase().split(",")[1]) {
                    case "l":
                        break a;
                    case "r":
                        /removed;
                        break a
                }
            e = 2
        }
        this.wa.setPosition(cka(d), e, i, -1);
        jc(this.ea.va(), "T-ays-avH");
        ud(this.ea.va(), 0, 0);
        this.ea.Mc().innerHTML = c; //c = Data from Google+;
        this.wa.To(a);
        this.wa.Me(k, 0)
    }; 


This Gmail Code was creating a Tool-tip that Included profile circles information that comes from your Google Plus friend's account, if they used a payload, your mail account would have been at a serious risk.


Exploiting the Vulnerability - malicious Google+ Account.


As First it is important to note that Anyone that already got accepted as your friend in Google+ could trigger this attack on your Gmail account!

So all that is left is crafting a very nice Google+ account with some attractive profile, then after this evil account gets many friends/victims - Attack em all!

Google+ was and still is blocking the possibility of using a payload in the required field that was used to trigger this attack, but I found a way around it, sorry but I cannot reveal how I did that. (I am sure some of you pros might know how).

After I used my technique and crafted the Google+ evil profile it was possible to attack Gmail of all of that profile's friends! 


PoC Picture: 



As always I appreciate the opportunity to preserve my skills and gain some more experience
Thank you Google security team.


"Ben Hayak" - Google Security Hall of Fame Page
http://www.google.com/about/company/halloffame.html



Friday, June 15, 2012

Layer3 DOM XSS in Latest jquery - Etsy

Turning Useless Self DOM XSS into a treat!

During my research and study over DOM XSS and developing my own detection technique, I found this interesting case which a DOM XSS undetected by any DOM XSS scanner I came across triggered, so I decided to share and provide a quick overview of how I took this self layer 3 DOM XSS into a Working and exploitable DOM XSS.
it all started with this small code:

1
2
3
4
<script type="text/javascript">
Etsy.loader.require('jquery.ba-hashchange');
Etsy.loader.require('help');
</script>

This is Going to be a long one but this covers:

  • DOM XSS.
  • Logic Flow Exploitation .
  • JQuery Vulnerability (Latest release - Unpatched yet).


Final Conclusions:
1. 1st conclusion(easy) the main javascript layer loads a second dynamic block (covered)

2. the payload goes through the dynamic code block and inside gets through a filter to avoid DOM XSS (appears as Self-Only).
3. the layer 2 code block loads another layer(3) this time it is jquery, and then exectue a function that is vulnerable to DOM XSS(latest version 1.72 and older versions as well).

Self DOM XSS?

using the help section search feature I could trigger a very simple XSS by typing the payload in the search box and hit search X_X,This is pretty lame. 
(once I used a payload directly in the url it got filtered without trigger)
We need the victim to be careless enough to actually type the payload and click the search button. I consider this situation as almost worthless and low risk Self XSS,
so I thought this might be useless and not exploitable.

Strange Behavior (not so fast...):

But, that is when I noticed a strange behavior! Look at the picture below:
 (using a payload of <img src=1 onerror=javascript......>)



Something strange?

If you do not see it you should gather yourself and look more carefully next time you think you covered the security holes and were about to report: not exploitable or low risk vulnerability.



What is so strange?


what you can see in the picture is that the XSS triggered (<img src=1> TAG) and for some reason the payload "disappeared" from the URL Query right?

Oh wait, was it??? No!
It was only filtered! the query is now changed to "http://site.com/help/2643#/afsddddddd/1" where did that "/1" came from? what is going on?
let us run more tests:
Look what happens when I used this URL:
"http://site.com/help/2643#/String     2ndString/1"

The filter turned it into the following:
http://site.com/help/2643#/String/2ndString/1

Now that is definitely worth a deeper look at the code loaded as layer 2:


Filter Details (YES It is vulnerable):

The Filter was checking for location.hash, and replaced any space with a "forward slash" to separate the query string as well as replacing any potential XSS HTML Tag with NULL using a regex.

seems right, but, There was a HUGE Security Hole.

Final Conclusions again:
1. 1st conclusion(easy) the main javascript layer loads a second dynamic block (covered).

2. the payload goes through the dynamic code block and inside gets through a filter to avoid DOM XSS (appears as Self-Only) (covered).
3. the layer 2 code block loads another layer(3) this time it is jquery, and then execute a function that is vulnerable to DOM XSS(latest version 1.72 and older versions as well).

HUGE Security Hole in legitimate XSS Filter:


This is where the magic happened! there is a javascript code block condition, this condition determines if the user is actually using the search feature and should be checked for DOM XSS using the layer 2 code block javascript code or not.
after researching all the relevant code in the javascript filter block, it appeared that exploitation is pretty simple!
legitimate behavior:
http://site.com/help/2643#/PAYLOAD/1

So once the search string starts with Forward Slash "/" the condition match, the system consider this a legitimate safe search, and the filter will replace any payload with NULL then pass filtered payload to a vulnerable jquery function.

Remember! This is a DOM event that executes jquery!

So what had to be done is:
1. Insert a Forward slash into the global URI (Before the hash sign).


2. Then insert the payload into the client-side only URI (Right after the hash sign without a slash)

Logic flow Vulnerability:
This way I managed to Trick the system to pass the Forward Slash Condition, and cause the filter to fail and step over the regex to the next stage of passing my payload directly into the vulnerable jquery function!

Final Payload:
http://site.com/help/2643/#<img src=1 onerror=javascript:alert('EXPLOITABLE!')>




but why is this vulnerable?


Vulnerable DOM XSS CODE - 

JQUERY(line 10):



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
(function(){
        o=$("#attachment-shim");
        k=$("#file-form");
        var a="iframe"+(new Date).getTime();
        g=$('<iframe id="'+a+'" name="'+a+'" />').hide();//<iframe id="iframe1334892619493" name="iframe1334892619493" />

        k.attr("target",a).after(g);
        o.bind("change",q);
        if(a=window.location.hash.substring(1)) // sets a to "<img src=1 onerror=javascript:alert(1)>"
if($('a[name|="'+a+'"]')[0]) { // GAME OVER we got our Executer "a[name|=\"<img src=1 onerror=javascript:alert(1)>\"]" (later will be parsed with jquery " for(s.innerHTML=m[1]+l+m[2];o--;) "
            a=$('a[name|="'+a+'"]').parents("div.topic");
            a.find("ol span").removeClass("bottom");
            a.find(".view-less").show();
            a.find(".view-all").hide()
        }
        else m();
        f=true;
        topic_box=
        $("#topic");
        topic_box_val=topic_box.val();
        if(topic_box_val!=0||$("#message").val()!=""){
            d=true;
            h=topic_box_val;
            n()
        }
        
    })()
});

inside this "IF" Condition(line 10) there is a call to a vulnerable jquery function:

if($('a[name|="'+a+'"]')[0])


Which executes a function in jquery code that include the following line:
for(s.innerHTML=m[1]+l+m[2];o--;)

after bypassing all of these conditions our payload will be stored in "l" variable like this

l = "<img src=1 onerror=javascript:alert('DOM XSS')>"
and as a result of the for loop, will be injected into the innerHTML of the page triggering the XSS.

After I reported I noticed that, I never knew but it seems like there is an opened ticket in jquery bugs,
Reference: http://bugs.jquery.com/ticket/9521

Final Conclusions again:
1. 1st conclusion(easy) the main javascript layer loads a second dynamic block (covered).
2. the payload goes through the dynamic code block and inside gets through a filter to avoid DOM XSS (appears as Self-Only) (covered).
3. the layer 2 code block loads another layer(3) this time it is jquery, and then execute a function that is vulnerable to DOM XSS(latest version 1.72 and older versions as well) (covered).


It is always fun when web applications are open for a vulnerability report allowing me to research over these very interesting security flows that requires combining all the pieces together.


Thank you etsy!
Etsy Thank you list: http://www.etsy.com/help/article/2463

Tuesday, May 8, 2012

Twitter Vulnerability Potential XSS Worm!!! another hero?

Twitter is one of the leading social networking and information sharing system these days.
I have recently discovered(and reported) a XSS vulnerability that if not reported could lead to something similar to "HyHack is my hero"  ;).

For whoever of you who did not know, Twitter Implemented a feature called "Lists", this feature lets any user  the ability of adding anyone, without any terms or relation to the "follow" mechanism (they don't have to follow the attacker and vice versa)*, to his malicious XSSed list.

The reason of this being so High Risk stored XSS vulnerability, is that the attack potentially triggered on anyone who entered the attacker's profile "Lists" using a mobile. after a victim got infected, the attack triggers again and infect anyone who will view the victim's "Lists" and anybody who will view theirs and so on... (only victims that will use a mobile will get infected! reminds you of something? )

*I did not test if a user can add a protected (locked) people to his lists.  any comment on this will be appreciated.

PoC Picture watching the victim's profile:

The effect of this XSS is ONLY on victims that use twitter on Mobile!
I most say the lists feature was not fully implemented in the browser at the time I was testing, so most of my testing performed on the "Me" tab.
Twitter did a great job resolving this vulnerability very quickly (~Day after my report), and placed my name in the Twitter Security Whitehats page(2012) later on.
I would like to thank Twitter for their work and for giving me the opportunity to report a responsible disclosure and help keeping Twitter Users safe.

Saturday, April 2, 2011

Google Security Vulnerability Reward Program: Google Adwords Billing poisoning

Overview
Google Adwords Google's Online Advertising service, boost website traffic and sales, was vulnerable to a persistent XSS in the Billing information.

What Had to be done?
                            
The Billing information details was vulnerable to a persistent xss in 5 different fields.
The locations were:
Business name,
Contact name:
both Street Addresses, and City.
This attack was performed by editing the billing information with the right xss payload (no special bypass required).
This XSS is so persistent that it isn't possible even for the administrator to delete the poisoned billing information.


Screen shoot:

This issue has been fixed by Google security team.

I appreciate the opportunity to preserve my skills and gain some more experience
Thank you Google security team.

Tuesday, March 22, 2011

Google Security Vulnerability Reward Program: Take Control Over Adwords Service!

Overview
Google Adwords Google's Online Advertising service, boost website traffic and sales, was vulnerable to a persistent XSS in the main page Dashboard!

What Had to be done?

Well, here I discovered that the Dashboard page stored the Campaigns and the Ad groups as 'widgets' so I went for it and found it was vulnerable. this attack target could be anyone in the adwords service either 'read only','standard' or 'Administrator' access of course, a member who can edit/add Campaigns can take control over the administrator's account and perform actions with administrator permissions as for example attacker could cause the administrator give the attacker admin access with a malicious javascript payload , without the need of any user interaction from the administrator this attack will trigger as soon as the admin or the other victim, enters the adwords service. this way I could perform session hijacking or take control over the account.

Image triggering the xss on the
Vulnerable location #1 (Campaign):


Vulnerable location #2 (Ad Group):

This issue has been fixed by Google security team.

I appreciate the opportunity to preserve my skills and gain some more experience
Thank you Google security team.

Sunday, February 27, 2011

Google Security Vulnerability Reward Program: Google Website Optimizer - Stored XSS

Overview
Google WebsiteOptimizer Google's free website testing and optimization tool, missed a very important check when people create their experiments. additionally they made it more easier to exploit.

What Had to be done?

The first step was creating a new experiment I preferred A/B Experiment, then I had an option to add URLs to verify my website is real, as first I inserted some string "BenHayak" for example and pressed continue.
After that screen I had an option to throw the dirty job over to my "Webmaster" - "Your Webmaster will install and do the dirty work for you ;)". Great they give me a link to Google domain validation page with links to BenHayak when I clicked it I noticed it opens a page with only "BenHayak" in the address bar.
Then I made another Experiment filled with many javascript:alert('BenHayak'); and sent this stored xss report alog with recommendation to always check for "http://" in the input.

POC link: Click to trigger the Alert stored xss

Image triggering the xss:


I appreciate the opportunity to preserve my skills and gain some more experience
Thank you Google security team.

Thursday, February 17, 2011

Google Security Vulnerability Reward Program: Google Bookmarks Stored XSS

Overview
Google Bookmarks lets you create an online bookmark lists. I found this one in the "New Section" function. In order for this XSS to trigger though, the victim had to edit your section.

What Had to be done?

The first step was creating a new bookmark list. After I got that done, I created a New section with Image tag poisioned with XSS payload. The final step was inviting the victim by giving him/her access to my bookmarks list.



This issue has been fixed by Google security team.

I appreciate the opportunity to preserve my skills and gain some more experience
Thank you Google security team.

Wednesday, February 16, 2011

Google Security Vulnerability Reward Program: Google Finance Stored XSS

Overview
Google Finance lets you create Portfolios. After a few tries I figured a method to 
Trigger XSS using portfolio name.

What Had to be done?

OK, at First I used different payloads in the Portfolio name but nothing triggered,
but after some more research I found that after I create my Portfolio payload and click on one of these Deposit / Withdraw my Portfolio name is inserted into this function
function initPage() {
initVars();
dview = google.finance.portfolio.init({
id: '8',
expected_hash: 'U66jb3VTR2ZPUjgtaXJqaXRZc2s33VNmVWdjfDEyOTc4NzE22NDk',
edition: 'us',
name: '--XSS PAYLOAD--',
currency: 'USD'
}, true,
'/finance/s/7skxqAM7Z8M/chart9.swf?hl=en&gl=us',
true
,
false,
''
);
name: '--XSS PAYLOAD--' , so I inserted this payload as portfolio name: </script><body onload=alert(1)>  there was a filter that when you insert this </script> the server removed everything before the </script>


I appreciate the opportunity to preserve my skills and gain some more experience
Thank you Google security team.