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.
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 ^^
[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.
[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.