Email-injection
Un article de Le wiki de 2 noisettes - noisette.ch.
Sommaire |
L'injection d'emails
Qu'est-ce que c'est ?
L'email injection est l'action d'utiliser la fonction mail d'un site web pour envoyer des mails à des personnes quelconques.
Les formulaires de contacts sont les cibles idéals, car ils se composent :
* un champ expéditeur * un champ sujet * un champ texte ou commentaire
Puis le bout de code responsable de l'envoi du mail ressemblera à quelque chose du style :
<?
// si l'utilisateur a cliqué sur le bouton "send"
if (isset($_POST['send'])) {
mail("the_contact_email", $_POST['sujet'], $_POST['commentaire'], "From: " . $_POST['expediteur'] . "\n");
}
?>
Bien que l'adresse du destinataire est écrit dans le fichier, on va voir qu'il y a différents moyen d'outre passer cette restriction et d'envoyer le mail à n'importe qui d'autre.
C'est grave docteur ?
Le mail envoyé par injection contiendra dans son en-tête les informations concernant le serveur qui héberge ce formulaire. Ceci permet de rester totalement anonyme. Quelle aubaine pour les spammeurs !
Une solution
Une solution est de mieux vérifier le contenu des variables et interdire l'usage de headers spécifiques.
Voici une fonction email qui opère quelques tests avant d'envoyer le mail. A utiliser massivement, pour le bien de votre formulaire de contact et celui de votre hébergeur :
/*
* Check if the param is a valid email address
*/
function isValidEmail($email) {
return (preg_match('/^[A-z0-9][\w\.\-]*@[A-z0-9][\w\.\-]+\.[A-z0-9]{2,6}$/', $email));
}
/*
* Check for injection content in the param
* Return true or false.
*/
function isValidStrings($string) {
$badStrings = array("Content-Type:", "MIME-Version:", "Content-Transfer-Encoding:", "bcc:", "cc:");
foreach($badStrings as $v){
if(strpos($string, $v) !== false){
return false;
}
}
return true;
}
/*
* Sanitized email function which avoid [b]?cc injection
* Send the email and return true, or return false without sending the email.
*
*/
function email($to, $subject, $body, $headers = "") {
$verbose = true;
/*
* Check the $to parameter
*/
if (!isValidEmail($to)) {
if ($verbose) echo "The recipient email isn't valid.";
return false;
}
if (!isValidStrings($to)) {
if ($verbose) echo "The recipient contains illigal characters.";
return false;
}
/*
* Check the $subject parameter
*/
if (!isValidStrings($subject)) {
if ($verbose) echo "The subject contains illigal characters.";
return false;
}
/*
* Check the $body parameter
*/
if (!isValidStrings($body)) {
if ($verbose) echo "The body contains illigal characters.";
return false;
}
/*
* Check the $headers parameter
*/
if (!isValidStrings($headers)) {
if ($verbose) echo "The headers contains illigal characters.";
return false;
}
mail($to, $subject, $body, $headers);
if ($verbose) echo "Email sent";
return true;
}
/*
* Simple usage : include the previous functions above your call to mail(),
* and then replace the mail() call by email().
*/
email("the_email@the_domaine.ext", "Fonction mail()", "Voici une fonction mail() saine.");
