Az alábbi cikket Ys. írta a 0×90 blogon, és mivel a cikksorozata kapcsolódik az iPhone-hoz, mi érdekesnek gondoljuk a számotokra is, így ezeket engedelmével egymás után át is emelnénk ide, a Szifonra.
***
Az SSL az az intézmény, ami A használható eszköz hálózati forgalom bevédésére. Tulajdonképpen nem is nagyon van olyan hálózati forgalmat bonyolító alkalmazás, ami így vagy úgy, de ne használná. Kicsit távolabbról nézve a dolgot, az SSL olyan, mint a Mátrix: “It is all around us.”
Az SSL voltaképp a bizalomról szól, arról, hogy mennyire bízunk egy nyilvános kulcsban. Könnyed bevezetőként először is nézzük felhasználói oldalról a dolgot: mi történik az iOS felületén, ha büdös a tanúsítvány pl. a Safariban? Milyen üzenettel tájékoztatja a felhasználót? “Kedves felhasználó! Valaki megpróbálja épp lehallgatni a hálózati forgalmadat! Ha ezt engedni akarod, üssél rá a Continue gombra, de inkább ne tegyél így, ha érzékeny adatokat szeretnél forgalmazni!” Neeeeem.
Akkor most egészen pontosan mi is az üzenet? Safarit érintő hibáról tájékoztatja a felhasználót: nem tudta verifikálni a beütött HTTPS-szerver identitását. Ez azt sugallja, hogy amúgy minden rendben van, de a Safari b@szakodik megint, valami gyíkja van. Ilyen felvezetővel viszont a felhasználók nem fogják megnézni, hogy a “Details” gomb után mi lehet – amúgy ha meg is nézik, maximum egyszer fognak így tenni, ugyanis a “Details” gomb után feldobja a certificatenézegető beállításpanelt, további leírás vagy tájékoztatás nélkül. Teljesen biztos vagyok abban, hogy ez még az életben senkit sem tántorított el attól, hogy Continue-t üssön reflexből.
Az Apple amúgy is notórius vendor olyan tekintetben, hogy az openSSL “hivatalos” branchéhez képest akár évekkel később javítanak ki sebezhetőségeket (pl. Basic Constraintes Marlinspike-támadás 2002-es publikálásához képest a 4.3.5-ös iOS-ben fixálták ki a hibát 2011-ben. No comment.)
Amikor iOS-es alkalmazások SSL-kezelését teszteljük, van néhány tipikus hibaforrás, ami az esetek 99%-ában megtalálható, amikor az adott alkalmazás először jár nálunk a homokozóban.
A medve nem játék, az iPades alkalmazás meg nem böngésző.
A legtöbb SSL-implementációs probléma onnét ered, hogy a kütyük tömeges elterjedéséig böngészőkben találkoztunk vele meg desktop alkalmazásokban, ahol a támadó maximum a hálózati folyamhoz férhet hozzá pl. ARP poisoninggel, de nem valószínű, hogy hozzáfér fizikailag az eszközhöz. Ez a helyzet gyökeresen megváltozott azzal, hogy egy iPhone-t vagy iPadet caklipakli el lehet lopni, és a tesztelt alkalmazások fejlesztőinek számolniuk kell az eszközhöz fizikailag is hozzáférő támadó esetével.
Böngészők esetében ugye az alábbiakat nézzük meg a tanúsítványon:
- Érvényes (nem járt le)
- Annak a webszervernek a neve szerepel a CN mezőben, akitől kaptuk
- Aláírta valami megbízható CA a tanúsítványlánc elejét
Ez a megközelítés hatástalan abban az esetben, ha a támadó hozzáfér az iOS felületéhez, ugyanis ebben az esetben simán hozzá tud adni egy új tanúsítványkiadó hatóságot (CA) az eszközben található listához, generál egy érvényes tanúsítványt a HTTP/TCP proxy-jához és zokszó nélkül azon keresztül fogja az alkalmazás bonyolítani a forgalmát.
Egy esetben a fejlesztők ennek a MiTM-es támadásnak a kivédésére két változtatást implementáltak a következő verzióban, ami postafordultával visszajött a riportunk után, és ezek remekül rávilágítanak arra, hogy mennyire nehéz is a feladat:
- Kliensoldali tanúsítványt tettek be, jelszóval. Enélkül a szerver SSL szinten dobja el a kapcsolatot.
- Az alkalmazás nem veszi figyelembe az iOS-es HTTP-proxy beállításokat, minden esetben közvetlenül próbálkozik.
Az első pontot úgy cseleztük ki, hogy az alkalmazás binárisát felboncolva megtaláltuk a bedrótozott és base64-enkódolt tanúsítványt, a jelszavát pedig pár sorral arrébb találtuk meg IDÁban. A második probléma megoldásához pedig egyszerűen annyit csináltunk, hogy a saját DNS szerverünket adtuk meg a DHCP-válaszban, amikor az (ellopott) eszközzel csatlakoztunk a homokozós wifihez.
Oké, akkor mi legyen most, jöhet a kérdés – lássunk két gyakori megoldást-megoldási kísérletet, előnyökkel és hátrányokkal, ha már az iOS default ellenőrzését ilyen ügyesen ki tudjuk cselezni. Nyitott vagyok minden javaslatra, ha van gondolatotok, ne tartsátok vissza a kommentekben.
A felhasználó jelszava nyitja ki a kliensoldali tanúsítványt, hogy mindenképpen kelljen megfelelően authentikáló felhasználói interakció a hálózati forgalom elindításához. Trükkös gondolat, viszont ha HTTP-szerű működésben gondolkodunk, akkor a kliensoldali tanúsítvány akkor ér valamit, ha a szerver el is tudja utasítani. Egy lehetséges támadás ez ellen a módszer ellen az, hogy lecserélem/átütöm a kliensoldali certet valami ismert jelszavú tanúsítványra, gdb-t használva becsempészem a valódi jelszót és amikor az app forgalmazni kezd, az én kis mindent elfogadós HTTP proxy-mban már látom is, hogy az alkamazás mit akart küldeni a szervernek.
Ellenőrizzük, hogy a tanúsítványt aláíró CA rootcertjének fingerprintje ismert és előzőleg tárolt érték-e. Nyilvánvaló hátránya a módszernek, hogy ha új certet deployolnak, akkor hirtelen nem fog működni az alkalmazás, plusz a támadó ezt az “ismert jó” fingerprintet simán felül tudja csapni a binárisban.
További érdekes kérdés, hogy mi történjen az olyan alkalmazások esetében, amik rendszeresen bejelentkeznek (pl. VoIP appok, gTalk). Ha nyafog a cert miatt, az rontja a felhasználói élményt, ha nem, az meg a biztonságot. Ha csendben nem csatlakozik megfelelő cert hiányában, az a legrosszabb, a felhasználó annyit fog látni, hogy “van internet”, de nem tudja használni az alkalmazást – és itt bele is csöppentünk a használhatóság vs. biztonság nehézsúlyú ökölvívómérkőzés következő menetébe.
Összességében annyit mondhatunk, hogy nincs általános érvényű megoldás a hálózati kommunikáció védelmére, mindig az adott alkalmazás működéséhez kell igazítani a megoldást. Ami működik a böngésző-szerver világban, az nem fog, ha egy az egyben átültetjük iOS-es alkalmazásra.
Néhány pont a végére, gondolatébresztőnek:
- Minél többféle hálózati kommunikáció zajlik a háttérben, annál nehezebb megvédeni. Többféle kommunikáció alatt olyasmit értek, hogy pl. egy tipikus VoIP app fenntart egy sessionkezelési és egy SRTP-s csatornát.
- Minél inkább pattanós felhasználói érzést szeretnénk nyújtani, annál nehezebb megvédeni a hálózati kommunikációt (a “pattanós érzés” itt a seamless user experience magyarítása próbál lenni).
- Ha az alkalmazást rá lehet venni arra, hogy hálózati kommunikációba kezdjen, mielőtt a felhasználó authentikálta volna magát a GUI-n, akkor nagyon nehéz kivédeni, hogy dönthető legyen.
Update.
A certificate-kezelés kérdésére két megoldásba is belefutottam, mióta kiraktam a posztot. Az egyiket dc4420-on hallottam, a másikat meg a belsős fejlesztőcsapatunk ötlötte ki – hiába no, tanulnak a srácok. 🙂
Egy. Tudta-e Ön, hogy az iOS-es Twitter-app legfrissebb verziójában már certificate pinninget használ? Bele van derótozva a binárisba egy certificate, és minden esetben ezt a certet keresi, különben dobja a kapcsolatot. A defconos kolléga szerint ez elsősorban az iráni/szíriai/líbiai kormány tömeges MiTM-támadásai ellen lett bevezetve.
Kettő. A belsős iOS fejlesztőteamünk talált ki egy egészen ügyes megoldást arra, hogy hogy lehet kliensoldali certet deployolni úgy, hogy ne legyen bedrótozva a jelszó a binárisba. Pofonegyszerű: amikor felrakod az appot, nem működik a hálózati szinkronizálás – ahhoz, hogy ez a fícsör használható legyen, iTunes-on keresztül be kell rántani egy frissen generált kliensoldali certet, amit a felhasználó erős jelszava nyit. Ez a megoldás meg ügyesen kihúzza a méregfogát a “difótból jön a cert”-megközelítésnek.
2 Comments
Annak idején az SSL-t, mint titkosítási eljárást úgy találták ki, hogy belátható időn belül sem online sem offline nem lehetett törni egy bizonyos időn belül. Alapvetően a titkosítási algoritmusok valamelyikével és 3db kulcspárral lehet megoldani a tökéletes titkosítást szerver – kliens között.
Név szerint: szerver cert és kulcs, kliens cert és kulcs és aláíró cert és kulcs.
Amit ma SSL titkosítás gyanánt használnak a legtöbb helyen, az sajnos korántsem elégíti ki a a titkosítási eljárás minimális szintjét. Előszeretettel szeretik elhagyni a kliens certificate -et, nyilván költség megtakarítás miatt, különben az SSL használata nagyon drága lenne.
De azért ne feledkezzünk meg róla, hogy az SSL akkor SSL, ha megvan a két tanusítvány és azt egy közbenső (mindkét fél által elfogadott) aláíró aláírta. Amíg ez nincs meg, addig ha ott is van, hogy SSL, a biztonság csak illúzió. Megtörése nem csak idő kérdése, mint az eredeti koncepció szerint.
Írásomra bizonyítékot is találhattok a bankok ÁSZF -ében, ahol semmiféle felelősséget nem vállalnak az adatkapcsolatra… 😀
Akit ez a dolog bővebben érdekel, az olvasson esetleg utána a Men in the midlle attack nevű támadási eljárásnak. 😀
@kotta: Igen, a man-in-the-middle egy jo pelda erre, ugye az in-app vasarlasokat “ingyenesito” orosz hacker is pontosan azt csinalta, amit YS itt leir: sajat proxy, sajat cert, oszt hadd szoljon 😀