Защита от вредоносных запросов POST
Нравится вам это или нет, но есть скрипты и боты, которые забивают ваши сайты бесконечными HTTP-запросами POST. Запросы POST — это своего рода противоположность запросам GET. Вместо того, чтобы получать какой-либо ресурс или файл с сервера, данные публикуются или отправляются на него.
Чтобы проиллюстрировать, нормальный серфинг в Интернете предполагает, что ваш браузер выполняет серию запросов GET для всех ресурсов, необходимых для каждой веб-страницы. HTML, JavaScript, CSS, изображения и др. Но всякий раз, когда вы оставляете комментарий, публикуете что-то в Твиттере или делитесь на Facebook, браузер отправляет ваш контент вместе с другими данными на сервер в виде POST-запроса. Это совершенно нормальная и ожидаемая часть того, как работает Интернет.
Эта проблема
Проблема в том, что на типичном сервере нет ограничений на запросы POST. Таким образом, злоумышленники могут запускать сценарии, которые отправляют бесконечные POST-запросы на ничего не подозревающие сайты 24 часа в сутки, 7 дней в неделю, 365 дней в году. Например, если у вас есть контактная форма на вашем сайте, велика вероятность, что на нее засыпают огромные объемы неприятного спама POST. Точно так же и для других форм или сценариев, использующих Ajax — даже статические HTML-сайты с абсолютным нулем постобработки неоднократно проверяются злонамеренными запросами POST.
Как мы увидим чуть позже в статье, незаконные запросы POST обычно включают большие объемы данных. Чтобы предотвратить обнаружение и фильтрацию, спамеры POST любят преобразовывать, кодировать и скрывать свой код, что может значительно увеличить общий размер запроса. Со временем совокупный эффект массивных POST-запросов к вашему сайту может восприниматься как медленный всасывающий звук, поскольку ресурсы и пропускная способность сервера поглощаются непрекращающимися скриптами спама и другим злонамеренным поведением.
Еще хуже — постоянная угроза того, что какой-нибудь назойливый неудачник обнаружит уязвимость и воспользуется вашим сайтом. На это ни у кого нет времени. Итак, в этой статье мы узнаем больше о POST-запросах, о том, как их отслеживать, и, что наиболее важно, о том, как защитить свои онлайн-ресурсы от вредоносной POST-активности.
Ответ сервера
Каждый сервер имеет свою собственную конфигурацию, но в целом запросы POST обрабатываются либо успешно, либо нет. Например, если у вас есть контактная форма и кто-то отправляет запросы POST, запросы будут успешно выполнены, если они соответствуют требованиям, указанным в сценарии контакта. В противном случае запросы POST, которые не прошли проверку или не соответствуют требованиям формы, либо тихо умрут, либо получат в ответ ошибку 404.
Однако постоянная угроза POST-запросов заключается в том, что они могут выявить уязвимость где-то на сервере. Это основная причина, по которой спамеры и другие гнусные типы тратят время и ресурсы, бесконечно публикуя свои вредоносные полезные данные через запросы POST: они ищут возможности для использования, грабежа и кражи ваших онлайн-активов. Легко и просто.
Обнаружение запросов POST
Обнаружение запросов POST в журналах сервера требует простого поиска слова «POST» (это может показаться очевидным, но вы можете быть удивлены). Итак, просматривая ваши последние журналы доступа на сервере Apache, зарегистрированные HTTP-запросы будут выглядеть примерно так:
137.175.3.226 - [27/Jul/2013:08:43:50 -0700] "POST / HTTP/1.0" 404 14566 "http://example.com/" "Mozilla/5.0 (Windows NT 6.0; rv:16.0) Gecko/20100101 Firefox/16.0"
137.175.3.226 - [27/Jul/2013:08:43:51 -0700] "POST / HTTP/1.0" 404 14566 "http://example.com/" "Mozilla/5.0 (Windows NT 6.0; rv:16.0) Gecko/20100101 Firefox/16.0"
198.245.49.39 - [27/Jul/2013:08:44:39 -0700] "POST / HTTP/1.0" 404 14566 "http://example.com/" "Opera/9.80 (Windows NT 6.1; WOW64; MRA 6.0 (build 5976)) Presto/2.12.388 Version/12.11"
Для каждого зарегистрированного запроса * у нас есть IP-адрес посетителя, дата / время, запрос, ответ, размер байта и пользовательский агент. Хотя вся информация полезна для различных анализов, в центре внимания находится запрос , который сам по себе состоит из следующих деталей:
- Тип запроса (например,
GET
,POST
,HEAD
и т.д.) - URI запроса (например,
/some-page/
или/
) - Протокол HTTP (например,
HTTP/1.0
илиHTTP/1.1
)
Эти данные позволяют легко идентифицировать запросы POST, но анализ затруднен без знания фактического содержимого запроса POST. Это объясняет, почему, если вы отслеживаете, скажем, ошибки 404, вы можете иногда получать отчеты об ошибках 404 для страниц и ресурсов, которые ДЕЙСТВИТЕЛЬНО существуют. Например, если кто-то / что-то отправляет POST-запрос на URL-адрес, который не оборудован для его обработки, сервер может вернуть ответ 404 «Not Found». Поэтому, если вы получаете ошибку 404 для страниц и ресурсов, которые действительно существуют на сервере, возможно, что POST-запросы являются необнаруженным виновником.
Мониторинг запросов POST
Хорошая новость заключается в том, что, когда вы знаете, что искать, остается лишь написать код для доступа к информации. В этом случае мы можем отслеживать запросы POST так же, как мы отслеживаем запросы 404 . Рассмотрим следующий код PHP, который обычно включается в сценарии мониторинга 404:
$http_host = $_SERVER['HTTP_HOST'];
$server_name = $_SERVER['SERVER_NAME'];
$remote_ip = $_SERVER['REMOTE_ADDR'];
$remote_host = $_SERVER["REMOTE_HOST"];
$request_uri = $_SERVER['REQUEST_URI'];
$http_ref = $_SERVER['HTTP_REFERER'];
$query_string = $_SERVER['QUERY_STRING'];
$user_agent = $_SERVER['HTTP_USER_AGENT'];
Это предоставит множество данных о запросе, но во многих таких сценариях, которые я видел, отсутствует ключевая информация, фактическое содержимое POST:
$post_vars = clean(file_get_contents('php://input'));
Включение этой строки в сценарий мониторинга ошибок дает вам прямой доступ ко всем данным POST, которые публикуются на вашем сайте. После внедрения будьте готовы испытать на себе огромное количество мусора POST-запросов.
ПОЧТОВЫЙ КОНТРОЛЬ И ЗАЩИТА
Теперь, когда мы увидели, что такое запросы POST, почему они могут быть опасными и как их отслеживать, пора серьезно заняться безопасностью и заблокировать запросы POST в соответствии с нашими конкретными потребностями.
Ключом к созданию собственной стратегии обработки запросов POST является понимание того, какие запросы действительны или приняты на вашем сайте. Когда у вас есть эта информация, несложно собрать набор правил для блокировки недействительных запросов, обеспечивая при этом нормальный доступ к действительным данным POST. Имея это в виду, давайте рассмотрим некоторые методы защиты .htaccess от нежелательных данных POST.
httpd.conf
. Пожалуйста, сделайте резервные копии всех соответствующих файлов и тщательно протестируйте перед запуском.Запретить все запросы POST
Для сайтов, которые их не принимают, отклонение всех запросов POST — идеальное решение. Например, если ваш сайт представляет собой полностью статический HTML-код без каких-либо форм или отправленных данных (например, одностраничный сайт-портфолио), защита от мошеннических запросов POST так же проста, как добавление этого в корневой файл .htaccess:
# deny all POST requests
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} POST
RewriteRule .* - [F,L]
</IfModule>
При этом используется модуль перезаписи Apache для обнаружения и отклонения любых / всех запросов POST. Легко и просто. Никаких изменений не требуется, но вы можете перенаправить заблокированные запросы на определенную страницу или файл; для этого замените правило перезаписи следующим:
RewriteRule .* /custom.php [R=301,L]
Затем измените место перенаправления /custom.php
на любое необходимое.
Запретить запросы POST с использованием HTTP 1.0
Я видел много плохих запросов POST, поступающих как HTTP 1.0 , а не как HTTP 1.1 . В этом нет ничего особенного, но с HTTP 1.0 больше возможностей для неприятностей, прежде всего потому, что протокол не требует заголовка Host. Таким образом, еще одна стратегия работы с нежелательными запросами POST (и другими типами запросов, если на то пошло) — требовать протокол HTTP 1.1.
# require HTTP 1.1 for POST
<IfModule mod_rewrite.c>
RewriteCond %{THE_REQUEST} ^POST(.*)HTTP/(0\.9|1\.0)$ [NC]
RewriteRule .* - [F,L]
</IfModule>
При добавлении в .htaccess сервер ответит запросом 403 Forbidden для любого запроса POST, который не отправляется через HTTP 1.1.
Запросы POST в белый список
Я предпочитаю заносить в белый список запросы POST для определенных ресурсов. Например, на одном сайте у меня есть контактная форма обрабатывается файлом PHP, contact.php
. Вот .htaccess для выполнения этой работы:
# whitelist POST requests
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} !/contact.php [NC]
RewriteCond %{REMOTE_ADDR} !127.0.0.1
RewriteRule .* - [F,L]
</IfModule>
Обратите внимание, что IP-адрес localhost ( 127.0.0.1
) также включен, так как контактная форма также взаимодействует с сервером через запросы Ajax. Дополнительные ресурсы могут быть внесены в белый список по следующему шаблону:
RewriteCond %{REQUEST_URI} !/contact.php [NC]
RewriteCond %{REQUEST_URI} !/business.php [NC]
RewriteCond %{REQUEST_URI} !/pleasure.php [NC]
Совет от профессионалов: поскольку мы инвертируем каждый из этих файлов, [NC]
флаг объявляется для каждой строки. Если бы это были положительные совпадения (то есть без восклицательного знака !
), мы бы использовали бы [NC,OR]
флаг для каждой строки, ЗА ИСКЛЮЧЕНИЕМ последней строки, например:
RewriteCond %{REQUEST_URI} /contact\.php [NC,OR]
RewriteCond %{REQUEST_URI} /business\.php [NC,OR]
RewriteCond %{REQUEST_URI} /pleasure\.php [NC]
Как в той старой телевизионной рекламе: «Чем больше ты знаешь» …
Контролировать POST через реферер
Еще одна эффективная стратегия, зависящая от вашей настройки, — это ограничение запросов POST на основе реферера. Это не на 100% надежно, поскольку информация о реферере может быть подделана, но я видел, как эффективно используется для сокращения незаконных запросов POST.
# allow POST based on referrer
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} /contact\.php
RewriteCond %{HTTP_REFERER} !(.*)example.com(.*)
# RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule .* - [F,L]
</IfModule>
В этом коде замените /contact\.php
ваш собственный файл (ы), а также замените example.com
свое собственное доменное имя. После этого этот метод будет отклонять любой запрос POST, отправленный не с вашего домена.
Обратите внимание, что добавлено закомментированное исключение, чтобы разрешить пустые / пустые пользовательские агенты. Это может потребоваться в зависимости от функциональности защищаемого ресурса. Если вы раскомментируете / активируете эту строку, не забудьте добавить [OR]
флаг к предыдущей строке (со значком example.com
).
Расширенный контроль POST
В предыдущих методах мы использовали различные переменные sever для управления доступом к POST-запросам. Итак, в дополнение к каждой из этих переменных:
REQUEST_METHOD
THE_REQUEST
REQUEST_URI
REMOTE_ADDR
HTTP_REFERER
HTTP_USER_AGENT
Например, если на сервер забивают неприятные запросы POST от следующего хоста:
pool-71-97-3-178.dfw.dsl-w.verizon.net
# deny POST based on host
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{HTTP_HOST} .*(dfw\.dsl-w\.verizon\.net).* [NC]
RewriteRule .* - [F,L]
</IfModule>
Идем дальше
Чтобы действительно заблокировать это, вы можете запретить доступ к другим неиспользуемым / ненужным типам запросов, добавив что-то подобное следующему:
# deny unused request types
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} ^(delete|head|trace|track) [NC]
RewriteRule .* - [F,L]
</IfModule>
И даже со всем, что мы рассмотрели в этой статье, мы лишь поверхностно касаемся конфигурации, настройки и защиты, которые стали возможными с помощью директив Apache, применяемых через файл конфигурации или через .htaccess. Чтобы по-настоящему вникнуть, ознакомьтесь с моей книгой .htaccess, упрощенный для получения дополнительной информации об управлении доступом и защите вашего сайта с помощью Apache и .htaccess.