O perigo no gerenciador de uploads do PHP

O PHP é capaz de receber o upload de qualquer browser que siga a norma RFC-1867, o que permite o upload de arquivos cliente => servidor. Ele ainda provê o controle total de quem pode fazer o upload e o que fazer com o arquivo após sua transferência, mas mesmo com esse controle, somente poucas pessoas sabem do perigo real do mal uso desse recurso.

[ Hits: 29.411 ]

Por: Ragen Dazs em 03/11/2003 | Blog: http://www.orkut.com


is_uploaded_file() e move_uploaded_file()



Vejamos também as funções is_uploaded_file() e move_uploaded_file() para entender sobre as falhas que poderiam surgir durante a nossa programação.

is_uploaded_file ( string filename) -- Diz se o arquivo foi uploaded

Retorna TRUE se o arquivo com o nome filename foi uploaded via HTTP POST. Isto é útil para ter certeza que um usuário malicioso não está tentando confundir o script em trabalhar em arquivos que não deve estar trabalhando --- por exemplo, /etc/passwd.

Este tipo de confirmação é importante principalmente se existe alguma chance que qualquer coisa feita com os arquivos carregados poderiam revelar o seu conteúdo para o usuário ou mesmo para outros usuários no mesmo sistema.

is_uploaded_file() está disponível somente em versões do PHP 3 depois da 3.0.16 e em versões do PHP 4 posteriores a 4.0.2. Se você ainda está utilizando uma versão anterior, você pode utilizar o seguinte código para se proteger:

Nota: O exemplo seguinte não funcionará em versões do PHP posteriores a 4.0.2. Isto depende de uma funcionalidade interna do PHP que mudou depois dessa versão.

<?php
/* Teste de arquivo carregado pelo usuário */
function is_uploaded_file($filename) {
   if (!$tmp_file = get_cfg_var('upload_tmp_dir')) {
      $tmp_file = dirname(tempnam('', ''));
   }
   $tmp_file .= '/' . basename($filename);
/* Pode haver uma barra no final do php.ini... */
   return (ereg_replace('/+', '/', $tmp_file) == $filename);
}

/* Utilize isto se por acaso você não tiver
* move_uploaded_file() em versões antigas: */

if (is_uploaded_file($HTTP_POST_FILES['userfile'])) {
   copy($HTTP_POST_FILES['userfile'], "/place/to/put/uploaded/file");
} else {
   echo "Possível ataque de carregamento de arquivo:
   filename '$HTTP_POST_FILES[userfile]'.";
}
?>

Bem... Moral da história:

Pense naqueles sites que possuem sistemas do tipo "fale conosco" com suporte a anexos e confirmação que não utilizam esse tipo de validação? E como seria se um usuário "fuçador" começasse a explorar um fórum com o sistema de upload mal implementado? Não precisamos nem pensar muito no que um usuário malicioso pode fazer. Um exemplo seria o usuário setar o campo de upload com o caminho /etc/passwd, ou ./index.php. Enfim, qualquer arquivo do servidor e recebê-lo pela confirmação em seu e-mail.

Mas a função move_uploaded_files() que eu utilizei no exemplo possui uma peculiaridade. Vale lembrar que quando ela 'move' o arquivo no servidor, a mesma manda os arquivos somente com permissões de escrita (o que no caso de imagens para um site por exemplo não é viável), podendo sempre, lógico, alterar estas permissões.

Como deu pra ver, as possibilidades para falhas são inúmeras e quem não fizer esse tipo de validação está sujeito a muita dor de cabeça no futuro ^^

Fonte: Manual do PHP

[]`s
Ragen

Página anterior    

Páginas do artigo
   1. Introdução
   2. Tratando o processo de upload
   3. is_uploaded_file() e move_uploaded_file()
Outros artigos deste autor

Entendendo um pouco sobre os daemons

Usando cache na classe Fast Template

Adaptação das empresas de TI aos trabalhadores da era digital

Tratamento de dados fornecidos pelo usuário: projetando sistemas com mais segurança

PHP 6.0 - Você está pronto?

Leitura recomendada

Enviar mensagem ao usuário trabalhando com as opções do php.ini

PEAGLE: Serviço Web de busca indexada em seu servidor local

Gerando documentos PDF com a classe FPDF no PHP

Organizando fotos de camêra digital

Upload de imagens com criação de thumbnails em PHP

  
Comentários
[1] Comentário enviado por pmichelazzo em 20/01/2004 - 10:28h

Meu caro, esse não é um artigo mas sim uma cópia do manual do PHP com algumas alterações nanicas aqui e ali. Não seria mais honrado escrever um artigo verdadeiramente?

Perdi meu tempo pois tudo o que li aqui, já tinha lido no manual do PHP e nada me acrescentou.

Paulino Michelazzo

[2] Comentário enviado por Ragen em 12/02/2004 - 17:05h

Caro michelazzo,

Não foi à toa que coloquei "Fonte: Manual do PHP" no rodapé do texto. Mas da proxima vez, antes de usar algo já escrito, farei uma citação antes do mesmo e não mais no rodapé do texto.

[]`s

Ragen


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts