J'ai un simple script PHP mailer qui prend les valeurs d'un formulaire soumis via POST et me les envoie par mail:
<?php
$to = "[email protected]";
$name = $_POST['name'];
$message = $_POST['message'];
$email = $_POST['email'];
$body = "Person $name submitted a message: $message";
$subject = "A message has been submitted";
$headers = 'From: ' . $email;
mail($to, $subject, $body, $headers);
header("Location: http://example.com/thanks");
?>
Comment puis-je désinfecter l'entrée?
Désinfectez la variable post avec filter_var()
.
Exemple ici . Comme:
echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
Puisque vous ne créez pas de requête SQL ou quoi que ce soit ici, la seule validation pertinente que je peux voir pour ces entrées est une validation par e-mail pour $ _POST ["e-mail"], et peut-être un filtre alphanumérique sur les autres champs si vous voulez vraiment pour limiter la portée de ce que le message peut contenir.
Pour filtrer l'adresse e-mail, utilisez simplement filter_var :
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
Selon la suggestion de Frank Farmer, vous pouvez également filtrer les nouvelles lignes dans le sujet de l'e-mail:
$subject = str_replace(array("\r","\n"),array(" "," "),$subject);
Comme d'autres l'ont noté, filter_var
est génial. S'il n'est pas disponible, ajoutez-le à votre toolchest.
La variable $headers
Est particulièrement mauvaise en termes de sécurité. Il peut être ajouté et provoquer l'ajout d'en-têtes usurpés. Cet article intitulé Email Injection en parle assez bien.
filter_var i
Est génial, mais une autre façon de garantir que quelque chose est une adresse e-mail et non quelque chose de mauvais consiste à utiliser une fonction isMail()
. En voici un:
function isEmail($email) {
return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email);
};
Donc, pour l'utiliser, vous pouvez faire:
if (isset($_POST['email']) && isEmail($_POST['email'])) {
$email = $_POST['email'] ;
} else {
// you could halt execution here, set $email to a default email address
// display an error, redirect, or some combination here,
}
En termes de validation manuelle, limiter la longueur à l'aide de substr()
, exécuter strip_tags()
et autrement limiter ce qui peut être mis.
Vous devez supprimer toutes les nouvelles lignes des entrées fournies par les utilisateurs dans $ headers, qui sont transmises à mail () ($ email dans votre cas)! Voir injection d'email .
PHP devrait s'occuper de la désinfection de $ to et $ subject, mais il existe des versions de PHP avec des bugs (les affectés sont PHP 4 <= 4.4.6 et = PHP 5 <= 5.2.1, voir MOPB-34-2007 ).
Vous pouvez utiliser le code de la réponse de artlung
ci-dessus pour valider l'e-mail.
J'utilise ce type de code pour empêcher l'injection d'en-tête ..
// define some mail() header's parts and commonly used spam code to filter using preg_match
$match = "/(from\:|to\:|bcc\:|cc\:|content\-type\:|mime\-version\:|subject\:|x\-mailer\:|reply\-to\:|\%0a|\%0b)/i";
// check if any field's value containing the one or more of the code above
if (preg_match($match, $name) || preg_match( $match, $message) || preg_match( $match, $email)) {
// I use ajax, so I call the string below and send it to js file to check whether the email is failed to send or not
echo "failed";
// If you are not using ajax, then you can redirect it with php header function i.e: header("Location: http://example.com/anypage/");
// stop the script before it reach or executing the mail function
die();
}
Le filtrage des en-têtes de mail()
ci-dessus est trop strict, car certains utilisateurs peuvent utiliser les chaînes filtrées dans leur message sans intention de détourner votre formulaire de courrier électronique, alors redirigez-le vers une page qui explique quel type de chaînes n'est pas autorisé dans le formulaire ou expliquez-le sur votre page de formulaire.