如何在邮寄之前清理PHP中的用户输入?

时间:2009-06-28 18:34:30

标签: php security email sanitize

我有一个简单的PHP邮件程序脚本,它从通过POST提交的表单中获取值并将它们邮寄给我:

<?php
$to = "me@example.com";

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

如何清理输入?

5 个答案:

答案 0 :(得分:52)

使用filter_var()清理帖子变量。

Example here。像:

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

答案 1 :(得分:12)

由于您没有在此处构建SQL查询或任何内容,我可以看到这些输入的唯一相关验证是$ _POST [“email”]的电子邮件验证,如果是其他字段的字母数字过滤器,则可能是你真的想限制消息可以包含的范围。

要过滤电子邮件地址,只需使用filter_var

即可
$email = filter_var($email, FILTER_SANITIZE_EMAIL);

根据Frank Farmer的建议,您还可以过滤掉电子邮件主题中的换行符:

$subject = str_replace(array("\r","\n"),array(" "," "),$subject);

答案 2 :(得分:4)

正如其他人所说,filter_var很棒。如果它不可用,请将其添加到您的工具箱中。

$headers变量的安全性特别差。它可以附加到并导致添加欺骗标题。这篇名为Email Injection的帖子很好地讨论了它。

filter_var i很棒,但确保某些内容是电子邮件地址的另一种方法是使用isMail()功能。这是一个:

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

所以要使用它,你可以这样做:

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,
}

在手动验证方面,使用substr()限制长度,运行strip_tags()并限制可以放入的内容。

答案 3 :(得分:4)

您需要从$ headers中的用户提供的输入中删除任何换行符,这些换行符将传递给mail()(在您的情况下为$ email)!请参阅Email injection

PHP应该负责清理$ to和$ subject,但是有些版本的PHP有bug(受影响的是PHP 4&lt; = 4.4.6和PHP 5&lt; = 5.2.1,请参阅MOPB-34-2007 )。

答案 4 :(得分:1)

您可以使用上面artlung的答案中的代码验证电子邮件..

我使用这种代码来防止标头注入..

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

}

上面的mail()标头过滤过于严格,因为某些用户可能在其邮件中使用过滤后的字符串而无意劫持您的电子邮件表单,因此将其重定向到的页面是解释表单中不允许使用哪种字符串或在表单页面上解释它。