<?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>Yet another blog about PHP, HTML and CSS &#187; Database</title>
	<atom:link href="http://blog.pepa.info/php-html-css/category/database/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.pepa.info</link>
	<description>Petr 'PePa' Pavel</description>
	<lastBuildDate>Thu, 19 Aug 2010 18:17:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>MySQL comparison catch: &#8216;abc&#8217; = 00</title>
		<link>http://blog.pepa.info/php-html-css/programming-techniques/mysql-comparison-catch-abc-00/</link>
		<comments>http://blog.pepa.info/php-html-css/programming-techniques/mysql-comparison-catch-abc-00/#comments</comments>
		<pubDate>Mon, 25 May 2009 20:39:00 +0000</pubDate>
		<dc:creator>Petr 'PePa' Pavel</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming Techniques]]></category>

		<guid isPermaLink="false">http://blog.pepa.info/?p=113</guid>
		<description><![CDATA[I was shocked to find a weakness in my authentication library today. It was possible to get around the password check if you knew the username. All you had to do was to enter 00 as the password. Or you just entered 00 as the username too and you got authenticated as the first user. [...]]]></description>
			<content:encoded><![CDATA[<p>I was shocked to find a weakness in my authentication library today. It was possible to get around the password check if you knew the username. All you had to do was to enter 00 as the password. Or you just entered 00 as the username too and you got authenticated as the first user.<br />
<span id="more-113"></span><br />
The bug was a combination of these three things:</p>
<ol>
<li>A password (or/and username) that doesn&#8217;t contain any numbers</li>
<li>MySQL type conversion in conditions &#8211; when comparing a VARCHAR column to an INTEGER value it converts VARCHAR to INTEGER, not the other way around.</li>
<li>My own database wrapper was trying to be smart and didn&#8217;t wrap numeric values with apostrophes</li>
</ol>
<p>Consider this template:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> <span class="nu0">1</span> <span class="kw1">FROM</span> my_users <span class="kw1">WHERE</span> <span class="br0">&#40;</span>username = %s<span class="br0">&#41;</span> <span class="kw1">AND</span> <span class="br0">&#40;</span>password = %s<span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p>and something along these PHP lines:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$_REQUEST</span><span class="br0">&#91;</span><span class="st0">&#8216;username&#8217;</span><span class="br0">&#93;</span> &amp;&amp; <span class="re0">$_REQUEST</span><span class="br0">&#91;</span><span class="st0">&#8216;password&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// will catch 0 but not 00</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>mysqlValue<span class="br0">&#40;</span><span class="re0">$sqlTemplate</span>, <span class="re0">$_REQUEST</span><span class="br0">&#91;</span><span class="st0">&#8216;username&#8217;</span><span class="br0">&#93;</span>, <span class="re0">$_REQUEST</span><span class="br0">&#91;</span><span class="st0">&#8216;password&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216;welcome&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216;wrong password&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>I won&#8217;t go into details about <code>mysqlValue()</code>. The important part is that it checks for special cases of NULL, true, false and is_numeric() and runs the rest through mysql_real_escape_string(). Then it inserts all parameters into the template using vprintf().</p>
<p>The problem is with is_numeric(). After being evaluated as a numeric value, &#8217;00&#8242; is entered into the query without apostrophes.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> <span class="nu0">1</span> <span class="kw1">FROM</span> my_users <span class="kw1">WHERE</span> <span class="br0">&#40;</span>username = <span class="st0">&#8216;my_username&#8217;</span><span class="br0">&#41;</span> <span class="kw1">AND</span> <span class="br0">&#40;</span>password = <span class="nu0">00</span><span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p>And because any varchar that doesn&#8217;t contain a number compared to an integer is evaluated as true the result is a catastrophe.</p>
<p><code>'abc' = 00</code> is evaluated as true. <code>'abc1' = 00</code> would be false however, unfortunately only few users append a number to their password. If you use 00 for both the username and the password you get authenticated as the first user who didn&#8217;t do so.</p>
<p>Check out this <a href="http://bugs.mysql.com/bug.php?id=42241">false bug report</a> or the <a href="http://dev.mysql.com/doc/refman/5.0/en/type-conversion.html">related documentation page</a>.</p>
<h2>Why you could want to pass numeric values without apostrophes</h2>
<p>I wonder myself :-) Here are some reasons I remembered:</p>
<ul>
<li>I need to pass NULL in some cases and for that I can&#8217;t use %d
<li>Using apostrophes for integer comparison (1 = &#8217;1&#8242;) means unnecessary type conversion that takes time. A small amount of time but still.</li>
<li>An argument for abandoning the is_numeric() code: Using %d and %s in SQL templates provides a visual clue about what values can be expected there. But then I couldn&#8217;t insert NULL values.</li>
</ul>
<h2>So how to fix this mess?</h2>
<p>What do you think? Should I remove the is_numeric() test and replace all %d with %s in all SQL templates? Remember that <code>printf("%d", "'123'")</code> will return 0.<br />
Or should I keep the is_numeric() test and rewrite vulnerable queries to use for example CAST:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> <span class="nu0">1</span> <span class="kw1">FROM</span> my_users <span class="kw1">WHERE</span> <span class="br0">&#40;</span>username = CAST<span class="br0">&#40;</span>%s <span class="kw1">AS</span> CHAR<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">AND</span> <span class="br0">&#40;</span>password = CAST<span class="br0">&#40;</span>%s <span class="kw1">AS</span> CHAR<span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p>Update 2010-01-18: I added the real reason for wanting to preserve %s in the template.</p>
<p>Update 2010-01-20:<br />
Unfortunately, what I thought to be a solution (CAST(%s AS CHAR)) has another flaw &#8211; strips leading zeroes from the username / password which results into authentication failure.<br />
So dear reader, any ideas?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepa.info/php-html-css/programming-techniques/mysql-comparison-catch-abc-00/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to deal with IMMUTABLE error in indexes that work with timestamps</title>
		<link>http://blog.pepa.info/php-html-css/postgresql/how-to-deal-with-immutable-error-in-indexes-that-work-with-timestamps/</link>
		<comments>http://blog.pepa.info/php-html-css/postgresql/how-to-deal-with-immutable-error-in-indexes-that-work-with-timestamps/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 12:14:54 +0000</pubDate>
		<dc:creator>Petr 'PePa' Pavel</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://blog.pepa.info/2008/03/postgresql/how-to-deal-with-immutable-error-in-indexes-that-work-with-timestamps/</guid>
		<description><![CDATA[Say that in an older version of PostgreSQL you had an index like this: CREATE INDEX logTypeDay ON myLog &#40;eventType, date_trunc&#40;&#8216;day&#8217;, creationTime&#41;&#41;; and now after upgrading to 8.1+ you&#8217;re getting: ERROR: functions in index expression must be marked IMMUTABLE The reason is that date_trunc may return different results based on the current time zone. There&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Say that in an older version of PostgreSQL you had an index like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">CREATE</span> <span class="kw1">INDEX</span> logTypeDay <span class="kw1">ON</span> myLog <span class="br0">&#40;</span>eventType, date_trunc<span class="br0">&#40;</span><span class="st0">&#8216;day&#8217;</span>, creationTime<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>and now after upgrading to 8.1+ you&#8217;re getting:<br />
<strong> ERROR:  functions in index expression must be marked IMMUTABLE</strong></p>
<p><span id="more-16"></span>The reason is that date_trunc may return different results based on the current time zone. There&#8217;s an example query in <a target="_blank" href="http://archives.postgresql.org/pgsql-hackers/2004-10/msg00030.php">PostgreSQL Mailing List Archives</a> that you can run to believe.</p>
<p>If you are absolutely sure that you will always access your data with the same time zone you can redefine your index like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">CREATE</span> <span class="kw1">INDEX</span> logTypeDay <span class="kw1">ON</span> myLog <span class="br0">&#40;</span>eventType, date_trunc<span class="br0">&#40;</span><span class="st0">&#8216;day&#8217;</span>::text, creationTime AT TIME ZONE <span class="st0">&#8216;Europe/Prague&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>The whole immutable business with indexes containing functions that process timestamps is well explained in these threads:<br />
<a target="_blank" href="http://archives.postgresql.org/pgsql-interfaces/2004-06/msg00045.php"> http://archives.postgresql.org/pgsql-interfaces/&#8230;/msg00045.php</a><br />
<a target="_blank" href="http://www.webservertalk.com/archive307-2007-2-1817943.html"> http://www.webservertalk.com/archive307-2007-2-1817943.html</a><br />
<a target="_blank" href="http://www.mydatabasesupport.com/forums/postgresql/209895-re-date_trunc-d-timestamp-index-possible.html"> http://www.mydatabasesupport.com/forums/&#8230;-possible.html</a></p>
<p>All credit goes to Tom Lane. I admire him for being always so patient and polite, and for spending so much of his valuable time with talking to users. I would love to link to his homepage but I failed to find it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pepa.info/php-html-css/postgresql/how-to-deal-with-immutable-error-in-indexes-that-work-with-timestamps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
