Salut à tous,
Imaginez, vous venez de créer votre site en PHP et vous souhaitez ajouter un formulaire de contact. De plus, vous voulez que ce formulaire envoie automatiquement un mail à votre adresse perso afin d'être informé rapidement. Et avec ça, n'ayant pas accès au fichier
php.ini de votre hébergeur, vous voulez passer par un serveur
SMTP (quelle exigence) !
Mais voilà, comment envoyer des mails en PHP via SMTP ? Une rapide recherche sur Google et vous trouvez une solution qui semble faire l'unanimité :
PHPMailer.
PHPMailer est la
bibliothèque la plus utilisée en ce qui concerne l'
envoi de mail en PHP. Elle est utilisée dans
le monde entier, traduite dans
47 langues, vue dans de nombreux projets tels que
WordPress,
Drupal,
1CRM,
SugarCRM,
Yii ou encore
Joomla! pour ne citer que les plus populaires d'entre eux. Voyant tout cela, vous vous dites que vous seriez idiot de ne pas l'utiliser pour votre site, qu'il s'agit d'un système sûr, fonctionnel et surtout
sécurisé... Et sur ce dernier point vous auriez tord car
une faille a été découverte il y a à peine quelque jours !
Il y a 3 jours pour être précis, le 25 décembre 2016, une
faille critique a été révélée dans la fonction
mailSend() de la bibliothèque. Critique car elle permet l’exécution
à distance de
code arbitraire sur le serveur.
Cet extrait de la fonction
mailSend() vous permettra de comprendre un peu mieux le principe de cette faille :
if (!empty($this->Sender)) {
$params = sprintf('-f%s', $this->Sender);
}
// [...]
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
La fonction
mailPassthru() appelle directement la fonction PHP
mail() en utilisant les mêmes paramètres. Cette dernière utilise le serveur de messagerie
sendmail afin d'envoyer le mail en question. Notez que la fonction
mail() prend en paramètre optionnel
additional_parameters qui permet au développeur de faire passer ses propres paramètres lors de l’exécution de
sendmail.
Dans la fonction
mailSend() de PHPMailer, la propriété
Sender qui contient l'adresse de l’émetteur du message est envoyée vers la fonction
mailPassthru() en tant que paramètre additionnel sous la forme
-fMonAdresse@mail.com. Un utilisateur malveillant pourrait choisir d'entrer une adresse comme
MonAdresse -evilparam -otherparam@mail.com ce qui aurait pour conséquence d'exécuter
sendmail avec des paramètres que
l'utilisateur aurait choisi ! Pas très safe tout ça...
Oui mais voilà, la propriété
Sender est définie par le biais de la fonction
setForm() qui
n'accepte pas les espaces (normal, pas dans une adresse mail). En revanche, elle accepte le format
Émetteur <emetteur@mail.com> à condition qu'il soit écrit entre guillemets. Soit, l'attaquant pourrait très bien inscrire
"MonAdresse -evilparam -otherparam"@mail.com comme adresse mail... Sauf que
sendmail reconnaitra tout ce qui est entre guillemets comme
un seul et même paramètre. Inexploitable me direz-vous ?
Eh bien si ! Comment faire en sorte qu'un guillemet soit détecté par l'un mais pas par l'autre ? Tout simplement grâce aux
caractères d'échappements. Si notre utilisateur malveillant utilise une adresse du style
"MonAdresse\" -evilparam -otherparam"@mail.com, la fonction
setform ne verra le second guillemet que comme un caractère faisant partie de l'adresse. En revanche,
sendmail le verra comme le caractère de fin de la chaine
MonAddress\ ! Il percevra donc la suite comme étant
d'autres paramètres et là, danger !
Pourquoi danger ? Si l'attaquant utilise le paramètre
-X logfile, il peut faire en sorte que
sendmail écrive le corps de son mail dans
le fichier de son choix sur le serveur (comme une nouvelle page par exemple, avec des fonctions malicieuses) !
Un patch correctif a été publié afin de filtrer la variable
params avec la fonction
escapeshellcmd(). Il est cependant
toujours possible d'exploiter la faille en utilisant une adresse du type
"MonAdresse\' -evilparam -otherparam"@mail.com.
Plus d'informations :
CVE-2016-10033 et
CVE-2016-10045 (bypass du patch correctif)
Quelques liens supplémentaires :