<?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>Rafael Bernard Araujo &#187; register globals</title>
	<atom:link href="http://rafael.bernard-araujo.com/tag/register-globals/feed" rel="self" type="application/rss+xml" />
	<link>http://rafael.bernard-araujo.com</link>
	<description>desenvolvendo... while(!success){  try(); }</description>
	<lastBuildDate>Wed, 25 Jan 2012 01:00:20 +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>Segurança no PHP&#160;II</title>
		<link>http://rafael.bernard-araujo.com/seguranca-no-php-ii.php</link>
		<comments>http://rafael.bernard-araujo.com/seguranca-no-php-ii.php#comments</comments>
		<pubDate>Fri, 16 Sep 2011 05:06:55 +0000</pubDate>
		<dc:creator>rafael</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[register globals]]></category>
		<category><![CDATA[segurança]]></category>
		<category><![CDATA[sessão]]></category>

		<guid isPermaLink="false">http://rafael.bernard-araujo.com/?p=846</guid>
		<description><![CDATA[Requisito 4: Sem erros para o usuário Falaremos aqui de outro ponto importantíssimo na questão de segurança que é freqüentemente ignorado pelos desenvolvedores: as mensagens de erro. As mensagens de erro foram feitas para que o desenvolvedor possa trabalhar de forma mais prática e descobrir o que ele está fazendo de errado. Observem, entretando, que, [...]]]></description>
			<content:encoded><![CDATA[<!-- boo-widget start -->
          <script type="text/javascript">
            bb_keywords = "cookie";
            bb_bid  = "1613262";
            bb_lang = "pt-BR";
            bb_name = "custom";bb_limit = "9";bb_format = "bbo";
          </script>
          <script type="text/javascript" src="http://widgets.boo-box.com/javascripts/embed.js"></script>
          <!-- boo-widget end --><p><strong>Requisito 4: Sem erros para o usuário</strong></p>
<p>Falaremos aqui de outro ponto importantíssimo na questão de segurança que é freqüentemente ignorado pelos desenvolvedores: as mensagens de erro.</p>
<p>As mensagens de erro foram feitas para que o desenvolvedor possa trabalhar de forma mais prática e descobrir o que ele está fazendo de errado. Observem, entretando, que, quando uma aplicação atinge maturidade suficiente para &#8220;entrar em produção&#8221;, torna-se imperativo que o usuário não visualize mensagens de erro.</p>
<p>A razão disso é muito simples: as mensagens de erro freqüentemente trazem informações sensíveis. Observe como exemplo uma típica mensagem de falha de conexão com a base de dados:</p>
<p><code>Warning: <span style="color: #ff0000;">mysql</span>_connect() [function.mysql-connect]:<br />
Access denied for user '<span style="color: #ff0000;">foo</span>'@'<span style="color: #ff0000;">localhost</span>' (using password: YES)<br />
in <span style="color: #ff0000;">/usr/local/apache/htdocs/script.php</span> on line 2<br />
</code><br />
Note, através das partes destacadas, que esta mensagem me informa:</p>
<ol>
<li>O tipo de RDBMS: mysql</li>
<li>O usuário de conexão com a base: foo</li>
<li>Que este usuário está tentando uma conexão de dentro do servidor: localhost</li>
<li>O caminho absoluto da raiz web: /usr/local/apache/htdocs</li>
<li>O nome do script: script.php</li>
</ol>
<p>É por isso que, quando colocamos uma aplicação em produção, ocultamos as mensagens de erro e as gravamos diretamente em um arquivo de log. Isto é muito simples de implementar:</p>
<p>Exemplo:</p>
<p><code>display_errors = Off<br />
log_errors = On<br />
error_log = /log/php_errors.log<br />
</code><br />
<strong>Requisito #5: Esconda do servidor web o que ele não precisa acessar</strong></p>
<p>Quantos de nós não usamos em nossas aplicações um arquivo, tipicamente chamado de config.php ou setup.php, onde guardamos, por exemplo, usuário e senha da base de dados?</p>
<p>Não há nada de errado nisso, mas cuidado: se este arquivo não gera saída de informação em HTML, por que deixá-lo acessível via web?</p>
<p>Para esclarecermos o problema, vamos definir 3 coisas:</p>
<ol>
<li>minha raiz web é: /usr/local/apache/htdocs</li>
<li>meu arquivo de configuração fica localizado em /usr/local/htdocs/config/config.php</li>
<li>este é um código típico que usa este arquivo:</li>
</ol>
<p><code>require_once("/urs/local/htdocs/config/config.php");<br />
/* bla bla bla */<br />
</code><br />
Observe que o erro neste caso é confundir interpretador PHP e servidor web. O Apache (ou IIS, Xitami etc) não precisa saber onde está este arquivo. Isto é responsabilidade do interpretador.</p>
<p>Outro problema é que se arquivo fica desnecessariamente exposto, afinal de contas basta eu abrir um navegador e digitar:</p>
<p>http://www.meusite.com.br/config/config.php</p>
<p>Não faz sentido. Por mais que você possa argumentar que não há forma de ler o código-fonte deste arquivo, ainda assim, isto não muda o fato de que ele está desnecessariamente exposto.</p>
<p>A solução é simples: movemos o arquivo para fora da raiz web:</p>
<p>/usr/local/config/config.php</p>
<p>E depois apenas acertamos as permissões e corrigimos nosso código:</p>
<p><code>require_once("/urs/local/config/config.php");<br />
/* bla bla bla */<br />
</code><br />
A partir de agora nosso arquivo de configuração só pode ser lido por quem precisa dele: o interpretador PHP.</p>
<p><strong>Requisito #6: Use criptografia</strong></p>
<p>Dados sigilosos são chamados assim por um motivo. Quando tratamos especificamente de senhas é impressionante a quantidade de aplicações web que gravam senhas em texto puro na base de dados.</p>
<p>Ora, se a senha possui a importância que tem e quem a escolhe é o usuário, por que alguém mais precisa ler essa senha?</p>
<p>Se a senha possui este peso em nossa aplicação, não podemos nos dar o luxo de fazer com que ela trafegue pela aplicação totalmente exposta.</p>
<p>PHP implementa criptografia de várias formas, mas eu sugiro &#8211; para quem puder usar, pois exige instalação e configuração extra &#8211; a utilização da função <code>mcrypt</code>.</p>
<p>Os <em>hashes</em> MD5 e SHA-1 são opções válidas, mas o problema é a sua fragilidade: para o MD5 existe até dicionário de dados, enquanto o SHA-1 foi recentemente &#8220;quebrado&#8221; por um pesquisador chinês.</p>
<p><strong>Conclusão</strong></p>
<p>A implementação de regras básicas de segurança depende apena da boa vontade do desenvolvedor. Você deve ter percebido como a maior parte das soluções aqui apresentadas significam simples mudanças de hábito.</p>
<p>É mais do que tempo de nós, desenvolvedores PHP, deixarmos de lado nossos antigos vícios e começarmos a implementar boas práticas de programação.</p>
<p>Ganha o profissional, ganha a sua aplicação, ganha o seu cliente, ganha o mercado. Só quem perde nessa situação é quem tenta se aproveitar de nossa aplicação.</p>
<p><strong>Referências e links sugeridos</strong></p>
<p>[PHP Security Consortium] &#8211; <a class="extlink" href="http://phpsec.org/" target="_blank">http://phpsec.org/</a><br />
[PHP RS] &#8211; <a class="extlink" href="http://www.phprs.com.br/" target="_blank">http://www.phprs.com.br/</a></p>
<blockquote><p>Er Galvão Abbott trabalha há mais de dez anos com programação de websites e sistemas corporativos com interface web. Autodidata, teve seu primeiro contato com a linguagem HTML em 1995, quando a internet estreava no Brasil. Atualmente, além de lecionar em diversos cursos, tem se dedicado ao desenvolvimento de sistemas baseados na web, tendo nas linguagens PHP, Perl e JavaScript suas principais paixões.</p></blockquote>
<p><a title="Segurança no PHP" href="http://rafael.bernard-araujo.com/seguranca-no-php.php">Parte I</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rafael.bernard-araujo.com/seguranca-no-php-ii.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Segurança no&#160;PHP</title>
		<link>http://rafael.bernard-araujo.com/seguranca-no-php.php</link>
		<comments>http://rafael.bernard-araujo.com/seguranca-no-php.php#comments</comments>
		<pubDate>Wed, 12 Nov 2008 16:17:11 +0000</pubDate>
		<dc:creator>rafael</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[register globals]]></category>
		<category><![CDATA[segurança]]></category>
		<category><![CDATA[sessão]]></category>

		<guid isPermaLink="false">http://rafael.bernard-araujo.com/?p=70</guid>
		<description><![CDATA[Os 6 requisitos mínimos por Er Galvão Abbott (http://www.galvao.eti.br/) na revista PHPMagazine (http://www.phpmagazine.org.br/) Apresentareremos neste artigo 6 requisitos que todo o desenvolvedor PHP deveria contemplar em sua aplicação. São boas práticas e hábitos simples que implementam um nível mínimo de segurança em qualquer sistema ou ferramenta desenvolvida com a linguagem. A linguagem PHP é, sem [...]]]></description>
			<content:encoded><![CDATA[<!-- boo-widget start -->
          <script type="text/javascript">
            bb_keywords = "cookie";
            bb_bid  = "1613262";
            bb_lang = "pt-BR";
            bb_name = "custom";bb_limit = "9";bb_format = "bbo";
          </script>
          <script type="text/javascript" src="http://widgets.boo-box.com/javascripts/embed.js"></script>
          <!-- boo-widget end --><h3>Os 6 requisitos mínimos</h3>
<p><em>por Er Galvão Abbott (<a class="extlink" href="http://www.galvao.eti.br/" target="_blank">http://www.galvao.eti.br/</a>) na revista PHPMagazine (<a class="extlink" href="http://www.phpmagazine.com.br/" target="_blank">http://www.phpmagazine.org.br/</a>)</em></p>
<p align="center"><a href="http://www.phpmagazine.org.br/" target="_blank"><img src="http://rafael.bernard-araujo.com/img/phpmagazine-logo-medio.gif" alt="logo-phpmagazine" width="144" height="68" border="0" /></a></p>
<p><img src="http://www.galvao.eti.br/img/foto.jpg" alt="" width="100" height="105" align="left" />Apresentareremos neste artigo 6 requisitos que todo o desenvolvedor PHP deveria contemplar em sua aplicação. São boas práticas e hábitos simples que implementam um nível mínimo de segurança em qualquer sistema ou ferramenta desenvolvida com a linguagem.</p>
<p>A linguagem PHP é, sem dúvida, uma das mais populares quando o assunto é desenvolvimento de aplicações web. Existe, porém, um preconceito muito grande com a linguagem quando a questão é segurança. Neste artigo veremos 6 requisitos básicos que toda aplicação deveria possuir e que implementarão o mínimo de segurança em tudo o que você desenvolver.</p>
<p><strong>Conceito: PHP é uma linguagem mais vulnerável do que as outras?</strong></p>
<p>Atualmente impera no mercado de desenvolvimento um preconceito relacionado à segurança de aplicações PHP. A linguagem é freqüentemente alvo de duras críticas por parte da própria comunidade de desenvolvimento, e não é raro presenciarmos aplicações extremamente vulneráveis que, com toda a certeza, dão razão a essas críticas.</p>
<p>Este preconceito, totalmente equivocado, tem suas origens na extrema flexibilidade de configuração e uso da linguagem e no número cada vez maior de desenvolvedores inexperientes que começam sua carreira desenvolvendo aplicações PHP, ignorando questões básicas, seja por falta de conhecimento ou porque estão procurando agilizar sua produção pessoal.</p>
<p>Este artigo não é destinado apenas aos que estão começando. É surpreendente o número de desenvolvedores mais experientes que, por terem adquirido vícios, ainda ignoram as questões que apresentaremos aqui.</p>
<p><strong>Requisito #1: Esqueça <em>register_globals</em>!</strong></p>
<p><em>Register_globals</em> é, sem dúvida alguma, a diretiva de configuração mais popular e polêmica já implementada no PHP. É popular entre os desenvolvedores por tornar o processo de programação muito mais ágil e prático. É polêmica porque retira tanto do programador quanto do interpretador da linguagem a responsabilidade em definir a origem das informações utilizadas pela aplicação.</p>
<p>Esta diretiva causou tantos problemas que começou a vir desabilitada por <em>default</em> a partir da versão 4.2.0 e <strong>será eliminada na versão 6</strong>. Por isso, se você ainda programa com <em>register_globals</em> ligada, está mais do que na hora de mudar.</p>
<p>Observe o seguinte exemplo de código:</p>
<p><code>$url = "http://www.meusite.com.br/index.php";<br />
$errMsg = "Usuário%20não%20autenticado";<br />
if (!$autenticado) {<br />
header("Location: $url?erro=$errMsg");<br />
} else {<br />
/* A aplicação age com se o usuário estivesse autenticado */<br />
}<br />
</code><br />
Este código verifica por uma variável booleana chamada <code>$autenticado</code>, que tipicamente viria de uma sessão aberta quando o usuário se autenticou em nossa aplicação ou mesmo de um <em>cookie</em>. Ao utilizarmos os recursos da <em>register_globals</em>, porém, não estamos dizendo ao interpretador PHP que este dado deve vir obrigatoriamente de uma destas duas fontes.</p>
<p>Sendo assim, o interpretador procurará por esta variável em diversas fontes (variável do servidore web, dados de formulário, <em>cookie</em>, arquivos enviados por <em>upload</em>, <em>query string</em> ou sessões) das quais ele obteve informações até encontrá-la, desprezando se esta fonte está correta.</p>
<p>Torna-se extremamente simples &#8220;enganar&#8221; a sua aplicação PHP, basta que eu chame o seu arquivo passando a variável esperada por <em>query string</em>.</p>
<p>http://www.meusite.com.br/script.php?autenticado=1</p>
<p>Ao receber a <em>query string</em> contendo a informação &#8220;autenticado&#8221;, este dado será automaticamente interpretado como uma variável pelo interpretador, quer exista sessões ou <em>cookies</em> ou não.</p>
<p>Uma dúvida freqüente é &#8220;se não tenho autorização para desligar a <em>register_globals</em> o que eu posso fazer?&#8221;. A resposta para isso é tão simples quanto tudo o mais na linguagem: <strong>programe como se ela estivesse desligada!</strong> Veja como fica o nosso código ao não utilizar a <em>register_globals</em>:</p>
<p><code>$url = "http://www.meusite.com.br/index.php";<br />
$errMsg = "Usuário%20não%20autenticado";<br />
if (!$_SESSSION['autenticado']) {<br />
header("Location: $url?erro=$errMsg");<br />
} else {<br />
/* A aplicação age com se o usuário estivesse autenticado */<br />
}</code></p>
<p>Observe a mudança: ao utilizarmos o <em>array</em> super global <code>$_SESSION</code>, estamos explicitando para o interpretador que a informação &#8220;autenticado&#8221; tem que, obrigatoriamente, vir de uma sessão. Isto significa que será impossível para o interpretador confundir este dado com um dado enviado pela <em>query string</em>, pois este fica armazenado em um <em>array</em> super global diferente:</p>
<ul>
<li>$_SERVER &#8211; Informações definidas pelo servidor web (Apache, IIS etc)</li>
<li>$_GET &#8211; Informações passadas por <em>query string</em> ou por um formulário web utilizando o método GET</li>
<li>$_POST &#8211; Informações enviadas, tipicamente, por um formulário web utilizando o método POST</li>
<li>$_COOKIE &#8211; Informações fornecidas por um cookie HTTP</li>
<li>$_FILES &#8211; Informações fornecidas por arquivos que foram enviados via <em>upload</em> HTTP</li>
<li>$_ENV &#8211; Informações fornecidas pelo ambiente do servidor</li>
<li>$_REQUEST* &#8211; Informações fornecidas por GET, POST ou COOKIE</li>
</ul>
<p><strong>* Cuidado</strong>: O uso do <em>array</em> super global <code>$_REQUEST</code> é quase tão perigoso quanto a <em>register_globals</em> em si, pois nesse caso a informação pode vir de qualquer um dos 3 métodos: GET, POST ou COOKIE.</p>
<p><strong>Requisito #2: Use require e não include</strong></p>
<p>O comando <code>include</code> e seus derivados &#8211; como <code>include_once</code> &#8211; são freqüentemente usados em detrimento do comando <code>require</code>. Este fato curioso a princípio é conseqüência da similaridade do comando <code>include </code>com outras linguagens, como C e Java.</p>
<p>O que muita gente não sabe, porém, é que este comando carrega consigo um risco muito grande para sua aplicação: se por algum motivo a inclusão do arquivo falhar &#8211; erro de digitação, disco corrompido etc &#8211; será gerado um erro de nível <em>warning</em>, um nível leve de erro que não causa a parada da execução do script.</p>
<p>Utilizando o comando <code>require</code>, garantimos que, no caso de falha na carga do arquivo, seja gerado, além do erro de nível <em>warning</em>, um erro de nível <em>fatal</em>. Em bom português isso significa que a execução do seu script será imediatamente interrompida neste caso. Por que é bom que seu script seja interrompido no caso de falha de inclusão de outro arquivo? Simples: no caso de falhas, as variáveis, as funções, as constantes e o que mais este arquivo carregava consigo, simplesmente, não estarão disponíveis.</p>
<p><strong>Requisito #3: Filtre a entrada de dados!</strong></p>
<p>Um dos principais conceitos de segurança é a filtragem dos dados que são recebidos antes de utilizá-los. A falta de fitlragem é a causa de inúmeros problemas de segurança, incluindo o infame <em>SQL Injection</em>, ou Injeção de SQL. Observe o seguinte código:</p>
<p><code>require_once("conecta.php");<br />
$conn = conecta();<br />
$sql = "SELECT email FROM usuarios WHERE usuario_id = " . $_GET['uid'];<br />
$recordSet = mysql_query($sql);<br />
while ($record = mysql_fetch_assoc($recordSet)) {<br />
echo $record['email'] . '&lt;br /&gt;';<br />
}<br />
mysql_close();</code></p>
<p>O problema deste código é utilizar um dado informado pela <em>query string</em> (uid) sem fazer nenhuma filtragem, ou seja, nosso script aceitará cegamente qualquer coisa que for digitada como valor de uid. Observe a seguinte URL:</p>
<p>http://www.meusite.com.br/script.php?uid=198%20OR%20&#8242;x&#8217;='x&#8217;</p>
<p>Após a conversão dos caracteres especiais desta URL, o valor de uid será (sem aspas duplas): &#8220;198 or &#8216;x&#8217;='x&#8217;&#8221;. Note que, quando concatenarmos isto à nossa <em>query</em>, ela terá sofrido uma grande modificação:</p>
<p><code>SELECT email FROM usuarios WHERE usuario_id = 198 <span style="color: #ff0000;">or 'x'='x'</span></code></p>
<p>É por isso que a chamamos de &#8220;Injeção de SQL&#8221;. A parte em vermelho acima é formada de SQL válido, mas completamente alienígena à nossa plicação: <strong>ele modifica o comportamento original da query</strong>.</p>
<p>Observe que, com um mínimo de esforço, um usuário conseguiu expor todos os e-mails cadastrados em nossa base de dados: como foi utilizado o operador &#8220;OR&#8221; e a segunda condição (&#8216;x&#8217;='x&#8217;) é sempre verdadeira, serão exibidos todos os registros.</p>
<p>Para evitarmos este tipo de problema, devemos aplicar um tratamento à informação <strong>antes</strong> de utilizá-la. Caso a minha <em>query</em> &#8211; como neste exemplo &#8211; esteja esperando um número inteiro, a solução é simples: forçamos a conversão do dado recebido para número inteiro:</p>
<p><code>require_once("conecta.php");<br />
$conn = conecta();</code></p>
<p><code>settype($_GET['uid'], integer);</code></p>
<p><code>$sql = "SELECT email FROM usuarios WHERE usuario_id = " . $_GET['uid'];<br />
$recordSet = mysql_query($sql);<br />
while ($record = mysql_fetch_assoc($recordSet)) {<br />
echo $record['email'] . '&lt;br /&gt;';<br />
}<br />
mysql_close();</code></p>
<p>A partir de agora, qualquer dado enviado pela <em>query string</em> será primeiro convertido para inteiro e somente depois desta conversão é que o utilizaremos. No caso de uma tentativa de Injeção de SQL, nosso script considerará apenas a parte numérica (198), como deveria ser. Além disso, se por um acaso nosso script receber apenas texto, a função <code>settype</code> converterá isto para o número 0.</p>
<p>Caso a minha <em>query</em> esteja esperando uma <em>string</em> a solução reside em criar um tratamento que valide esta <em>string</em>. Vejamos um exemplo: possuo uma <em>query</em> que busca dados de um usuário através de seu endereço de e-mail:</p>
<p><code>$sql = "SELECT nome, sobrenome FROM usuarios WHERE email = '" . $_GET['email'] . "'";<br />
</code><br />
Sabemos que um endereço de e-mail é formado por um nome de usuário, uma arroba e um domínio. Para fins de simplificação do exemplo, trabalharemos como se o usuário só pudesse usar letras, números e o caracterese de ponto &#8211; para quem levar a validação de e-mail a sério consulte a RFC 822. Podemos representar isso através de uma expressão regular:</p>
<p><code>/^[A-Z|a-z|0-9|\.|]+\@[A-Z|a-z|0-9\.|]+/</code></p>
<p>Sendo assim, só aceitaremos o dado de endereço de e-mail se ele estiver dentro dos padrões de minha expressão regular. Nosso código então ficaria assim:</p>
<p><code>require_once("conecta.php");<br />
if (preg_match('</code><code>/^[A-Z|a-z|0-9|\.|]+\@[A-Z|a-z|0-9\.|]+/'</code><code>, $_GET['email'])) {<br />
$conn = conecta();</code></p>
<p><code>$sql = "SELECT nome, sobrenome FROM usuarios WHERE email = '" . $_GET['email'] . "'";<br />
$recordSet = mysql_query($sql);<br />
while ($record = mysql_fetch_assoc($recordSet)) {<br />
echo $record['email'] . '&lt;br /&gt;';<br />
}<br />
} else {<br />
die("O dado informado não é um endereço de e-mail válido.");<br />
}<br />
mysql_close();<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://rafael.bernard-araujo.com/seguranca-no-php.php/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

