Eötvös Loránd Tudományegyetem Természettudományi Kar Marosvári Ágnes A Wi-Fi titkosítás matematikai alapjai Szakdolgozat Matematika BSc Témavezető: Szabó István Valószínűségelméleti és Statisztika Tanszék Budapest, 2019
Tartalomjegyzék 1. Bevezetés 2 1.1. Vezeték nélküli helyi hálózat.......................... 2 1.2. Használt rövidítések............................... 3 2. Wired Equivalent Privacy 4 2.1. A protokollról................................... 4 2.2. Az RC4-hez nem kapcsolódó gyengeségei.................. 5 2.3. A Klein-féle támadás.............................. 8 3. Wi-Fi Protected Access 14 3.1. Működése..................................... 14 3.2. A Beck- és Tews-féle támadás......................... 19 4. Wi-Fi Protected Access II 23 4.1. Mi változott a WPA-hoz képest?........................ 23 4.2. A KRACK-támadás............................... 26 1
1. fejezet Bevezetés A dolgozat középpontjában álló technológiát senkinek nem kell bemutatnom: a Wi-Fi használata széleskörben elterjedt, akár otthoni, munkahelyi vagy akár nyilvános Wi-Fire gondolunk. De vajon mennyire biztonságos a használata? Vezetékes hálózat esetén a fizikai hozzáférés szükségessége elegendő biztonságot ad, viszont a vezetéknélküliségnek nagy hátránya, hogy az ilyen módon küldött üzenetekhez nemcsak az férhet hozzá, akinek szánták, hanem bárki, aki elég közel tartózkodik. Emiatt az üzenetek titkosítására van szükség. Dolgozatom célja, hogy bemutassam, hogyan fejlődtek a titkosítást ellátó protokollok, és hogy megindokoljam, miért volt szükséges a korábban használtak lecserélése. Három megoldásról lesz szó: a WEP, WPA és WPA2 mindegyikének egy-egy fejezetet dedikáltam, amelyekben először mindig [1] és [2] alapján felvázolom a működésüket, majd bemutatom, milyen sebezhetőségeik vannak. Támadás alatt csak a külső, a hálózathoz nem csatlakozó támadó próbálkozásait értem, ezek közül is csak azokat, ahol a brute force-nál gyorsabb eljárást alkalmaz. A hitelesített, csatlakoztatott kliensek, azaz akik rendelkeznek a titkos kulccsal vagy kulcsokkal, természetesen támadhatják egymást sikerrel, de ezt nem szokás gyengeségnek tekinteni. A dolgozat inkább elméleti jellegű, már amennyire ezt egy ennyire gyakorlatias téma engedi. Az itt szereplő protokollokat absztrakt módon fogom leírni, és az ezek ellen irányuló támadásoknál se a konkrét informatikai megvalósítás leírására fogok törekedni, hanem az ötletek magas szinten való bemutatására. Ettől függetlenül minden, ami a dolgozatban szerepel, nemcsak elméleti síkon érdekes, hanem a való életben is használható. 1.1. Vezeték nélküli helyi hálózat A WLAN technológia kettő vagy több eszköz összekötését, együttműködését teszi lehetővé vezeték nélküli módon. Az interoperabilitáshoz, a gördülékeny működéshez szükség van egy szabályrendszerre, amely a kereteket definiálja. Ma már a vezeték nélküli háló- 2
zatok túlnyomó többsége az IEEE nemzetközi szervezet által kiadott 802.11 szabványon és annak kiegészítésein alapul. Amennyiben egy gyártó szeretné, hogy egy terméke megkapja a Wi-Fi Certified jelzőt, teszteltetnie kell azt. Ezt nem az IEEE, hanem egy másik szervezet, a Wi-Fi Alliance végzi. A teszt részben a szabványnak való megfelelést méri, részben pedig a más Wi-Fi Certified eszközökkel való együttműkődési képességet. Az IEEE 802.11 kétféle működési módot támogat: Ad-hoc: nincs központi elem, a kliensek közvetlenül kommunikálnak. Infrastructure: a kliensek (ezeket STA-val fogom jelölni) csak közvetve tudnak kommunikálni, ezt egy csatlakozási ponton (AP) keresztül teszik meg. Ez utóbbi az elterjedtebb, így a dolgozatban csak ilyenekre koncentrálok. 1.2. Használt rövidítések AES AP ARP CCMP CRC EAPOL GMK GTK IEEE ICV IV MIC MPDU MSDU QoS PMK PTK RSN STA TKIP TSC WEP WLAN WPA Advanced Encryption Standard Access Point Address Resolution Protocol Counter Mode Cipher Block Chaining Message Authentication Code Protocol Cyclic Redundancy Check Extensible Authentication Protocol over LAN Group Master Key Group Temporal Key Institute of Electrical and Electronics Engineers Integrity Check Value Initialization Vector Message Integrity Code MAC Protocol Data Unit MAC Service Data Unit Quality of Service Pairwise Master Key Pairwise Transient Key Robust Security Network Station Temporal Key Integrity Protocol TKIP Sequence Counter Wired Equivalent Privacy Wireless Local Area Network Wi-Fi Protected Access 3
2. fejezet Wired Equivalent Privacy 2.1. A protokollról A Wired Equivalent Privacy (WEP) protokoll, ahogy a neve is utal rá, a vezetékes hálózatokéval egyenértékű védelmet hivatott biztosítani. A titkosítás a hálózat RK (root key) kulcsával történik, amely WEP esetén 40 vagy 104 bites lehet. Elvileg lehetséges lenne, hogy az AP több kulcsot is fenntartson, hogy a különböző STA-k kommunikációjának titkosítása elkülönüljön, de a kulcsmenedzsment egyszerűsítése érdekében a gyakorlatban szinte mindig csak egy titkos kulcs van. Maga a titkosítás a következőképpen történik: 1. Tegyük fel, hogy STA egy már hitelesített, a hálózathoz csatlakozó kliens, és üzenetet szeretne küldeni az AP-nek, M-et. Ehhez választ egy 24 bites inicializációs vektort (IV), és ebből elkészíti a csomag kulcsát: IV-t és RK-t összefűzi (IV RK). 2. Kiszámolja a csomag sértetlenségét garantáló 4 byte hosszú ellenőrző összeget (Integrity Check Value - ICV), és M-hez kapcsolja. 3. Az IV RK kulcsból az RC4 folyamkódoló segítségével előállít egy megfelelő hosszú véletlen sorozatot, és a csomaghoz XOR-olva (jelölés: ) előállítja C-t. 4. C és IV (utóbbi nyíltan) átvitelre kerül, néhány további, de a titkosítás szempontjából nem lényeges mezővel kiegészítve (például a feladóra és a címzettre vonatkozó információk). Az üzenet dekódolását az AP ehhez hasonlóan hajtja végre. IV RK ismeretében elő tudja állítani az X folyamot, amelyet C-hez XOR-olva visszakapja M-et, hiszen az XOR művelet önmaga inverze. Ezek után kiszámolja az üzenet ICV-jét, ha ez egyezik az üzenethez kapcsolt értékkel, akkor ezzel meggyőződött arról, hogy M nem sérült az átvitel folyamán. 4
2.1. ábra. WEP 2.2. Az RC4-hez nem kapcsolódó gyengeségei Megjegyzés. Nem mehetünk el megjegyzés nélkül amellett, hogy ez az eljárás ma már teljesen elavultnak számít, sőt egyáltalán nem ajánlott a használata, így jogos kritika lenne, hogy mi értelme van még foglalkozni vele. Egyrészt remek példa a rossz protokolltervezésre, és lehetőséget ad arra, hogy listába szedjem, mely követelményeknek kell ahhoz teljesülnie, hogy biztonságosnak mondhassunk egy ilyen protokollt. Ezt [5]-t felhasználva teszem meg. Másrészt [12] statisztika szerint a Wi-Fi hálózatok kicsivel több, mint 6%-át ma is a WEP védi, ami a több, mint félmilliárd Wi-Fi hálózatot számon tartó adatbázisban egy igencsak jelentős szám. Hitelesítés Ennek célja, hogy az AP igazolja kilétét az STA felé, és viszont. Itt az első iránnyal nem is kell külön foglalkoznunk - a protokollban ugyanis nincs olyan lépés, ahol a csatlakozó STA megbizonyosodhatna, hogy ténylegesen a jó AP-vel kommunikál, mivel az nem hitelesíti magát. A másik irány kétféleképpen történhet: nyílt mód esetén nem szükséges az STA-nak sem hitelesítenie magát. A másik eljárás egy kihívás-válasz alapú hitelesítés, amely négy lépésből áll: 1. Az STA küld egy csatlakozási kérelmet az AP felé. 2. Az AP generál egy véletlen 128 byte-os stringet, és azt titkosítás nélkül, nyíltan küldi vissza. 3. Az STA a titkos kulcs (és egy tetszőleges IV) segítségével inicializálja a folyamkódolót, és titkosítja a stringet, majd ezt és az IV-t (utóbbit nyíltan) visszaküldi AP-nek. 5
4. Az AP dekódolja az üzenetet, ha visszakapja az általa generált stringet, akkor megbizonyosodik, hogy a másik birtokában van a titkos kulcsnak, és elfogadja, hogy az STA az, akinek mondja magát. Megjegyzés. A 4. lépésből látszik, hogy bárki kiadhatja magát az AP-nek: küldhet egy sikeres hitelesítést indikáló üzenetet, még ha nincs is a kulcs a birtokában. Ezzel a módszerrel azonban további problémák is vannak: Ugyanazzal a kulccsal történik a hitelesítés, majd utána az üzenetek titkosítása. Ezeknek mindenképpen el kellene különülniük, hogy egy támadó a titkos kulcs megszerzésere tett kísérlete folyamán a protokoll minél kevesebb gyengeségét tudja felhasználni. Csak a csatlakozáskor történik meg, utána már bárki tud az adott MAC-cím nevében üzenetet küldeni. Mivel mindenki ugyanazt a kulcsot használja, így ez lehetőséget ad visszajátszásos támadásra. Ismét felhasználva, hogy az XOR önmaga inverze, ha a támadó lehallgatja a 2. lépésben küldött kihívást (jelöljük M-mel), és az arra adott választ (M X, illetve az IV), akkor a kettőt XOR-olva: M M X = X-hez és az ehhez tartozó IV-hez jut hozzá. Ezentúl bármely kihívásra helyesen tud válaszolni (hiszen ő választja az IV-t), továbbá a birtokába jutott X folyam-iv párt a kulcs megszerzésére indított támadásban is fel tudja használni. Összeségében tehát nem jelent nagyobb biztonságot, ha az utóbbi módot használjuk, sőt talán még jobb is a nyílt, hiszen ekkor a támadó nem jut kulcsról szóló információhoz. Hozzáférés-vezérlés A hitelesítés csak arra jó, hogy megállapítható legyen a csatlakozni kívánó STA kiléte, ezek után még el kell dönteni, hogy az illető valóban csatlakozhat-e a hálózathoz. Az, hogy ez a gyakorlatban hogyan történjen, nem volt pontosan definiálva az eredeti IEEE 802.11 szabványban. Mivel a kommunkáció során a különböző eszközök azonosítása a MAC-címmel történik, így az elterjedt megoldás egy barátságos MAC-címek listájának létrehozása volt. Az a probléma ezzel, hogy bár egy MAC-cím elvileg egyedi, egy eszköz címe könnyen megváltoztatható, és így más nevében is kommunikálhatunk az AP-vel. Visszajátszás A visszajátszásos támadás lényege, hogy egy korábban küldött és érvényes, de a támadó által lehallgatott üzenetet a támadó visszajátszik az áldozatának egy későbbi időpontban. A WEP protokoll semmifajta eljárást nem tartalmaz, amely ezt detektálná. Egy üzenet bármennyiszer visszajátszható, nincsen olyan érték hozzákapcsolva, amely 6
alapján a fogadó fél ellenőrizhetné az eredeti küldés időpontját. Gyakorlatilag ez az egyetlen pontja a WEP-nek, amelyre azt mondhatjuk, hogy nincs feltörve, de sajnos csak amiatt, mert nem volt mit. A tervezők valamiért úgy döntöttek, nem szükséges, hogy bármit is implementáljanak, amely megakadályozna ilyen típusú támadásokat. Sértetlenség Honnan tudhatja az üzenet címzettje, hogy a továbbítás folyamán az üzenet nem változott meg valami hibának vagy akár aktív támadásnak köszönhetően? Ezt az ICV hivatott garantálni, amely még a titkosítás előtt van hozzákapcsolva az üzenethez. WEP esetén ez a szám az üzenetre számolt CRC-32-érték, amelynek fontos tulajdonsága, hogy lineáris az XOR műveletre nézve: CRC(M 1 M 2 ) = CRC(M 1 ) CRC(M 2 ). Nézzük meg, hogy a támadó hogyan tudja úgy módosítani az üzenetet, hogy továbbra is stimmeljen az ICV; jelölje M a nyílt üzenetet, M a változtatást, továbbá X az RC4 által előállított folyamot. A támadó az (M CRC(M)) X üzenetet fogta el, és szeretné ebből előállítani (M M CRC(M M )) X üzenetet úgy, hogy nem ismeri a titkos kulcsot, tehát X-et sem. Könnyű dolga van: M CRC(M )-t ki tudja számolni, és ezt az elfogott üzenethez XOR-olva kész is van, ugyanis: ((M CRC(M)) X) (M CRC(M )) = (M M CRC(M) CRC(M )) X = (M M CRC(M M )) X, ahol az első lépésben az XOR műveleti tulajdonságait használjuk ki, majd pedig a fent említett linearitást. Titkosítás Folyamkódoló használata esetén a kulcsok ismétlődését tanácsos elkerülni. Az RC4 ránézésre egy random sorozatot állít elő, de természetesen determinisztikus: azonos kulcs esetén ugyanaz a sorozat fog előállni. Legyenek M 1 és M 2 olyan üzenetek, amelyeket azonos folyamot használva titkosítottunk. Ha a két üzenetet XOR-oljuk: (M 1 X) (M 2 X) = M 1 M 2, a kapott eredmény már egyáltalán nem véletlenszerű, így akár gyakoriságelemzésbe kezdhetünk. Ennyi gyengeség felsorolása után talán már nem meglepő, de a WEP-ben ez a hiba is jelen van. Az IV 3 byte hosszú, így összesen 2 24 17 millió különböző folyam lehetséges. Ezt akár egyetlen kliens is ki tudja meríteni néhány óra alatt. 7
2.3. A Klein-féle támadás Az előző alfejezetben már szerepelt jó néhány kriptográfiai gyengeség, ezek azonban mind eltörpülnek a legkomolyabb problémához képest: egy WEP protokoll által védett hálózat titkos kulcsa percek alatt feltörhető a kulcs bonyolultságától függetlenül. Számos támadásból lehetne itt választani, én a Klein-féle mellett döntöttem, amelynek elméleti hátterét [6]-ból vettem, az ötlet gyakorlati felhasználását pedig [4] alapján mutatom be. Ez a módszer karakterenként töri fel a kulcsot, ehhez mindig a kulcs megelőző karaktereit, illetve a PRGA által generált folyam egy karakterét használja. Ez azt jelenti, hogy a végrehajtásához szükséges, hogy elegendő számú IV-X párt álljon rendelkezésre. Ilyenek szerzése egy módszer [3]-ban található, ezt az ötletet röviden a következőképpen foglalhatjuk össze. Bittau-féle támadás A protokoll megengedi az üzenetek több részre tördelését, sőt azt is, hogy ezek titkosítása ugyanazzal a folyammal, azaz ugyanazt az IV-t használva történjen. Tegyük fel, hogy a támadó rendelkezésére áll egy IV és a hozzátartozó m hosszú véletlen X folyam, ezt például egy kihívás-válasz alapú hitelesítés lehallgatásával, vagy egy üzenet tartalmának megtippelésével szerezhette meg. Mivel az ICV 4 byte-os, így tud küldeni 16 darab m 4 hosszú üzenetet az AP-nek. Ha ez egy broadcast üzenet (azaz egy olyan üzenet, amelyet a hálózat többi STA-jának szán), akkor az AP a tördelt üzenet összeállítja egy darab 16(m 4) hosszú üzenetté, és egy új IV-vel elküldi a többieknek - a támadó máris megszerzett egy 16(m 4) + 4 hosszú X folyamot, hiszen ismeri az eredeti üzenet tartalmát. Ezt elég sokáig folytatva egy idő után bármilyen hosszú üzenetet fog tudni küldeni (a kulcs ismerete nélkül is), de akár szótárat is építhet az IV-X párokból. A szótár segítségével lehallgathatja mások üzeneteit, vagy pedig ha már elég hosszú a szótár, végrehajthatja a Klein-féle támadást. Az RC4 leírása Az RC4 egy olyan folyamkódoló, amelynek két része van: a Key Scheduling Algorithm (KSA), amely az RK kulcsot használva előállítja {0,..., n 1} egy véletlen permutációját, és a Pseudo Random Generator Algorithm (PRGA), amely a KSA által előállított permutációt használva visszaad egy véletlen byte-ot. WEP esetén n = 256, továbbá a titkosítás folyamán a PRGA-t annyiszor futtatjuk, ahány byte az XOR-oláshoz kell. Az egyszerűség kedvéért a továbbiakban úgy fogunk tekinteni az algoritmusra, mintha S aktuális állapota, illetve j értéke egyenletes eloszlást követne. Ez a valóságban nem teljesen van így, de ez megfelelő közelítés ahhoz, hogy sikeres támadást lehessen rá építeni. 8
RC4-KSA 1: for i 0 to n 1 do 2: S[i] i 3: end for 4: j 0 5: for i 0 to n 1 do 6: j j + S[i] + K [i mod len(k )] 7: csere(s[i], S[j]) 8: end for 9: i 0 10: j 0 RC4-PRGA 1: i i + 1 2: j j + S[i] 3: csere(s[i], S[j]) 4: return S[S[i] + S[j]] Az összeadások elvégzése értelemszerűen úgy történik, hogy ne indexeljünk ki S-ből, azaz modulo n számolunk. A jelölések egyszerűsítése érdekében ezt a továbbiakban is elhagyom. Továbbá S aktuális állapotát a k-adik lépésben S k jelöli, valamint az l-edik előállított véletlen byte X[l] lesz (l = 0, 1,...). A Jenkins-korreláció Az alábbi tétel egy erős kapcsolat létezését mondja ki az ismert i és S[S[i]+S[j]] értékek, illetve az RC4 aktuális belső állapotát leíró ismeretlen j, S[i] és S[j] értékek között. Tétel. Legyen n 2 (n N) és i {0,..., n 1} tetszőleges rögzített index. Ekkor x {0,..., n 1}-re és a 0,..., n 1 számok egy véletlen S permutációjára teljesül: P(S[j] + S[ S[i] + S[j] ] = i S[j] = x) = 2 n. Továbbá c {0,..., n 1}, c i-re: P(S[j] + S[ S[i] + S[j] ] = c S[j] = x) = n 2 n(n 1). Bizonyítás. Mindkét egyenletben S[j] = x-re veszünk feltételt, és mivel j nincs rögzítve, ez az összes lehetséges permutációt jelenti. Egy fokkal nehezebb feladat a metszetekhez tartozó permutációk összeszámlálása, kezdjük az elsővel. Jelölje k az S[i] + S[j] értéket, ekkor az S[j] + S[k] = i állapotokat szeretnénk megszámolni, amelyet átírhatunk k + S[k] = i + S[i] alakra. Két esetünk van: 9
1. i = k Ekkor k +S[k] = i+s[i] triviálisan teljesül, továbbá S[i] = S[k] = i S[j] = i x, így S[i]-t i x-nek kell rögzíteni, és az S többi indexén álló értékeket szabadon megválaszthatjuk (n 1)!-féleképpen. 2. i k S[k]-t i x-nek kell választanunk, és kell még, hogy S[i] = k + S[k] i. k értékét megválaszthatjuk (ez n 1 lehetőség), és az S még üres n 2 indexét is szabadon tölthetjük ki: (n 1)(n 2)! lehetőség. Tehát összesen 2(n 1)! állapot van, amikor S[j] + S[k] = i és S[j] = x, amiből P(S[j] + S[k] = i S[j] = x) = 2(n 1)! n! = 2 n. A második állítás bizonyítása hasonlóan történik, a k + S[k] = c + S[i] állapotokat szeretnénk megszámolni, feltéve, hogy S[j] = x. Itt 3 esetet különböztetünk meg: 1. i = k Ekkor az egyenlet a következő alakot ölti: i + S[i] = c + S[i], amit persze nem lehet kielégíteni, hiszen i c. 2. c = k Ebben az esetben sem állhat fenn az egyenlőség, hiszen a c + S[k] = c + S[i] egyenletből az következne, hogy S[k] = S[i], márpedig k = c i. 3. i k és c k Ebben az esetben kettő indexet kell rögzíteni, hogy a megfelelő feltételek teljesüljenek: S[k] legyen i x és S[i] = k + S[k] c. Ekkor k értékét válaszhatjuk meg (n 2 lehetőség), és a további n 2 szabad indexet. Ez az eset fogja adni az összes olyan állapotot, amely kielégíti a fenti feltételt. Így tehát Ezzel a tételt beláttuk. P(S[j] + S[k] = c S[j] = x) = (n 2)(n 2)! n! = n 2 n(n 1). 10
A támadás Tegyük fel, hogy ismerjük a kulcs első l elemét (K [0],..., K [l 1]), így le tudjuk játszani a KSA első l lépését. Az l + 1-edik lépésben a v = S l [j l + S l [l] + K [l]] értéket cseréljük fel az S l+1 [l] értékkel, vizsgáljuk meg, hogy ezek után, mi történhet. Az i pointer l-et legközelebb pontosan n 2 lépés után fog felvenni, ugyanis a KSA folyamán még tesz n l 1 lépést, majd a PRGA során l 1-et. Így tehát v csak akkor mozdul el, ha j valamikor eltalálja. Itt is feltételezzük, hogy j valóban véletlenszerűen veszi fel értékeit, azaz annak a valószínűsége, hogy az elkövetkező n 2 lépésben az aktuális permutáció l-edik indexe nem lesz módosítva (1 1 n )n 2 (azaz j nem veszi fel az l értéket). Ezt és a Jenkins-korrelációt fogjuk felhasználni a támadás felépítésére. Az alapján, hogy módosul-e az érték azelőtt, hogy i = l ismét, két esetet különböztethetünk meg: 1. S n+l 1 [l] = v Ekkor a Jenkins-korrelációt felhasználva P(v + X[l 1] = l v = S n+l 1 [l]) = 2 n. 2. S n+l 1 [l] v Szintén a Jenkins-korrelációt használva, ekkor a valószínűség így alakul: P(v + X[l 1] = l v S n+l 1 [l]) = n 2 n(n 1). Összességében P(v + X[l 1] = l) = ( 1 1 ) n 2 2 ( ( n n + 1 1 1 ) n 2 ) n 2 n n(n 1). Ha P argumentumában álló kifejezést átalakítjuk, akkor azt kapjuk, hogy a várt 1 n helyett. P(S 1 l [l X[l 1]] (j l + S l [l]) = K [l]) 1, 37 n Megjegyzés. Ez a valószínűség nem függ l-től, hiszen mindig n 2 lépés, mire i ismét felveszi az l értéket. 11
Implementálás Világos, hogy ha a kulcs egy karaktere egy bizonyos értéket a vártnál nagyobb valószínűséggel vesz fel, akkor ez felhasználható egy támadás felépítésére. Mivel az IV nyíltan kerül átvitelre, így az RC4-et inicializáló kulcs (IV RK) első 3 byte-ja mindenképpen ismert. Ezek után minden elfogott üzenet szavaz RK első karakterére, azaz kiszámoljuk az IV ismeretében, hogy a Klein-féle támadás jelöléseit használva S 1 3 [3 X[2]] (j 3+S 3 [3]) mennyi. A legtöbb szavazatot szerző értéket fogjuk RK[0]-nak választani, és folytatjuk a következő karakterrel. Ha a számolás végén esetleg nem a helyes kulcsot kapjuk, korrigálunk: egy lehetséges módszer például az, hogy azon az indexen, ahol az első és a második helyezett között a legkisebb az eltérés, onnantól a második helyezettet választva újraszámolunk. A módszert én is implementáltam C++ nyelven, egy részlet a kódból a következő oldalon található. Egy RC4 titkosítót az azonos nevű osztály ír le, ahol a KSA függvény egy K kulcs segítségével előállítja az S permutációt, a PRGA függvény pedig visszaad egy l + 1 hosszú véletlen sorozatot, továbbá a test függvény a kulcs K [l] karakterére számolt tippet adja vissza. A támadás hatékonyságának tesztelését a következőképpen végeztem: a teszt folyamán a program a kulcsokat és az IV-ket is véletlenszerűen választotta, amelyekből az X folyamokat generatestreams állította elő A rendelkezésre álló folyamok száma 5000-esével nőtt minden körben egészen 100 ezerig, és minden körben 100 kulcsot generáltam. Sikeres kísérletnek csak az számított, ha elsőre eltalálta a program a titkos kulcsot, nem implementáltam a fentebb említett korrekciót. Ez alapján a támadás 50%-os sikeréhez körülbelül 45 ezer IV-X pár kell, a 95%-os sikerhez pedig 70 ezer. Tapasztalataimat a következő grafikonon foglaltam össze. 2.2. ábra. A Klein-féle támadás hatékonysága 12
1 #i n c l u d e <i o s t r e a m > 2 #i n c l u d e <v e c t o r > 3 #i n c l u d e <map> 4 #i n c l u d e <a l g o r i t h m > 5 #i n c l u d e <random> 6 t y p e d e f s t d : : map<s t d : : v e c t o r <i n t >, s t d : : v e c t o r <i n t >> s t r e a m ; 7 c l a s s RC4{ 8 s t d : : v e c t o r <i n t > S ; 9 i n t n ; 10 p u b l i c : 11 RC4 ( i n t n ) ; 12 v o i d KSA ( c o n s t s t d : : v e c t o r <i n t >& K) ; 13 s t d : : v e c t o r <i n t > PRGA( i n t l ) ; 14 i n t t e s t ( i n t l, c o n s t s t d : : v e c t o r <i n t >& testkey, i n t tmp ) ; 15 } ; 16 v o i d g e n e r a t e S t r e a m s ( c o n s t s t d : : v e c t o r <i n t >& K, i n t a v a i l a b l e S t r e a m s, s t r e a m & keystreams ) ; 17 i n t mod ( i n t num, i n t d i v ) ; 18 19 i n t main ( ) { 20 i n t n = 2 5 6 ; 21 i n t a v a i l a b l e S t r e a m s = 45000; 22 s t d : : v e c t o r <i n t > K ; 23 f o r ( i n t k = 0 ; k < 1 3 ; ++k ) {K. push_back ( rand ( ) % n ) ; } 24 s t r e a m keystreams ; 25 g e n e r a t e S t r e a m s ( K, a v a i l a b l e S t r e a m s, keystreams ) ; 26 s t d : : v e c t o r <i n t > t e s t K e y ; 27 f o r ( i n t i = 0 ; i < K. s i z e ( ) ; ++i ) { 28 s t d : : v e c t o r <i n t > v o t e s ( n, 0 ) ; 29 f o r ( c o n s t a u t o & i t : keystreams ) { 30 s t d : : v e c t o r <i n t > testppk ; 31 f o r ( c o n s t a u t o & i t r : i t. f i r s t ) { testppk. push_back ( i t r ) ; } 32 f o r ( c o n s t a u t o & i t r : t e s t K e y ) { testppk. push_back ( i t r ) ; } 33 RC4 t e s t C i p h e r ( n ) ; 34 ++v o t e s [ t e s t C i p h e r. t e s t ( i +3, testppk, mod ( i+3 i t. second [ i +2], n ) ) ] ; 35 } 36 t e s t K e y. push_back ( max_element ( v o t e s. begin ( ), v o t e s. end ( ) ) v o t e s. begin ( ) ) ; 37 } 38 i f ( s t d : : equal ( t e s t K e y. begin ( ), t e s t K e y. end ( ), K. begin ( ) ) ) { 39 s t d : : c o u t << " key f o u n d : " ; 40 f o r ( c o n s t a u t o & i t r : t e s t K e y ) { s t d : : c o u t << i t r << " " ; } 41 s t d : : c o u t << s t d : : e n d l ; 42 } 43 r e t u r n 0 ; 44 } 13
3. fejezet Wi-Fi Protected Access 3.1. Működése A WEP protokoll feltörésével vezeték nélküli hálózatok milliói maradtak védelem nélkül. Az IEEE azonnal elkezdett dolgozni a 802.11 szabvány i jelű kiegészítésén, amely egy új típusú vezeték nélküli hálózatot definiált, az RSN-t (robust security network). Ez teljesen újfajta eszközöket kívánt, a széles körben elterjedt, WEP-et támogató eszközök nem voltak erre alkalmasak. Azt azonban nem lehetett elvárni, hogy egyik napról a másikra az egész világon mindenki lecserélje a saját felépített infrastruktúráját. Ennek, illetve a szabványosítás hosszas folyamatának köszönhetően született egy köztes megoldás, ez lett a Wi-Fi Protected Access (WPA). Ez az RSN-t definiáló -ekkor még csak vázlatos formában létező- szabvány egy részét implementálta, az új titkosítási protokoll a Temporal Key Integrity Protocol (TKIP) lett. A TKIP a WEP köré lett építve, ennek jelentősen megerősített változata, de az igazán jó hír az volt, hogy ennek köszönhetően kompatibilis volt a régi eszközökkel. Kulcsok A WEP legfőbb hibája a gyenge kulcsmenedzsment volt. Általában egyetlen titkos kulcs volt, és a protokoll ezt használta mindenre. Ezt kijavítandó, a WPA egy teljesen új megközelítést vezet be, a kulcsok hierarchiáját. Az AP és az STA-k közötti kommunikációhoz kettő kulcstípusra van szükség: a unicast üzenetekhez páronkénti egyedi kulcsok, amelyek tehát egy darab STA-hoz (és az AP-hez) tartoznak, és csoportkulcsok, amelyek a multi- és broadcast üzeneteket védik. Ez két hierarchiát jelent, amelyeken belül a kulcsokat az alapján fogjuk megkülönböztetni, hogy mire használatosak. Így mindkét esetben lesz egy mesterkulcs (MK), amely nem kerül közvetlenül felhasználásra, illetve lesznek az MK-ból generált további kulcsok. A páronkénti kulcsok esetében MK-t PMK-val fogjuk jelölni, amely kétféleképpen kerülhet a felek a birtokába. Enterprise módban működő hálózat esetén van egy ennek 14
a funkciónak dedikált hitelesítő szerver, amelyre a kliens egy felhasználónév-jelszó pár beírásával léphet be. Ez a szerver bírálja el a csatlakozási kérelmeket, illetve juttattja el biztonságosan a PMK-t mind az STA-nak, mind az AP-nek. A másik mód, amellyel az otthoni vagy kisebb hálózatokon találkozhatunk, az előre megosztott kulcsot várja (pre-shared key - PSK), és lényegében ez lesz a használt PMK. Csoportos kommunikáció esetében a mesterkulcsot (GMK) az AP generálja, és ezt nem osztja meg senkivel, ugyanis nem szükséges, hogy rajta kívül bárki ismerje. Akár Enterprise, akár PSK módban vagyunk, az AP és az STA is meg szeretne győzödni arról, hogy a másik birtokában van a közös titoknak (PMK). A hitelesítés a négyutas kézfogással történik, amelynek azonban nem ez az egyetlen funkciója. Ahogy mindjárt láthatjuk, a kézfogás közben fog létrejönni a 4 128 = 512 bites session key, ennek neve Pairwise Transient Key (PTK), illetve az AP ennek segítségével juttatja el a multiés broadcast üzenetek dekódolásához szükséges kulcsokat a klienseknek, amelyeket együttesen Group Temporal Key-nek (GTK) nevezünk. A PTK egyedi, így egy darab STA-hoz és az AP-hez tartozik, előállításához a PMK, az STA és az AP MAC-címe, illetve kettő darab véletlen generált, egyszer használatos szám (nonce) szükséges. Ez utóbbi azért kell, hogy az STA minden csatlakozásakor más PTK jöjjön létre, hiszen az első három érték (a PMK és a MAC-címek) állandó. A 2 128 = 256 bites GTK előállítása a PTK generálásával konzisztens módon történik: a GMK, az AP MACcíme és egy nonce szükséges hozzá. Ezután mindkét kulcsot feldaraboljuk. A PTK négy darab kulcsra bontható szét: Key Encryption Key (KEK), Key Confirmation Key (KCK), Temporal Key (TK) és Message Integrity Code Key (MIC-kulcs). Az előbbi két kulcs a négyutas kézfogás üzeneteinek titkosítására és sértetlenség-védelmére szolgál, az utóbbi kettő pedig a kézfogás utáni üzenetek esetén lát el hasonló funkciókat. A MIC-kulcs még tovább bomlik, az egyik fele az AP által, a másik fele az STA által küldött csomagok sértetlenségét őrzi. A GTK két részre osztható: az egyik a csoportos üzenetek titkosítására szolgál, a másik pedig ezek sértetlenség-védelmére. A négyutas és a csoportkulcsos kézfogás A négyutas kézfogás tehát több célt is szolgál: a kölcsönös hitelesítést, ahol az AP és az STA is demonstrálja, hogy birtokában van a PMK-nak, a friss PTK-ról való megegyezést, továbbá a GTK eljuttatását az új klienshez. Ahogy a név is utal rá, a folyamat négy darab EAPOL-Key üzenet váltásából áll. 1. Az AP generál egy nonce értéket, ANonce-ot, és elküldi STA-nak titkosítás nélkül. A 3.1 ábrán ezt Msg 1 (r, ANonce) jelöli, ahol r egy számláló, ami az EAPOL üzenetekhez tartozik, és amelyet mindig az AP emel, az STA pedig azonos számlálóval válaszol. 2. Az STA is előállítja a saját SNonce értékét, ekkor ő már rendelkezik az összes 15
szükséges információval, hogy elkészítse a PTK-t. Ezután ő is elküldi a saját SNonce-át AP-nek nyíltan, de most már a KCK segítségével előállítja az üzenet MIC-értékét, és az üzenethez kapcsolja. A MIC egyrészt védi az üzenetet sértetlenségét, ezzel az első lépésben még nem kellett foglalkozni, ha esetleg egy támadó módosítja ANonce-ot, csak a kézfogás sikertelenségét idézheti elő. De ami még fontosabb, bizonyítja, hogy az STA ismeri a PMK-t. 3. Most már az AP is elő tudja állítani a kulcsokat, és a Msg 2 MIC-értékének ellenőrzésével megbizonyosodik arról, hogy az STA rendelkezik a PMK-val. Válaszul elküldi Msg 3 -at, amely tartalmazza a GTK-t titkosítva (a KEK segítségével), továbbá a Msg 2 üzenethez hasonlóan a MIC-értéket. 4. Az STA is leellenőrzi Msg 3 MIC-értékét, ha mindent rendben talál, visszajelez az AP-nek, hogy készen áll a titkosított kommunikációra, és telepíti a kulcsokat. 3.1. ábra. Kézfogások A kézfogás eredményeképpen létrejött egy biztonságos kapcsolat az AP és az STA között, továbbá az újonnan hitelesített kliens a GTK-val titkosított üzeneteket is tudja ezentúl dekódolni. Azonban elképzelhető, hogy a (P/G)TK-t frissíteni kell, sőt tanácsos is frissíteni, hiszen minél tovább használunk egy kulcsot, annál nagyobb esélyt adunk egy támadónak. A PTK újratárgyalása a négyutas kézfogás megismétlésével történik, ekkor a kézfogás üzenetei titkosítva vannak az addig használt kulcs segítségével is. A GTK frissítése viszont sokkal egyszerűbb, az AP és az STA között meglévő biztonságos 16
kapcsolatot vesszük igénybe. Ez szintén EAPOL üzeneteket használva történik, és csak két lépésből áll: 1. Az AP generál a GMK-ból egy új GTK-t, és elküldi az STA-nak. A 3.1 ábrán ezt EncrPT x K {GrMsg 1(r + 2; GT K )} jelöli, ahol Encr PT K azt jelenti, hogy az üzenet TKIP-et (kulcsként a PTK-t) használva lett titkosítva, x pedig arra vonatkozik, hogy ez az x-edik unicast üzenet, amelyet az AP küld ennek az STA-nak. 2. Az STA nyugtázza a frissítést az AP-nak küldött, y IV-t használó üzenetével, és telepíti a kulcsot. Titkosítás Az üzenetek titkosításáért a TKIP felel. Ennek működése a korábban említetteknek megfelelően igencsak hasonló lesz a WEP műkődéséhez. A TKIP szintén az RC4-et használja, de a folyamkódolót inicializáló kulcs előállítása teljesen új. A WEP-nél ez egy 24 bites IV és egy minden üzenetre konstans kulcs összefűzésével történt. Itt a küldő fél egy 48 bites IV-t használ, illetve a 128 bites TK-t, azonban ezek összefűzése egyrészt jóval több bitet eredményezne, mint az a 24+104, amit az RC4 vár, másrészt nem a legjobb megoldás, ahogyan azt már a WEP-nél is láttuk. Ehelyett egy kétfázisú kulcsmixelés történik. A kettő fázis oka az, hogy sok időt venne el, ha minden egyes üzenethez egy teljesen új kulcsot készítene a küldő fél. 3.2. ábra. A kulcsok előállítása Ehelyett az első fázisban veszi az IV első 32 bitjét, a saját MAC-címét és a TK-t, és egy bonyolultabb algoritmussal előállít egy elég sok ideig konstans értéket. Ez az érték csak akkor változik, amikor az IV első 32 bitje, azaz 2 16 üzenet után kell csak újrakalkulálni. A második fázisban pedig ezt a konstans értéket mixeli össze az IV maradék 16 bitjével egy egyszerűbb algoritmust használva, és így áll elő az a kulcs, amely a WEP esetén a root key volt. Végül a feladó a kulcs elejére fűzi az IV azon 16 bitjét, amelyet a második fázisban is használt, kiegészítve a hiányzó 8 bittel (d) úgy, hogy elkerülje egy gyenge kulcs használatát. Ezek olyan kulcsok, amelyek esetén az RC4 által generált folyam első néhány byte-ja kiszámítható, például az FMS-támadás, amely az első olyan 17
publikált támadás volt, amely a WEP-kulcsot törte fel, is erre épített. Egy további probléma a WEP protokollal a visszajátszás detektálásának teljes hiánya volt. Ezt a feladatot itt egy TKIP Sequence Counter (TSC) fogja ellátni. Mivel az IV mérete kétszeresére növekedett, így nem fordulhat elő az IV-tér kimerítése. Ennek megfelelően az IV használható a visszajátszások megakadályozására úgy, hogy a PTK telepítésekor az IV-t 0-ra állítjuk, majd minden elküldött üzenettel 1-gyel nő az értéke. Ha a fogadó fél nem a megfelelő IV-vel kap üzenetet, akkor elutasítja. Végezetül már csak egyetlen problémát kellett megoldani, amely a WEP-et érintette, és ez a gyenge sértetlenség-védelem volt. A küldő fél továbbra is hozzákapcsolja minden átvitelre kerülő csomaghoz annak CRC-32-értékét, viszont minden elküldendő üzenetre számol egy MIC-értéket is a Michael algoritmust és a saját MIC-kulcsát használva. Fontos különbség van aközött, hogy melyik értéket mire számoljuk. A teljes elküldendő üzenetet jelölje MSDU (MAC Service Data Unit), amely elképzelhető, hogy túl nagy ahhoz, hogy egyben átvitelre kerüljön. Ilyenkor felbontjuk kisebb egységekre, ezeket MPDU-nak (MAC Protocol Data Unit) nevezzük. Tehát a MIC az MSDU sértetlenségét védi, az ICV, vagyis a CRC-32-érték pedig az egyes MPDU-két. Fogadáskor a TSC ellenőrzése után a dekódolt üzenetek ICV-inek vizsgálata következik, végül pedig az ekkor már nyílt MPDU-kból összeállított MSDU MIC-értéke kerül tesztelésre. A dekódolás a titkosításhoz hasonlóan történik. Az IV nyíltan kerül átvitelre, így a fogadó fél is elő tudja állítani az RC4 által generált folyamot, amit a kapott csomaghoz XOR-olva a nyílt üzenet áll elő. Összességében tehát a WEP minden gyengeségén javított a TKIP. A protokoll egyszerűsített menete a 3.3 ábrán látható. 3.3. ábra. TKIP 18
3.2. A Beck- és Tews-féle támadás Noha a WPA-TKIP egy sokkal biztonságosabb megoldás, mint a WEP, szintén nem ajánlott a használata. Ennek egyik oka a most következő lehetséges támadási módszer, amely az MSDU-ra számolt MIC-értéket előállító Michael algoritmus gyengeségeit használja ki. Ez volt az egyik első ismert támadás a TKIP ellen, végrehajtása a támadót hozzájuttatja egy AP által használt MIC-kulcshoz. Az alábbi alfejezetet [8] alapján írtam, de az előkészületekhez felhasználtam [4], [6] és [9]-et. Michael Az algoritmus inputként egy 2 32 bit hosszúságú kulcsot vár, illetve olyan üzenetet, amely felbontható 32 méretű blokkokra. Ezt úgy érjük el, hogy az eredeti üzenetet kipótoljuk a megfelelő hosszúságra: a végére fűzünk egy 1 byte hosszú konstans számot (0x5a), majd 4-7 byte-nyi 0-t, attól függően, hogy mikor kapunk megfelelő hosszúságot. Jelölje (K 0, K 1 ) a kulcsot, és M 0, M 1,..., M n 1 a blokkokra bontott üzenetet. Ekkor az algoritmus pszeudokódja a következő: Michael( (K 0, K 1 ), (M 0, M 1,..., M n 1 ) ) 1: (L, R) (K 0, K 1 ) 2: for i 0 to n 1 do 3: L M i 4: (L, R) B(L, R) 5: end for 6: return (L, R) B(L, R) 1: R R (L <<< 17) 2: L (L + R) mod 2 32 3: R R XSWAP(L) 4: L (L + R) mod 2 32 5: R R (L <<< 3) 6: L (L + R) mod 2 32 7: R R (L >>> 2) 8: L (L + R) mod 2 32 9: return (L, R) A B(L, R) függvényben <<< k a bitek balra mozgatását jelenti, ahol a transzformáció közben minden elem k-val mozdul el. Az XSWAP művelet pedig az első 2 byte pozícióját cseréli fel egymással, és hasonlóan jár el az utolsó kettővel is. Ha például L = (1234), akkor XSWAP(L) = (2143). Látható, hogy B nem függ (K 0, K 1 )-től, így triviálisan invertálható: végezzük el a lépéseket fordított sorrendben, mindig az aktuális lépés 19
inverzét véve. Sőt, több is igaz: egy nyílt üzenet és ennek MIC-értéke birtokában (K 0, K 1 ) is megszerezhető. Induljunk ki a MIC-ből, és a Michael algoritmus ciklusában n 1-ről lefelé lépkedve, végezzük el a B -1 műveletet, majd a kapott értékhez XORoljuk a nyílt üzenet soronkövetkező blokkját. A ciklus végén pont (K 0, K 1 )-hez fogunk megérkezni. Ezen gyengeség miatt szükség van ellenintézkedésre: amennyiben az AP valamely MICkulcs ellen irányuló támadást észlel, minden STA-t kiléptet, és csak 60 mp elteltével engedélyezi az újracsatlakozásokat. A támadás észlelése kétféleképpen történhet. Ha az AP-hez 1 percen belül kettő helytelen MIC-értékű üzenetet is beérkezik, vagy pedig ha valamely STA-tól 1 percen belül kettő MIC-hibát indikáló jelentést kap (MIC failure report). A támadás Az alapötlet a következő: először is a támadó olyan üzenetet fog el, amelynek tartalmát nagyjából ismeri. Ezután az ismeretlen byte-okat egyenként levágja az üzenetről, és a maradékot mindig úgy módosítja, hogy az ICV lehetőleg helyes maradjon, majd az AP-t orákulumként használva, eldönti, hogy jól tippelt-e. Ha sikerült az üzenetet megfejteni, invertálja a Michael-algoritmust, ezzel megszerzi az AP egy MIC-kulcsát. A gondolatmenet helyességéhez be kell látnunk, hogy amennyiben a levágott byte értéke ismert, egyértelmű, hogy milyen módosításokat kell eszközölni a rövidített üzeneten. Ezt a CRC-32-érték és az F 2 [x] gyűrű vizsgálatával tesszük meg. Egy bitsorozat felfogható úgy, mint egy F 2 [x]-beli elem, azaz a sorozatban adott helyiértéken álló 0-ra vagy 1-re tekinthetünk úgy, mint egy polinom megfelelő fokú tagjának együtthatójára. Egy üzenetnek a CRC-32-értéke pontosan akkor helyes, ha az üzenet és a CRC-érték összefűzésével kapott P mint polinom kielégíti ezt az egyenletet: 31 P mod P CRC = x i, ahol i=0 P CRC = x 32 + x 26 + x 23 + x 22 + x 16 + x 12 + x 11 + x 10 + x 8 + x 7 + x 5 + x 4 + x 2 + x + 1 irreducibilis polinom F 2 [x] felett, így F 2 [x] / R CRC véges test. Ha most egy byte-tal lerövidítjük P-t, akkor nagy valószínűséggel nem fogja a fenti egyenlőséget kielégíteni, ezért korrigálnunk kell. Írjuk P-t Qx 8 + R alakban, ahol R jelöli az elhagyott byte-ot, Q pedig az üzenet többi részét, ezt szeretnék megváltoztatni, 20
hogy az ellenőrző összeg ismét helyes legyen. Tudjuk, hogy 31 Qx 8 x i + R mod P CRC, és mivel véges test felett vagyunk, így x 8 -nak létezik inverze: i=0 Így (x 8 ) 1 = x 31 + x 29 + x 27 + x 24 + x 23 + x 22 + x 20 + x 17 + x 16 + x 15 + x 14 + x 13 + + x 10 + x 9 + x 7 + x 5 + x 2 + x. Q ( 31 i=0 ) x i + R (x 8 ) 1 mod P CRC. A helyes CRC-értékhez az kellene, hogy a jobb oldal megegyezzen 31 x i -vel. Tehát Q-hoz a következő korrekciós tagot kell hozzáadnunk: 31 i=0 x i + ( 31 i=0 ) x i + R (x 8 ) 1. Látható, hogy ez a tag csak és kizárólag R-től függ, ha ennek értéke ismert, a korrigálás elvégezhető. Térjünk vissza a támadáshoz. Jelölje C az 1 byte-tal lerövidített titkosított üzenetet. Ekkor az ICV nagy valószínűséggel helytelen, de az előbb belátottak szerint ha a levágott byte-ot ismerjük, akkor a korrekció elvégezhető, és ezt a változtatást közvetlenül a titkosított szövegen is végrehajthatjuk. Legyen X a folyam, M a nyílt üzenet, M és C jelölje a helyes CRC-vel rendelkező változatokat, és D az eszközölt módosításokat. C = M X = (M D) X = (M X) D = C D i=0 Ezt felhasználva el lehet kezdeni egy titkosított üzenet dekódolását. Megtippeljük, hogy az elhagyott byte értéke micsoda, korrigálunk, és a módosított üzenetet elküldjük egy STA-nak. Először a TSC ellenőrzést kell kijátszani, ezt a Quality of Service technológiát támogató STA választásával lehet megtenni. Ez egy olyan szolgáltatás, amely különböző csatornákat definiál a hálózat kapacitásának minél optimálisabb kihasználásért, és ilyenkor a csomagok útvonala a prioritásuktól függ. Ilyen STA jelenléte nem egy irreális feltételezés, továbbá a forgalom jelentős része az első QoS csatornán történik. Minden csatornának megvan a saját, többi csatornától független TSC-je, így megtehetjük azt, hogy a módosított csomagot egy olyan csatornán küldjük el, ahol alacsonyabb a számláló. Itt elfogadja az STA, és leellenőrzi az ICV-t. Ha rosszul tippeltünk, és ez helytelen, 21
akkor az üzenetet eldobja. Ha viszont jól tippeltünk, akkor jön következő ellenőrzés, a MIC-érték kiszámítása. Ez majdnem biztosan helytelen, tehát az STA generál egy MIC-hibaüzenetet, és elküldi az AP-nek. Ezt lehallgatva meggyőződhetünk arról, hogy a találgatás helyes volt. Továbbá az üzenet fogadása nem volt sikeres, azaz STA nem emeli a TSC értékét, így tovább próbálkozhatunk. Mivel percenként legfeljebb egy darab MIC-hibát kényszeríthetünk ki, hogy az AP ne vessen be ellenintézkedést, így percenként legfeljebb 1 byte-ot találhatunk ki. Ez meglehetősen lassú, így olyan üzenetet kell választani, amelynél csak néhány byte ismeretlen. Erre pont megfelelőek az ARP reply üzenetek, amelyek a MAC és az IP címeket rendelik egymáshoz. Egy ilyen csomag négy dolgot tartalmaz: a küldő és a fogadó fél IP címét, illetve az ezeknek az eszközöknek megfelelő MAC-címeket. Mivel az üzenet ilyen kis méretű, így nincsen tördelve, a MIC és az ICV is ehhez a csomaghoz van kapcsolva. Ekkor elegendő ennek a kettőnek a kitalálása, ez 4+8=12 byte dekódolását jelenti körülbelül ugyanennyi perc alatt. A csomag többi részének kitalálása máshogy történik: a MAC-címek ismertek, és ha az IP-címtartomány olyan, hogy a byte-ok nagy része kitalálható (például 192.168.0.x), akkor ez 2 1 byte-nyi találgatást jelent, és az egyes tippeket az ICV kiszámolásával ellenőrizhetjük le. Az üzenet dekódolásával hozzájutunk egy nyílt szöveg-mic párhoz, amiből visszafejthetjük a MIC-kulcsot, sőt az IV-X párt is felhasználva az alacsonyabb TSC-vel rendelkező csatornákon saját üzeneteket is tudunk küldeni. Hatása A TKIP ellen nem léteznek olyan katasztrofális hatású támadások, mint a WEP ellen, egyelőre nincs olyan módszer, amely a titkosításra használt TK megszerzését tenné lehetővé. Biztonságosnak mégsem mondhatjuk. A fenti gondolatmenetet felhasználva a támadás továbbfejleszthető, például [9] tartalmaz egy gyakorlatban is igazolt módszert tetszőleges csomagok dekódolására. Szerencsére ezek ellen lehet védekezni, a kulcsok gyakori (például percenkénti) változtatásával. A legjobb megoldás azonban a következő fejeztben tárgyalt AES-CCMP használata. 22
4. fejezet Wi-Fi Protected Access II 4.1. Mi változott a WPA-hoz képest? Ahogyan már korábban is szerepelt, a WPA tervezői komoly korlátok közé voltak szorítva. Ebből a szempontból a WPA2 tervezőinek könnyebb dolga volt, hiszen tiszta lappal kezdhettek. Az IEEE 802.11i azon részei, amelyek már a WPA-ban is implementálva voltak, maradtak: a hitelesítés és a kulcsok hierarchiába rendezése, menedzselése is hasonlóan történik. Viszont egy teljesen új, az MPDU-szinten működő titkosítást és sértetlenségvédelmet ellátó protokoll jelenik meg, ez a Counter Mode Cipher Block Chaining Message Authentication Code Protocol (CCMP), amely az AES-t használja. A hosszú név sokat elárul a működéséről, de nézzük meg közelebbről is. Megjegyzés. Az AES műkődését nem részletezem, ugyanis jelen esetben egyetlen tulajdonsága fontos, mégpedig az, hogy ez egy blokktitkosító, amely itt 128 bites kulcsokkal és ugyanekkora blokkokkal dolgozik. Egy blokktitkosító használata kettő problémát vet fel. Az egyik az, hogy ha az üzenet hossza nem 128-nak többszöröse, akkor az utolsó, hiányos blokkal az algoritmus nem tud mit kezdeni. A másik pedig, hogy ha azonos kulccsal titkosítunk többször, akkor egy blokk esetleges ismétlődése meglátszik a titkosított szövegen is, hiszen a blokktitkosító ugyanazt a transzformációt fogja elvégezni. Az AES köré épített mechanizmus, a CCMP mindkettőre megoldást ad. CBC-MAC A protokoll nevének második felét a sértetlenség védelmét ellátó funkciójáról kapta. Egy MSDU MIC értéke a következő módon áll elő: 1. A csomagot kiegészítjük nullákkal, hogy összességében k 128 méretű legyen (padding). Ezek persze nem kerülnek átvitelre, csak a MIC kiszámításakor vannak jelen. 23
2. Előállítunk egy 128 bites startblokkot. Ezt egy 48 bites nonce érték, a küldő MACcímének, továbbá a csomagra jellemző adatok (4 byte) összefűzésével tesszük meg. A kapott értéket titkosítjuk AES-t alkalmazva, ahol kulcsként a TK-t használjuk. 3. XOR-oljuk a következő blokkal (ez az első körben épp az MSDU első blokkja), az eredményt ismét titkosítjuk. 4. Vesszük az eddigi eredményt, és GOTO 3. Ezzel előáll egy 128 bites érték, amely az üzenet minden információját hordozza. Ennek a fele eldobásra kerül, a WPA2-ben a MIC csak 8 byte-os. Ez azonban még így is elegendő biztonságot nyújt: amennyiben az üzenet egyetlen bitje is megváltozna, egy teljesen más eredményt kapnánk (1 2 64 valószínűséggel). A kapott értéket az MPDU végére fűzzük, és következhet a titkosítás. Counter Mode Ez a módszer az AES-t nem közvetlenül használja az üzenetek rejtjelezésére. Ehelyett először előállítunk egy megint csak 128 bites értéket, nevezzük ezt IV-nek. Ezt majdnem teljesen ugyanúgy kell elkészíteni, mint az első blokkot a CBC-MAC-nél, még a használt nonce értéknek is meg kell egyeznie, az egyetlen eltérés abban a bizonyos 4 byte-ban van. Ennek fele a CBC-MAC-nél a blokkok számát jelentette, itt viszont más funkciója lesz ennek a 2 byte-nak. Egy számlálót fog elkódolni, amely 1-ről indul, és az MPDU minden egyes blokkjával eggyel nő az értéke. A 4.1 ábra jelöléseit használva a C i titkosított blokk előállítása a következőképpen történik: az i számlálóval rendelkező IV-t titkosítjuk AES-t és a TK-t használva, és M i -hez XOR-oljuk. Ezzel lényegében egy folyamkódolót definiáltunk. A 4.1 és 4.2 ábrákon csak a számláló értékét jelöltem, a teljes doboz mindkét esetben az IV-t takarja. 4.1. ábra. Counter Mode 24
Tulajdonságok: Ez a mód megoldja a blokktitkosító használatával kapcsolatban felvetett problémákat. Egyrészt az XOR-olásnak köszönhetően nem fontos, hogy az üzenet maradék nélkül felosztható legyen blokkokra, az utolsó értékből előállított output végét eldobhatjuk. Másrészt kettő azonos tartalmú blokkra különböző titkosított blokkokat fog előállítani, hiszen a számlálónak köszönhetően különböző folyammal történik a rejtjelezés. A CBC-MAC móddal ellentétben ez az eljárás párhuzamosítható: a kulcsok ismertek már a kezdetkor, és a blokkok titkosítása egymástól függetlenül történik. Az eddigi két protokollhoz hasonlóan a dekódolás ugyanúgy történik, mint a titkosítás. Ismét kihasználható az, hogy az XOR önmaga inverze, így ha előállítjuk a számlálóból generált folyamot, akkor ezt a titkosított szöveghez XOR-olva az eredeti üzenetet kapjuk. Azaz a használt módnak köszönhetően nem kell implementálni az AES titkosításhoz tartozó feloldó algoritmust is. A visszajátszás elleni védelemre a nonce értéket használjuk, ezért a PTK telepítésekor 0-val inicializáljuk, és minden elküldött üzenet előtt megnöveljük 1-gyel. Az eddigiekhez hasonlóan ez nyíltan kerül átvitelre. Megjegyzés. Köszönhetően annak, hogy a protokoll ugyanazt a kulcsot használja két funkcióra is (titkosítás és sértetlenség-védelem), a PMK-ból így csak három darab kulcsot (KEK, KCK és TK), a GMK-ból pedig csak egy kulcsot kell generálni. 4.2. ábra. CCMP 25
4.2. A KRACK-támadás A WPA2 egy évtizeden át ellenállt a rajta biztonsági gyengeségeket kereső vizsgálatoknak. Az egyetlen problémát a gyenge jelszó használata okozhatta, de ez ellen sajnos nem nagyon lehet védekezni. Azonban 2017. októberében 2 belga kutató, Mathy Vanhoef és Frank Piessen bejelentette, súlyos hibát találtak a protokollban. A problémát nem egy gyártói implementációs hiba okozta, a baj magával a protokollal volt. A Key Reinstallation Attack (KRACK) egy közbeékelődéses támadás (man-in-the-middle attack - MitM), amely a különböző kézfogásokat támadja, és közben azt a tényt használja ki, hogy bár ezek a kézfogások és az AES-CCMP külön-külön formálisan bizonyíthatóan biztonságosak, a kettő ötvözése mégis lehetőséget ad hibákra. Ezeket a [10] tanulmányban publikálták, az alfejezetet ez alapján írtam. Megjegyzés. A támadás a WPA-TKIP kézfogásai ellen is működik, sőt a hatása még súlyosabb: az üzenetek visszajátszásán vagy dekódolásán kívül még csomagok hamisítására is lehetőséget ad. A négyutas kézfogás elleni támadás A támadó elfoglal egy MitM-pozíciót az AP és a csatlakozni kívánó STA között. Ennek kivitelezése nem triviális feladat, de megvalósítható a gyakorlatban. A négyutas kézfogás első három üzenetéhez nem nyúl, ezeket csak továbbítja a két fél között. Ezek után sor kerül arra, hogy az STA küldjön egy üzenetet az AP felé, amelyben nyugtázza, hogy a kézfogás sikerrel lezajlott, és az AP hitelesítette magát, így ő telepítit a PTKt, és készen áll a titkosított kommunikációra. Ha viszont a támadó blokkolja ezt a 4. üzenetet (Msg 4 ), akkor ezt az AP úgy fogja értelmezni, hogy az általa küldött Msg 3 a továbbítás közben elveszett, és nem érkezett meg az STA-hoz, így újraküldi Msg 3 -at egy megnövelt visszajátszás-számlálóval (r + 2). Ekkor implementációtól függően két eset lehetséges: a kulcsok telepítése után az STA elfogad még titkosítatlan üzenetet, vagy pedig már nem. A rossz hír az, hogy ennek nincs jelentősége, a támadás mindkét esetben kivitelezhető. 1. STA elfogadja a nyílt Msg 3 -at A támadó ez esetben továbbítja az üzenetet az STA felé, aki egy 4. üzenettel válaszol. STA viszont eddigre már telepítette a kulcsokat, így ez az üzenet titkosítva lesz! Ezt a 4.3 ábrán EncrPT 1 K {Msg 4(r + 2)} jelöli, ahol Encr felső indexe a titkosításkor használt nonce értéket jelenti. Az üzenetet a támadó nem továbbítja, hiszen az AP még nem telepítette a PTK-t, így nem fogadná el. Ehelyett az előbb elfogott Msg 4 (r + 1)-et játssza vissza, amelyet a vártnál alacsonyabb számláló ellenére is el fog fogadni az AP. A szabvány szerint egy kézfogáson belül az AP minden eddig előforduló számlálóval 26
rendelkező Msg 4 -t érvényesnek tekinthet (legalábbis azokat a számlálókat, amelyekkel ő már küldött üzenetet, de még nem kapott). 4.3. ábra. 1. eset Ezenkívül még egy fontos dolog történik az STA oldalán: az újratelepítés. Egy Msg 4 üzenet küldése után az STA-nak mindig telepítenie kell a PTK-t, jelen esetben a már használatban lévő kulcsot telepítit újra, sőt az elvileg adott kulccsal csak egyszer használt nonce érték is visszaáll az eredeti 0-ra. Ezzel a támadó nonce-újrafelhasználásra kényszeríti az STA, aminek soha nem szabadna előfordulnia. Ez ugyanis lehetőséget ad visszajátszásos támadásra, hiszen ennek megakadályozásáért a nonce érték minden elküldött üzenettel való növekedése felel. Másrészt a nonce ismétlődése egy titkosító folyam ismétlődését is jelenti, ugyanis a következő üzenetben az 1-es érték lesz ismét használva: EncrPT 1 K {M}. Vegyük észre, hogy azt a folyamot, amellyel ez az M üzenetet titkosítva lesz, korábban akkor használta az STA, amikor elküldte a második Msg 4 -et. Ezek után már könnyű a folyamot megszerezni: a támadó hozzáfér egy olyan párhoz, ahol ismeri az eredeti üzenetet és annak titkosított alakját. Ez a pár természetesen Msg 4 (r + 1) és Encr 1 PT K {Msg 4(r + 2)}, ahol az eltérő számlálók miatt van egy kis különbség, de a két Msg 4 majdnem teljesen megegyezik. A kettő XORolásával a kapott eredmény lényegében az 1-es nonce értékhez tartozó folyam, amelyet EncrPT 1 K {M}-hez XOR-olva a támadó dekódolni tudja az M üzenet. 2. STA nem fogadja el a nyílt Msg 3 -at Ebben az esetben a támadás egy kicsit körülményesebb. Implementációtól függően elképzelhető, hogy az STA ugyan elfogadja az újraküldött nyílt Msg 3 -at, de csak ha 27