Спамер, умри! Избавляемся от Email Injection
08 04 2010 | Рубрика: Безопасность, Интернет, Хак |
|
Проблема спама – одна из наиболее актуальных для обитателей всемирной паутины на сегодняшний день. Бесчисленное количество людей постоянно пытаются создать уникальные фильтры для прочистки почтового трафика, однако злые спамеры продолжают активно атаковать наши ящики каждый день предложениями купить что-нибудь или воспользоваться их услугами. Надоедает удалять весь этот ненужный контент, не так ли? Вот я и задумался, что же позволяет многим спамерам активно бомбить наши e-mail. Как оказалось, все довольно банально. Огромное количество злоумышленников используют так называемую E-mail инъекцию, которая присутствует практически на любом сайте с формой обратной связи или возможностью посоветовать материал другу на e-mail. О ней и поговорим.
E-mail Injection – уязвимость веб сайтов, эксплуатируемая в целях отправки большому числу адресатов почтовых писем, естественно не с поздравлениями с Днем Рождения
. 95% сайтов в сети обязательно содержат форму обратной связи или предлагают пользователю отправить ссылку на эту страничку другу на электронную почту. Очень редко информация, введенная пользователем, поддается какой-нибудь проверке со стороны скрипта отправки письма (обычно это код на PHP) за исключением самого текста письма, да и то только на наличие HTML тегов. Ну а цель спамера какая? – правильно, не попытка XSS атаки на сайт, а донести какую-то информацию до почтовых ящиков пользователей. Инъекции поддается вводимая пользователем информация. Данный фактор позволяет без каких-либо препятствий рассылать нежелательную корреспонденцию. Причем, IP адрес отправителя будет адресом сайта, с которого производится рассылка, а не самого злоумышленника. Это позволяет защититься от фильтров по blaklist-у, а заодно и делает спамера анонимным.
Техника e-mail инъекции заключается в использовании особенностей MIME формата (подробнее о нем можно почитать в Википедии: http://ru.wikipedia.org/wiki/MIME), в частности – добавление дополнительного списка получателей. MIME формат использует так называемый «возврат каретки», что позволяет ему отделять информацию друг от друга. Так вот этот «возврат каретки» или символ переноса строк используется спамером для отделения и добавления большого числа адресатов и отправки им сообщения за один проход. Чтобы иметь представление об этой уязвимости на примере, рассмотрим для начала устройства самого почтового сообщения.
Ковыряем «внутренности» письма
Итак, что собой представляет обычное электронное письмо? Во-первых, это обычный текст. Простой набор строк с ключевыми словами (заголовками), благодаря которым программа-отправитель имеет представление об адресате, отправителе, теме письма и прочей информации. При отправке письма изначально идут заголовки письма с их значениями, а потом уже сам текст. Зная их предназначение можно даже самому «читать» письмо, причем видеть его таким, какое оно есть на самом деле, а не таким, каким его показывает почтовая программа или сайт.
Если рассматривать письмо с отображение его заголовков в почтовом клиенте, например в TheBat, то оно будет выглядеть следующим образом:
Текст, выделенный жирным шрифтом – это и есть заголовки сообщения, после которых идет текст письма. Заголовки, начинающиеся с X – необязательные. Они используются для разнообразной служебной информации, такой как имя почтового клиента-отправителя или результат проверки на спам. Все достаточно просто.
E-mail injection в действии
Техника e-mail инъекции, как я писал ранее, построена на особенности обработки этих заголовков. В рамках этой статьи мы рассмотрим три способа проведения атаки: при помощи манипуляции с полем «отправитель», при помощи манипуляции с полем «получатель» и при помощи подмены текста письма. Все они будут производиться из формы обратной связи и с использованием стандартной для PHP функции mail(). Заглянув в любой справочник, можно увидеть следующее описание данной функции:
Bool mail([RECIPIENT],[SUBJECT],[MESSAGE],[EXTRAHEADERS], [EXTRAPARAMS])
В качестве RECIPIENT выступает ящик, куда будет отправлено письмо; SUBJECT – тема письма; MESSAGE – текст сообщения; EXTRAHEADERS – дополнительные заголовки; EXTRAPARAMS – дополнительные параметры вроде флагов для командной строки программы-отправителя почты. Теперь можно приступить к рассмотрению примеров.
1. Манипуляции с отправителем
На сайте присутствует форма с полями «ФИО», «Обратный E-mail» и «Текст сообщения». Код отправки письма выглядит следующим образом:
<?php
if($_POST['submit']) {
$title = htmlspecialchars($_POST['title']);
$mess = htmlspecialchars($_POST['message']);
mail('admin@site.ru', $title, $mess, 'From:'.$_POST['email']);
echo 'Сообщение отправлено.'; }
?>
<form action="" method=post>
<div align="center">ФИО<br>
<input name="from" size="40"><br>Обратный e-mail<br>
<input name="title" size="40"><br>Сообщение<br>
<textarea rows="10" cols="40"></textarea><br>
<input value="Отправить"></div>
</form>
Функция htmlspecialchars используется для преобразования специальных символов в HTML сущности, что позволяет защитить от простейших атак. Для отправки сообщения рассмотренная выше функция mail. “Мыльная” инъекция в таком случае производится путем подстановки специально сформированных данных в параметр EXTRAHEADERSвышеуказанной функции. Подставить можно, например, такие данные:
original@test.ru
CC: spam_mail@gmail.com, second_spam_mail@gmail.com, third_spam_mail@mail.ru
Функция mail() без всяких запросов вставит данный текст как заголовок в наше письмо. А почтовый агент при отсылке письма отправит его копию всем указанным в CC (Carbon Copy) адресатам, тем самым помогая спамеру делать его грязно дело. Все просто как дважды два.
2. Манипуляции с получателем
Второй случай реализации инъекции доступен только тогда, когда разработчик web сайта конкретно обезумел, и код отправки письма у него выглядит следующим образом:
<?php
if($_POST['submit']) {
$title = htmlspecialchars($_POST['title']);
$to = htmlspecialchars($_POST[' to']);
$mess = htmlspecialchars($_POST['message']);
mail($to, $title, $mess, 'From:'.$_POST['email']);
echo 'Сообщение отправлено.'; }
?>
В этом случае любой желающий может нагло и явно подставлять любое количество адресатов. В качестве $to можно подставить такие данные:
rcp@mail.ru%0ACC:any_mail@mail.ru%0ABCC:some1@ya.ru,some2@ya.ru%0Ato:some3@ya.ru
Из такого запроса письмо отправится четырем пользователям из заголовков TO, CC и BCC. Они разделены между собой символом переноса «\n» в шестнадцатеричном виде (0x0A).
3. Манипуляции с текстом письма
Ранее я уже упоминал про MIME формат. Он имеет один замечательный заголовок, Content type, который позволяет отправлять любые вложения в электронном письме. А еще он может быть использован для проведения e-mail инъекции. В качестве значения Content type можно использовать multipart/mixed (или multipart/alternative или multipart/related) , тем самым разделяя письмо на части. Эти части отделяются друг от друга некоторым набором символов (boundary). Пример письма с использованием заголовка Content-Type выглядит следующим образом:
To: test@mail.ru
Subject: Test Injection
From: test_inj@host.ru
Content-Type: multipart/mixed; boundary="part1";
Скрытый текст
-- part1
Content-Type: plain/text;
Производим проверку на инъекцию
-- part1--
Еще один скрытый текст
Все заголовки до Content-Type мы уже рассматривали. Далее можно видеть boundary, значением которой служит «part1». Это и есть тот набор символов, который будет разделять наше письмо. Затем идет текст «Скрытый текст» – он не будет виден в почтовом клиенте, так как он расположен до первого обозначения начала письма, которое идет следом за ним. Следующий текст будет виден как текст сообщения, заканчиваться он будет строкой «– part1–», указывающей на конец текста письма. А за ним идет второй скрытый текст, который также не будет виден большинством email клиентов.
Чтобы организовать такое письмо, достаточно в качестве отправителя указать следующие данные:
sender@mail.ru%0AContent-Type:multipart/mixed;%20boundary="part1";%0A--part1%0AContent-Type:text/html%0A%0AТестовый%20Текст.%0A----part1--
Из такого запроса мы получим следующее сообщение:
To: recip@mail.ru
Subject: Тест инъекции
From: sender@mail.ru
Content-Type:multipart/mixed; boundary="part1";
--part1
Content-Type:text/html
Тестовый текст
--part1--
Привет, твой сайт очень классный!
Полученное письмо будет содержать только текст «Тестовый текст» (формат письма будет HTML, как видно из заголовка Content-Type:text/html), а «Привет, твой сайт очень классный!» останется незамеченным. Такой метод инъекции подходит для сайтов, в которых есть функция «Поделиться с другом». Чаще всего она не позволяет редактировать текст письма, но позволяет указать отправителя. В этом случае достаточно применить вышеуказанный способ, тогда вместо оригинального текста, подставленного авторами сайта, будет любой, указанный спамером. А оригинал будет смещен в конец сообщения, как это сделано в нашем примере выше.
В сочетании со вторым рассмотренным примером e-mail инъекции, можно разослать таким хитрым способом любые сообщения большому количеству народа. Для этого достаточно подкорректировать ранее рассмотренный пример таким образом:
sender@mail.ru%0ASubject:Testing%0ABCC:another_mail@mail.ru%0AContent-Type:multipart/mixed; %20boundary="part1";%0A--part1%0AContent-Type:text/html%0A%0AТестовый%20Текст.%0A----part1--
Письмо будет сформировано таким же образом, как и в примере выше. Однако оно будет отправлено еще одному получателю, указанному в заголовке BCC – another_mail@mail.ru. А их может быть указано очень много.
Вот так довольно-таки легко можно воспользоваться брешью в защите web сайта в своих целях. Что и делают нехорошие люди, о чем свидетельствуют, например, письма, приходящие мне на почту. Анализ заголовков показал, что это и есть та самая E-mail Injection. Собственно поэтому я и решил написать эту статью. Чем меньше будет уязвимых сайтов, тем меньше будет поток спама. Поэтому предлагаю рассмотреть способы защиты web сайта от инъекций подобного рода.
4 эшелона обороны
Способов защититься от подобной атаки довольно много, некоторые из них очень даже просты в реализации. Но, несмотря на это, мало кто заботится о безопасности. Я рассмотрю несколько самых актуальных и действующих алгоритмов. Советую защитить свой сайт одним из них, если у Вас есть форма обратной связи, или что-нибудь, позволяющее отправлять письмо.
Задача защиты от e-mail injection сводится к фильтрации введенных данных («золотое правило» безопасности), а точнее – проверке на присутствие переносов строк (\r\n). Реализовать это можно по-разному:
1) С помощью регулярных выражений (Regex). Код проверки очень прост:
<?php
$from = $_POST["sender"];
if (eregi("(\r|\n)", $from)) {
die("Неверно заполнены поля формы!"); }
?>
Проверять таким способом надо все поля: тема, отправитель и прочие.
2) С помощью специальных классов для PHP. Это Zend_Mail, PEAR Mail и Swift Mailer. Все они в обязательном порядке проверяют указанные данные на попытку произвести инъекцию. Найти их в Интернете не составит труда, поэтому ссылки я приводить не буду.
3) Установить mod_security на сервер. Для проверки и защиты от инъекции потребуется настроить его на фильтрацию фраз «bcc», «to» и «cc» в POST и GET запросах. Для этого надо создать следующее правило в настройках mod_security:
SecFilterSelective ARGS_VALUES "\n[[:space:]]*(to|bcc|cc)[[:space:]]*:.*@"
4) Давать возможность заполнить только текст письма. Это самый простой способ и один из самых эффективных. Где же указать email для обратной связи с отправителем? Ну пусть укажет его в теле письма. Все гениальное – просто
.
Заключение
Вот мы и обогатили наш багаж знаний еще одной уязвимостью современных web проектов. Не забывайте проверять все входящие данные, будь то SQL запрос или данные об отправителе письма на предмет посторонних символов. На этом я закончу свою статью, а вам пожелаю удачи и поменьше спама.
Булай Никита
bulka@sa-sec.org
Тэги: Email Injection, атака, Безопасность, взлом, защита, спам
Возник вопрос после прочтения? Или автор не описал важный момент?
Есть что сказать на эту тему, а комментарий - это не твое?
Тогда Go на наш форум.
Общайся на темы ИТ свободно, развивайся и рассказывай новое другим! Мы будем рады принять тебя в нашу компанию














2 Комментария (ев)
skyblade
23 Июн 2010
Четвертый «гениальный» пункт может уже сильно повредить usability проекта. Рядовой пользователь привык вводить адрес получателя в отдельное поле и ввод этой информации в тело письма будет останавливать его от ожидаемого владельцем проекта действия – собственно отправки ссылки на материал другу. Это лишний тормоз.
А в остальном, спасибо за статью. Было очень познавательно.
Булка
28 Июн 2010
Потому и приведены еще 3 способа фильтрации. И если очень хочется иметь поле отдельное для указания мыла отправителя – его надо проверять на Inj в первую очередь
Оставьте комментарий