Skip to content

Instantly share code, notes, and snippets.

@TiuTalk
Created February 20, 2015 02:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save TiuTalk/534927c91bc82811170b to your computer and use it in GitHub Desktop.
Save TiuTalk/534927c91bc82811170b to your computer and use it in GitHub Desktop.
<?php
// Define o tempo máximo de execução em 0 para as conexões lentas
set_time_limit(0);
// Arqui você faz as validações e/ou pega os dados do banco de dados
$aquivoNome = 'imagem.jpg'; // nome do arquivo que será enviado p/ download
$arquivoLocal = '/pasta/do/arquivo/'.$aquivoNome; // caminho absoluto do arquivo
// Verifica se o arquivo não existe
if (!file_exists($arquivoLocal)) {
// Exiba uma mensagem de erro caso ele não exista
exit;
}
// Aqui você pode aumentar o contador de downloads
// Definimos o novo nome do arquivo
$novoNome = 'imagem_nova.jpg';
// Configuramos os headers que serão enviados para o browser
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="'.$novoNome.'"');
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($aquivoNome));
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Expires: 0');
// Envia o arquivo para o cliente
readfile($aquivoNome);
@inkeliz
Copy link

inkeliz commented Mar 13, 2017

Tem uma crítica vulnerabilidade nisto, uma vez que não há qualquer filtro no $aquivoNome. Por essa razão todas as pastas que podem ser acessadas. Não recomendo utiliza-la sem utilizar ao menos um if(!preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $aquivoNome)){. O ataque pode ser feito da seguinte maneira, imagine o cenário:

/public_html
- snippet.php
/arquivos
- documento.pdf

Supostamente você vai fazer a leitura de:

../arquivos/documento.pdf

Correto? Se for feito algo do tipo:

../arquivos/.$_GET['arquivos'];

Você espera que o parâmetro arquivos seja documento.pdf. Porém, uma pessoa poderá fazer um GET utilizando o parâmetro arquivos=../public_html/snippet.php, logo irá baixar o arquivo:

../arquivos/../public_html/snippet.php

Pronto, ele baixou o snippet.php, o arquivo PHP.

Isso pode ser mais grave, porque pode baixar o arquivos de senhas, como o etc/passwd....

Existem duas soluções, podem ser utilizadas em conjunto o realpath para eliminar os caminhos dinâmicos, porém não impede /alcancar/outras/pastas, para somente filtrar o nome do arquivo e o seu formato (exemplo.formato) poderá utilizar o regex mencionado acima, inclusive fiz isto neste fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment