我正在为网站构建一个简单的联系表单。它不连接到数据库,只是发送电子邮件。此代码是否会阻止垃圾邮件发送者使用标头注入?我有没有看到任何漏洞?
//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);
?>
答案 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)
不,那不会消毒任何东西。
很容易捏造邮件。
我可以在帖子值中添加任何内容(您阅读)以操纵邮件程序。