I have a website with a contact form on PHP and a mail server.
Email are sent with the help of PHP mail
function like so
$name = cleanInput($_POST["name"]);
$e = $_POST["email"];
$email = filter_var(cleanInput($e), FILTER_SANITIZE_EMAIL);
if (strpos($name, "@") !== false) {
$msg = 'Invalid name!';
exit();
}
else if (strcmp($e, $email) !== 0 ||
filter_var($email, FILTER_VALIDATE_EMAIL) === false ||
!checkdnsrr(substr(strrchr($email, "@"), 1))) {
$msg = 'Invalid email address!';
exit();
}
else
{
$message = nl2br(cleanInput($_POST['message']));
$subject = 'Support request';
$to = 'support@domain.com';
$sender = 'webmaster@domain.com';
$headers = array(
'From' => $name . '<' . $email . '>',
'MIME-Version' => '1.0',
'Content-type' => 'text/html; charset=iso-8859-1'
);
$result = mail($to, $subject, $message, $headers, '-r' . $sender);
}
function cleanInput($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
Recently I've been attacked by a spammer who is posting emails with From
field value like this
check@mydomain.com, this@mydomain.com, link@mydomain.com,
"US:http"@mydomain.com://www.somedomain.com/page <somename@mail.com>
So I prohibited the @
character in the name field like so
if (strpos($_POST["name"], "@") !== false)
exit()
I've tried sending a POST request with a name like name@
from Postman and it was rejected successfully but am still getting the same spam emails.
Any ideas please how the spammer is bypassing the validation check?
Update
Here is an example of a spam email with error_log of the raw input fields https://pastebin.com/29ppLGuX
Update2
Thanks to @mti2935 it was figured out that there is no injection peformed. The spammer is just putting a simple line of text with a link into the name
field and the MTA (Postfix) to some reason is appending the domain name to all words in that text.
I've tried playing with the data and found out that it is the colon
which causes all this trouble.
If $name="one two three" then the header of the received email looks good
From: one two three<name@mail.com>
If $name="one: two three" then
From: one@mydomain.com:two three <name@mail.com>
If $name="one: two: three" then
From: "one:two"@mydomain.com:three <name@mail.com>
I've tried converting the header array into a string prior to feeding it into the mail
and got the same results.