Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Безопасная эксплуатация Apache, часть 5: использование уязвимостей архитектуры сообщений HTTP

Оригинал: Securing Apache, Part 5: HTTP Message Architecture
Автор: Arpit Bajpai
Дата публикации: 1 января 2011 г.
Перевод: А.Панин
Дата перевода: 21 января 2013 г.

В четырех предыдущих статьях данной серии мы обсудили SQL-инъекции, XSS-, CSRF-, XST- и XSHM-атаки, а также мероприятия по их нейтрализации. В данной статье проводится рассмотрение атак, в ходе которых происходит эксплуатация уязвимостей архитектуры сообщений HTTP при работе по схеме клиент-прокси-сервер.

Вмешательство в механизм HTTP-сообщений всегда имело высокий приоритет в списке задач взломщиков. Наиболее важным аспектом данного вмешательства является взаимодействие сервера и клиента. Наличие промежуточных узлов, таких, как кэширующих серверов, межсетевых экранов или прокси серверов, работающих в режиме "reverse proxy" делает обмен данными небезопасным. Атаки, связанные с вмешательством в механизм HTTP-сообщений, могут быть разделены на следующие категории:
  • Атаки с разделением ответов HTTP (HTTP response splitting)
  • Атаки некорректной передачи запросов HTTP (HTTP request smuggling)
  • Атаки с разделением запросов HTTP (HTTP request splitting)
  • Атаки некорректной передачи ответов HTTP (HTTP response smuggling)

Давайте рассмотрим их по очереди.

Атаки с разделением ответов HTTP

В ходе данной атаки, также называемой CRLF-инъекцией, уязвимый веб-сервер отвечает на специально сформированный вредоносный запрос ответом HTTP, который интерпретируется как два отдельных ответа вместо одного. Это становится возможным в случаях, когда в заголовках ответа HTTP используются данные, введенные пользователем без дополнительных проверок. Взломщик может спровоцировать ситуацию, при которой браузер жертвы атаки интерпретирует добавленный заголовок как ответ на второй запрос, при этом специально сформированные данные будут отображены и, возможно, добавлены в кэш браузера.

Для реализации разделения ответов HTTP с использованием уязвимого сервера, взломщик выполняет следующие действия:
  1. Обнаруживает возможности для ввода данных пользователем с возможностью добавления этих данных в заголовок HTTP.
  2. Формирует вредоносную строку для завершения запроса от приложения и добавления своего собственного запроса с необходимыми данными в заголовке.
  3. Принуждает жертву атаки к отправке двух запросов серверу. Первый запрос содержит специально сформированные вредоносные данные в составе заголовка HTTP, а второй - запрос от приложения, поэтому браузер жертвы атаки интерпретирует разделенный ответ таким образом, что он считается принадлежащим второму запросу.
Данная атака в общем случае направлена на веб-приложения и осуществляется с помощью вставки вредоносных или недопустимых символов в пользовательские данные, которые используются для обработки статуса 3xx Переадресации HTTP и в параметрах заголовка HTTP "Location" или "Set-Cookie". Это возможно в первую очередь из-за недостаточной проверки введенных пользователем данных на наличие символов, таких, как CR (Возврат каретки, Carriage Return=%0d=\r) и LF (Переход на новую строку, Line Feed=%0a=\n). В таких приложениях происходит вставка кода, такого, как \r\n, в одной из множества форм его кодирования.
<?php
    header ("Location: " . $_GET['page']);
?>

Запросы данной страницы, такие, как http://test.example.com/~arpit/redirect.php?page=http://www.example.com, должны перенаправлять браузер пользователя на ресурс http://www.example.com. Давайте рассмотрим заголовки HTTP, генерируемые в ходе данной сессии.

Простой GET-запрос, отправляемый пользователем серверу:
GET /~arpit/redirect.php?page=http://www.example.com HTTP/1.1\r\n
Host: test.example.com\r\n
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9)
Gecko/2008052960 Firefox/3.6.2\r\n
......
Accept-Language: en-us,en;q=0.5\r\n
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n
Keep-Alive: 300\r\n
Connection: keep-alive\r\n
\r\n
Статус HTTP 302, отправляемый сервером пользователю в качестве ответа:
HTTP/1.1 302 Found\r\n
Date: Tue, 12 Apr 2005 21:00:28 GMT\r\n
Server: Apache/2.3.8 (Unix) mod_ssl/2.3.8 OpenSSL/1.0.0a\r\n
Location: http://www.example.com\r\n [User input in headers]
......
Content-Type: text/html\r\n
Connection: Close\r\n
Запрос GET, отправляемый пользователем серверу при переходе на страницу переадресации:
GET / HTTP/1.1\r\n
Host: www.example.com\r\n
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9)
Gecko/2008052960 Firefox/3.6.2\r\n
......
Accept-Language: en-us,en;q=0.5\r\n
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n
Keep-Alive: 300\r\n
Connection: keep-alive\r\n

После этого сервер должен вернуть статус HTTP 200 OK и пользователь увидит страницу, загруженную с ресурса www.example.com. Обычные заголовки HTTP, приведенные выше, могут быть также отображены графически таким образом, как показано на Рисунке 1.

Обычный обмен данными между клиентом и сервером при переадресации со статусом HTTP 302
Рисунок 1: Обычный обмен данными между клиентом и сервером при переадресации со статусом HTTP 302

Теперь взломщик может использовать последовательность символов %0d%0a для добавления в заголовок данных, аналогичных представленным ниже:
Вставленные данные в удобной для чтения форме:
\r\n
Content-Type: text/html\r\n
HTTP/1.1 200 OK\r\n
Content-Type: text/html\r\n
Content-Length: 6\r\n
\r\n
<html>HACKED</html>
В случае перехода жертвой атаки по данной вредоносной ссылке, (сокращенной при помощи специальных сервисов) серверу будет отправлен следующий запрос:
Сервер должен ответить следующим образом:
HTTP/1.1 302 Found [Первый стандартный ответ со статусом HTTP 302]
Date: Tue, 12 Apr 2005 22:09:07 GMT
Server: Apache/2.3.8 (Unix) mod_ssl/2.3.8 OpenSSL/1.0.0a
Location:
Content-Type: text/html
HTTP/1.1 200 OK [второй ответ на новый запрос, сформированный взломщиком]
Content-Type: text/html
Content-Length: 6
<html>HACKED</html> [Введенные произвольные данные отображаются в качестве страницы перенаправления]
Content-Type: text/html
Connection: Close

Как мы можем увидеть в описании процесса обмена данными выше, сервер отправляет стандартный ответ HTTP со статусом 302, но возможность ввода произвольных данных в строку запроса приводит к передаче нового ответа HTTP со статусом 200 OK, что позволяет показать введенные данные жертве атаки в виде обычного ответа веб-сервера. Таким образом, жертва атаки должна увидеть веб-страницу с текстом "HACKED". Схематично данные шаги отображены на Рисунке 2.

Процесс реализации атаки с разделением ответов HTTP
Рисунок 2: Процесс реализации атаки с разделением ответов HTTP (кликните для увеличения)

Этот пример представляет собой простой случай эксплуатации XSS-уязвимости с использованием атаки с разделением ответов HTTP. Кроме этого, взломщик может также добавить вредоносные данные к кэш сервера (Web-cache poisoning), провести межпользовательские атаки (Cross-user attacks) и добавить вредоносные данные в кэш браузера (Browser cache poisoning).

Межпользовательские атаки: При межпользовательских атаках второй ответ, отправленный веб-сервером, может быть ошибочно интерпретирован как ответ на другой запрос, возможно отправленный другим пользователем, использующим это же TCP-соединение с сервером. В этом случае запрос от одного пользователя обслуживается с использованием данных другого пользователя.

Для добавления вредоносных данных в кэш взломщик просто использует параметр "Last-Modified" в сформированной части заголовка (для сохранения в кэше вредоносной веб-страницы в течение времени, заданного параметром "Last-Modified" заголовка, заданная данным параметром дата всегда опережает текущую). Более того, использование параметров Cache-Control: no-cache и/или Pragma: no-cache в добавленном заголовке позволяет добавить в кэш даже не предназначенные для этого страницы веб-сайтов.

Мероприятия по повышению безопасности

Данная уязвимость веб-приложений может привести к замене страниц сайта с помощью помещения вредоносных данных в кэш сервера (Web-cache poisoning) и к возможности использования межсайтовых уязвимостей сценариев,но следующие методы повышения безопасности позволяют нейтрализовать ее:
  • Лучшим способом устранения уязвимостей разделения ответов HTTP является поиск во всех введенных пользователями данных символов CR/LF, т.е, \r\n, %0d%0a или любой другой формы их кодирования (или других небезопасных символов) перед использованием этих данных в любых заголовках HTTP.
  • Следует правильно форматировать строки URI в любых местах сообщений HTTP, например, в параметре "Location" заголовка HTTP; после этого символы CRLF (/r, /n) не будут обрабатываться браузером.
  • Миф о том, что использование SSL позволяет противодействовать этим атакам не является правдой; при использовании данной технологии кэш веб-браузера и соединения вне SSL остаются незащищенными. Не полагайтесь на технологию SSL для защиты от рассматриваемого типа атак.

Для получения информации о других направлениях атак и методах защиты от них, не забудьте рассмотреть раздел дополнительных ресурсов в конце статьи.

Атаки некорректной передачи запросов HTTP

Атаки некорректной передачи запросов используются против распределенных систем, обрабатывающих HTTP-запросы (особенно тех, которые используют вложенные запросы) различными способами. Эти различия в обработке запросов могут эксплуатироваться при взаимодействии с серверами или приложениями, отправляющими HTTP-запросы далее напрямую к другому серверу - например, с прокси-серверами, кэширующими серверами или межсетевыми экранами.

Если промежуточный сервер интерпретирует запрос одним способом (рассматривая запрос определенным образом), конечный сервер интерпретирует его другим способом (рассматривая запрос отличным образом), то ответы не будут ассоциированы с корректными запросами.

Следовательно, промежуточное устройство, которое должно защищать сеть от опасных HTTP-запросов, трактует вредоносный запрос как данные, в то время, как сервер может интерпретировать его как корректный запрос.

Это разобщение может привести к помещению вредоносных данных в кэш (Cache poisoning) или возможности использования межсайтового скриптинга (XSS) с показом пользователю неуместного содержимого страницы в итоге. Также это может привести к обходу межсетевого экрана или к нарушению соответствия и последовательности запросов и ответов, что делает ваш сервер уязвимым к другим, возможно более опасным атакам.

Почему данная атака возможна? Атаки некорректной передачи запросов эксплуатируют недостаточное соответствие в обработке и интерпретации данных протокола HTTP спецификации (RFC 2616). Спецификация RFC2616 указывает на то, что в заголовке должен быть один и только один параметр Content-Length.

Но при использовании нескольких параметров Content-Length в заголовке становится возможным ввести в заблуждение прокси-сервера и обойти некоторые межсетевые экраны, в зависимости от их интерпретации заголовков HTTP. Частично это происходит из-за того, что в спецификации RFC2616 нет указания на то, как должен вести себя конечный сервер при получении множества заголовков HTTP и частично из-за того, что конечные сервера всегда достаточно свободно интерпретируют запросы от клиентов, которые пользуются этой особенностью их работы, не следуя в точности спецификации протокола HTTP.

Некоторые конечные сервера при обработке запроса игнорируют первый или второй заголовок, после чего обрабатывают данные, размер которых задан параметром "Content-Length". Эта особенность может использоваться для того, чтобы заставить прокси-сервер трактовать запросы как данные и наоборот, что позволяет ввести в заблуждение конечный сервер и заставить его выполнить вредоносные запросы, скрытые внутри корректных запросов.

Сценарий атаки

В данном отдельном случае описывается атака по добавлению вредоносных данных в кэш веб-сервера с помощью некорректной передачи запроса. В ходе атаки отправляется ряд HTTP-запросов для эксплуатации уязвимостей веб-сервера (www.example.com) и кэширующего прокси-сервера. В данном случае целью взломщика является добавление в кэш содержимого страницы www.example.com/resource_denied.html вместо содержимого страницы www.example.com/welcome.html.

Примечание: Для успешной реализации атаки некорректной передачи запросов HTTP необходимо, чтобы веб-приложение содержало XSS-уязвимость.
В ходе атаки происходит отправка запроса HTTP POST с несколькими параметрами "Content-Length" в заголовке. Взломщик отправляет следующий запрос прокси-серверу:
POST http://www.example.com/some.html HTTP/1.1
Host: www.example.com
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Content-Length: 39

GET /resource_denied.html HTTP/1.1
Blah: GET http://www.example.com/welcome.html HTTP/1.1
Host: www.example.com
Connection: Keep-Alive
Прокси-сервер произведет обработку первой секции заголовка (с запросом POST). После этого он использует последний параметр "Content-Length" (39 байт) заголовка для обработки данных; на основании полученной информации он считает данные (длиной 39 байт) и отправит запрос из первой секции веб-серверу в форме, представленной ниже:
POST http://www.example.com/some.html HTTP/1.1
Host: www.example.com
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Content-Length: 39

GET /resource_denied.html HTTP/1.1
Blah:
Веб-сервер обработает первый запрос, использовав первый параметр "Content-Length" заголовка и интерпретирует данный запрос следующим образом:
POST http://www.example.com/some.html HTTP/1.1
Host: www.example.com
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Content-Length: 39
Заметьте, что данные не подвергаются обработке (первый параметр "Content-Length" имеет значение 0 байт). Веб-сервер ответит на данный запрос, после чего он перейдет к обработке следующего неполного запроса (представленного ниже), ожидающего обработки в очереди:
GET /resource_denied.html HTTP/1.1
Blah:
После этого прокси-сервер получит первый ответ от веб-сервера, направленный взломщику и перейдет к обработке последнего запроса взломщика, который представлен ниже:
GET http://www.example.com/welcome.html HTTP/1.1
Host: www.example.com
Connection: Keep-Alive
После этого становится ясно, что ответ веб-сервера на этот запрос будет добавлен в кэш прокси-сервера в качестве ответа на запрос со строкой URL http://www.example.com/welcome.html. Прокси-сервер передает этот запрос веб-серверу. Он добавляется в конец неполного запроса веб-сервера, который представляется в следующем виде:
GET /resource_denied.html HTTP/1.1
Blah: GET http://www.example.com/welcome.html HTTP/1.1
Host: www.example.com
Connection: Keep-Alive

В конце концов веб-сервер получает второй запрос от клиента, который он может обработать. Он интерпретирует его как HTTP-запрос страницы http://www.example.com/resource_denied.html. Запрос Blah не имеет значения согласно спецификации HTTP RFC, поэтому он игнорируется веб-сервером. В результате содержимое страницы http://www.example.com/resource_denied.html возвращается в ответ на (специально сформированный) запрос страницы http://www.example.com/welcome.html. Теперь до момента истечения срока хранения данных в кэше прокси-сервера, пользователям, запросившим страницу welcome.html, будут передаваться копии страницы resource_denied.html.

Данный сценарий является примером частично управляемой атаки по добавлению данных в кэш веб-сервера (смотрите Рисунок 3), поскольку взломщики так и не получили полный контроль над содержимым кэша. Более того, они не получили полного контроля над возвращаемыми заголовками HTTP и, что более важно, взломщикам пришлось использовать существующую (и кэшируемую) страницу целевого веб-сайта в качестве замены (в примере выше это страница resource_denied.html).

Однако, кроме описанных выше действий, взломщики могут также обойти межсетевые экраны/IDS/IPS и похитить аутентификационные данные - конечно же, с помощью данного типа атаки это не сложно. Для того, чтобы узнать больше о атаках некорректной передачи запросов HTTP, не забудьте обратиться к разделу дополни тельных ресурсов в конце статьи.

Атака некорректной передачи запросов HTTP
Рисунок 3: Атака некорректной передачи запросов HTTP (кликните для увеличения)

Мероприятия по повышению безопасности

  • Устанавливайте экраны для веб-приложений, защищающие от атак некорректной передачи запросов HTTP. Некоторые экраны до сих пор уязвимы для данного типа атак; обратитесь к производителю экрана с вопросом о том, обеспечивает ли он защиту от этих атак.
  • Применяйте стойкие техники управления сессиями. Завершайте сессии после каждого запроса.
  • Отключите распределение TCP-соединений на промежуточных устройствах. Распределение TCP-соединений улучшает производительность, но позволяет взломщикам проводить атаки некорректной передачи запросов HTTP.
  • Активируйте запрет на кэширование всех страниц. Для подробного описания обратитесь к ресурсу www.web-caching.com.

Атаки разделения запросов HTTP

В ходе данных атак браузеры пользователей отправляют множество HTTP-запросов вместо единственного запроса. На данный момент известны два механизма для осуществления данного типа атак: использование объекта XmlHttpRequest (для краткости обозначаемого XHR) и использование механизма HTTP-аутентификации при помощи хэшей (HTTP digest). Для осуществления данной атаки жертва атаки должна использовать прокси-сервер. В общем случае для разделения HTTP-запроса, в него добавляются последовательности символов CRLF.

XmlHttpRequest является объектом JavaScript, позволяющим отправлять с помощью клиентского JavaScript-кода практически необработанные HTTP-запросы к заданному узлу и получать доступ к данным ответов в необработанной форме. Объект XmlHttpRequest как таковой является основным компонентом технологии AJAX.

Сценарий атаки

Давайте рассмотрим веб-приложение, имеющее XSS-уязвимость, причем работа пользователя с ним осуществляется через прокси-сервер, находящийся между компьютером жертвы атаки и веб-сервером. Взломщик вводит в заблуждение жертву атаки, заставляя перейти по ссылке со следующим вредоносным сценарием, использующим объект XmlHttpRequest:
Примечание: код, приведенный выше, будет работать только в браузере Internet Explorer; модификации, необходимые для его работы в браузере Mozilla закомментированы и вы можете просто раскомментировать их в случае необходимости.
Когда браузер жертвы атаки выполняет приведенный выше сценарий, он отправляет одиночный HTTP-запрос с целевым адресом www.attacker.com. При этом не нарушаются ограничения, накладываемые технологией защиты "same-origin policy (SOP)", поэтому запрос выполняется. Тем не менее, прокси-сервер должен получить следующий запрос:
GET\thttp://www.attacker.com/page1.html\tHTTP/1.0
Host:\twww.attacker.com
Proxy-Connection:\tKeep-Alive
GET http://www.attacker.com/page2.html HTTP/1.0
Host: www.attacker.com
......
......
Content-Type: text/html
Connection: Keep-Alive

Следовательно, он ответит на два HTTP-запроса. Первый ответ (http://www.attacker.com/page1.html) будет обработан самим объектом XHR, а второй (http://www.attacker.com/page2.html) будет ожидать в очереди ответов браузера до того момента, пока с помощью браузера не будет запрошена страница http://www.example.com/index.html (так как в этот момент будет выполнен метод window.open()). После этого браузер сопоставит ответ на запрос страницы http://www.attacker.com/page2.html с запросом со строкой URL http://www.target.com/index.html и покажет в окне страницу, выбранную взломщиком с данной строкой URL!!

Важное замечание: в примере атаки, приведенном выше, мы использовали горизонтальную табуляцию (\t) вместо простых пробелов по той причине, что браузер IE не позволяет использовать пробелы в параметрах метода x.open(). Причина по которой мы использовали версию протокола HTTP/1.0 заключается в том, что версия HTTP/1.1 содержит строгое требование исключительного использования пробелов в то время, как версия HTTP/1.0 не содержит таких ограничений.

Вредоносный сценарий, исполняемый браузером жертвы атаки отправляет только один запрос, но прокси-сервер получает два HTTP-запроса (теоретически это могут быть запросы для разных доменов), поэтому прокси-сервер отправляет два различных ответа HTTP.

Мероприятия по повышению безопасности

Хотя атаки разделения запросов HTTP и применяются крайне редко, следует серьезно отнестись к следующим рекомендациям:
  • Владельцам сайтов следует использовать технологию SSL для их защиты.
  • Полное устранение XSS-уязвимостей, несомненно, поможет в борьбе с данными атаками в значительной степени.
  • Часто советуют также заблокировать запросы по протоколу HTTP/1.0 на уровне веб-сервера. Хотя данная методика и работоспособна, ее применение заблокирует доступ к сайту ботов большинства поисковых машин, так как они в большинстве случаев используют протокол HTTP/1.0.
  • Следует применить методики, предложенные для борьбы с другими типами атак в данной статье (особенно фильтрацию введенных пользователем данных с целью удаления последовательностей CRLF).

Атаки некорректной передачи ответов HTTP

Данная атака применяется крайне редко. В ходе атаки взломщик передает два ответа HTTP от сервера клиенту через промежуточное устройство, работающее по протоколу HTTP и позволяющее принимать единичные ответы от сервера. Для осуществления этой атаки используются непостоянные или ошибочные интерпретации сообщений протокола HTTP различными приложениями.

Например, возможно использование различных символов для завершения блоков (CR или LF по отдельности), с помощью которых становится возможным добавлению дублирующих полей заголовка, которые интерпретируются браузерами как принадлежащие к разным ответам, а также использование других техник. В качестве последствий таких атак могут проводиться атаки разделения запросов HTTP, атаки на основе межсайтового скриптинга, замена страниц на выбранных сайтах, добавление данных в кэш и подобные действия.

Данная атака наиболее полезна в качестве метода для обхода механизмов противодействия атакам разделения ответов HTTP (anti-HRS). Для успешной реализации данного типа атак необходимо, чтобы сервер позволял взломщику добавлять данные, которые впоследствии будут содержаться в ответе сервера.

Атаки некорректной передачи ответов HTTP используют техники, аналогичные применяемым при атаках некорректной передачи запросов HTTP для использования расхождений в том, как механизм противодействия атакам разделения ответов HTTP (или прокси-сервер) определяет корректность потока ответов HTTP и как поток ответов HTTP обрабатывается прокси-сервером (или браузером). Поэтому в том случае, если механизм anti-HRS считает определенный поток ответов безопасным (единичным HTTP-ответом), прокси-сервер или браузер может обрабатывать его как два отдельных HTTP-ответа и, таким образом, быть восприимчивым ко всем последствиям классической атаки разделения запросов HTTP (в одном случае) или к подмене страниц в кэше (в другом случае).

Например, некоторые механизмы anti-HRS, используемые приложениями, могут запрещать вставку последовательности символов CR+LF в заголовок ответа. При этом взломщик может заставить приложение вставить в заголовок только символы LF или только символы CR, тем самым обходя механизм защиты. Некоторые прокси-серверы могут также трактовать символы CR (единичные) как разделители заголовков и данных ответов и, таким образом, комбинация веб-сервера и прокси-сервера будет уязвимой к атаке, способной модифицировать кэш прокси-сервера.

Так как данная атака имеет множество зависимостей (поэтому она и применяется очень редко), я советую вам обратиться к разделу дополнительных ресурсов ниже для того, чтобы узнать больше о ней. В качестве меры дополнительной безопасности следует строго придерживаться единой системы интерпретации сообщений HTTP там, где это возможно. (Помните о том, что не должны использоваться единичные символы CR и LF.) Более того, кодирование введенной пользователями информации в заголовках (таким образом, что пользовательские данные не будут интерпретироваться промежуточными узлами) является также хорошим способом сдерживания атаки. Наконец, следует отклонять все ответы сервера, не соответствующие стандарту RFC.

Все примеры сценариев атак, описанные выше, приводятся исключительно в образовательных целях. Еще раз обращаю внимание на то, что ни я ни журнал LFY не ставим своей целью научить вас атаковать серверы. Напротив, техники атак приведены с целью получения вами необходимых знаний для защиты собственной инфраструктуры. Мы рассмотрим другие опасные атаки на веб-приложения и Apache в следующей статье.

Всегда помните: нужно знать все о взломе, но не заниматься им.

Дополнительные ресурсы

Продолжение серии: "Безопасная эксплуатация Apache, часть 6: атаки на механизм управления сессиями"