<?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; PHP</title>
	<atom:link href="http://insanesecurity.info/blog/tag/php/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>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>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>OWASP Code Review Guide</title>
		<link>http://insanesecurity.info/blog/owasp-code-review-guide</link>
		<comments>http://insanesecurity.info/blog/owasp-code-review-guide#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:25:00 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=50</guid>
		<description><![CDATA[Code review is probably the single-most effective technique for identifying security flaws. When used together with automated tools and manual penetration testing, code review can significantly increase the cost effectiveness of an application security verification effort. (Introduction) The first section (Methodology) walks you through the: introduction to code review, preparation for code review, security code [...]]]></description>
			<content:encoded><![CDATA[<p>Code review is probably the single-most effective technique for identifying security flaws. When used together with automated tools and manual penetration testing, code review can significantly increase the cost effectiveness of an application security verification effort. (<a href="http://www.owasp.org/index.php/Code_Review_Introduction" target="_blank">Introduction</a>)<br />
<span id="more-50"></span><br />
<img src="http://insanesecurity.info/wp-content/uploads//owasp-code-review-guide.jpg" style="float:right;margin: 0 0 0 4px" width="200" />The first section (Methodology) walks you through the: introduction to code review, preparation for code review, security code review in software development life cycle (waterfall and agile), security code review coverage, application threat modeling and code review metrics. From this first section I&#8217;ve found very interesting the &#8220;application threat modeling&#8221; page, because I never did know how to classify (evaluate) the risk of a vulnerability and it really made me understand a lot about it.</p>
<p>The next section of the guide is about crawling code, what to look for in JAVA/ASP/JavaSript.</p>
<p>I&#8217;ll skip the rest (I&#8217;ll let you discover it) and only mention the &#8220;example by technical control&#8221;, section which I would recommend to any web developer (regardless of language) because It points out every aspect for the following technical controls: authentication, authorization, session management, input/data validation, error handling, secure deployment, cryptographic controls.</p>
<p>That being said, you can read the guide on-line at <a href="http://www.owasp.org/index.php/OWASP_Code_Review_Guide_Table_of_Contents" target="_blank">owasp.org</a>, or download the pdf version from <a href="http://www.lulu.com/content/5678680" target="_blank">lulu.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/owasp-code-review-guide/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP 5.2+ Data Filtering Extension = BAD?</title>
		<link>http://insanesecurity.info/blog/php-5-data-filtering-extension-bad</link>
		<comments>http://insanesecurity.info/blog/php-5-data-filtering-extension-bad#comments</comments>
		<pubDate>Wed, 24 Jun 2009 06:15:30 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Discussion]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=44</guid>
		<description><![CDATA[Yesterday while browsing some security tagged discussions on stackoverflow.com I&#8217;ve noticed someone mentioned some filter_ prefixed PHP functions. At first I thought they were some custom written ones, but on a quick check it turned out that there really where this functions. I was shocked. Anyway, let&#8217;s digg into it&#8230; Filters In the filters extensions [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday while browsing some <a href="http://stackoverflow.com/questions/tagged/security" target="_blank">security tagged discussions on stackoverflow.com</a> I&#8217;ve noticed someone mentioned some filter_ prefixed PHP functions. At first I thought they were some custom written ones, but on a <a href="http://www.php.net/filter" target="_blank">quick check</a> it turned out that there really where this functions. I was shocked. Anyway, let&#8217;s digg into it&#8230;</p>
<p><span id="more-44"></span><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>Filters</h2>
<p>In the filters extensions we have 3 types of filters: validate, sanitize and other filters. Let&#8217;s take em each separately and see what the extension has to offer us.</p>
<ul><big><strong>Validate Filters</strong></big></p>
<li>
<ul><big><em>Data Type Validation</em></big></p>
<li><code>FILTER_VALIDATE_BOOLEAN</code>
<p>        Validates if the specified variable/value is a boolean value.
      </li>
<li><code>FILTER_VALIDATE_FLOAT</code>
<p>        Validate if the specified variable/value is of type float.
      </li>
<li><code>FILTER_VALIDATE_INT</code>
<p>        Besides the fact that it validates integers it allows you to specify a range in which the specified variable or value should be. It also allows you to validate octal and hexadecimal numbers.
      </li>
</ul>
</li>
<li>
<ul><big><em>String Validation</em></big></p>
<li><code>FILTER_VALIDATE_EMAIL</code>
<p>        Validates if the variable/value is a well formed email address.
      </li>
<li><code>FILTER_VALIDATE_IP</code>
<p>        Can be used for validating IPv4/IPv6 addresses, having flags to disallow reserved/private IP ranges.
      </li>
<li><code>FILTER_VALIDATE_REGEXP</code>
<p>        Validates variable/value with regular expressions.
      </li>
<li><code>FILTER_VALIDATE_URL</code>
<p>        Validate URL&#8217;s. I wouldn&#8217;t recommend it though, since it validates <code>'http://...'</code>. Better of with regular expressions here.
      </li>
</ul>
</li>
</ul>
<ul><big><strong>Sanitize Filters</strong></big></p>
<li><code>FILTER_SANITIZE_EMAIL</code>
<p>    I highly recommend to not use this filter, because it won&#8217;t sanitize the email address. The characters <code>!#$%&#038;'*+-/=?^_`{|}~@.[]</code> will remain intact.
  </li>
<li><code>FILTER_SANITIZE_ENCODED</code>
<p>    URL-encode string, optionally strip or encode special characters.
  </li>
<li><code>FILTER_SANITIZE_MAGIC_QUOTES</code>
<p>    Applies <code>addshashes()</code> to the specified variable/value. Seriously, shouldn&#8217;t this be extinct already. I though we    should have left them behind once we moved away from PHP 4.x. Try to not use this one, because in some SQL systems backslashes    are not escape characters.
  </li>
<li><code>FILTER_SANITIZE_NUMBER_FLOAT</code>
<p>    Remove all characters except digits, <code>+-</code> and optionally <code>.</code>,<code>eE</code>.
  </li>
<li><code>FILTER_SANITIZE_NUMBER_INT</code>
<p>    Remove all characters except digits, plus and minus sign.
  </li>
<li><code>FILTER_SANITIZE_SPECIAL_CHARS</code>
<p>    HTML-escape <code>'"&lt;&gt;&amp;</code> and characters with ASCII value less than 32, optionally strip or encode other special characters.
  </li>
<li><code>FILTER_SANITIZE_STRING</code>
<p>    Strip tags, optionally strip or encode special characters.
  </li>
<li><code>FILTER_SANITIZE_STRIPPED</code>
<p>    Alias for the above filter.
  </li>
<li><code>FILTER_SANITIZE_URL</code>
<p>    Remove all characters except letters, digits and <code>$-_.+!*'(),{}|^~[]`<>#%";/?:@&#038;=</code>.
  </li>
<li><code>FILTER_UNSAFE_RAW</code>
<p>    Do nothing, optionally strip or encode special characters.
  </li>
</ul>
<ul><big><strong>Other Filters</strong></big></p>
<li><code>FILTER_CALLBACK</code>
<p>    Call user-defined function to filter data.
  </li>
</ul>
<p>As you must have noticed the sanitizing filters are pretty bad, some even repetitive. Although haven&#8217;t marked red all of them, I surely won&#8217;t use them. For sanitizing (against XSS) I&#8217;ll use good old <a href="http://www.php.net/strip_tags" target="_blank">strip_tags</a>() combined with <a href="http://www.php.net/htmlspecialchars" target="_blank">htmlspecialchars</a>() because this way I can define quote style encoding, and charset in which to encode. As for safe SQL queries, I use db specific functions.</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 src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script></p>
<h2>Functions</h2>
<p>Ok, so we had some complains about the filters. But let&#8217;s look beyond that for a moment and see what the filtering functions have to offer us.</p>
<ul>
<li><big><strong>filter_has_var</strong></big></li>
</ul>
<p>Through this function we can check if a POST, GET, ENV, SERVER, COOKIE value has been set.</p>
<pre name="code" class="php">
if(filter_has_var(INPUT_POST, 'submit')) {
  echo 'yes the submit value has been set';
}
</pre>
<p>Although this might seem similar to a <a href="http://www.php.net/isset" target="_blank">isset</a>() usage, be not fooled by it. It (probably) takes a snapshot of all the superglobals (POST, GET, ENV, SERVER, COOKIE) so&#8230;</p>
<pre name="code" class="php">
/*
 submit isn't set
*/
$_POST['submit']=1;
if(filter_has_var(INPUT_POST, 'submit')) {
  echo 'this will not be echoed';
}
</pre>
<p>Is this a good thing? Well, it depends. Haven&#8217;t seen till now somebody who controlled the flow of the application (in a script) through setting/unsetting a value in the superglobals, but I have seen hand coded register_globals implementation (for backwards compatibility) in PHPList which permitted that the SERVER['file'] (named something like that) to be overwritten and making it vulnerable to remote file inclusion. So in that particular scenario it would have helped.</p>
<ul>
<li><big><strong>filter_id and filter_list</strong></big></li>
</ul>
<p>One returns the numeric value of a filter, while the other returns a list of filters&#8230; moving on.</p>
<ul>
<li><big><strong>filter_input and filter_input_array</strong></big></li>
</ul>
<p>The (ONE) function for the &#8220;Data Filtering Extension&#8221;. I&#8217;ll post an example from the documentation.</p>
<pre name="code" class="php">

$search_html = filter_input(
    INPUT_GET,
    'search',
    FILTER_SANITIZE_SPECIAL_CHARS
);
$search_url = filter_input(
    INPUT_GET,
    'search',
    FILTER_SANITIZE_ENCODED
);

echo "You have searched for $search_html.\n";
echo "&lt;a href='?search=$search_url'&gt;Search again.&lt;/a&gt;";
</pre>
<ul>
<li><big><strong>filter_var and filter_var_array</strong></big></li>
</ul>
<p>It works in the same way as filter_input, just that now you can use the filters on variables/string&#8230; these examples are also from the documentation.</p>
<pre name="code" class="php">
// will validate
var_dump(filter_var(
    'bob@example.com',
    FILTER_VALIDATE_EMAIL
));

// will fail (return false), because it
// misses the scheme (http://)
var_dump(filter_var(
    'example.com',
    FILTER_VALIDATE_URL,
    FILTER_FLAG_SCHEME_REQUIRED
));
</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>Should I use it?</h2>
<p>Well, can&#8217;t say for sure. The validation filters seem pretty good unless you count the URL one&#8230; actually that could be a good filter also if you shouldn&#8217;t add 3 flags to behave like you normally would expect&#8230;</p>
<p>The other reason why I can&#8217;t pronounce a final answer (maybe someone who reads this will) because I haven&#8217;t checked the source code of the extension&#8230;</p>
<p>You have more information about it (not quite that big of a difference) from the online documentation page found <a href="http://www.php.net/manual/en/book.filter.php" target="_blank">here</a>. Waiting your opinion on this one&#8230;</p>
<p><strong>Update:</strong> Chuck Norrises was here and updated the text, removing my opinion of vulnerable code. eof!</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/php-5-data-filtering-extension-bad/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>userAtuh – frontend to backend encryption</title>
		<link>http://insanesecurity.info/blog/useratuh-%e2%80%93-frontend-to-backend-encryption</link>
		<comments>http://insanesecurity.info/blog/useratuh-%e2%80%93-frontend-to-backend-encryption#comments</comments>
		<pubDate>Wed, 24 Jun 2009 05:50:02 +0000</pubDate>
		<dc:creator>dblackshell</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Encryption]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://insanesecurity.info/blog/?p=18</guid>
		<description><![CDATA[How many times did you check a web application of yours with a security auditing tool? I can tell you that I did it a couple of times. And as usual it always hit me with the same warning: &#8216;the login information is sent in plain text to &#8230;php&#8217;, or something of sort. And ignoring [...]]]></description>
			<content:encoded><![CDATA[<p>How many times did you check a web application of yours with a security auditing tool?<br />
I can tell you that I did it a couple of times. And as usual it always hit me with the same warning: &#8216;the login information is sent in plain text to &#8230;php&#8217;, or something of sort.</p>
<p><span id="more-18"></span><br />
And ignoring this warning is half as bad as having a sql injection vulnerability. Even if home users no longer are a part in a shared network thus sniffing is highly improbable, companies have LAN&#8217;s which would make a sniffing attack possible (if the sysadmin didn&#8217;t do his  job). Throwing away all your security implementations, password enforcements&#8230;</p>
<p>SSL is the solution for this case but isn&#8217;t necesarily needed. Here comes in <a href="http://sourceforge.net/projects/useratuh/">userAtuh</a>. Yes it&#8217;s a typo, but who cares how it&#8217;s called as long as it does a great job?</p>
<p><strong>UserAtuh</strong> is a php/js library used for serverside/client side password encryption, ment to mask the password sent by login forms. You can download it from it&#8217;s <a href="http://sourceforge.net/projects/useratuh/">project page on SourceForge</a>.</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>How does it work? Actually it&#8217;s quite straight forward, but I could better show it&#8217;s working by pointing out the key portions of code.</p>
<p>It all starts with the login form with has defined to the on submit event assigned to the <strong>setEncryption()</strong> function, which: hashes the password, joins it with the username and key and double hashes the result storing it in a hidden input field.</p>
<p>Upon form submision the only two values that are requested are the username and the result of the <strong>setEncryption()</strong> function. The rest is ignored. Forgot to mention that the <strong>setEncryption()</strong> function also changes the password from the input field with a substring of its result.</p>
<p>The authentification is done by the function with the same name from the <strong>KeyHandler</strong> object:</p>
<pre>
public function authenticate($name,$encodedPass,$sha1=true){
    //get the last key that was generated for this
    //session
    $ip = getenv('REMOTE_ADDR');
    $key  = $this->_dba->getKeyFromDB($ip);

    //check if a user exists with this name
    if ($this->_dba->userExists($name)==false) return false;    	

    //retrive the password for the user
    $pass = $this->_dba->getPass($name);

    //make sure password is hashed
    if (!$sha1) $pass = sha1($pass);

    //create a hashed string from the date collected
    $encoded = sha1(sha1($pass.$name.$key));

    //generate a new key, so the last key won't be usable
    $this->generateKey();

    //check the hashed string with the key sent by the
    //client side
    return ($encodedPass==$encoded);
}
</pre>
<p>Simple, easy, useful. It&#8217;s implementation can take at maximum a couple of minutes. Quick and painless, just as I like &#8216;em.</p>
]]></content:encoded>
			<wfw:commentRss>http://insanesecurity.info/blog/useratuh-%e2%80%93-frontend-to-backend-encryption/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
