<?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>Ataraxia! &#187; segurança</title>
	<atom:link href="http://www.ataraxia.com.br/posts/tag/seguranca/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ataraxia.com.br</link>
	<description>O estado da arte em TI</description>
	<lastBuildDate>Sun, 17 Jul 2011 21:36:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Evitando SQL injection em PHP</title>
		<link>http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php</link>
		<comments>http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php#comments</comments>
		<pubDate>Thu, 23 Apr 2009 00:13:09 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[segurança]]></category>
		<category><![CDATA[fieo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[validação]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=318</guid>
		<description><![CDATA[Em um mundo ideal, todos os desenvolvedores, ao programar seus aplicativos em qualquer linguagem, deveriam se preocupar com segurança, em especial com a validação dos dados. No PHP, isso não é diferente. Uma classe de problemas de segurança bem específica do ambiente web é a chamada SQL Injection, literalmente uma &#8220;Injeção de SQL&#8221;. E embora [...]]]></description>
			<content:encoded><![CDATA[<p>Em um mundo ideal, todos os desenvolvedores, ao programar seus aplicativos em qualquer linguagem, deveriam se preocupar com segurança, em especial com a <a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php">validação dos dados</a>. No PHP, isso não é diferente.<br />
Uma classe de problemas de segurança bem específica do ambiente web é a chamada <em>SQL Injection</em>, literalmente uma &#8220;Injeção de SQL&#8221;. E embora a solução seja simples, é preciso que o programador preste atenção, pra evitar que seu aplicativo acabe sendo explorado por uma falha de segurança como esta.</p>
<h2>O problema</h2>
<p>Digamos que na página principal do nosso site, a gente tenha um formulário de login mais ou menos assim:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;login.php&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span>&gt;</span>
Login: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;login&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
Senha: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;password&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;senha&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></pre></div></div>

<p>Um formulário bem simples. E para tratar este formulário, temos o login.php, que vai checar em um banco de dados se o login e a senha estão corretos, da seguinte forma (colocarei apenas o trecho com a consulta SQL relevante):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM usuarios WHERE login = '<span style="color: #006699; font-weight: bold;">{$_POST['login']}</span>' AND senha = '<span style="color: #006699; font-weight: bold;">{$_POST['senha']}</span>'&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$res</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">mysql_num_rows</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;Login OK&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;Login e senha não conferem&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Ou seja, verificamos na tabela <em>usuarios</em> se temos uma linha com o login e a senha fornecidos. Caso essa consulta retorne alguma coisa, significa que existe uma linha com o login e a senha fornecidos, caso contrário, não existe.<br />
Se no formulário eu preencho o login com &#8220;joe&#8221; e a senha com &#8220;xxxx&#8221;, a seguinte consulta SQL será montada e executada:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> usuarios <span style="color: #993333; font-weight: bold;">WHERE</span> login <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'joe'</span> <span style="color: #993333; font-weight: bold;">AND</span> senha <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'xxxx'</span></pre></div></div>

<p>Porém, o que acontece se eu preecher o formulário com o login = joe, e a senha com:  xxxx&#8217; OR true &#8211;<br />
Neste caso, teremos a seguinte consulta:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> usuarios <span style="color: #993333; font-weight: bold;">WHERE</span> login <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'joe'</span> <span style="color: #993333; font-weight: bold;">AND</span> senha <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'xxxx'</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">TRUE</span> <span style="color: #808080; font-style: italic;">--'</span></pre></div></div>

<p>Essa consulta vai retornar todas as linhas do banco de dados (por causa do &#8220;OR true&#8221; no final), e como a checagem no código é se a consulta retornou mais de uma linha, estaremos logados.<br />
Existem formas mais sofisticadas de proceder com este tipo de ataque, mas o foco do artigo é na defesa.</p>
<h2>FIEO</h2>
<p><acronym title="Filter Input/Escape Output">FIEO</acronym> é uma técnica bastante usada para aumentar a segurança dos aplicativos web. Significa &#8220;Filter Input/Escape Output&#8221;, ou traduzindo, &#8220;Filtre a Entrada/Escape a Saída&#8221;.<br />
O primeiro passo é a filtragem da entrada, já que a regra número 1 da segurança em aplicativos web diz que não podemos jamais confiar em informações vindas de fontes externas. No nosso caso, poderíamos fazer a filtragem do login e da senha checando se eles possuem apenas caracteres permitidos. Por exemplo, o site poderia ter uma regra especificando que o login deve conter apenas letras e números. A filtragem então, poderia ser feita usando a função <a href="http://br2.php.net/ctype_alnum">ctype_alnum()</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">ctype_alnum</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;login possúi caracteres inválidos&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Se o <em>FI</em> do FIEO lida com a filtragem da entrada, o <em>EO</em> lida com a manutenção da saída no contexto em que for lida.<br />
Ou seja, <em>FI</em> garante que a nossa entrada é valida, e <em>EO</em> garante que quem quer que receba os nossos dados, irá interpretá-los da forma correta.<br />
No nosso caso, é importante que as aspas simples não sejam interpretadas como delimitadores na consulta SQL. E se eu quisesse ter uma senha que tivesse uma aspa simples no meio?<br />
Existem 3 formas clássicas de se resolver este problema.</p>
<h2>Forma 1: addslashes() no PHP</h2>
<p>É a forma mais simples (e ingênua) de se tratar o problema. Por exemplo, se queremos nos proteger das aspas simples, poderíamos simplesmente escapá-las no PHP da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$login</span> <span style="color: #339933;">=</span> <span style="color: #990000;">addslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$senha</span> <span style="color: #339933;">=</span> <span style="color: #990000;">addslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'senha'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Dessa forma, caso uma aspa simples chegasse do usuário, seria devidamente <em>escapada</em> com uma &#8220;\&#8221; antes, e o servidor SQL não iria interpretá-la como um delimitador.<br />
Para o nosso exemplo de ataque, resolveria.<br />
O grande problema com esta solução é que ela só prevê ataques que usem aspas simples. Bancos de dados diferentes podem usar caracteres de controle diferentes, como aspas duplas, quebras de linha, ou outras coisas mais estranhas. E checar por todas estas formas é longe de ser a maneira mais eficaz (e viável!) de se proceder.<br />
Temos uma outra opção, suportada por vários bancos de dados.</p>
<h2>Forma 2: deixar o próprio banco escapar</h2>
<p>A segunda opção é passar a string para o banco e deixar ele se virar. Afinal, ele sabe o que pode e o que não pode entrar em uma string. No MySQL, isso poderia ser feito da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$login</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_real_escape_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$senha</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_real_escape_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'senha'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Segundo a documentação, chamando esta função, o banco escapa automaticamente as seguintes sequencias: \x00, \n, \r, \, &#8216;, &#8221; e \x1a. Ou seja, pelo visto as aspas simples não eram nosso único problema mesmo.<br />
Existem funções semelhantes para outros bancos de dados (por exemplo, <em>pg_escape_string()</em> para o PostgreSQL).<br />
Porém, a solução que considero mais elegante é usar consultas preparadas.</p>
<h2>Forma 3: consultas preparadas</h2>
<p>A idéia de se preparar uma consulta é dizer ao banco de dados o formato da consulta (apenas os parâmetros formais), e fazer a amarração dos parâmetros reais somente na hora da execução.<br />
A maior parte dos bancos de dados suportam consultas preparadas, mas vou mostrar o exemplo usando MySQL, devido a popularidade.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$dbh</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> mysqli<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;localhost&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;ususario&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;senha&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;banco&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$dbh</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prepare</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT * FROM usuarios WHERE login = ? AND senha = ?&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;login&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;senha&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'senha'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Ou seja, primeiro informamos ao banco qual será a consulta a ser executada. Perceba que usamos interrogações no lugar dos parâmetros reais. Com isso, o banco prepara a consulta pra ser executada.<br />
Logo em seguida, dizemos ao banco o valor que cada parâmetro irá receber. Esta etapa se chama amarração (binding). Como o banco de dados sabe o tipo de cada campo, ele também sabe como proceder pra escapar corretamente cada valor.<br />
E por último, executamos a consulta. Simples, fácil e seguro!</p>
<h2>Conclusão</h2>
<p>SQL Injection é um problema sério que afeta muitos aplicativos web por aí afora, porém é um problema que só existe por causa da ingenuidade dos programadores, que não programam pensando em segurança. A solução, como vimos, é bem simples.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/agendando-eventos-no-wordpress" title="Agendando eventos no WordPress">Agendando eventos no WordPress</a></li><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-com-memcached" title="Otimização de sites com memcached">Otimização de sites com memcached</a></li><li><a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo" title="Os 10 piores CAPTCHAs do mundo">Os 10 piores CAPTCHAs do mundo</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-spam-em-formularios" title="Evitando spam em formulários">Evitando spam em formulários</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Criando CAPTCHAs em PHP</title>
		<link>http://www.ataraxia.com.br/posts/criando-captchas-em-php</link>
		<comments>http://www.ataraxia.com.br/posts/criando-captchas-em-php#comments</comments>
		<pubDate>Sun, 12 Apr 2009 03:06:23 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[segurança]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=236</guid>
		<description><![CDATA[Após postar a galeria dos 10 piores CAPTCHAs do mundo, estou postando o artigo prometido sobre como criar um CAPTCHA em PHP. Como já dito antes, a função de um CAPTCHA é apresentar um problema de fácil solução para um ser humano, mas de difícil resolução por um computador. Normalmente, os CAPTCHAs tomam a forma [...]]]></description>
			<content:encoded><![CDATA[<p>Após postar a <a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo">galeria dos 10 piores CAPTCHAs do mundo</a>, estou postando o artigo prometido sobre como criar um CAPTCHA em PHP.<br />
Como já dito antes, a função de um <acronym title="Completely Automated Public Turing test to tell Computers and Humans Apart">CAPTCHA</acronym> é apresentar um problema de fácil solução para um ser humano, mas de difícil resolução por um computador. Normalmente, os CAPTCHAs tomam a forma de imagens com letras distorcidas, e é exatamente este o tipo que iremos criar neste artigo.</p>
<h2>Como funciona na teoria?</h2>
<p>O funcionamento de um CAPTCHA de letras tortas é bem simples. O servidor gera uma string que será transformada em uma imagem. A string é salva em algum lugar (normalmente em uma variável de sessão). A imagem é apresentada dentro de um formulário. Ao submeter o formulário, o script checa se o que o usuário digitou bate com o conteúdo da variável de sessão. Se bater, o usuário passou no teste.<br />
Na teoria, tudo muito simples.</p>
<h2>Mas e na prática?</h2>
<p>Na prática, tudo também pode ser igualmente simples. Ao invés de reinventar a roda, podemos utilizar uma classe chamada <a href="http://www.phpcaptcha.org/">Securimage</a>, que serve justamente para gerar CAPTCHAs.</p>
<h2>Securimage</h2>
<p>Securimage é uma classe em PHP que utiliza a biblioteca gráfica GD para gerar imagens com CAPTCHAs. A classe é bastante versátil, e suporta várias opções, como fontes <acronym title="TrueType Font">TTF</acronym>, imagens de fundo, linhas, arcos e bem mais.<br />
O primeiro passo é baixar o pacote com a <a href="http://www.phpcaptcha.org/download/">versão mais recente</a> e descompactá-lo em algum lugar. A partir deste ponto, vou assumir que o pacote foi descompactado em uma pasta chamada &#8220;securimage&#8221; no diretório raiz do site.</p>
<h2>Criando o form com a imagem</h2>
<p>Dentro do formulário que se deseja proteger, colocamos uma tag <b>img</b>, que irá conter a imagem gerada pelo Securimage:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;captcha&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/securimage/securimage_show.php&quot;</span> <span style="color: #000066;">alt</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;CAPTCHA&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>Este script <b>securimage_show.php</b> é bem pequeno (3 linhas), e irá criar um CAPTCHA com as opções padrões da classe. Veremos mais adiante algumas formas de se customizar a imagem.<br />
Além da imagem, também precisamos de um campo para o usuário digitar as letras contidas na imagem:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;captcha_txt&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>E com isso o formulário está pronto.</p>
<h2>A checagem no backend</h2>
<p>O usuário viu a imagem, digitou os dados e submeteu o formulário. Agora é hora de checar se o código digitado bate com o texto contido na imagem.<br />
Logo no início do script que recebe os dados do formulário (em caso de dúvida, veja o atributo <b>action</b> da tag <b>form</b>), é preciso inicializar as variáveis de sessão:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>É importante que este código venha antes de qualquer saída, ou teremos um erro do tipo &#8220;Cannot modify header information &#8211; headers already sent&#8230;.&#8221;. Na dúvida, coloque logo no início.<br />
O restante da checagem é bastante simples. Basta instanciarmos um objeto da classe Securimage e chamar um método que faz a checagem:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'DOCUMENT_ROOT'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/securimage/securimage.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$securimage</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Securimage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$securimage</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">check</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'captcha_txt'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Código digitado corretamente</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Ok, o código foi digitado corretamente.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Código digitado não bate com a imagem</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Erro: código incorreto.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>O exemplo acima apenas ilustra como é feita a checagem. As chamadas a <b>die()</b> devem ser substituídas de acordo com a lógica da página onde o CAPTCHA está sendo inserido. No caso do código estar correto, deve-se prosseguir com o processamento do formulário, e caso não esteja, possivelmente exibir novamente o formulário com uma mensagem de erro. Será gerado um novo CAPTCHA automaticamente.</p>
<h2>Outras opções</h2>
<p>Como dito anteriormente, a classe é bastante versátil, e suporta diversas opções para a geração das imagens. Todas as opções estão descritas na <a href="http://www.phpcaptcha.org/Securimage_Docs/Securimage/classes/Securimage.html">documentação da classe</a>, mas vou transcrever várias das opções aqui.<br />
Para se customizar a imagem, basta editar diretamente o script <b>securimage_show.php</b>, que é o script usado na tag <b>img</b>. Originalmente, ele é apenas o seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">include</span> <span style="color: #0000ff;">'securimage.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$img</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> securimage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Podemos passar opções para a classe antes de chamar o método <b>show()</b>. Apenas para ilustrar, aqui vai um exemplo bem customizado:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">include</span> <span style="color: #0000ff;">'securimage.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$img</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> securimage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">code_length</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">8</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 8 ao invés de apenas 4 caracteres</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">charset</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;AEIOU&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Apenas vogais</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">image_width</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">280</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Padrão é 175px para 4 caracteres</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">multi_text_color</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;#ff0000,#0000ff&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Letras azuis e vermelhas</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">image_bg_color</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;#ffff00&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Fundo amarelo</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>E abaixo, 3 exemplos de CAPTCHAs gerados por este script:</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/11.png" alt="CAPTCHA - Exemplo 1" title="CAPTCHA - Exemplo 1" width="280" height="45" class="alignnone size-full wp-image-251" /><br />
<img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/21.png" alt="CAPTCHA - Exemplo 2" title="CAPTCHA - Exemplo 2" width="280" height="45" class="alignnone size-full wp-image-252" /><br />
<img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/31.png" alt="CAPTCHA - Exemplo 3" title="CAPTCHA - Exemplo 3" width="280" height="45" class="alignnone size-full wp-image-253" /></p>
<p>Como já dito, a classe suporta muitas outras opções, o melhor mesmo é ler a documentação caso se deseje customizar mais.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo" title="Os 10 piores CAPTCHAs do mundo">Os 10 piores CAPTCHAs do mundo</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/agendando-eventos-no-wordpress" title="Agendando eventos no WordPress">Agendando eventos no WordPress</a></li><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-spam-em-formularios" title="Evitando spam em formulários">Evitando spam em formulários</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/criando-captchas-em-php/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Os 10 piores CAPTCHAs do mundo</title>
		<link>http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo</link>
		<comments>http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo#comments</comments>
		<pubDate>Fri, 10 Apr 2009 04:02:03 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[humor]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[hahaha]]></category>
		<category><![CDATA[segurança]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=217</guid>
		<description><![CDATA[Todos nós já vimos os CAPTCHAs por aí. São aquelas imagens com letras tortas, normalmente utilizadas para evitar que robôs automatizem tarefas que não devem ser automatizadas (por exemplo, criação de contas em webmails para envio de spam). CAPTCHA é um acrônimo para &#8220;Completely Automated Public Turing test to tell Computers and Humans Apart&#8221;, ou [...]]]></description>
			<content:encoded><![CDATA[<p>Todos nós já vimos os <a href="http://en.wikipedia.org/wiki/Captcha">CAPTCHAs</a> por aí. São aquelas imagens com letras tortas, normalmente utilizadas para evitar que robôs automatizem tarefas que não devem ser automatizadas (por exemplo, criação de contas em webmails para envio de spam). CAPTCHA é um acrônimo para &#8220;Completely Automated Public Turing test to tell Computers and Humans Apart&#8221;, ou &#8220;Teste de Turing público completamente automatizado para distinguir computadores de seres humanos&#8221;.</p>
<p>A idéia de um CAPTCHA é mostrar graficamente um problema onde a solução é muito simples para um ser humano, mas muito difícil para um computador resolver. Normalmente, letras tortas servem bem para isso, pois é difícil para um programa conseguir diferenciar as letras.</p>
<p>Porém, existem casos em que os CAPTCHAs podem ser extremamente difíceis de se resolver, mesmo para seres humanos. Apenas pra descontrair um pouco, extraí os exemplos abaixo do <a href="http://www.johnmwillis.com/other/top-10-worst-captchas/">blog do John Willis</a>, e decidi compartilhar por achar interessantes. Escreverei em breve um artigo sobre a criação de CAPTCHAs, mas por enquanto, fiquemos apenas com os piores deles. Seguindo a mesma ordem do blog original, aqui vão eles, do melhor para o pior:</p>
<h2>#10 &#8211; Fundo de plasma</h2>
<p>Ok, este nem está tão ruim assim. Dá pra se ler claramente o que está escrito:</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/1.jpg" alt="CAPTCHA com plasma" title="CAPTCHA com plasma" width="307" height="161" class="size-full wp-image-219" /></p>
<h2>#9 &#8211; Letras parecidas</h2>
<p>Alguem consegue olhar e me dizer de cara o que está escrito nessa imagem? Seria &#8220;muaummwwv&#8221;?</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/2.jpg" alt="Letras parecidas" title="Letras parecidas" width="335" height="203" class="size-full wp-image-223" /></p>
<h2>#8 &#8211; Substituição</h2>
<p>A idéia desse é até interessante, mas convenhamos, não é nada prático. Um humano normalmente tolera perder uns 2 segundos no máximo com um CAPTCHA. Quanto tempo você perdeu pra chegar na resposta desse?</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/3.jpg" alt="CAPTCHA de substituição" title="CAPTCHA de substituição" width="500" height="197" class="alignnone size-full wp-image-224" /></p>
<h2>#7 &#8211; Impossível?</h2>
<p>Este, sem a cola que tem logo embaixo, imagino que seja impossível. A imagem tá tão poluída que pelo menos eu não consegui distinguir nada ali.</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/4.jpg" alt="CAPTCHA poluído" title="CAPTCHA poluído" width="230" height="100" class="alignnone size-full wp-image-225" /></p>
<h2>#6 &#8211; Problema matemático</h2>
<p>Ok, já vi alguns CAPTCHAs que pedem pra fazer contas simples de adição e subtração. Agora, um que pede pra resolver uma derivada ou encontrar raízes de polinômios de grau 5? Acreditem, é real! <a href="http://random.irb.hr/signup.php">Verifiquem vocês mesmos</a>. Caso não apareça a derivada de primeira, só dar reload até aparecer. Não demora muito.</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/5.jpg" alt="CAPTCHA matemático" title="CAPTCHA matemático" width="446" height="271" class="alignnone size-full wp-image-226" /></p>
<p>O mais interessante é que esses problemas, embora assustem, são matematicamente muito simples de serem resolvidos. Esta derivada, fazendo x=0 acaba se tornando a derivada de uma constante, e todos nós coitados que já <del datetime="2009-04-10T03:28:00+00:00">sofremos com</del> estudamos cálculo I sabemos que a derivada de qualquer constante vale 0. Todas as derivadas que eu vi nesse site caem nessa categoria.</p>
<h2>#5 &#8211; Psicodélico</h2>
<p>Esse eu também não consegui distinguir nada. Qual será a resposta correta?</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/6.jpg" alt="CAPTCHA psicodélico" title="CAPTCHA psicodélico" width="388" height="138" class="alignnone size-full wp-image-227" /></p>
<h2>#4 &#8211; Texto na cor do fundo</h2>
<p>Ok a imagem ter um fundo colorido com padrões pra dificultar a leitura automatizada da imagem, mas usar uma cor no texto quase igual a cor de fundo dificulta um pouco, não?</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/7.jpg" alt="Texto na cor do fundo" title="Texto na cor do fundo" width="334" height="171" class="alignnone size-full wp-image-228" /></p>
<h2>#3 &#8211; Que alfabeto é esse?</h2>
<p>É uma sequencia grande de caracteres, só não sei de que língua ou alfabeto. Me parece que alguem na hora de bolar o CAPTCHA escolheu a fonte errada e acabaram saindo essas coisas estranhas:</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/8.jpg" alt="Que língua é essa?" title="Que língua é essa?" width="500" height="162" class="alignnone size-full wp-image-229" /></p>
<h2>#2 &#8211; Pontilhismo</h2>
<p>Esse CAPTCHA deve ter sido feito por algum apreciador do impressionismo ou do pontilhismo. Alguém adivinha o que está escrito?</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/9.jpg" alt="Pontilhismo" title="Pontilhismo" width="433" height="94" class="alignnone size-full wp-image-230" /></p>
<h2>#1 &#8211; Not Found?</h2>
<p>E quando a imagem não carrega? Como fazer pra resolver o CAPTCHA? Acho que de todos, este é o mais impossível de se resolver!</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/10.jpg" alt="Not Found" title="Not Found" width="379" height="254" class="alignnone size-full wp-image-231" /></p>
<div class="divisoria"></div>
<p>Alguém já esbarrou por aí em algum outro CAPTCHA que mereça entrar em uma galeria como esta?</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-spam-em-formularios" title="Evitando spam em formulários">Evitando spam em formulários</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Evitando spam em formulários</title>
		<link>http://www.ataraxia.com.br/posts/evitando-spam-em-formularios</link>
		<comments>http://www.ataraxia.com.br/posts/evitando-spam-em-formularios#comments</comments>
		<pubDate>Thu, 29 Jan 2009 11:00:56 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[email]]></category>
		<category><![CDATA[segurança]]></category>
		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://blog.ataraxia.com.br/?p=177</guid>
		<description><![CDATA[Muitas vezes, nossos sites possuem algum formulário de contato. Algo como um &#8220;Fale Conosco&#8221;, ou alguma outra forma genérica de contato. O importante é que o visitante acessa o formulário, preenche os dados e submete. Normalmente, esses dados são enviados a alguem por email. Até aí, tudo muito bonito. Funciona muito bem. Porém, os spammers [...]]]></description>
			<content:encoded><![CDATA[<p>Muitas vezes, nossos sites possuem algum formulário de contato. Algo como um &#8220;Fale Conosco&#8221;, ou alguma outra forma genérica de contato. O importante é que o visitante acessa o formulário, preenche os dados e submete. Normalmente, esses dados são enviados a alguem por email.</p>
<p>Até aí, tudo muito bonito. Funciona muito bem. Porém, os spammers acharam uma forma de propagar links para sites de origem duvidosa através destes formulários. Então, bolaram robôes que varrem a Internet em busca de formulários como estes. Ao encontrar um formulário, preenchem automaticamente todos os campos, e submetem os dados.</p>
<p>O resultado disso é o recebimento de várias mensagens inúteis com links muitas vezes utilizados pra disseminar vírus e outras ameaças.</p>
<p>Uma das formas de se resolver isso é colocando um <acronym title="Completely Automated Turing Test To Tell Computers and Humans Apart">CAPTCHA</acronym>, aquelas imagens com letras tortas que teoricamente só um humano consegue decifrar. Alguns dos problemas com os CAPTCHAs: as vezes, o CAPTCHA é fraco, e é possível se usar um programa para quebrá-lo. Já aconteceu algumas vezes com serviços grandes, como Hotmail e Gmail. Outro problema, é que as vezes as letras ficam tão tortas que nem um humano consegue decifrar de primeira. Eu mesmo já tentei fazer um cadastro no BOL, e só consegui lá pra quarta ou quinta tentativa.</p>
<p>Uma outra forma, mais simples, consiste em se colocar no formulário um campo escondido via CSS. O formulário ficaria mais ou menos assim:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/email/send&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span>&gt;</span>
Nome: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nome&quot;</span> <span style="color: #66cc66;">/</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">br</span> <span style="color: #66cc66;">/</span>&gt;</span>
Email: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;email&quot;</span> <span style="color: #66cc66;">/</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">br</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;vazio&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;display:none&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Enviar&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></pre></div></div>

<p>Notem que o formulário possui um campo chamado <em>vazio</em>, que está escondido através do estilo &#8220;<em>display:none</em>&#8220;. A técnica é simples: o script que processa o post do formulário, verifica se este campo está preenchido ou não. Se estiver, muito provavelmente se trata de um robô fazendo spam, já que a princípio este campo não deveria nunca ser exibido na tela, e portanto não poderia ser preenchido.</p>
<p>Embora não seja 100% eficaz e peque um pouco pela falta de acessibilidade (já que dependendo do dispositivo que acesse o celular, o campo pode aparecer), ainda assim se trata de mais uma opção, ao meu ver, menos obstrusiva que um CAPTCHA.</p>
<p>NOTAS:</p>
<ul>
<li>O HTML acima está simples, sem seguir nenhum padrão, só para efeitos de demonstração da técnica. Deveria usar tags como &lt;fieldset&gt; e &lt;label&gt; para manter o formulário bonitinho;</li>
<li>O <em>style</em> não deveria estar explícito no campo, e sim externo em um CSS, setando o display pra hidden ou através de uma classe ou através de um ID.</li>
</ul>
<p>Já faço uso desta técnica em alguns sites que recebiam um volume considerável de spam automático, e hoje o nível caiu pra 0.</p>
<p>Outro aspecto do envio de email que também é extramamente importante é em relação ao <a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails">spam envolvendo a manipulação dos cabeçalhos do email</a>, como já descrito em um outro artigo.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-massa" title="Envio de emails em massa">Envio de emails em massa</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-fornecer-seu-email-verdadeiro" title="Evitando fornecer seu email verdadeiro">Evitando fornecer seu email verdadeiro</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo" title="Os 10 piores CAPTCHAs do mundo">Os 10 piores CAPTCHAs do mundo</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/evitando-spam-em-formularios/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Segurança no envio de emails em PHP</title>
		<link>http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails</link>
		<comments>http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails#comments</comments>
		<pubDate>Sun, 28 Dec 2008 22:40:18 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[segurança]]></category>

		<guid isPermaLink="false">http://blog.ataraxia.com.br/?p=44</guid>
		<description><![CDATA[Muitas aplicações, e a maioria dos sites, qualquer que seja a linguagem em que tenha sido desenvolvido, precisa enviar emails, seja para contato do visitante, ou para enviar o link para um amigo, ou até mesmo como confirmação de um formulário qualquer. Porém, se não forem tomados os devidos cuidados, sua aplicação pode ser explorada, [...]]]></description>
			<content:encoded><![CDATA[<p>Muitas aplicações, e a maioria dos sites, qualquer que seja a linguagem em que tenha sido desenvolvido, precisa enviar emails, seja para contato do visitante, ou para enviar o link para um amigo, ou até mesmo como confirmação de um formulário qualquer.</p>
<p>Porém, se não forem tomados os devidos cuidados, sua aplicação pode ser explorada, e seu servidor pode passar a ser mais uma ferramente nas mãos dos spammers, pronto pra ficar enviando todo tipo de lixo pra meio mundo.</p>
<p>O principal problema com isso, além do fato do seu servidor passar a disseminar a praga que é o spam, é que seu servidor pode cair em algumas das listas negras, e com isso você passa a não conseguir mais enviar emails legítimos pra quem usa as tais listas pra se proteger contra o spam.</p>
<p>Resumindo: é uma dor de cabeça que você não quer ter.</p>
<p>Os cuidados que você precisa tomar no PHP pra não acabar com um problema desses é bem simples. Vamos ver, passo a passo, como normalmente é feito o envio de emails através do PHP, e onde podemos melhorá-lo.</p>
<p>Um formulário típico de contato de algum site, poderia ter a forma abaixo:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;envia.php&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span>&gt;</span>
Nome: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nome&quot;</span> <span style="color: #66cc66;">/</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">br</span> <span style="color: #66cc66;">/</span>&gt;</span>
Email: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;email&quot;</span> <span style="color: #66cc66;">/</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">br</span> <span style="color: #66cc66;">/</span>&gt;</span>
Mensagem: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">textarea</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;mensagem&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">textarea</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">br</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></pre></div></div>

<p>Ou seja, com o formulário acima, o usuário coloca seu nome, seu email, e a mensagem que deseja enviar. Ao se clicar no botão de submit, os dados são passados para o script envia.php, que tem a tarefa de enviar um email com a mensagem do usuário. Esse script, muitas vezes é implementado da seguinte forma, usando a função mail() do PHP:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$para</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;equipe@site.com.br&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$assunto</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Contato do site&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$msg</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mensagem'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$headers</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;From: <span style="color: #006699; font-weight: bold;">{$_POST['nome']}</span> &lt;<span style="color: #006699; font-weight: bold;">{$_POST['email']}</span>&gt;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">mail</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$para</span><span style="color: #339933;">,</span> <span style="color: #000088;">$assunto</span><span style="color: #339933;">,</span> <span style="color: #000088;">$msg</span><span style="color: #339933;">,</span> <span style="color: #000088;">$headers</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Tudo muito bonito. O usuário envia seu nome, email e a mensagem, e o script PHP manda um email para equipe@site.com.br com o conteúdo do email. Estaria perfeito se não fosse pela montagem do cabeçalho From. O grande problema está em não tratar esses dados que foram enviados pelo usuário. Se o usuário faz o envio normalmente, teríamos um email mais ou menos assim (estou ignorando alguns cabeçalhos para simplificar o exemplo):</p>

<div class="wp_syntax"><div class="code"><pre class="email" style="font-family:monospace;"><span style="color: #000040;"><span style="color: #800000; font-weight: bold;">From</span><span style="color: #66cc66;">:</span> Bruno Lustosa <span style="color: #66cc66;">&lt;</span><span style="color: #0000FF;">bruno@lustosa.net</span><span style="color: #66cc66;">&gt;</span></span>
<span style="color: #000040;"><span style="color: #800000; font-weight: bold;">To</span><span style="color: #66cc66;">:</span> <span style="color: #0000FF;">equipe@site.com.br</span></span>
<span style="color: #000040;"><span style="color: #800000; font-weight: bold;">Subject</span><span style="color: #66cc66;">:</span> Contato do site</span>
&nbsp;
Olá, aqui vai a minha mensagem.</pre></div></div>

<p>Nesse caso, postei meu nome, meu email, e a mensagem acima é enviada para a equipe do site. Porém, como o usuário tem o controle sobre o que entra no cabeçalho da mensagem, ele pode ser um pouco sacana, e colocar uma quebra de linha no nome dele, com algumas coisas depois. Por exemplo, se no lugar do meu nome eu coloco &#8220;Buy Viagra &lt;xx@xx.com&gt;nBcc: email1, email2, email3&#8243; e na mensagem eu coloco algo sobre venda de viagra, teríamos o seguinte email montado:</p>

<div class="wp_syntax"><div class="code"><pre class="email" style="font-family:monospace;"><span style="color: #000040;"><span style="color: #800000; font-weight: bold;">From</span><span style="color: #66cc66;">:</span> Buy Viagra <span style="color: #66cc66;">&lt;</span><span style="color: #0000FF;">xx@xx.com</span><span style="color: #66cc66;">&gt;</span></span>
<span style="color: #000040;">Bcc<span style="color: #66cc66;">:</span> email1, email2, email3</span>
<span style="color: #000040;"><span style="color: #800000; font-weight: bold;">To</span><span style="color: #66cc66;">:</span> <span style="color: #0000FF;">equipe@site.com.br</span></span>
<span style="color: #000040;"><span style="color: #800000; font-weight: bold;">Subject</span><span style="color: #66cc66;">:</span> Contato do site</span>
&nbsp;
Compre Viagra, baratinho!!</pre></div></div>

<p>Isso foi apenas um exemplo, mas dá pra combinar outras técnicas e conseguir por exemplo sobrescrever o assunto da mensagem. E hoje em dia, já existem robôs vasculhando formulários de sites buscando por vulnerabilidades desse tipo. Aconteceu em um código antigo da empresa onde estou trabalhando agora. Começamos a entrar em algumas listas negras e sem entender o porque. Quando fomos verificar a fila de emails esperando pra sair do servidor, eram mais de 30 mil spams sobre todo tipo de lixo. E vasculhando os logs do servidor web, chegamos ao script culpado.</p>
<p>É claro que isso <strong>NÃO É</strong> um problema do PHP. O PHP é tão seguro quanto uma pistola. Se o programador decide dar um tiro no próprio pé, não dá pra colocar a culpa na arma, não é? Esse é apenas mais um exemplo do tipo de problema que podemos enfrentar quando não validamos os dados enviados pelo usuário. Sempre que qualquer informação for enviada de um lugar não confiável, essa informação deve ser checada. Uma simples verificação em $_POST['nome'], buscando por quebras de linha, ou em $_POST['email'], verificando se se trata de um email válido, já resolveria esse problema.</p>
<p>A grande maioria dos problemas que vemos divulgados diariamente em todo tipo de script PHP se baseiam no fato de que os programadores não tem o hábito de programar pensando em segurança, e não fazem as checagens mais básicas, deixando os scripts vulneráveis a ataques como o descrito acima e outros.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-spam-em-formularios" title="Evitando spam em formulários">Evitando spam em formulários</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/agendando-eventos-no-wordpress" title="Agendando eventos no WordPress">Agendando eventos no WordPress</a></li><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-massa" title="Envio de emails em massa">Envio de emails em massa</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo" title="Os 10 piores CAPTCHAs do mundo">Os 10 piores CAPTCHAs do mundo</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-fornecer-seu-email-verdadeiro" title="Evitando fornecer seu email verdadeiro">Evitando fornecer seu email verdadeiro</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

