+3

Principais erros de segurança em códigos PHP

criado por Marcos Regis em 12/06/2008 8:17am
- Nunca executar consultas não-escapadas

O PHP tem uma propriedade, ativa por default, que automaticamente escapa (adicionando uma contrabarra antes de) certos caracteres que vierem de um GET, POST, ou COOKIE.

A aspa simples (') é um exemplo de um character que é escapado automaticamente. Isto é feito de assim que você incluir variáveis de entrada em suas consultas SQL, e ele não irá tratar aspas simples como parte da consulta. Diga a seu usuário para entrar com <span class="var">$name</span> de um formulário e você performar esta consulta:

UPDATE  users SET Name='$name'  WHERE ID=1;

Normalmente, se for digitado $name com aspas simples, elas serão escapadas, então o MySQL poderá ver assim:

UPDATE  users SET Name='Joe\'s' WHERE ID=1;

Fazendo com que a aspa simples dentro de "Joe's" não interfira com a sintaxe da consulta. Em algumas situações, você pode usar stripslashes() em uma variável de entrada.

Se você colocar a variável dentro de uma consulta, certifique-se de usar addslashes() ou mysql_escape_string() para escapar as aspas simples antes de executar a consulta. Imagine se uma consulta não escapada passar, e um usuário malicioso tiver entrado parte de uma consulta com seu nome!?

UPDATE  users SET Name='Joe\'s',Admin='1' WHERE ID=1;

No formulário de entrada, o usuário pode ter entrado: Joe',Admin='1

Como seu nome, e desde que aspas simples não foram escapadas, ele/ela serão capazes de verdadeiramente terminar a definição do nome, colocando uma virgula, e ajustando uma outra variável chamada Admin!

A consulta final com se parecerá como esta:

UPDATE  users SET Name='Joe',Admin='1' WHERE ID=1;

Em algumas configurações, magic_quotes_gpc (a propriedade que automaticamente colocar barras em todos as entradas) está ajustado em OFF. Você pode utilizar a função get_magic_quotes_gpc() para verificar seu estado (ela retorna verdadeiro ou falso). Se retornar falso, simplesmente use addslashes() para colocar barras em todas as entradas (é mais fácil se você usar $_POST, $_GET, e $_COOKIE ou $HTTP_POST_VARS, $HTTP_GET_VARS, e $HTTP_COOKIE_VARS, ao invés das globais porque você poderá percorrer estes vetores usando um loop foreach() e adicioanar barras a cada um deles).

Comentários:

Mostrando 1 - 10 de 24 comentários
Parabéns pelo artigo! :-)
31/03/2011 2:13am (~13 anos atrás)

Dam disse:
Bom artigo.
20/11/2008 4:21am (~16 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.
17/11/2008 4:36am (~16 anos atrás)

Ricardo Gama disse:
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
13/11/2008 9:09am (~16 anos atrás)

Marcos Regis disse:
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.
13/11/2008 8:38am (~16 anos atrás)

Ricardo Gama disse:
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?
13/11/2008 8:05am (~16 anos atrás)

Marcos Regis disse:
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.
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]
03/11/2008 4:49pm (~16 anos atrás)

hinom disse:
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

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)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)