Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Nébulas

Segurança no upload: Validação de arquivos

Recommended Posts

Boa noite galera.

 

Estou com um sério problema de segurança na validação dos arquivos que faço upload, já pesquisei muito e só encontrei as maneiras mais comuns.

Veja alguns exemplos de validação de upload.

 

UPLOAD DE IMAGENS

 

1º Situação: Tenho q vefiticar o tipo do arquivo usando $_FILES["imagem"]["type"] e se retornar image/jpg, image/gif, image/png... é verdadeiro.

FALHA: Se renomear a extensão do arquivo "teste.txt" para "teste.jpg" ele ja passa nessa 1º verificação apenas mascarando o arquivo.

 

2º Situação: Como toda imagem é composta por pixels posso usar getimagesize($_FILES["imagem"]["tmp_name"]) e se retornar as medidas é verdadeiro.

CONCLUSÃO: Para imagens não encontrei outra meneira melhor de validar imagens, pois mesmo se renomear a extensão do arquivo como no 1º exemplo ele não terá pixels.

 

 

UPLOAD DE OUTROS ARQUIVO

 

Situação: A unica maneira que encontrei foi usar $_FILES["imagem"]["type"], mas como mostrado no exemplo anterior, essa função tem a falha do renomeio da extensão do arquivo.

PERIGO: Um arquivo exe, php, py, ou qualquer outro tipo pode quebrar está verificação apenas um o renomeio da extensão.

 

Penssei em usar a função fopen() e validar o código fonte, mas alem de não saber como fazer essa validação, não sei se é seguro abrir o arquivo caso ele esteja mascarado.

 

Alguem sabe outra maneira de validação com segurança?

Compartilhar este post


Link para o post
Compartilhar em outros sites

$_FILES["imagem"]["type"]

deve retornar o content type que é independente da nomenclatura do arquivo, pois a leitura é baseada no cabeçalho do conteúdo do arquivo.

 

o nome do arquivo pode ser "qualquer_coisa.seila" e ser do tipo image/jpg ou exe ou pkg.. enfim, qualquer coisa..

a nomenclatura é apenas um recurso visual / amigável para o usuário e util tambem para referenciar extensões a determinados tipos de softwares..

 

o que importa verificar, no momento do upload, é o content type

Compartilhar este post


Link para o post
Compartilhar em outros sites

Verificação por mime type é "bypasseável" se não houver validação na extensão do arquivo.

 

Já peguei casos em que se upava um arquivo de nome "foto.php.jpg" e era interpretado como php, por causa da configuração do Apache.

 

$ext = strtolower(end(explode('.', $filename)));

 

Assim você pode verificar se ext é 'jpg', 'jpeg', enfim, apenas extensões permitidas.

 

[]'s

Compartilhar este post


Link para o post
Compartilhar em outros sites

vcs estão confundindo ainda..

 

extensão da nomenclatura do arquivo não tem a ver com o content-type ou mime-type, que seja..

 

a informação sobre o content-ttype esta dentro do arquivo, no cabeçalho.. todo arquivo tem um cabeçalho que o identifica... um arquivo .exe pode ser um simples image/jpeg..

você pode até permitir que envie um arquivo imagem.php, desde que o content-type seja image/alguma coisa.. ou o tipo que for permitido pelas regras de negócio..

E logicamente, se permitir enviar como .php, altere o nome do arquivo e extensão ou deixe-o fora do folder onde o php é executado.

 

obviamente nem tudo é 100% seguro, mas, verificando o content-type é a forma mais adequada.. se quer um exemplo,

há sistemas operacionais como o macosx, por exemplo, que permite salvar imagens sem a extensão. Até no windows é possível..

 

imagine um usuário tentando fazer upload de um arquivo jpeg legítimo e ser bloqueado por não ter extensão..

por isso e outros pontos básicos já abordados, o mais adequado é verificar o cabeçalho..

 

mas pode ter certeza de uma coisa, verificar apenas a extensão é o modo mais inseguro.

Compartilhar este post


Link para o post
Compartilhar em outros sites

É como eu falei, para imagens o metodo mais seguro que encontrei é usar:

 

list($largura, $altura) = getimagesize($_FILES["foto"]["tmp_name"]);

if($largura=="" || $altura ==""){
//ARQUIVO INVÁLIDO
}

 

Mas o problemas é para outros tipos de arquivos.

Vamos dizer que eu permita o upload de PDF, se mascarar o arquivo, apenas renomeando, teste.php para teste.pdf a validação do tipo do arquivo permite.

Compartilhar este post


Link para o post
Compartilhar em outros sites

vcs estão confundindo ainda..

 

extensão da nomenclatura do arquivo não tem a ver com o content-type ou mime-type, que seja..

 

a informação sobre o content-ttype esta dentro do arquivo, no cabeçalho.. todo arquivo tem um cabeçalho que o identifica... um arquivo .exe pode ser um simples image/jpeg..

você pode até permitir que envie um arquivo imagem.php, desde que o content-type seja image/alguma coisa.. ou o tipo que for permitido pelas regras de negócio..

E logicamente, se permitir enviar como .php, altere o nome do arquivo e extensão ou deixe-o fora do folder onde o php é executado.

 

obviamente nem tudo é 100% seguro, mas, verificando o content-type é a forma mais adequada.. se quer um exemplo,

há sistemas operacionais como o macosx, por exemplo, que permite salvar imagens sem a extensão. Até no windows é possível..

 

imagine um usuário tentando fazer upload de um arquivo jpeg legítimo e ser bloqueado por não ter extensão..

por isso e outros pontos básicos já abordados, o mais adequado é verificar o cabeçalho..

 

mas pode ter certeza de uma coisa, verificar apenas a extensão é o modo mais inseguro.

 

Hi.

 

Não estou confundindo não. =p

O Content-Type pode ser facilmente burlado editando a requisição. Qualquer programador com um http sniffer e uma lib curl em mãos conseguiria burlar. Aliás, só um Tamper data já mudaria o Content-type de text/plain para image/gif. Digo, isso quando verificamos pelo $_FILES['input']['type'].

 

Já o mime type, também pode ser burlado. É possível colocar os headers no topo do arquivo, ou inserir a propria phpshell dentro do GIMP ou tools como edicomjpg. Há uns dois anos atrás, assim era o maior foco de exploração de LFI (local file inclusion).

 

O correto mesmo é validar a extensão do arquivo, e tomar cuidado com "null byte poisoning", que seria fazer upload de shell.php%00.gif. Se o servidor for mal configurado, o script validará mas o arquivo ficará shell.php no servidor.

 

Se não for validar, seria bom renomear o arquivo com uma hash md5, configurar o .htaccess para desabilitar a execução de scripts .php, .php[0-9], .cgi, .sh, etc. Ou então utilizar BLOB e guardar os dados diretamente na database.

 

 

Palavras de um ex-defacer que já pegou vários sites confiando em mime-type e content-type. =p

 

[]'s

Compartilhar este post


Link para o post
Compartilhar em outros sites

sim obviamente, fazia muito isso quando brincava com defacement..

mas são casos mais específicos ..

mas de qualquer forma, para evitar o php injection, apenas mantenha os uploads da pasta executável do php.

 

 

Vamos dizer que eu permita o upload de PDF, se mascarar o arquivo, apenas renomeando, teste.php para teste.pdf a validação do tipo do arquivo permite.

sim.. como comentei acima.

não tem problema. uma vez identificado que o content-type não condiz com a extensão, você pode bloquear e emitir um alerta ao usuário ou permitir e automaticamente renomear para a extensão apropriada.

há também o caso que o fvox comentou sobre manipular os headers.. é muito fácil fazer, por isso jamais guarde os arquivos numa pasta onde o php é interpretado.

 

o usuario pode até conseguir enviar um virus mas se o virus não for executado não fará diferença alguma no server.

um problema que pode ocorrer é por exemplo, o usuario conseguir fazer upload de um arquivo desses applet java e outros com javascript que vão rodar em lado cliente.

 

por isso tem um monte de site com esses virus, cujos administradores não fazem idéia de como foram parar no servidor.

mas já tem uma pista de que o culpado é o fvox rss

Compartilhar este post


Link para o post
Compartilhar em outros sites

Culpado, eu?! Já tenho meu nome limpo no zone-h há uns anos UHAHUAHUA. Agora sou profissional. =p

 

Upload em si é algo complicado de ser seguro. Se for algo aberto ao usuário, recomendo fortemente que o nome do arquivo seja renomeado. E aí sim pode ser validado e então renomeado de acordo com o mime type recebido.

Se for uma phpshell, vai ser só um jpg inválido no servidor.

 

[]'s

Compartilhar este post


Link para o post
Compartilhar em outros sites

usa str_replace para trocar o nome dos arquivos upados

mais ou menos assim

$categoria = $_POST["categoria"];

$pasta = "pasta/";

$nome = $_FILES['arquivo']['name'];

$nome = str_replace("H", "", $nome);

$nome = str_replace("h", "", $nome);

$ext = explode('.', $nome);

$ext = strtolower($ext[count($ext) - 1]);

$nome = "".rand(11,99)."".time().".".$ext."";

 

ele renomeia qualquer arquivo que contenha h ou H na extenssao

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.