Является ли эта функция mail() безопасной от инъекции заголовка?


Я создаю простую контактную форму для веб-сайта. Он не подключается к базе данных, а просто отправляет электронное письмо. Будет ли этот код препятствовать спамерам использовать инъекции заголовка? Есть ли какие-то уязвимые места, которые я не вижу?

//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."nn".
            $message;

$fromaddress = "From:" . $email;

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

3 ответа:

Инъекция заголовка основана на возможности вставки дополнительных новых строк в переменные заголовка, что делает строку похожей на новый заголовок.

Например, разрешение значения субъекта 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_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(), так как основное руководство PHP очень коротко по информации.


Обновление: Как указал Альнитак, через \n\n в коде это на самом деле не имеет значения.

Нет, это ничего не дезинфицирует.

Было бы очень легко подделать этот почтовый ящик.

Я могу добавить что угодно в значение post (которое Вы читаете), чтобы манипулировать почтовым отправителем.