<?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>TiagoFigueira.com &#187; sql injection</title>
	<atom:link href="http://tiagofigueira.com/tag/sql-injection/feed/" rel="self" type="application/rss+xml" />
	<link>http://tiagofigueira.com</link>
	<description>Web Developer &#38; SysAdmin</description>
	<lastBuildDate>Thu, 24 Jun 2010 01:36:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>SQL Injection: segurança de aplicações Web</title>
		<link>http://tiagofigueira.com/sql-injection-seguranca-de-aplicacoes-web/262/</link>
		<comments>http://tiagofigueira.com/sql-injection-seguranca-de-aplicacoes-web/262/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 11:29:17 +0000</pubDate>
		<dc:creator>tiago</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[segurança aplicações web]]></category>
		<category><![CDATA[sql injection]]></category>

		<guid isPermaLink="false">http://tiagofigueira.com/?p=262</guid>
		<description><![CDATA[Na semana passada ao navegar por um site, lembrei-me de fazer um pequeno teste à segurança do mesmo e para minha surpresa, ou não, o site era vulnerável a ataques do tipo sql injection. Depois de ter enviado um e-mail aos responsáveis do site a avisar e de eles terem corrigido o problema, lembrei-me de [...]]]></description>
			<content:encoded><![CDATA[<p>Na semana passada ao navegar por um site, lembrei-me de fazer um pequeno teste à segurança do mesmo e para minha surpresa, ou não, o site era vulnerável a <a title="Wikipedia - SQL Injection" href="http://en.wikipedia.org/wiki/SQL_injection" target="_blank">ataques do tipo sql injection</a>.</p>
<p>Depois de ter enviado um e-mail aos responsáveis do site a avisar e de eles terem corrigido o problema, lembrei-me de falar um pouco sobre este tema.</p>
<h5>O que é que são ataques do tipo SQL Injection?</h5>
<blockquote><p>Basicamente são ataques que exploram o facto as instruções SQL serem criadas dinamicamente com os valores dos inputs (formulários / querystring), sem que estes sejam devidamente tratados. Estes ataques tornam possível executar código sql, tal como U_PDATE, I_NSERT, D_ROP, etc., e até executar programas no servidor web!</p></blockquote>
<h5>Mas como é que funciona?</h5>
<p>Vou tentar mostrar como é que o SQL Injection funciona através  de um exemplo muito simples.</p>
<p>Para isso vou criar uma página de autenticação de utilizadores feita em PHP e MySQL.<br />
Resumidamente vou ter:</p>
<ul>
<li>uma base de dados MySQL com uma <a href="#MySQLTable">tabela &#8220;utilizadores&#8221;</a>;</li>
<li>um ficheiro em php (<a title="Código PHP" href="#codigoPHP">login.php</a>) onde vou ter o formulário HTML e o código PHP para validar os utilizadores na base de dados.</li>
</ul>
<p>O aspecto da página <a href="#codigoPHP">login.php</a> será qualquer coisa deste género:</p>
<div id="attachment_331" class="wp-caption alignnone" style="width: 310px"><img class="size-medium wp-image-331 " title="sqlInjection-login-vazio" src="http://tiagofigueira.com/wp-content/uploads/2009/08/sqlInjection-login-vazio-300x83.jpg" alt="sqlInjection-login-vazio" width="300" height="83" /><p class="wp-caption-text">Formulário de Login (login.php)</p></div>
<p><em><strong>Passando à parte prática<br />
</strong></em></p>
<p>Neste exemplo,  a construção da instrução SQL é feita de forma dinâmica, utilizando os valores dos formulários sem qualquer tipo de validação.<br />
Temos então que:</p>
<pre class="brush: php;">
$sql=&quot;S_ELECT id F_ROM utilizadores WHERE login='&quot;.$_POST[&quot;utilizador&quot;].&quot;' and password='&quot;.$_POST[&quot;password&quot;].&quot;'&quot;;
</pre>
<p>Se no formulário introduzirmos os dados:  &#8220;<strong>admin</strong>&#8221; e &#8220;<strong>1234</strong>&#8220;, a nossa instrução sql vai ficar:</p>
<pre class="brush: sql;">
S_ELECT id F_ROM utilizadores WHERE login='admin' and password='1234'
</pre>
<p>Aparentemente até aqui não existe qualquer problema. Só se adivinharmos o utilizador e a password é que vamos conseguir efectuar o login com sucesso.</p>
<p>O problema começa quando começamos a utilizar caracteres especiais do sql (que podem variar consoante a base de dados) nos inputs.<br />
Por exemplo: vamos ver o que acontece se introduzirmos  no utilizador o seguinte texto:</p>
<pre class="brush: plain;"> xpto' or 1=1#</pre>
<p>O SQL resultante seria:</p>
<pre class="brush: sql;">
S_ELECT id F_ROM utilizadores WHERE login='xpto' or 1=1#' and password='1234'
</pre>
<p>Neste caso estou a utilizar dois caracteres especiais. a pelica &#8220;  <strong>&#8216;</strong> &#8221; e o cardinal &#8220;  <strong>#</strong> &#8220;.<br />
O 1.º serve para delimitarmos campos do tipo &#8220;texto&#8221;.<br />
O 2.º serve para fazer comentários.</p>
<p>Assim sendo, como carácter <strong>#</strong> é um carácter especial ( carácter p/ comentários), tudo o que vier depois do # vai ser ignorado pelo motor da BD. Ficamos então com:</p>
<pre class="brush: sql;">
S_ELECT id F_ROM utilizadores WHERE login='xpto' or 1=1#
</pre>
<p>Se analisarmos o sql vemos que além de termos ignorado todo o código sql que vier depois do #, estamos também a inserir a condição &#8220;<strong> OR 1=1 </strong>&#8220;. Como esta condição é sempre verdade (1=1), o resultado da pesquisa vai devolver sempre pelo menos um id (a não ser que a tabela utilizadores esteja vazia).<br />
Isto é, apesar de até poder não existir nenhum utilizador com o login=xpto, 1 é sempre igual a 1 <img src='http://tiagofigueira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Outro código que podem experimentar é:</p>
<pre class="brush: plain;"> xpto' or 1=1 limit 1#</pre>
<p><em><strong>Porquê o &#8220;limit 1&#8243;?</strong></em><br />
porque desta forma limitamos o n.º de resultados a 1.</p>
<p><em><strong>Então mas porque é que isso é importante?</strong></em><br />
Pode ser ou não. Depende da forma como o programador está a validar o resultado da query à base de dados.<br />
Se o programador tivesse feito qualquer coisa deste género:</p>
<pre class="brush: php;">

// ligação à base de dados
 mysql_connect(&quot;localhost&quot;, &quot;root&quot;, &quot;******&quot;)or die(&quot;cannot connect&quot;);
 mysql_select_db(&quot;junkDB&quot;)or die(&quot;cannot select DB&quot;);
 // construção da instrução sql
 $sql=&quot;S_ELECT * F_ROM utilizadores WHERE login='&quot;.$_POST[&quot;utilizador&quot;].&quot;' and password='&quot;.$_POST[&quot;password&quot;].&quot;'&quot;;
 // execução da instrução sql
 $result=mysql_query($sql);
 // variável que diz o n.º de resultados obtidos
 $count=mysql_num_rows($result);

 // se o n.º de resultados for igual a 1, então é porque os dados introduzidos
 // no formulário são válidos. Isto é, existe um utilizador com o login e password
 // iguais aos introduzidos no formulário
 if($count==1) {
    echo &quot;Dados correctos!&quot;;
 }
 else{
    echo &quot;Dados incorrectos!&quot;;
 }
</pre>
<p>com o código:</p>
<pre class="brush: plain;"> xpto' or 1=1#</pre>
<p>Só iríamos conseguir &#8220;entrar&#8221; caso existisse apenas 1 registo na tabela utilizadores.<br />
Bastava a tabela ter dois utilizadores para já não conseguirmos &#8220;entrar&#8221;.<br />
Ao utilizarmos o &#8220;limit 1&#8243; estamos a dizer que só queremos 1 registo. Logo a condição ($count==1) vai ser sempre verdadeira.</p>
<h5>Código Necessário para simular este exemplo:</h5>
<p><a name="MySQLTable">Criar a tabela &#8220;utilizadores&#8221;:</a></p>
<pre class="brush: sql;">
--
-- Table structure for table `utilizadores`
--
C_REATE TABLE IF NOT EXISTS `utilizadores` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `login` varchar(65) NOT NULL DEFAULT '',
 `password` varchar(65) NOT NULL DEFAULT '',
 PRIMAR Y KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
--
-- Dumping data for table `utilizadores`
--
I_NSERT INTO `utilizadores` (`id`, `login`, `password`) VALUES
(1, 'gestor', '1234'),
(2, 'admin', '1234');
</pre>
<p><a name="codigoPHP">O conteúdo do ficheiro login.php é:</a></p>
<pre class="brush: php;">

&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
    &lt;head&gt;
        &lt;title&gt;Login - Security test&lt;/title&gt;
        &lt;style type=&quot;text/css&quot;&gt;
            /*folha de estilos básica*/
            *{font-family:verdana; font-size:12px; color:#333;}
            form{width:400px; border:2px solid #ddd;}
            form p{font-size:14px; font-weight:bold;}}
            input{ border: solid 1px #ddd; background-color:#f5f5f5;}
            label{font-weight:bold;}
            .red{color:red;}
            .green{color:green;}
            #sql{ width:400px; background-color:#336699; color:white; padding:5px; margin:10px; text-align:left;}
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;center&gt;
&lt;!-- formulário --&gt;
        &lt;form name=&quot;form1&quot; method=&quot;post&quot; action=&quot;login.php?action=validateUser&quot;&gt;
            &lt;p&gt;Acesso Reservado&lt;/p&gt;
            &lt;label for=&quot;username&quot;&gt;Utilizador:&lt;/label&gt;
            &lt;input name=&quot;utilizador&quot; type=&quot;text&quot; id=&quot;username&quot; /&gt;
            &lt;br /&gt;
            &lt;label for=&quot;password&quot;&gt;Password:&lt;/label&gt;
            &lt;input name=&quot;password&quot; type=&quot;password&quot; id=&quot;password&quot; /&gt;
            &lt;br /&gt;
            &lt;input type=&quot;submit&quot; name=&quot;Submit&quot; value=&quot;Login&quot; /&gt;
        &lt;/form&gt;
&lt;!-- // formulário --&gt;

        &lt;?php
// &quot;verificar&quot; se o formulário foi submetido e validar o utilizador
            if(isset($_POST[&quot;utilizador&quot;]) &amp;&amp; isset($_POST[&quot;password&quot;]) ) {

// ligação à base de dados
mysql_connect(&quot;localhost&quot;, &quot;root&quot;, &quot;********&quot;)or die(&quot;cannot connect&quot;);
mysql_select_db(&quot;junkDB&quot;)or die(&quot;cannot select DB&quot;);

// construção da instrução sql
// notem que estou a utilizar os inputs directamente, sem qualquer tipo de validação.
                $sql=&quot;S_ELECT * F_ROM utilizadores WHERE login='&quot;.$_POST[&quot;utilizador&quot;].&quot;' and password='&quot;.$_POST[&quot;password&quot;].&quot;'&quot;;

// execução da instrução sql
                $result=mysql_query($sql);

// variavel que diz o n.º de resultados obtidos
                $count=mysql_num_rows($result);

// se o n.º de resultados for igual a 1, então é porque os dados introduzidos
// no formulário são válidos. Isto é, existe na base de dados UM utilizador
// com o login e password iguais aos introduzidos no formulário
                if($count==1) {
                    echo &quot;&lt;p class=\&quot;green\&quot;&gt;Dados correctos!&lt;/p&gt;&quot;;
                }
                else{
                    echo &quot;&lt;p class=\&quot;red\&quot;&gt;Dados incorrectos!&lt;/p&gt;&quot;;
                }
                echo &quot;&lt;div id=\&quot;sql\&quot;&gt;&lt;b&gt;SQL:&lt;/b&gt;&lt;br&gt;$sql&lt;/div&gt;&quot;;
            }
            ?&gt;
        &lt;/center&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Para quem quiser aprofundar os conhecimentos sobre este tema ficam aqui alguns links muito interessantes:</p>
<ul>
<li><a href="http://unixwiz.net/techtips/sql-injection.html">SQL Injection Attacks by Example</a></li>
<li><a href="http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/#LineCommentAttacks">SQL Injection Cheat Sheet</a></li>
<li><a href="http://www.securiteam.com/securityreviews/5DP0N1P76E.html">SQL Injection Walkthrough</a></li>
<li><a href="http://dev.mysql.com/tech-resources/articles/guide-to-php-security-ch3.pdf">guide-to-php-security-ch3</a></li>
<li><a href="http://www.owasp.org/index.php/Testing_for_SQL_Injection_%28OWASP-DV-005%29">Testing for SQL Injection (OWASP-DV-005)</a></li>
</ul>
<h5>Notas:</h5>
<ul>
<li>Este exemplo é muito simples e tem como objectivo apenas mostrar o que é o sql Injection.</li>
<li>Relativamente ao site do meu teste, de referir que enviei um e-mail aos responsáveis pelo site a avisar dos problemas de segurança, tendo corrigido de imediato os problemas e agradecido o meu aviso. Gostei <img src='http://tiagofigueira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 1090px; width: 1px; height: 1px;">Testing for SQL Injection (OWASP-DV-005)</div>
]]></content:encoded>
			<wfw:commentRss>http://tiagofigueira.com/sql-injection-seguranca-de-aplicacoes-web/262/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
