2009-06-28 4 views
38

У меня есть простой PHP скрипт почтовой программы, которая принимает значения из формы, представленной с помощью POST и почт их мне:Как очистить ввод пользователя в PHP перед отправкой?

<?php 
$to = "[email protected]"; 

$name = $_POST['name']; 
$message = $_POST['message']; 
$email = $_POST['email']; 

$body = "Person $name submitted a message: $message"; 
$subject = "A message has been submitted"; 

$headers = 'From: ' . $email; 

mail($to, $subject, $body, $headers); 

header("Location: http://example.com/thanks"); 
?> 

Как я могу дезинфицировать вход?

+1

Если вы используете прямое текстовое поле, в ваших данных $ _POST не должно быть никаких htmlentities. Если вы используете какой-то богатый текстовый редактор, который генерирует html, используйте html_entity_decode(). Обязательно удалите управляющие символы из объекта - символы новой строки в теме могут испортить ваши заголовки электронной почты. –

+16

@Frank Farmer: вы предлагаете ему полагаться, что он не должен доверять, что ни один оскорбительный код не достигнет его кода, потому что он использовал «прямое текстовое поле"? Это ужасный совет. –

+9

Хех, прямое текстовое поле. Просто сделал XSS-тест на тех, кто это сделал. Им не понравилась забавная картинка, отправленная через ссылку img, введенную в «прямое текстовое поле». –

ответ

44

Санируйте почтовую переменную filter_var().

Example here. Как:

echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL); 
+0

Мне нравится filter_var для этого, к сожалению, не все настройки хостинга имеют 5.2, но, похоже, это хорошо продуманная функция. – artlung

+0

php 5 неплохое filter_var (PHP 5> = 5.2.0) –

+2

Не все настройки хостинга имеют 5.2, хе-хе, это так 2009. Теперь это больше похоже на то, что они все еще работают 5.4. – markus

10

Поскольку вы не строим запрос SQL или что-нибудь здесь, единственным важным подтверждением того, что я могу видеть, для этих входов является проверка электронной почты для $ _POST [ «электронная почта»], и может быть алфавитно-цифровой фильтруйте другие поля, если вы действительно хотите ограничить объем содержимого сообщения.

Для фильтрации электронной почты, просто используйте filter_var:

$email = filter_var($email, FILTER_SANITIZE_EMAIL); 

В соответствии с предложением Фрэнка Фармера, вы также можете отфильтровать новые строки в теме письма:

$subject = str_replace(array("\r","\n"),array(" "," "),$subject); 
+2

символы новой строки в темы электронной почты несколько проблематичны. –

+0

Привет, Франк, я отредактировал свой ответ, чтобы отразить ваше предложение. –

+7

В зависимости от того, как создается электронная почта, символы новой строки могут быть введены в любой заголовок электронной почты, что позволяет злоумышленнику добавлять новые или заменяемые заголовки электронной почты, которые ему нравятся. В дополнение к этому, вводя целую пустую строку (две новые строки), затем позволяет злоумышленнику вставлять тело электронной почты по своему выбору, полностью перекрывая сгенерированную электронную почту. – Cheekysoft

4

Как уже отмечалось, filter_var отлично. Если он недоступен, добавьте его в свой инструмент.

Переменная $headers особенно плохая по соображениям безопасности. Он может быть добавлен и добавлен поддельные заголовки. Этот пост под названием Email Injection обсуждает его довольно хорошо.

filter_var i s отличный, но еще один способ гарантировать, что что-то является адресом электронной почты, а не что-то плохое - использовать функцию isMail(). Вот один:

function isEmail($email) { 
    return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email); 
}; 

Так, чтобы использовать это, вы могли бы сделать:

if (isset($_POST['email']) && isEmail($_POST['email'])) { 
    $email = $_POST['email'] ; 
} else { 
    // you could halt execution here, set $email to a default email address 
    // display an error, redirect, or some combination here, 
} 

С точки зрения ручной проверки, ограничивая длину с помощью substr(), работает strip_tags() и иным способом ограничить то, что можно положить в

.
+1

Говоря о filter_var, у него также есть фильтр для проверки электронной почты, поэтому ваша функция isEmail является плохим и ненужным (не говоря уже о том, что регулярное выражение не может правильно проверять электронные письма). – 2015-01-13 11:29:09

4

Вам нужно удалить любую новую строку из ввода, предоставленной пользователями в $ headers, которая будет передана mail() ($ email в вашем случае)! См. Email injection.

PHP должен заботиться о дезинфицирующих $ до и $ темы, но есть версии PHP с ошибками (Пораженные являются PHP 4 < = 4.4.6 и PHP 5 < = 5.2.1, см MOPB-34-2007).

0

Вы можете использовать код из artlung заголовка «ответ выше s, чтобы проверить электронную почту ..

Я использую этот вид кода, чтобы предотвратить инъекции заголовка ..

// define some mail() header's parts and commonly used spam code to filter using preg_match 
$match = "/(from\:|to\:|bcc\:|cc\:|content\-type\:|mime\-version\:|subject\:|x\-mailer\:|reply\-to\:|\%0a|\%0b)/i"; 

// check if any field's value containing the one or more of the code above 
if (preg_match($match, $name) || preg_match($match, $message) || preg_match($match, $email)) { 

// I use ajax, so I call the string below and send it to js file to check whether the email is failed to send or not 
echo "failed"; 

// If you are not using ajax, then you can redirect it with php header function i.e: header("Location: http://example.com/anypage/"); 

// stop the script before it reach or executing the mail function 
die(); 

} 

mail()» s фильтрации выше является слишком строгим, поскольку некоторые пользователи могут использовать отфильтрованные строки в своем сообщении без каких-либо намерений захватить вашу электронную почту, поэтому перенаправляйте ее на страницу, в которой объясняется, какие строки, которые не разрешены в форме, или объясняют это на вашем форма страница.

Смежные вопросы