这个mail()函数是否可以从头部注入安全?

时间:2012-06-14 19:48:41

标签: php security spam-prevention

我正在为网站构建一个简单的联系表单。它不连接到数据库,只是发送电子邮件。此代码是否会阻止垃圾邮件发送者使用标头注入?我有没有看到任何漏洞?     

//create short variable names
$name= filter_var($_POST['Name'],FILTER_SANITIZE_STRING);
$email= filter_var($_POST['Email'],FILTER_SANITIZE_STRING, FILTER_VALIDATE_EMAIL);
$subject= filter_var($_POST['Subject'],FILTER_SANITIZE_STRING);
$message= filter_var($_POST['Message'],FILTER_SANITIZE_STRING);

//set up some static information
$toaddress = 'blah@localhost.com,blahblah@localhost.com';

$mailcontent = "Customer name: ".$name."\n".
            "Customer email: ".$email."\n".
            "Subject: ".$subject."\n\n".
            $message;

$fromaddress = "From:" . $email;

//invoke mail() function to send mail
mail($toaddress, "Website Contact Form",$mailcontent, $fromaddress);
?>

3 个答案:

答案 0 :(得分:8)

标头注入依赖于能够在标头变量中插入额外的换行符,这使得字符串看起来像一个新的标题。

例如,允许主题值Testing\nCc: spamrecipient@example.com\n\nSome body text会导致邮件标题包含:

Subject: Testing
Cc: spamrecipient@example.com

Some body text

即。施虐者不仅添加了额外的收件人,而且还设法提供了自己的正文。

但是在您的情况下,$toaddress是常量,即使$toaddress已由用户提供,也应由mail()函数正确清理。

您的主题标题同样不变

$message变量是安全的,因为根据定义,它是正文文本,只在真实标题之后发送。

只留下$fromaddress,并且您已经在FILTER_VALIDATE_EMAIL上使用了FALSE,它也应该拒绝任何带有换行符的内容。

但是,您应该严格检查该测试的结果,并在结果为mail()时中止整个测试。如果验证失败,那么From:会抱怨给出一个空白From:地址,但那里没有标题注入机会。

据我所知,这段代码实际上是安全的。


此外,恕我直言,您不应该从用户提供的电子邮件地址发送电子邮件。这将违反SPF等反垃圾邮件机制。

您应该使用属于您自己的域的常量Reply-To值。如果您愿意,可以在{{1}}标题中使用正确清理的值,以便让后续回复更容易转到所需的地址。

答案 1 :(得分:1)

恕我直言,您的代码不安全,因为您错过了\r\n个字符。如果filter_var()FILTER_SANITIZE_STRING一起使用,则FILTER_FLAG_STRIP_LOW只会杀死这些,这也会过滤掉ASCII 32以下的任何字符:

$message= filter_var($_POST['Message'], 
                     FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);

此外,FILTER_VALIDATE_MAIL将返回true或false,您也不会考虑。我建议查看filter_var() \n\n的优秀来源,因为主要的PHP手册信息很短。


更新:正如Alnitak指出的那样,通过代码中的{{1}},这实际上并不重要。

答案 2 :(得分:0)

不,那不会消毒任何东西。

很容易捏造邮件。

我可以在帖子值中添加任何内容(您阅读)以操纵邮件程序。