PHP Injection
Esse artigo é apenas um pequeno resumo das inúmeras possibilidades de aplicar e evitar o PHP Injection.
Uma coisa com que nos devemos sempre preocupar são as nossas query string: essas 2 abaixo são as mais usadas (páginas e includes), e claro isso é valido para outras variáveis também.
pagina.php?pag=
pagina.php?inc=
Por incrível que pareça, isso é muito comum e é com essa vulnerabilidade que muitos sites são hackeados.
Por exemplo: se você fizer uma busca no Google com o termo.
Esses são só sites que você irá testar, portanto facilita muito a vida, se você colocar no Google: allinurl: string - você encontra muita coisa interessante, aproximadamente 2.770.000 para allinurl: string
Com a busca você vai encontrar muita coisa do tipo:
pagina.php?pag=
Com o crescimento de muitos sites e maior facilidade no desenvolvimento, surgem claro muitos servidores mal cuidados e muitos programadores despreocupados com a segurança e com isso uma pessoa com intenção de prejudicar pode usar um exploit remoto assim:
Você tem a url: www.qualquercoisa.xb/pasta/foto.gif
. Com um exploit você pode fazer www.qualquercoisa.xb/pasta/foto.gif?&exp=comando
(exp exploit).
Não irei entrar em questões mais técnicas que não é o objectivo, mas se com isso você pegar um servidor vulnerável, você pode escalar privilégios e poderá ter até o root da máquina. Essas maquinas são usadas muito por spammers, e são chamadas de máquinas zumbi.
Algumas maneiras para melhorar a segurança
Primeiro, edite o php.ini
especifique as opções:
allow_url_fopen = Off
Isso vai impedir que um include
ou um open
que não esteja hard coded, ou seja, que tenham os seus valores fornecidos por uma variável, façam includes remotos, como no exemplo citado no início deste post.
register_globals = Off
O "register globals" ligado diz para o PHP que qualquer variável passada como parâmetro deve ser reconhecida como uma variável válida dentro do código PHP. Isto facilita muito as coisas, pois com isso não precisamos ficar associando o array $_REQUEST
a variáveis internas. Mas ao mesmo tempo é perigoso, pois permite a um atacante controlar variáveis internas que você não tenha correctamente inicializado.
magic_quotes_gpc = On
Se você não tem conhecimento sobre como "tratar" variáveis antes de enviá-las para bancos de dados ou programas externos, uma boa opção é deixar o "magic quotes" ligado, pois ele dificulta bastante a manipulação de strings para, por exemplo, provocar um SQL Injection no seu acesso ao banco.
display_errors = Off
Ao invés de visualizar os erros de programação no browser, use o log do servidor. Esta opção impede que atacantes provoquem erros na sua aplicação para descobrirem paths da estrutura de arquivos.
Leia as demais opções do seu php.ini
, especialmente se você estiver a usar o PHP sob IIS/Windows. Existem coisas importantes lá, mas que nunca tive a oportunidade de usar.
Além das configurações, algumas práticas de programação podem salvar a sua pele. Por exemplo, nunca passe o nome de um arquivo como parâmetro para include
ou fopen
! É muito comum você encontrar sites com URLs do tipo: /index.php?inc=contato
. E então, quando mudamos a palavra contato
para qualquer outra coisa (por exemplo, testnotfound
) o PHP exibe a fatídica mensagem de erro de "Arquivo não encontrado". E atenção:
não confie no seu código se você está a acrescentar um path completo e a extensão do arquivo na hora de incluir, por exemplo:
include("/home/asnocoder/www/includes/".$inc.".php");
Não confie nisso! Continua perfeitamente possível incluir qualquer arquivo do seu sistema através da manipulação correta da variável $inc
.
E já que estamos a falar de includes, nunca coloque a extensão .inc
nos seus scripts ou bibliotecas. Estas extensões não são tratadas pelo webserver e o código-fonte do programa é exibido caso eles sejam chamados diretamente no browser. Você tem três opções:
- Renomear estes arquivos para
arquivo.inc.php
, por exemplo (e alterar os includes que fazem referência a eles). - Mover estes arquivos para uma parte da árvore de directórios que não seja acessível directamente pelo browser.
- Proteger o directório onde estes arquivos estão. Segue exemplo de directrizes do Apache:
<Location ~ "/[^ ](?=.inc(?[^ ]*)?)/"> Options None Order Allow, Deny Deny from All AllowOverride None Satisfy All </Location>
Quando eu tenho que fazer um include
/fopen
de acordo com uma opção do utilizador, eu costumo criar um ninho de if
s e passar como parâmetro para a página apenas um número, ou um código qualquer, fazendo algo do tipo:
inc = "index.php"; // Página default
if($_GET['opcao']=="1") { $inc = "pagina1.php"; }
if($_GET['opcao']=="2") { $inc = "pagina2.php"; }
include($inc);