Passando por Restrições de Upload de Arquivos

O script do lado do cliente verifica a extensão do arquivo. Antes de enviar qualquer dado para o servidor, o script JavaScript no cliente verifica se a extansão do arquivo selecionado é permitida.


function validarArquivo() {
   var arquivo = document.getElementsByName('arquivo_upload')[0].value;
   if (arquivo == null || arquivo == "") {
       alert("Selecione um arquivo para upload!");
       return false;
   }
   // Definir as extensões permitidas
   var extensoesPermitidas = ".jpg|.png|.gif";
   // Extrair a extensão do arquivo
   var extensao = arquivo.substring(arquivo.lastIndexOf("."));
   // Verificar se a extensão do arquivo está na lista permitida
   if (extensoesPermitidas.indexOf(extensao + "|") == -1) {
       var mensagemErro = "Este tipo de arquivo não é permitido. Por favor, envie arquivos dos tipos: " + extensoesPermitidas + ". A extensão atual é: " + extensao;
       alert(mensagemErro);
       return false;
   }
}
 

Segunda Etapa: Filtro de Content-Type no Servidor

O código do servidor verifica o Content-Type do arquivo enviado antes de processar o upload.


$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
   if (file_exists($DIRETORIO_UPLOAD)) {
       if (($_FILES['arquivo_upload']['type'] == 'image/jpeg') || ($_FILES['arquivo_upload']['type'] == 'image/png') || ($_FILES['arquivo_upload']['type'] == 'image/gif')) {
           if (move_uploaded_file($_FILES['arquivo_upload']['tmp_name'], $DIRETORIO_UPLOAD . '/' . $_FILES['arquivo_upload']['name'])) {
               $caminho_imagem = $DIRETORIO_UPLOAD . $_FILES['arquivo_upload']['name'];
               $is_upload = true;
           }
       } else {
           $msg = 'Tipo de arquivo inválido, tente novamente!';
       }
   } else {
       $msg = $DIRETORIO_UPLOAD . ' diretório não existe, crie manualmente!';
   }
}
 

Terceira Etapa: Bypass de Extensão

Alterar a extensão do arquivo para .phtml ou php2, php3 e fazer o upload.


$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
   if (file_exists($DIRETORIO_UPLOAD)) {
       $extensoesNegadas = array('.asp', '.aspx', '.php', '.jsp');
       $nome_arquivo = trim($_FILES['arquivo_upload']['name']);
       $nome_arquivo = removerPontoFinal($nome_arquivo); // Remover ponto final
       $extensao_arquivo = strrchr($nome_arquivo, '.');
       $extensao_arquivo = strtolower($extensao_arquivo); // Converter para minúsculo
       $extensao_arquivo = str_ireplace('::$DATA', '', $extensao_arquivo); // Remover ::$DATA
       $extensao_arquivo = trim($extensao_arquivo); // Remover espaços em branco

       if (!in_array($extensao_arquivo, $extensoesNegadas)) {
           if (move_uploaded_file($_FILES['arquivo_upload']['tmp_name'], $DIRETORIO_UPLOAD . '/' . $_FILES['arquivo_upload']['name'])) {
               $caminho_imagem = $DIRETORIO_UPLOAD . '/' . $_FILES['arquivo_upload']['name'];
               $is_upload = true;
           }
       } else {
           $msg = 'Extensões .asp, .aspx, .php, .jsp não são permitidas!';
       }
   } else {
       $msg = $DIRETORIO_UPLOAD . ' diretório não existe, crie manualmente!';
   }
}
 

Exemplos de extensões comuns para bypass:


Asp: .asa, .cer, .cdx
Aspx: .ashx, .asmx, .ascx
Php: .php3, .phtml
Jsp: .jspx, .jspf
 

Em servidores Windows, a extensão pode ser alterada para **".php."**. Para listas de permissão, o método de truncamento 00 pode ser usado. Este método explora uma vulnerabilidade em versões anteriores do PHP (<5.3.4), onde 0x00 é tratado como um caractere de terminação. Exemplo: **1.php%00.jpg**.

Quarta Etapa: Uso de .htaccess para Bypass

Se a lista negra ainda permite o upload de .htaccess, você pode configurá-lo para tratar todos os arquivos como PHP, então fazer o upload de um "imagem maliciosa" que será interpretada como PHP.

Conteúdo do .htaccess:


SetHandler application/x-httpd-php
 

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
   if (file_exists($DIRETORIO_UPLOAD)) {
       $extensoesNegadas = array(".php", ".php5", ".php4", ".php3", ".php2", "php1", ".html", ".htm", ".phtml", ".pHp", ".pHp5", ".pHp4", ".pHp3", ".pHp2", "pHp1", ".Html", ".Htm", ".pHtml", ".jsp", ".jspa", ".jspx", ".jsw", ".jsv", ".jspf", ".jtml", ".jSp", ".jSpx", ".jSpa", ".jSw", ".jSv", ".jSpf", ".jHtml", ".asp", ".aspx", ".asa", ".asax", ".ascx", ".ashx", ".asmx", ".cer", ".aSp", ".aSpx", ".aSa", ".aSax", ".aScx", ".aShx", ".aSmx", ".cEr", ".sWf", ".swf");
       $nome_arquivo = trim($_FILES['arquivo_upload']['name']);
       $nome_arquivo = removerPontoFinal($nome_arquivo); // Remover ponto final
       $extensao_arquivo = strrchr($nome_arquivo, '.');
       $extensao_arquivo = strtolower($extensao_arquivo); // Converter para minúsculo
       $extensao_arquivo = str_ireplace('::$DATA', '', $extensao_arquivo); // Remover ::$DATA
       $extensao_arquivo = trim($extensao_arquivo); // Remover espaços em branco

       if (!in_array($extensao_arquivo, $extensoesNegadas)) {
           if (move_uploaded_file($_FILES['arquivo_upload']['tmp_name'], $DIRETORIO_UPLOAD . '/' . $_FILES['arquivo_upload']['name'])) {
               $caminho_imagem = $DIRETORIO_UPLOAD . $_FILES['arquivo_upload']['name'];
               $is_upload = true;
           }
       } else {
           $msg = 'Este arquivo não é permitido!';
       }
   } else {
       $msg = $DIRETORIO_UPLOAD . ' diretório não existe, crie manualmente!';
   }
}
 

Tags: upload file-upload PHP Security htaccess

Publicado em 9-3 00:29