web-dev-qa-db-fra.com

Comment assainir l'entrée utilisateur dans PHP avant l'envoi)?

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?

47
Matt Hampel

Désinfectez la variable post avec filter_var() .

Exemple ici . Comme:

echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);   
52
Haim Evgi

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);
12
Wadih M.

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.

4
artlung

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 ).

4
blueyed

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.

1
KeepMove