+2

O perigo no gerenciador de uploads do PHP

criado por Allyson F. de Paula Reis em 04/11/2003 8:41pm
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

Comentários:

Mostrando 1 - 10 de 10 comentários
Diogo Gomes disse:
mesmo depois de ter lido a algum tempo, voltei aqui pra deixar meu comentário e tirar umas dúvidas... Parabéns...
12/12/2003 2:11pm (~21 anos atrás)

Fabiano Suet disse:
Existe, pelo menos no meu server, uma limitação quanto ao tamanho do arquivo, não passa nada acima de 1MB, e eu não tenho nenhum proxy que possa causar esse tipo de limitação. O apache da minha máquina é o 2.alguma coisa. Grato !!!! Fabiano.
10/12/2003 10:42am (~21 anos atrás)

Seria mesmo mais prudente bloquear os arquivos com extensão não permitida do client-side. Alguém sabe como fazer isso? Só que depois tem que bloquear também no php .. um usuário mal intensionado vai saber mesmo burlar a restrição client-side.
Marlon
07/12/2003 10:45am (~21 anos atrás)

acho que o legal não é bloquear os tipos de arquivos, e sim somente permitir, vc escolhe oque pode fazer upload e permite esses, o resto, bloqueia tudo, na certa que é melhor, pois vc pode esquecer alguma coisa e ai ja vio.
26/11/2003 11:44am (~21 anos atrás)

Concordo Ragen,

a documentação é linda :)
por isso existe gente traduzindo ela
para o nosso também lindo idioma :P
12/11/2003 5:45am (~21 anos atrás)

Valeu Marco,

Mas se você der uma pesquisada no manual do PHP você vai ver que tudo isso que eu disse está na documentação disponivel no php.net.

A documentação do PHP é linda :)

[]`s

Ragen
11/11/2003 6:41pm (~21 anos atrás)

O seu artigo, além de breve, foi capaz de resumir de forma bastante interessante o processo de upload. Recentemente estive desenvolvendo alguns scripts para upload e suas dicas são pertinentes. Todo cuidado é pouco. Parabéns!
11/11/2003 6:37pm (~21 anos atrás)

é realmente quem ja teve problemas com upload sabe o que pode acontecer :)

muito bom artigo!!

e os comentários são novamente muito preciosos!
06/11/2003 8:01am (~21 anos atrás)

Muito bem lembrado.

Geralmente esse tipo de validação por extensão se torna realmente mais fácil mesmo.

Mas mostrei as outras formas no caso de alguém precisar fazer um sistema de upload de um arquivos que compartilhe uma extensão comum ao servidor.

[]`s

Ragen
06/11/2003 4:24am (~21 anos atrás)

Cau Guanabara disse:
Bacana Ragen, bastante didático.
Uma dica legal também (se você puder fazer isso) é limitar os arquivos pela extensão,
tipo: se o nome do arquivo não terminar em '.htm' ou .html' ou '.txt', paramos o processo.
Só isso evita boa parte das possibilidades de ataques, pois os arquivos administrativos do linux, como o /etc/shadow ou passwd podem ser do tipo text/plain, mas não tem extensão.
$fname = $_FILES['userfile']['name'];
if(!preg_match("/\.htm$/",$fname) and
!preg_match("/\.html$/",$fname) and
!preg_match("/\.txt$/",$fname)) die("Tipo de arquivo não permitido");
05/11/2003 7:42pm (~21 anos atrás)

Novo Comentário:

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