Как IPv6 помогает роутеры ломать
ПредисловиеПроснулся я сегодня с мыслью, что огромное количество инструкций по настройке NAT советуют использовать строку вида: iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE Многие понимают проблемы этой конструкции, и советуют добавлять: iptables -A FORWARD -i ppp0 -o eth1 -m state --state ESTABLISHED, RELATED -j ACCEPT Но, зачастую, забывают задать таблице FORWARD действие REJECT по умолчанию, или добавить правило REJECT в конец таблицы.На первый взгляд, вроде бы, все кажется нормальным. Однако, это далеко не так. Дело в том, что если не запретить маршрутизировать трафик из WAN-порта в WAN-порт, кто-нибудь из вашей WAN-сети (предположим, что провайдер садит весь подъезд в одну /24) может маршрутизировать трафик через вас, просто прописав ваш IP в качестве шлюза. Все современные SOHO роутеры это учитывают, а вот неопытный администратор, который делает роутер под обычным linux, может не знать или забыть об этом. В подсети моего провайдера таких роутеров не оказалось, и мой план по захвату мира провалился. Однако, статья совсем не об этом.Магические двоеточия Как вы, может быть, знаете, многие современные программы и сервисы биндятся на IP: (два двоеточия), а не на 0.0.0.0, как было раньше. IPv6 адрес :: значит то же самое, что и IPv4 0.0.0.0, т.е. «слушаем все интерфейсы». Многие считают, что если программа слушает ::, то этот сокет может принимать только IPv6-соединения, однако это далеко не так.В IPv6 есть так называемое отображение IPv4-адресов в IPv6 диапазон. Если программа слушает сокет ::, а к ней обращаются из IPv4-адреса 1.2.3.4, то программа получит соединение с адреса :: ffff:1.2.3.4. Этого можно избежать, сделав: sysctl -w net.ipv6.bindv6only=1 Но это нужно далеко не всегда, т.к. обычно удобно, что программа слушает один сокет, а получать соединения может по двум протоколам сразу. Практически во всех дистрибутивах, IPv6-сокеты ведут себя именно так, т.е. bindv6only=0.ff80 и его друг ff02 Если вы не застряли в 90-х, вы гарантированно сталкивались с IPv6, сами того не зная. Абсолютно во всех современных операционных системах по умолчанию включена поддержка IPv6, а это значит, что на каждый (кроме редких исключений) интерфейс автоматически назначается IPv6 Link-Local адрес, который начинается с ff80::. Более того, в некоторых случаях этот адрес получается просто путем кодирования MAC-адреса.Казалось бы, найти Link-Local адреса должно быть проблематично, они же все-таки длинные и страшные, но тут нам на помощь приходит мультикаст-диапазон ff02::.Есть такой классный адрес: ff02::1. Если его попинговать (обязательно с указанием интерфейса, т.к. это Link Local адрес), то откликнутся все компьютеры в сети:
% ping6 ff02::1%enp4s0 PING ff02::1%enp4s0(ff02::1) 56 data bytes 64 bytes from fe80::21f: d0ff: fea2:46a3: icmp_seq=1 ttl=64 time=0.056 ms 64 bytes from fe80:: fe8b:97ff: fe66:9100: icmp_seq=1 ttl=64 time=1.60 ms (DUP!) 64 bytes from fe80::226:9eff: fe6d:22a0: icmp_seq=1 ttl=64 time=1.62 ms (DUP!) 64 bytes from fe80:: f2de: f1ff: fe27:3685: icmp_seq=1 ttl=64 time=1.70 ms (DUP!) 64 bytes from fe80::62a4:4cff: fe7b:1c90: icmp_seq=1 ttl=64 time=2.95 ms (DUP!) 64 bytes from fe80:: fac0:91ff: fe32:5bbe: icmp_seq=1 ttl=64 time=3.02 ms (DUP!) 64 bytes from fe80::226:18ff: fe9e:4b3a: icmp_seq=1 ttl=64 time=3.09 ms (DUP!) 64 bytes from fe80:: ba70: f4ff: fe8b:8dda: icmp_seq=1 ttl=64 time=3.14 ms (DUP!) 64 bytes from fe80::62a4:4cff: fea2: aee0: icmp_seq=1 ttl=64 time=3.27 ms (DUP!) 64 bytes from fe80::224:54ff: fedb: d17d: icmp_seq=1 ttl=64 time=3.93 ms (DUP!) 64 bytes from fe80::2a1: b0ff: fe40:904: icmp_seq=1 ttl=64 time=4.21 ms (DUP!) 64 bytes from fe80::76d0:2bff: fe69:31d8: icmp_seq=1 ttl=64 time=6.09 ms (DUP!) Как мы видим, откликнулось 11 устройств. Кстати, этот адрес очень удобно использовать, если у вас, например, сервер настроен на получение адреса через DHCP, а DHCP упал, или если вы напрямую подключились к порту сервера, а DHCP поднимать не хочется. Вам остается просто зайти по fe80-адресу по ssh.Если попинговать адрес ff02::2, то откликнутся все IPv6-роутеры в сети. К сожалению, в моем случае таких не было.
Сканируем роутеры Я решил просканировать эти адреса через nmap, и вот что вышло: % nmap -6 -T4 --open -n -iL list.txt Скрытый текст Starting Nmap 6.46 (http://nmap.org) at 2014–06–07 16:53 MSK Nmap scan report for fe80:: f2de: f1ff: fe27:3685 Host is up (0.0014s latency). Not shown: 999 closed ports PORT STATE SERVICE 53/tcp open domain
Nmap scan report for fe80:: fe8b:97ff: fe66:9100 Host is up (0.0012s latency). Not shown: 998 closed ports PORT STATE SERVICE 53/tcp open domain 80/tcp open http
Nmap scan report for fe80::226:9eff: fe6d:22a0 Host is up (0.0012s latency). Not shown: 998 closed ports PORT STATE SERVICE 53/tcp open domain 80/tcp open http
Nmap scan report for fe80::62a4:4cff: fea2: aee0 Host is up (0.00099s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap scan report for fe80::226:18ff: fe9e:4b3a Host is up (0.00094s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap scan report for fe80::62a4:4cff: fe7b:1c90 Host is up (0.00085s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap scan report for fe80::76d0:2bff: fe69:31d8 Host is up (0.00072s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap scan report for fe80:: fac0:91ff: fe32:5bbe Host is up (0.00037s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap scan report for fe80:: ba70: f4ff: fe8b:8dda Host is up (0.00059s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap scan report for fe80::2a1: b0ff: fe40:904 Host is up (0.00077s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap scan report for fe80::224:54ff: fedb: d17d Host is up (0.0012s latency). Not shown: 999 closed ports PORT STATE SERVICE 23/tcp open telnet
Nmap done: 11 IP addresses (11 hosts up) scanned in 4.04 seconds По IPv4 все эти порты закрыты.Как мы видим, у многих роутеров открыт Telnet, веб-интерфейс и DNS извне по IPv6.Что же это значит? Все просто — разработчики прошивки роутера просто-напросто забыли про IPv6.Роутеры с открытым telnet:
ASUS RT-N10 (2.0.3.2) ASUS RT-G32 ASUS RT-G32.C1 (2.0.2.6) Upvel UR-312N4G Роутеры с открытым веб-интерфейсом: D-Link DIR-615 (E4, 5.11NV) D-Link DIR-615 (E4, 5.11RU) На многих из них были стандартные пароли admin/admin.На большинстве этих роутеров ip6tables (iptables для IPv6) просто отсутствовал. Разработчики должны были либо вообще отключить поддержку IPv6 в ядре, либо убедиться, что http и telnet демоны слушают 0.0.0.0, а не: но, по какой-то причине не стали этого делать.
А что, если…? Если бы на роутере был каким-то образом настроен IPv6, и, соответственно, включена маршрутизация IPv6 пакетов (net.ipv6.conf.all.forwarding=1), а ip6tables либо вообще не настроен, либо настроен неправильно, то можно было бы точно так же, как в случае с IPv6, маршрутизировать пакеты через этот роутер, а учитывая отображение IPv4-адресов в IPv6, можно было бы маршрутизировать и IPv4 пакеты через Link-Local IPv6 адрес.Заключение Некоторым компаниям я уже отправил письма об этих уязвимостях, а некоторым еще не успел. В любом случае, письма будут отправлены всем.Используйте IPv6, не забывайте о нем.P.S. Для меня стало неожиданностью, что браузеры не умеют открывать адреса с указанием интерфейса. У меня никак не получилось открыть ссылку вида http://[fe80:: a: b: c: d%enp4s0] во всех браузерах. Говорят, что знак процента нужно экранировать, т.е. http://[fe80:: a: b: c: d%25enp4s0], но у меня и так не вышло. Пришлось использовать проброс портов.