В мае мы поделились статистикой по самым популярным атакам с отражением. Тогда средний размер атаки SSDP был в районе 12 Гбит/с, а крупнейшая атака SSDP с отражением была такой:
- 30 Мп/с (миллионов пакетов в секунду)
- 80 Гбит/с (миллиардов бит в секунду)
- 940 тыс. IP-адресов для отражения
Всё изменилось пару дней назад, когда мы заметили необычно крупное умножение пакетов SSDP. Это достойно более тщательного расследования, поскольку атака преодолела символический рубеж в 100 Гбит/с.
График пакетов в секунду:
Использование полосы:
Пакетный флуд продолжался 38 минут. Судя по выборке потока данных, использовались 930 тыс. отражающих серверов. По нашей оценке, каждый рефлектор отправил 120 тыс. пакетов на Cloudflare.
Отражающие сервера располагались по всему миру, больше всего в Аргентине, России и Китае. Вот уникальные IP-адреса по странам:
$ cat ips-nf-ct.txt|uniq|cut -f 2|sort|uniq -c|sort -nr|head
439126 CN
135783 RU
74825 AR
51222 US
41353 TW
32850 CA
19558 MY
18962 CO
14234 BR
10824 KR
10334 UA
9103 IT
...
Распределение IP-адресов по ASN вполне типично. Оно во многом соотносится с крупнейшими в мире домашними интернет-провайдерами:
$ cat ips-nf-asn.txt |uniq|cut -f 2|sort|uniq -c|sort -nr|head
318405 4837 # CN China Unicom
84781 4134 # CN China Telecom
72301 22927 # AR Telefonica de Argentina
23823 3462 # TW Chunghwa Telecom
19518 6327 # CA Shaw Communications Inc.
19464 4788 # MY TM Net
18809 3816 # CO Colombia Telecomunicaciones
11328 28573 # BR Claro SA
7070 10796 # US Time Warner Cable Internet
6840 8402 # RU OJSC "Vimpelcom"
6604 3269 # IT Telecom Italia
6377 12768 # RU JSC "ER-Telecom Holding"
...
Впрочем, что такое SSDP?
Данная атака состоит из UDP-пакетов с порта 1900. Этот порт используется протоколами SSDP и UPnP. UPnP — один из протоколов Zeroconf (Zero Configuration Networking), которые создают IP-сеть без конфигурации или специальных серверов. Скорее всего, ваши домашние устройства поддерживают его, чтобы их легче было найти с компьютера или телефона. Когда присоединяется новое устройство (вроде вашего ноутбука), оно может опросить локальную сеть на предмет наличия конкретных устройств, таких как интернет-шлюзы, аудиосистемы, телевизоры или принтеры. Подробнее см. сравнение UPnP и Bonjour.
UPnP плохо стандартизирован, но вот выдержка из спецификаций о фрейме M-SEARCH
— основном методе обнаружения:
Когда в сеть добавляется контрольная точка, протокол обнаружения UPnP позволяет этой контрольной точке поиск интересующих устройств в сети. Он делает это с помощью мультивещания поискового сообщения на зарезервированный адрес и порт (239.255.255.250:1900) с шаблоном, или целью, соответствующей типу идентификатора для устройства или сервиса.
Ответы во фрейм M-SEARCH
:
Чтобы быть найденным поисковым запросом, устройство должно отправить одноадресный ответ UDP на IP-адрес источника и порт, который прислал сообщение с помощью мультивещания. Ответ требуется, если в поле заголовка ST в запросе
M-SEARCH
указано “ssdp:all”, “upnp:rootdevice”, “uuid:”, а далее следует UUID, который в точности соответствует UUID устройства, или если запросM-SEARCH
соответствует типу устройства или типу сервиса, поддерживаемому устройством.
Так оно и работает на практике. Например, мой браузер Chrome регулярно опрашивает Smart TV, насколько я понимаю:
$ sudo tcpdump -ni eth0 udp and port 1900 -A
IP 192.168.1.124.53044 > 239.255.255.250.1900: UDP, length 175
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:dial-multiscreen-org:service:dial:1
USER-AGENT: Google Chrome/58.0.3029.110 Windows
Этот фрейм отправляется на IP-адрес для мультивещания. Другие устройства, которые слушают этот адрес и поддерживают специфический многоэкранный тип ST
(search-target), должны ответить.
Кроме запросов специфических типов устройств, существует два «общих» типа запросов ST
:
upnp:rootdevice
: поиск корневых устройствssdp:all
: поиск всех устройств и сервисов UPnP
Для имитации этих запросов вы можете запустить такой скрипт Python (основанный на этой работе):
#!/usr/bin/env python2
import socket
import sys
dst = "239.255.255.250"
if len(sys.argv) > 1:
dst = sys.argv[1]
st = "upnp:rootdevice"
if len(sys.argv) > 2:
st = sys.argv[2]
msg = [
'M-SEARCH * HTTP/1.1',
'Host:239.255.255.250:1900',
'ST:%s' % (st,),
'Man:"ssdp:discover"',
'MX:1',
'']
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.settimeout(10)
s.sendto('rn'.join(msg), (dst, 1900) )
while True:
try:
data, addr = s.recvfrom(32*1024)
except socket.timeout:
break
print "[+] %sn%s" % (addr, data)
В моей домашней сети отзываются два устройства:
$ python ssdp-query.py
[+] ('192.168.1.71', 1026)
HTTP/1.1 200 OK
CACHE-CONTROL: max-age = 60
EXT:
LOCATION: http://192.168.1.71:5200/Printer.xml
SERVER: Network Printer Server UPnP/1.0 OS 1.29.00.44 06-17-2009
ST: upnp:rootdevice
USN: uuid:Samsung-Printer-1_0-mrgutenberg::upnp:rootdevice
[+] ('192.168.1.70', 36319)
HTTP/1.1 200 OK
Location: http://192.168.1.70:49154/MediaRenderer/desc.xml
Cache-Control: max-age=1800
Content-Length: 0
Server: Linux/3.2 UPnP/1.0 Network_Module/1.0 (RX-S601D)
EXT:
ST: upnp:rootdevice
USN: uuid:9ab0c000-f668-11de-9976-000adedd7411::upnp:rootdevice
Файрвол
Теперь, когда мы понимаем основы SSDP, будет легко понять суть атаки с отражением. На самом деле есть два способа доставки фрейма M-SEARCH
:
- который мы показали, через адрес для мультивещания
- напрямую хосту UPnP/SSDP на обычном адресе (одноадресная передача)
Второй метод тоже работает. Мы можем конкретно указать IP-адрес моего принтера:
$ python ssdp-query.py 192.168.1.71
[+] ('192.168.1.71', 1026)
HTTP/1.1 200 OK
CACHE-CONTROL: max-age = 60
EXT:
LOCATION: http://192.168.1.71:5200/Printer.xml
SERVER: Network Printer Server UPnP/1.0 OS 1.29.00.44 06-17-2009
ST: upnp:rootdevice
USN: uuid:Samsung-Printer-1_0-mrgutenberg::upnp:rootdevice
Теперь проблема легко понятна: протокол SSDP не проверяет, находится ли отправитель сообщения в той же сети, что и устройство. Оно с радостью ответит на запрос M-SEARCH
, который пришёл из интернета. Требуется только чуть неправильная настройка файрвола, когда порт 1900 открыт внешнему миру — и вот идеальная мишень для умножения флуда UDP.
Если дать нашему скрипту такую мишень с неправильной конфигурацией файрвола, то он отлично сработает через интернет:
$ python ssdp-query.py 100.42.x.x
[+] ('100.42.x.x', 1900)
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: upnp:rootdevice
USN: uuid:3e55ade9-c344-4baa-841b-826bda77dcb2::upnp:rootdevice
EXT:
SERVER: TBS/R2 UPnP/1.0 MiniUPnPd/1.2
LOCATION: http://192.168.2.1:40464/rootDesc.xml
Умножение пакетов
Впрочем, самый реальный вред наносит тип ssdp:all
ST
. Его ответы намного больше по размеру:
$ python ssdp-query.py 100.42.x.x ssdp:all
[+] ('100.42.x.x', 1900)
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: upnp:rootdevice
USN: uuid:3e55ade9-c344-4baa-841b-826bda77dcb2::upnp:rootdevice
EXT:
SERVER: TBS/R2 UPnP/1.0 MiniUPnPd/1.2
LOCATION: http://192.168.2.1:40464/rootDesc.xml
[+] ('100.42.x.x', 1900)
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1
USN: uuid:3e55ade9-c344-4baa-841b-826bda77dcb2::urn:schemas-upnp-org:device:InternetGatewayDevice:1
EXT:
SERVER: TBS/R2 UPnP/1.0 MiniUPnPd/1.2
LOCATION: http://192.168.2.1:40464/rootDesc.xml
... и ещё 6 ответных пакетов....
В этом конкретном случае единственный пакет SSDP M-SEARCH
вызвал 8 пакетов в ответ. Просмотр в tcpdump:
$ sudo tcpdump -ni en7 host 100.42.x.x -ttttt
00:00:00.000000 IP 192.168.1.200.61794 > 100.42.x.x.1900: UDP, length 88
00:00:00.197481 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 227
00:00:00.199634 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 299
00:00:00.202938 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 295
00:00:00.208425 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 275
00:00:00.209496 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 307
00:00:00.212795 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 289
00:00:00.215522 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 291
00:00:00.219190 IP 100.42.x.x.1900 > 192.168.1.200.61794: UDP, length 291
Мишень совершила восьмикратное умножение пакетов и 26-кратное умножение трафика. К сожалению, это типичный случай SSDP.
Спуфинг IP
Последний шаг, необходимый для проведения атаки — убедить уязвимые серверы отсылать ответные пакеты на адрес жертвы, а не злоумышленника. Для этого злоумышленнику необходимо подделать IP-адрес отправителя в своих запросах.
Мы опросили IP-адреса рефлекторов, которые использовались в вышеупомянутой атаке на 100 Гбит/с. Оказалось, что из 920 тыс. адресов только 350 тыс. (35%) по прежнему отвечают на пробные запросы SSDP.
Ответившим на пробные запросы мы отправляли, в среднем, 7 пакетов:
$ cat results-first-run.txt|cut -f 1|sort|uniq -c|sed -s 's#^ +##g'|cut -d " " -f 1| ~/mmhistogram -t "Response packets per IP" -p
Response packets per IP min:1.00 avg:6.99 med=8.00 max:186.00 dev:4.44 count:350337
Response packets per IP:
value |-------------------------------------------------- count
0 | ****************************** 23.29%
1 | **** 3.30%
2 | ** 2.29%
4 |************************************************** 38.73%
8 | ************************************** 29.51%
16 | *** 2.88%
32 | 0.01%
64 | 0.00%
128 | 0.00%
Пакеты с запросами имели размер 110 байт. Пакеты с ответами — в среднем, 321 байт (± 29 байт).
Согласно нашим измерениям, используя тип ssdp:all
M-SEARCH
, злоумышленник может получить:
- 7-кратное умножение количества пакетов
- 20-кратное умножение трафика
Можно подсчитать, что атака на 43 млн пакетов в секунду и 112 Гбит/с была инициирована с помощью:
- 6,1 млн пакетов в секунду
- канала 5,6 Гбит/с
Другими словами, один хорошо подключенный сервер на 10 Гбит/с, способный на подделку IP, может сгенерировать значительную атаку SSDP.
Подробнее о серверах SSDP
Поскольку мы опросили уязвимые серверы SSDP, мы можем показать самые популярные значения заголовка Server
:
104833 Linux/2.4.22-1.2115.nptl UPnP/1.0 miniupnpd/1.0
77329 System/1.0 UPnP/1.0 IGD/1.0
66639 TBS/R2 UPnP/1.0 MiniUPnPd/1.2
12863 Ubuntu/7.10 UPnP/1.0 miniupnpd/1.0
11544 ASUSTeK UPnP/1.0 MiniUPnPd/1.4
10827 miniupnpd/1.0 UPnP/1.0
8070 Linux UPnP/1.0 Huawei-ATP-IGD
7941 TBS/R2 UPnP/1.0 MiniUPnPd/1.4
7546 Net-OS 5.xx UPnP/1.0
6043 LINUX-2.6 UPnP/1.0 MiniUPnPd/1.5
5482 Ubuntu/lucid UPnP/1.0 MiniUPnPd/1.4
4720 AirTies/ASP 1.0 UPnP/1.0 miniupnpd/1.0
4667 Linux/2.6.30.9, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
3334 Fedora/10 UPnP/1.0 MiniUPnPd/1.4
2814 1.0
2044 miniupnpd/1.5 UPnP/1.0
1330 1
1325 Linux/2.6.21.5, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
843 Allegro-Software-RomUpnp/4.07 UPnP/1.0 IGD/1.00
776 Upnp/1.0 UPnP/1.0 IGD/1.00
675 Unspecified, UPnP/1.0, Unspecified
648 WNR2000v5 UPnP/1.0 miniupnpd/1.0
562 MIPS LINUX/2.4 UPnP/1.0 miniupnpd/1.0
518 Fedora/8 UPnP/1.0 miniupnpd/1.0
372 Tenda UPnP/1.0 miniupnpd/1.0
346 Ubuntu/10.10 UPnP/1.0 miniupnpd/1.0
330 MF60/1.0 UPnP/1.0 miniupnpd/1.0
...
Самые популярные значения заголовка ST
:
298497 upnp:rootdevice
158442 urn:schemas-upnp-org:device:InternetGatewayDevice:1
151642 urn:schemas-upnp-org:device:WANDevice:1
148593 urn:schemas-upnp-org:device:WANConnectionDevice:1
147461 urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
146970 urn:schemas-upnp-org:service:WANIPConnection:1
145602 urn:schemas-upnp-org:service:Layer3Forwarding:1
113453 urn:schemas-upnp-org:service:WANPPPConnection:1
100961 urn:schemas-upnp-org:device:InternetGatewayDevice:
100180 urn:schemas-upnp-org:device:WANDevice:
99017 urn:schemas-upnp-org:service:WANCommonInterfaceConfig:
98112 urn:schemas-upnp-org:device:WANConnectionDevice:
97246 urn:schemas-upnp-org:service:WANPPPConnection:
96259 urn:schemas-upnp-org:service:WANIPConnection:
93987 urn:schemas-upnp-org:service:Layer3Forwarding:
91108 urn:schemas-wifialliance-org:device:WFADevice:
90818 urn:schemas-wifialliance-org:service:WFAWLANConfig:
35511 uuid:IGD{8c80f73f-4ba0-45fa-835d-042505d052be}000000000000
9822 urn:schemas-upnp-org:service:WANEthernetLinkConfig:1
7737 uuid:WAN{84807575-251b-4c02-954b-e8e2ba7216a9}000000000000
6063 urn:schemas-microsoft-com:service:OSInfo:1
...
Уязвимые IP-адреса как будто принадлежат, в основном, домашним маршрутизаторам.
Открытый SSDP — это уязвимость
Само собой понятно, что разрешить входящий трафик 1900/UDP из интернета на ваш домашний принтер или другое устройство — не самая лучшая идея. Эта проблема известна по крайней мере с января 2013 года:
- Уязвимости в безопасности UPnP
Авторы SSDP явно не думали о потенциале UDP как умножителя пакетов. Есть некоторые очевидные рекомендации об использовании SSDP в будущем:
- Авторы SSDP должны ответить, существует ли в реальном мире хоть какая-то возможность использования одноадресных запросов
M-SEARCH
. Насколько я понимаю,M-SEARCH
имеет практический смысл только как многоадресный запрос в локальной сети. - Поддержку одноадресных запросов
M-SEARCH
нужно либо отменить, либо ограничить по скорости, как действует ограничение DNS Response Rate Limit. - Ответы
M-SEARCH
должны отправляться только получателям в локальной сети. Ответы за пределы локальной сети имеют мало смысла и открывают возможность использования описанной уязвимости.
В то же время мы рекомендуем:
- Сетевые администраторы должны убедиться, что входящий порт 1900/UDP заблокирован на файрволе.
- Интернет-провайдеры никогда не должны разрешать IP-спуфинг в своей сети. Подделка IP-адресов — вот истинная корневая причина проблемы. См. пресловутый BCP38.
- Интернет-провайдеры должны разрешить своим пользователям использовать BGP flowspec для ограничения входящего трафика 1900/UDP, чтобы рассредоточить скопление трафика при крупных атаках SSDP.
- Интернет-провайдеры должны собирать образцы netflow. Это нужно для определения истинного источника атаки. С netflow будет просто ответить на вопросы типа: «Кто из моих клиентов отправлял 6,4 млн пакетов в секунду на порт 1900?» Для соблюдения конфиденциальности мы рекомендуем собирать образцы трафика с максимальным промежутком выборки: 1 из 64 000 пакетов. Этого достаточно для выявления DDoS-атак, и в то же время сохраняется достаточная конфиденциальность отдельных пользовательских сессий.
- Разработчикам не следует выкатывать свои собственные протоколы UDP, не приняв в расчёт проблемы умножения пакетов. UPnP нужно нормально стандартизировать и изучить.
- Конечным пользователям рекомендуется запустить скрипт для сканирования своих сетей на предмет устройств с функцией UPnP и подумать, стоит ли разрешать им выход в интернет.
Более того, мы сделали веб-сайт для онлайновой проверки. Зайдите на него, если хотите узнать, есть ли на вашем публичном IP-адресе уязвимые сервисы SSDP:
К сожалению, большинство незащищённых маршрутизаторов, которые использовались в этой атаке, находятся в Китае, России и Аргентине — местах, которые исторически не славятся расторопностью интернет-провайдеров.
Итог
Клиенты Cloudflare полностью защищены от атак SSDP и других атак с умножением класса L3. Эти атаки хорошо отражаются инфраструктурой Cloudflare и не требуют дополнительных действий. Однако увеличение размера SSDP может стать серьёзной проблемой для других пользователей интернета. Мы должны призвать своих интернет-провайдеров запретить IP-спуфинг в своих сетях, включить поддержку BGP flowspec и настроить сбор потока данных в сети (netflow).
Статью подготовили совместно Марек Майковски и Бен Картрайт-Кокс.
Автор: m1rko