I’m building a simple contact form for a website. It does not connect to a database, it just sends the email. Will this code prevent spammers from using header injections? Are there any vulnerabilities I’m not seeing?
<?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);
?>
Header injection relies on being able to insert additional newlines into header variables, which makes the string look like a new header.
For example, allowing a subject value of
Testing\nCc: spamrecipient@example.com\n\nSome body textwould result in a message header containing:i.e. the abuser has not only added additional recipients, but they’ve managed to supply their own body text too.
However in your case the
$toaddressis constant, and even if$toaddresshad been user-supplied it should be correctly sanitised by themail()function.Your subject header is similarly constant
The
$messagevariable is safe because by definition that’s the body text and only sent after the real headers.That only leaves
$fromaddress, and you’re already usingFILTER_VALIDATE_EMAILon that which should also reject anything with a newline in it.However you should strictly be checking the result of that test, and aborting the whole thing if the result is
FALSE. As it is if the validation fails thenmail()will complain about being given a blankFrom:address, but there’s no header injection opportunity there.As far as I can tell, then, this code is actually secure.
Also, IMHO, you shouldn’t send the emails from the user-supplied email address. That would fall foul of anti-spam mechanisms such as SPF.
You should use a constant
From:value belonging to your own domain. If you like you could then use a correctly sanitised value in theReply-Toheader to make it easier to have the subsequent reply go to the desired address.