¿Cómo desinfectar la entrada del usuario en PHP antes de enviar?


Tengo un simple script de correo PHP que toma valores de un formulario enviado por CORREO y me los envía por correo:

<?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");
?>

¿Cómo puedo desinfectar la entrada?

Author: Matt Hampel, 2009-06-28

5 answers

Desinfectar la variable post con filter_var().

Ejemplo aquí. Como:

echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);   
 46
Author: Haim Evgi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-17 01:11:06

Dado que no está construyendo una consulta SQL ni nada aquí, la única validación relevante que puedo ver para esas entradas es una validación de correo electrónico para $_POST["correo electrónico"], y tal vez un filtro alfanumérico en los otros campos si realmente desea limitar el alcance de lo que puede contener el mensaje.

Para filtrar la dirección de correo electrónico, simplemente use filter_var :

$email = filter_var($email, FILTER_SANITIZE_EMAIL);

Según la sugerencia de Frank Farmer, también puede filtrar nuevas líneas en el asunto del correo electrónico:

$subject = str_replace(array("\r","\n"),array(" "," "),$subject);
 12
Author: Wadih M.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-28 18:57:15

Como otros han señalado, filter_var es genial. Si no está disponible, agrégalo a tu toolchest.

La variable $headers es particularmente mala en cuanto a seguridad. Se puede añadir y hacer que se añadan encabezados falsos. Este post llamado Inyección de correo electrónico lo discute bastante bien.

filter_var is genial, pero otra forma de asegurar que algo es una dirección de correo electrónico y no algo malo es usar una función isMail(). Aquí hay uno:

function isEmail($email) {
    return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email);
};

Así que para usar esto, podría hacer:

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 términos de validación manual, limitar la longitud utilizando substr(), corriendo strip_tags() y de lo contrario limitar lo que se puede poner en.

 4
Author: artlung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-28 20:24:53

Necesita eliminar cualquier nueva línea de entrada proporcionada por los usuarios en hea headers, que se pasa a mail () (email email en su caso)! Ver Inyección de correo electrónico.

PHP debería encargarse de desinfectar $to y subject subject, pero hay versiones de PHP con errores (Afectados son PHP 4 MOPB-34-2007).

 4
Author: blueyed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-25 16:59:59

Puede usar el código de la respuesta de artlung para validar el correo electrónico..

Uso este tipo de código para evitar la inyección de encabezado ..

// 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();

}

El filtrado de encabezado de mail() anterior es demasiado estricto, ya que algunos usuarios pueden estar usando las cadenas filtradas en su mensaje sin ninguna intención de secuestrar su formulario de correo electrónico, así que redirígalo a una página que explique qué tipo de cadenas no están permitidas en el formulario o explíquelo en su página de formulario.

 0
Author: KeepMove,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-09 13:19:51