PHP - MAIL INJECTION
Un article de Wiki SOS-ADMIN.
Sommaire |
[PHP] - MAIL INJECTION
Article basé sur différentes sources (voir les liens en dessous) ! [ article en cours de rédaction ]
Ce n'est pas une faille en soit, mais une utilisation non rigoureuse de la fonction mail de PHP qui peut conduire à l'envoi massif de mail SPAM. Commençons par le début:
La fonction mail s'utilise de la manière suivante:
mail(string destinataire, string sujet, string message [, string en-tête(s) additionnelle(s) [, string parametre(s) additionnel(s)]] )
Le formulaire de contact
Lorsque l'on crée un formulaire de contact sur un site, souvent pour éviter d'y laisser trainer une adresse email inutilement, on le fait souvent de la façon suivante (désolé pour les puristes, je simplifie le code du formulaire):
formulaire.html
<form name="contact" method="POST" action="traitement.php">
<input type="text" name="email" size="20" />
<input type="text" name="sujet" size="50" />
<textarea name="message" rows="15" cols="50"></textarea>
<input type="submit" name="ok" value="Envoyer mon message" />
</form>
Le code d'envoi du mail
Maintenant, regardons à un code d'envoi du mail.
traitement.php
<?php
$expediteur=$_POST['email'];
$destinataire="destinataire@website.tld";
if (mail($destinataire,$_POST['sujet'],$_POST['message'],"From: $expediteur\n"))
{
echo "Mail envoyé";
}
else
{
echo "Mail non envoyé";
}
?>
Dangereux ce genre de formulaire ?
Vous vous dite: En quoi cela est-il dangereux ? Le destinataire est codé en dur !!!
Voyons ce que produit notre script:
mail($destinataire,$_POST['sujet'],$_POST['message'],"From: $expediteur\n")
Donne +/- le résultat suivant :
To: $destinataire Subject: $_POST['sujet'] From: $expediteur ------------------- $_POST['message']
Reprenons maintenant la syntaxe de la fonction mail:
mail(string destinataire, string sujet, string message [, string en-tête(s) additionnelle(s) [, string parametre(s) additionnel(s)]] )
On se rend compte que le From est en fait placé dans les en-têtes additionnelles.
Et c'est là qu'est le problème ! Et non seulement pour un formulaire de contact, mais aussi pour les formulaires du genre "Envoyer cet article/page à un ami".
Car par le champ du formulaire qui permet au visiteur de rentrer son adresse email, il peut ajouter des en-têtes au message et donc ajouter/remplacer :
- un ou des destinataires;
- un nouveau sujet;
- un message;
- une pièce jointe.
Prenons quelques exemples qui montrent comment il est possible d'ajouter des en-têtes
Ajouter un destinataire ?
Le visiteur, qui veut se servir de votre formulaire de contact pour spammer, peut entrer la chaine suivante dans la case email du formulaire:
spammeur@anonyme.tld%0ACc:adressespamee1@fai.tld%0ABcc:adressespamee2@fai.tld,adressespamee3@fai.tld
Cela enverra le mail avec le sujet et le message du spammeur, aussi bien à vous qu'aux 3 adresse spammées. Car il ajoute l'en-tête Cc: et Bcc:.
Cela donne dans les en-têtes du mail:
To: $destinataire Subject: $_POST['sujet'] From: spammeur@anonyme.tld Cc:adressespamee1@fai.tld Bcc:adressespamee2@fai.tld,adressespamee3@fai.tld ------------------- $_POST['message']
Maintenant, s'il entre ceci:
spammeur@anonyme.tld%0ABcc:adressespamee1@fai.tld,adressespamee2@fai.tld,adressespamee3@fai.tld
Vous recevrez son mail, en destinataire principal, mais vous ne verrez pas qu'il a été envoyé.
To: $destinataire Subject: $_POST['sujet'] From: spammeur@anonyme.tld Bcc:adressespamee1@fai.tld,adressespamee2@fai.tld,adressespamee3@fai.tld ------------------- $_POST['message']
Ajouter un nouveau sujet?
Il suffit simplement d'ajouter l'en-tête qu'il faut dans la case de l'adresse email de l'expéditeur
spammeur@anonyme.tld%0ASubject:Mon%20sujet%perso
Solutions
Plusieurs méthodes peuvent être envisagées pour éviter ce type d'injection, vous pouvez par exemple filtrer l'adresse que le script reçoit du formulaire afin de détecter les "%0A", "Bcc", "Subject", et autres éléments incongrus.
Vous pouvez également utiliser un test comme celui-ci:
<?php
if(!ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'.
'@'.
'[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'.
'[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$',
$_POST['email'])) mail($destinataire,$_POST['sujet'],$_POST['message'],"From: $_POST['email']\n")
?>
Dans ce cas l'email ne sera envoyé que si l'adresse entrée dans le formulaire semble correcte.
Attention: il existe de nombreuses manières de contrer la plupart des tests que vous pouvez effectuer, le code ci-dessus n'est pas garantit sans failles. Dans l'absolu, veiller à laisser le champ d'action le plus court possible aux intrusions.

