这个 mail() 函数对标头注入是否安全


Is this mail() function safe from header injection?

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

//create short variable names
$name= filter_var($_POST['Name'],FILTER_SANITIZE_STRING);
$email= filter_var($_POST['Email'], 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);
?>

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

例如,允许主题值为 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:地址,但那里没有标头注入机会。

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


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

应使用属于您自己的域的常量From:值。 如果您愿意,可以在Reply-To标头中使用正确清理的值,以便更轻松地将后续回复转到所需的地址。

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

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

此外,FILTER_VALIDATE_MAIL将返回 true 或 false,您也不考虑这些内容。我建议查看这个优秀的filter_var()来源,因为主要的PHP手册信息非常少。


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

不,这不会净化任何东西。

捏造那个邮件非常非常容易。

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