Самооборона по-хакерски. Мониторим атаки в радиоэфире

Содержание статьи

  • Деаутентификация
  • Захват PMKID
  • Брутфорс точки доступа
  • WPS
  • Evil Twin
  • WPA Enterprise — GTC downgrade
  • KARMA
  • Заключение

В этой статье мы раз­берем­ся, по каким приз­накам мож­но обна­ружить попыт­ки втор­жения зло­умыш­ленни­ка в бес­про­вод­ные сети. Мы научим­ся выяв­лять все акту­аль­ные ата­ки на Wi-Fi, лишь прос­лушивая ради­оэфир, ведь поч­ти у каж­дой из них есть свои харак­терные осо­бен­ности.

В пер­вой полови­не статьи речь пой­дет об ата­ках, нап­равлен­ных на точ­ки дос­тупа, а во вто­рой — на кли­ентов. Пред­положим, что хакер не сумел про­ник­нуть в твою инфраструк­туру из интерне­та, не начал раз­вивать ата­ки уже внут­ри на уров­не сети и не сумел зах­ватить Active Directory. Но рас­слаб­лять­ся все рав­но рано: если зло­умыш­ленник находит­ся в зоне дей­ствия бес­про­вод­ных сетей, он может про­вес­ти физичес­кую ата­ку. Бес­про­вод­ные сети — это пер­вое, с чем стол­кнет­ся внеш­ний наруши­тель, еще не успевший реали­зовать дру­гие тех­ники, но спо­соб­ный подоб­рать­ся к тво­ему офи­су на близ­кое рас­сто­яние. Не сто­ит недо­оце­нивать эту повер­хность атак, куда более пер­спек­тивную для дос­таточ­но замоти­виро­ван­ного внеш­него зло­умыш­ленни­ка, нежели хорошо защищен­ный периметр в интерне­те.

Ес­ли говорить о защите бес­про­вод­ных сетей, то в ИБ обыч­но при­нято лишь давать рекомен­дации по безопас­ной нас­трой­ке, в то вре­мя как сами ата­ки счи­тают­ся дос­таточ­но бес­шумны­ми. Нес­мотря на то что опре­делен­ные решения Wireless IDS сущес­тву­ют, боль­шая часть из них — это ака­деми­чес­кие подел­ки. Получа­ется дос­таточ­но инте­рес­ная ситу­ация: мы име­ем два перимет­ра — один в циф­ровом прос­транс­тве, защищен­ный вся­чес­кими WAF’ами, SOC’ами и про­чими IDS/IPS, вто­рой в реаль­ном мире — это бес­про­вод­ные сети, которые поч­ти всег­да выходят за кон­тро­лиру­емую зону и при этом никак тол­ком не охра­няют­ся.

В этой статье мы научим­ся чувс­тво­вать «тон­кие энер­гии» и выяв­лять все акту­аль­ные ата­ки на Wi-Fi, прос­лушивая ради­оэфир. Все, что нам пот­ребу­ется, — это обыч­ная сетевая кар­та Wi-Fi и режим монито­ра, фик­сиру­ющий каж­дый бес­про­вод­ной пакет. В ито­ге мы сде­лаем ни мно­го ни мало бес­про­вод­ной анти­вирус (Wireless IDS).

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

 

Деаутентификация

Нач­нем с самой рас­простра­нен­ной и прос­той ата­ки — деаутен­тифика­ции, ведь зна­ют про эту ата­ку, пожалуй, все хакеры. Ата­ка при­меня­ется на сети WPA PSK (самые рас­простра­нен­ные сегод­ня) и зак­люча­ется в одновре­мен­ном отклю­чении точ­ки дос­тупа и кли­ентов друг от дру­га. Дос­тига­ется это за счет отправ­ки спе­циаль­ных пакетов в обе сто­роны от име­ни и точ­ки дос­тупа, и кли­ентов. Это при­водит к тому, что кли­ент, на деле не собирав­ший­ся отклю­чать­ся от точ­ки дос­тупа, пов­торно отправ­ляет хеш пароля (handshake) во вто­ром сооб­щении EAPOL.

Пос­ледова­тель­ность отправ­ки пакетов пос­ле деаутен­тифика­ции WPA PSK

Для хакера handshake пред­став­ляет боль­шой инте­рес, ведь с его помощью он смо­жет выпол­нить ата­ку под­бора пароля по сло­варю на дос­таточ­но высоких ско­рос­тях (мил­лионы в секун­ду).

Ата­ку деаутен­тифика­ции нель­зя наз­вать такой уж бес­шумной, ведь при ее про­веде­нии стра­дают кли­енты. У поль­зовате­лей бес­про­вод­ной сети будет отва­ливать­ся под­клю­чение. Впро­чем, далеко не каж­дый рас­позна­ет в этом имен­но факт ата­ки, к тому же отклю­чение может длить­ся край­не неп­родол­житель­ное вре­мя. И заяв­ка о проб­лемах с Wi-Fi пой­дет ско­рее в отдел экс­плу­ата­ции, чем в отдел безопас­ности. Одна­ко, прос­лушивая ради­оэфир, мы лег­ко можем выяв­лять такие ата­ки по отправ­ке пакетов деаутен­тифика­ции сра­зу от двух сто­рон:

defence/wifi/deauth.py#!/usr/bin/python3from scapy.all import *from sys import argvfrom os import systemiface = argv[1]conf.verb = 0alerts = []def alert(src, dst, signal, essid): if src in alerts and dst in alerts: return print(f'[!] WPA handshake deauth detected: "{essid}" {src} <-x-> {dst} {signal}dBm') system("zenity --warning --title='PMKID gathering detected' --text='WPA handshake deauth detected' &") #system("echo 'WPA handshake deauth detected' | festival --tts --language english") alerts.append(src) alerts.append(dst)aps = {}deauths = {}def parse_raw_80211(p): signal = int(p[RadioTap].dBm_AntSignal or 0) if hasattr(p[RadioTap], "dBm_AntSignal") else 0 freq = p[RadioTap].ChannelFrequency if hasattr(p[RadioTap], "ChannelFrequency") else 0 if Dot11Beacon in p: # Beacon ap = p[Dot11].addr2 essid = str(p[Dot11Elt].info, "utf-8") if not ap in aps: aps[ap] = {"essid": essid} if Dot11Deauth in p: ap = p[Dot11].addr3 src = p[Dot11].addr2 dst = p[Dot11].addr1 if ap == src: print(f"[*] deauth {src} -> {dst}") elif ap == dst: print(f"[*] deauth {dst} <- {src}") deauths[src] = dst if deauths.get(dst) == src: alert(src, dst, signal, aps.get(ap,{}).get("essid"))sniff(iface=iface, prn=parse_raw_80211, store=0)

Ха­кер заходит в кафе непода­леку и запус­кает деаутен­тифика­цию, что­бы пой­мать хеши и потом подоб­рать пароль к ним.

Ха­кер про­водит ата­ку деаутен­тифика­ции и зах­вата handshake

А мы сра­зу же видим его активность.

Де­тект ата­ки деаутен­тифика­ции

Уро­вень сиг­нала поз­волит нам даже понять, нас­коль­ко близ­ко подоб­рался к нам хакер: -30dBm озна­чает, что он фак­тичес­ки сидит нап­ротив нас.

 

Захват PMKID

Для пок­рытия боль­шой тер­ритории кор­поратив­ные бес­про­вод­ные сети час­то исполь­зуют мно­жес­тво точек дос­тупа с иден­тичным име­нем. Это обес­печива­ет бес­шовное перек­лючение для сот­рудни­ков, ког­да те перехо­дят из зоны обслу­жива­ния одной точ­ки дос­тупа в дру­гую. На таких точ­ках дос­тупа при аутен­тифика­ции в пер­вом сооб­щении EAPOL M1 час­то содер­жится хеш (PMKID), прак­тичес­ки такой же, как handshake.

Пос­ледова­тель­ность отправ­ки пакетов для PMKID

Тут при­меча­тель­но то, что хеш переда­ется самой точ­кой дос­тупа, что дела­ет воз­можным зах­ват хеша и под­бор пароля без вза­имо­дей­ствия с кли­ента­ми.

Ха­керы и пен­тесте­ры очень любят эту ата­ку еще и за то, что она про­водит­ся дос­таточ­но быс­тро и бес­шумно и не при­водит к негатив­ным пос­ледс­тви­ям. Одна­ко в ее реали­зации есть одна осо­бен­ность, которая поможет нам выявить эту ата­ку.

При любой попыт­ке аутен­тифика­ции на точ­ке дос­тупа WPA PSK кли­ент всег­да отправ­ляет пакет EAPOL M2, услы­шав M1.

Пос­ледова­тель­ность отправ­ки пакетов легитим­ным кли­ентом при аутен­тифика­ции WPA PSK

И это нор­маль­ное поведе­ние. Для хакера попыт­ка зах­вата PMKID подоб­ным обра­зом при­ведет к нежела­тель­ному зах­вату half-handshake (EAPOL M2). И некото­рые хакер­ские ути­литы (нап­ример, Aircrack-ng) не уме­ют работать с PMKID (EAPOL M1) при зах­вачен­ном handshake (EAPOL M2). Поэто­му спе­циали­зиро­ван­ное хакер­ское ПО (ска­жем, hcxdumptool или bettercap) для зах­вата PMKID ведет себя нехарак­терно для типич­ного кли­ента, то есть не отправ­ляет M2 пос­ле под­клю­чения к точ­ке дос­тупа WPA PSK.

Пос­ледова­тель­ность отправ­ки пакетов хакер­ским ПО при зах­вате PMKID

Имен­но тут мы и можем пой­мать неуло­вимо­го хакера:

defence/wifi/pmkid.py#!/usr/bin/python3from scapy.all import *from threading import Threadfrom time import sleepfrom sys import argvfrom os import systemiface = argv[1]conf.verb = 0alerts = []def alert(client, essid): global aps, clients if client in alerts and essid in alerts: return print(f'[!] PMKID gathering detected: {client} {clients.get(client,{}).get("signal","-")}dBm to {essid}') system("zenity --warning --title='PMKID gathering detected' --text='PMKID gathering detected' &") #system("echo 'PMKID gathering detected' | festival --tts --language english") alerts.append(client) alerts.append(essid)aps = {}clients = {}def parse_raw_80211(p): signal = int(p[RadioTap].dBm_AntSignal or 0) if hasattr(p[RadioTap], "dBm_AntSignal") else 0 freq = p[RadioTap].ChannelFrequency if hasattr(p[RadioTap], "ChannelFrequency") else 0 if Dot11Beacon in p: # Beacon ap = p[Dot11].addr2 essid = str(p[Dot11Elt].info, "utf-8") if not ap in aps: aps[ap] = {"essid": essid, "m1":set(), "m2": set()} elif Dot11AssoReq in p: # Association req print("assoc %s -> %s" % (p[Dot11].addr2, p[Dot11].addr3)) clients[p[Dot11].addr2] = {"signal": signal} elif EAPOL in p and p[Dot11].addr3 in aps: #print("EAPOL") ap = p[Dot11].addr3 if p[Dot11].addr2 == ap: aps[ap]["m1"].add(p[Dot11].addr1) print('M1 %s <- %s' % (p[Dot11].addr1, ap)) elif p[Dot11].addr1 == ap: aps[ap]["m2"].add(p[Dot11].addr2) print('M2 %s -> %s' % (p[Dot11].addr1, ap)) #print(aps[ap])def analyze(): while True: for ap in aps.copy(): for client in aps[ap]["m1"] - aps[ap]["m2"]: alert(client, aps[ap]["essid"]) sleep(1)Thread(target=analyze, args=()).start()sniff(iface=iface, prn=parse_raw_80211, store=0)

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *