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.350 ]

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

DotGNU: a resposta Open Source ao dotNET

Usando cache na classe Fast Template

Populando sua SpamTrap com e-mails relevantes

Referências ou ponteiros em PHP

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

Leitura recomendada

Trabalhando com arquivos em PHP

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

Gerando documentos PDF com a classe FPDF no PHP

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

Organizando fotos de camêra digital

  
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