O perigo no gerenciador de uploads do PHP
Os arquivos serão guardados no diretório temporário do servidor a menos que outro lugar seja especificado com a opção upload_tmp_dir no php.ini. O diretório padrão do servidor pode ser mudado se mudando o valor da variável de ambiente TMPDIR no ambiente onde o PHP esta sendo executado PHP. Mudando-a com putenv() de um script PHP não irá funcionar. Esta variável de ambiente também pode ser usada para se ter certeza que outras operações estão funcionando no arquivo do upload.
Note que deve-se definir upload_temp_dir no php.ini ou TMPDIR, não podendo estarem ambos vazios, sendo recomendado no mínimo upload_tmp_dir.
Agora vamos ao que interessa: vamos validar o upload de arquivos.
O seguinte exemplo irá processar o envio de um arquivo que vem de um formulário:
O script PHP que irá receber o arquivo do upload deve implementar qualquer lógica que for necessária para determinar o que deve ser feito com o arquivo do upload. Você pode, por exemplo, usar a variável $_FILES['userfile']['size'] para descartar qualquer arquivo que seja muito pequeno ou muito grande. Você pode usar a variável $_FILES['userfile']['type'] para descartar qualquer arquivo que não seja de um certo tipo.
Desde o PHP 4.2.0, você pode usar $_FILES['userfile']['error'] e planejar a sua lógica de acordo com os códigos de erro. Qualquer que seja a lógica, você deve excluir o arquivo do diretório temporário ou movê-lo para outro lugar.
O arquivo será excluído do diretório temporário ao fim do script se não tiver sido movido ou renomeado.
Note que deve-se definir upload_temp_dir no php.ini ou TMPDIR, não podendo estarem ambos vazios, sendo recomendado no mínimo upload_tmp_dir.
Agora vamos ao que interessa: vamos validar o upload de arquivos.
O seguinte exemplo irá processar o envio de um arquivo que vem de um formulário:
<?php // Nas versões anteriores a 4.1.0, $HTTP_POST_FILES deve ser usado ao invés de $_FILES. // Nas versões anteriores a 4.0.3, use copy() e is_uploaded_file() ao invés // move_uploaded_file $uploaddir = '/var/www/uploads/'; print "<pre>"; if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir . $_FILES['userfile']['name'])) { print "O arquivo é valido e foi carregado com sucesso. Aqui esta alguma informação:\n"; print_r($_FILES); } else { print "Possível ataque de upload! Aqui esta alguma informação:\n"; print_r($_FILES); } ?>
O script PHP que irá receber o arquivo do upload deve implementar qualquer lógica que for necessária para determinar o que deve ser feito com o arquivo do upload. Você pode, por exemplo, usar a variável $_FILES['userfile']['size'] para descartar qualquer arquivo que seja muito pequeno ou muito grande. Você pode usar a variável $_FILES['userfile']['type'] para descartar qualquer arquivo que não seja de um certo tipo.
Desde o PHP 4.2.0, você pode usar $_FILES['userfile']['error'] e planejar a sua lógica de acordo com os códigos de erro. Qualquer que seja a lógica, você deve excluir o arquivo do diretório temporário ou movê-lo para outro lugar.
O arquivo será excluído do diretório temporário ao fim do script se não tiver sido movido ou renomeado.
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)
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
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
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
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!
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
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)
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");
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)