Domando o MIME

Er Galvao Abbott
O ElePHPant do Chapéu Branco
2 min readMar 29, 2017

Meu amigo Ayr Müller Gonçalves compartilhou comigo recentemente um vídeo do YouTube mostrando como explorar upload de arquivos para “instalar” um script malicioso em um servidor Apache.

O vídeo em questão (recomendo assistir)demonstra o upload de um arquivo de “dupla extensão” (no caso algo como foo.php.jpg).

O vídeo, embora sucinto e informativo comete dois equívocos:

  1. Associa a linguagem PHP com o problema em si, coisa comum demais em um mercado extremamente preconceituoso com a linguagem. Na realidade o problema nada tem a ver com PHP em si, mas com um módulo do Apache, o mod-mime. Isso significa que potencialmente qualquer linguagem web é vulnerável a esse exploit, já que o problema reside no módulo do servidor web em si (seguindo o demo do vídeo deve funcionar com foo.js.jpg, foo.py.jpg, foo.rb.jpg, etc…).
  2. O demo do vídeo é realizado com a versão 2.2 do Apache, que atualmente possui a versão 2.4 como a mais recente. Tentei replicar o demo com a versão 2.4, mas não foi possível, o Apache segue tratando o arquivo como imagem, independente da dupla extensão.

De qualquer maneira, apesar destes equívocos, o problema é sério, pois o mod-mime comporta-se desta maneira propositalmente — o que significa que este comportamento não pode ser classificado como vulnerabilidade ou mesmo bug. Como diz a boa e velha piada, não é um bug, é uma feature.

A boa notícia é que a solução é, na realidade, simples, pois se encontra na própria documentação do mod-mime (Ah, crianças, o bom e velho RTFM, sabem?): Podemos orientar o mod-mime (através até mesmo de um .htaccess) a trabalhar em cima da última extensão apenas, especificando o tipo de arquivo a ser trabalhado. Aqui, um exemplo de uso com arquivos de imagem (como o que foi usado no demo do vídeo):

<FilesMatch “[^.]+\.(jpg|gif|png)$”>
SetHandler default-handler
</FilesMatch>

O exemplo acima faz com que apenas as extensões finais (neste caso jpg, gif ou png) sejam tratadas, definindo o handler default do Apache para estas. O handler default basicamente transmite o conteúdo para o navegador e, embora eu não tenha conseguido reproduzir o bug em primeiro lugar, esta solução é, a princípio, sólida (caso alguém consiga encontrar algum problema por favor me avise que atualizarei este post).

Agora, o que muitos podem se perguntar é “Não dá pra facilitar e aplicar essa solução para qualquer extensão? Algo como substituir o (jpg|gif|png) por algo como .{3}? A resposta é um sonoro e retumbante NÃO!

O motivo pelo qual uma solução “catch-all” seria desastrosa nesse caso é justamente a questão do comportamento do handler default: se você aplicar um “catch-all” arquivos .php (ou de qualquer extensão/linguagem) serão abertos e seu código fonte transmitido diretamente para o browser, tornando o código visível, portanto tome muito cuidado ao aplicar este tipo de solução.

--

--

Er Galvao Abbott
O ElePHPant do Chapéu Branco

Brazilian programmer and web app security advisor; Zend Framework Evangelist.