Impulzus

 
A Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar Hallgatói Képviseletének lapja

Hekk

Sokakat érdeklő kérdéskör a számítástechnikában a szerverek lefagyasztásával, fontos weboldalak megbénításával járó, vagy éppen az egész világon számos hálózat túlterhelését okozó törések kérdésköre.

Milyen misztikusnak tűnik, amikor valaki a Solaris, esetleg Digital Unix forráskódját nyúlja le, vagy milyen meglepő lehet az is, hogy az ember összevész valakivel a hálózaton, és egyszercsak lekapcsolódik a modeme! Nem csoda, hogy az embert néha ördögi vágy keríti hatalmába az ilyen jellegű információk megszerzésére. És az sem, hogy az esetek túlnyomó részében erre esélye sincs – vagy mire igen, addigra már mindenhol ott van a patch, a védelem (amiről tudjuk, hogy azért – főként a microsoft világban, de alulfizetett egyetemi rendszergazdáknál sem ritkán – mégsincs ott mindig, mindenhol).

A nagy titok igazából az, hogy nincs titok. Figyelni kell, és konstruktívan kell hozzáállni mindenhez. Esetleg érdekes lehet nyomon követni egy folyamatosan fejlődő, biztonsági szempontból kritikus program fejlesztése során a forráskód változásait is az újonnan megjelenő biztonsági lyukak megtalálása érdekében. A megszerzett információt aztán pedig tovább lehet adni, vagy nem, ez már rajtunk múlik... Megjegyzem, én inkább az információ szabad áramlásának a híve vagyok, és nem hiszek benne, hogy az elkerülhetetlen fölösleges akadályozása ténylegesen javítja a hálózat biztonságát. Rövid távon igen, mert ha nem mondom el másoknak a nagy titkot, ami a tudomásomra jutott, akkor egész biztosan nem fognak tudni törni vele. Azonban egy biztonságos, gyors javítás lényegesen gyorsabban jön ki, és terjed el, ha a lyuk létére nem csak egy szállongó kacsa utal, hanem akárhonnan letölthető egy 2-3 k-s C program, amit lefordítva és elindítva egy gépet fel lehet törni. Ez különösen a kommerciális gyártóknál van így (például a Sunnak is voltak olyan, inkább csak viccnek nevezhető húzásai, amikor külön pénzt kért a javításokért).

Ahogy biztonsági hibából, úgy törésből is sokféle van, bár viszonylag jól osztályokba sorolhatók a hatásmechanizmusuk alapján. Lássuk a főbb típusokat a teljesség igénye nélkül...

Konfigurációs hiba

Egyes démonok, szolgáltatások olyan cselekedeteket engedélyeznek, amelyek közvetve és trükkösen kombinálva a rendszer feletti hatalom teljes megszerzését jelenthetik. Itt nincs semmi különös, semmi extra, elkapás után még azzal is védekezhetünk, hogy "Dehát a rendszer megengedte! Mi másért nem tiltották meg ezt és ezt?" Persze nem lesz igazunk, de az igazát kereső, bosszúszomjas rendszergazdának feltétlenül kényelmetlen perceket okozhatunk vele. Ugyanis ő tényleg megengedte, amit megengedett... Ilyen típushiba például, amikor engedélyezik az anonymous FTP-vel való feltöltést egy gépre (tehát valahol tetszőleges file-okat létrehozhatunk), ugyanakkor a teljes ftp könyvtár weben keresztül is elérhető, és természetesen CGI scriptek futtatása is engedélyezett benne. Ekkor egyszerűen feltöltünk egy backdoort (kiskaput, olyan programot, ami egy TCP/IP portot megnyitva, azon várja beérkező parancsainkat, melyeket nyomban végre is hajt), majd azt meghívjuk a webről a CGI segítségével. Így jutottak be néhány hónapja a www.apache.org-ra.

Általános jellegű programhiba

Ez egy démon, vagy más becsapandó processz nem bitbabrálós jellegű, hanem csak egyszerű programozási hibáját jelenti. Ilyen az, amikor néhány évvel ezelőtt a világ összes AIX-át egyetlen paranccsal, akár kívülről is fel lehetett törni egy rlogin -f -l root paranccsal - ugyanis az rlogin démon a -f (force, azaz a parancs hibákra tekintet nélküli, árkon-bokron keresztül történő végrehajtása) és -l root (bejelentkezés rendszergazdaként) kapcsolókat úgy kombinálta össze, hogy a belépést hibás jelszóval is megengedte, mivel root-ként jogunkban állt áthágni a hibás jelszóból eredő tiltást. Vagy amikor talán egy FTP démonnál nem létező felhasználói nevet "trükkösen" megadva, a démon bejelentkezéskor nem tudott semmilyen felhasználói azonosítót adni nekünk – ezért a default értéket, azaz 0-t adott. Ami viszont a root azonosítója...

/etc/passwd – a folytatásos história

A /etc/passwd file valamikor – többek közt – a felhasználói jelszavak kódolt változatát tartalmazta. Magát az eredeti jelszót a rendszer sehol sem tartotta nyilván. A belépő emberek jelszavát pedig úgy ellenőrizte, hogy a begépelt jelszót mégegyszer kódolta, és ha ugyanazt kapta vissza, ami a /etc/passwd-ben volt, akkor a jelszót érvényesnek tekintette. A kódoló algoritmus egyirányú volt, a jelszavakat visszakódolni nem lehetett, mivel a visszakódoláshoz szükség lett volna a kódolt jelszót meghatározó algoritmus végrehajtása során keletkező részeredményekre. Igen ám, de a /etc/passwd-ben más, a felhasználók normális működése számára létfontosságú adatok is voltak, ezért ennek olvasását (tehát a kódolt jelszavakét is) mindenképpen meg kellett engedni a felhasználók számára. Így azonban azok hozzáférést szereztek a felhasználók kódolt jelszavaihoz. Ebből adott volt egy közkedvelt módszer: egy szótár szavainak végigpróbálgatására célprogram írása (Crack, John). Szinte minden rendszeren egészen 1996-1997-ig működött, ez egy súlyos strukturális hiba volt. Ekkortájtól kezdték szinte mindenhol alkalmazni a shadow password-öt, ami a kódolt jelszavak egy másik, a felhasználók számára már nem olvasható file-ba, a /etc/shadow-ba juttatását jelentette. Ezt követően számos külön biztonsági hiba kizárólag azt jelentette, hogy segítségével valamilyen úton-módon mégiscsak meg lehetett nézni a /etc/shadow file-t. Amellett pedig a unixos hálózati autentikálást végrehajtó szabvány, a Yellow Pages, később NIS nagyon sokáig lehetővé tette az ypcat passwd parancs segítségével a tényleges shadow megismerését. Néhol ez mind a mai napig működik. Ezért is tilos sok helyen szótári, vagy akár csak értelmes szóra távolról is hasonlító jelszavak megadása. Ha már egy potenciális törögető hozzájutott a shadow-hoz, legalább nehezebb dolga legyen.

Sniff és társai

Számos SchNet felhasználónak ismerős lehet az jelenség, hogy Telnet, FTP, POP3 kapcsolataikat monitorozva akár egy szinttel lejjebb is figyelhetik. Még kellemetlenebb, ha ezt valaki automatizáltan műveli.

Ez rendkívül hatékony, és sajnos szinte kikerülhetetlen módszer, számos helyen mind a mai napig működik, és nemcsak Unixon, hanem Novellen, DOS-on, sőt, még a nagyon biztonságos VMS-en is – ugyanis nem magába a rendszerbe nyúl bele, csak a hálón átmenő jelszavakat hallgatja le. A konkrét megvalósítás elég triviális, megvannak rá a célprogramok (pl. sniffit).

Más, szintén sniffhez hasonló módszer a spoof. A spoof egy másik gép hálózati címének átvétele. Ez azért jó, mert lehetőve teszi az átjutást az összes hálózati cím szerinti szűrésen. A dolog sajnos annyira nem mindig egyszerű, mert egyszerre több, bekapcsolt gép ugyanazzal az IP-címmel egy hálózaton nem szokott hibátlanul, a kívánt formában működni. Ezért el kell érni a spoof-olandó gép hálózatról való eltüntetését, amire DoS támadások (ld. később) adnak lehetőséget – de néha az is célravezető, ha egyszerűen megvárjuk, amíg azt lekapcsolják. Egészen konkrét típushiba például, hogy NFS-en keresztül egy könyvtár egy másik (megbízható) gépnek írásra-olvasásra engedélyezve van...

A hálózati DoS támadások

A DoS jelen esetben, minden egyéb képzettársítás ellenére, nem legkedvesebb szoftvergyártónk legkidolgozottabb programját jelenti, hanem a Denial-of-Service rövidítése, ami szolgálatmegtagadást jelent. A szolgálatot, azaz valamely vagy az összes funkciót a célgép tagadja meg, pontosabban nem is megtagadja, hanem képtelen azt teljesíteni. Például azért, mert lefagyott. Lévén, hogy itt nem a védelmi rendszer bonyolult kijátszásáról, hanem csak egy gép megfektetéséről van szó, kivitelezni általában lényegesen egyszerűbb – de persze az elért eredmények sem igazán világraszólóak (noha alkalmas végső érv lehet egy vitában például egy modem lekapcsolása). Van DoS, amely végrehajtásában közel olyan bonyolult, mint egy buffer overrun exploit (sőt, akár buffer overrun elven is működik), ilyen volt például a lehetőség a 2.5-ös Solarisok syslogd-jának segfault-oltatása. A segfault, a windows general protection fault unixos változata, jelentése az, ami win alatt is: a program illegális műveletet hajtott végre... természetesen azért, mert értelmetlen zagyvalékra, vagy csak hibás kódra keveredett. A syslogd feladata pedig a rendszer eseményeinek figyelése, azok naplófile-okba gyűjtése, bizonyos esetekben pedig biztonsági riasztás. Ha ez leáll (például mert kinyírtuk), szabadon lehet garázdálkodni, mert nyoma, remélhetőleg már nem marad...

Valamivel általánosabb érvényű DoS támadás a loopconnect. A loopconnect szó szerint hurokkapcsolást jelent, valójában azonban a szerverprogramok egy általános működési tulajdonságát használja ki. Nevezetesen azt, hogy bizonyos szolgáltatások úgy működnek, hogy egy démon figyeli az adott szolgáltatáshoz tartozó porton bejövő hálózati kapcsolatokat, és minden új kapcsolathoz elindít egy külön al-szerverprogramot, ami csak az adott kapcsolatról jövő kéréseket, parancsokat hajtja végre. Egy ilyen szerverprogram elindítása általában lényegesen erőforrásigényesebb, mint egy TCP/IP kapcsolat létrehozása. Ezért valamely saját gépünk nem jelentős megterhelésével könnyen túl tudunk terhelni egy nálunk sokkal erősebb szervert is, ha elég sok TCP kapcsolatot hozunk létre elég gyorsan. Ilyenkor két eset van. Vagy le van korlátozva valami módon az egyszerre kiszolgált TCP kapcsolatok száma, vagy nincs. Ha nincs, akkor a rendszer hamar túlterhelődik, és vagy lefagy, vagy a működésképtelenségig lassul, vagy pedig memóriahiány miatt létfontosságú processzei is leállnak. Mindhárom eset végkimenetele egyértelmű. De ha le van korlátozva, sokkal akkor sem jobb a célgép helyzete, mivel akkor csak az adott szolgáltatás szünetel addig, amíg a loopconnect-et fenntartjuk.

Más, mindezeknél lényegesen egyszerűbb DoS támadások voltak a 97-99 közötti időszakban a windows-írtók gyűjtőnév alatt elhíresült, elsősorban a microsoft rendszerei ellen hatásos exploit-sorozat. Ez 3-4 kellemesen izgalmas ciklust jelentett, melynek egy periódusa a következőből állt:

a.) kijött egy új bug, amivel windowsos gépeket távolból meg lehet fagyasztani;

b.) rengeteg, de rengeteg windowst szinte sportból megállítottak;

c.) kijön a microsoft patch, ami természetesen nem tökéletes, ezért kezdődik minden elölről...

A sorozat első tagja a winnuke volt, ami inkább konfigurációs hibát jelentett a windows osztott könyvtárkezeléséhez tartozó registry bejegyzésekben. Ennek hatására a 139-es portra egy "bye" szócskát küldve a windowsok rövid úton csontra fagytak.

A következő bugok működése alapvetően másmilyen volt, azok IP fragmentumokkal dolgoztak. Ennek lényege az, hogy bitbabrált, több részletben elküldött adatcsomag-töredékeket a windows úgy másolta össze egy csomaggá, hogy közben a rendszermemóriát is kinullázta, illetve memóriaszeméttel töltötte fel – ami pedig, lévén e másolás a windows kernel legmélyebb bugyraiban, természetesen azonnali lefagyást okozott.

Szintén érdekes jelenség volt az ATH0 néven elhíresült bug. Ez a bug nem valamely operációs rendszer, hanem a modemek működésének elvi hibája, nevezetesen az, hogy bizonyos vezérlőparancsokat távolból is végrehajtott, így például a +++ATH0<enter> kódsorozatot is, amelyet például ping csomagba ágyazva távolból is a hálón bármely modemnek el lehetett küldeni. A parancs hatására a modem bontotta a vonalat, (akkor még) 150 Ft tényleges pénzügyi kárt is okozva ezzel.

Buffer overrun és más bitbabrálások

Ezek általában nem DoS, hanem remote, néha local root támadások szoktak lenni (bővebben lásd később).

Működésük alapja a bitbabrálás, tehát nagyon erősen platformfüggőek. Általános jelleggel védekezni ellenük szinte lehetetlen, mivel egy nagyon alapvető struktuális hibát használnak ki. Például 95 körül volt egy olyan local root exploit Solarisra, ahol a már említett shadow file-hoz lehetett hozzáférni, mégpedig a következő módszerrel: el kellett indítani egy login programot. Ez a program általában akkor indul el, amikor valaki be akar lépni a rendszerbe, és még nincs azonosítva. Ez kéri be a T. júzer loginnevét, jelszavát, veti össze a /etc/passwd-ben vagy a /etc/shadow-ban található értékkel... természetesen a programnak root joggal kell futnia, hiszen máskülönben nem tudna a csak root által olvasható shadow-hoz férni. Tehát, miután parancssorból elindítottuk a logint, igaz, hogy root-ként fut, dehát nincs túl sok jogunk felette, annyi azonban van, hogy szimulálhatjuk a számára, hogy ő most illegális utasítást hajtott végre. Ez természetesen nem igaz, de ilyet minden olyan programmal tehetünk, amit mi indítottunk el (SIGSEGV signal küldéséről van szó). Ennek hatására a program azonnal leáll, és az éppen aktív adat- és veremszegmenséből egy speciális file, egy bizonyos core file keletkezik, melynek célja az, hogy ezt analizálva megállapíthassuk a hiba okát. Igen ám, de addigra a login beolvasta már a teljes shadow-t, hogy a jelszóra várva összevethesse a tárolt értékekkel. Ezért aztán annak tartalma bekerült az adat- vagy veremszegmenségbe is, így a core file-ba is... ahonnan szépen kiolvashatjuk. Néhány, kevéssé ellenőrzött account-on meg természetesen egyből megindul a crack (igen pofátlan dolog, ha esetleg mindjárt a célgépen törünk – a gép végül is önmagát töri.)

És most térjünk rá a híres-hírhedt szörnyűségre, a buffer overrunra. Az elmúlt évtizedben, és valószínűleg a következőben is, ez volt/lesz a leggyakoribb hibafajta. Lényege, hogy az általában C nyelven megírt programok gyakran nem tesztelik egyes, bementként kapott string-jeik hosszát, és ugyanakkor csak egy előre meghatározott, konstans méretű, a hajdani programozó által biztosan elegendőnek vélt helyet hagynak neki. Például egy loginnévnek lehet hagyni 64 byte-ot. Akkor a program, amely azt hiszi, hogy csak egy loginnevet kér be, a következőt fogja tenni:

– eljut a loginnév bekérő részre;

– meghívja a loginnév bekérő függvényt (ez régen legtöbbször a gets() volt, amely, ugyebár, nem ellenőriz méretet...);

– elhelyezi a veremben a visszatérési címet (tehát ahova a függvény visszatérése után vissza kell ugrani);

– elhelyezi a veremben azt a 64 byte-nyi üres helyet, ahova a beírt loginnév kerül;

– bekéri a loginnevet úgy, hogy a begépelt loginnév erre a 64 byte-ra kerül;

– visszaugrik a veremben korábban eltárolt visszatérési címre.

A vermek mindig fentről lefele töltődnek fel, tehát ha például a 0xc0000100-as címen volt a visszatérési érték, akkor a 0xc00000bc-s címen (a visszatérési érték 4 byte, és hexadecimálisan számolunk) kezdődik majd az az ominózus 64 byte. Mi azonban nem 64, hanem 68 byte-os loginnevet adunk meg... így a visszatérési érték is felülíródik, mégpedig arra, amit akarunk. Tipikusan ennek a
64 byte-nak az elejét szokás megadni visszatérési címként, mivel annak tartalmát szintén mi mondjuk meg. És oda pedig egy nagyon rövid assembly kódrészt kerül, ami nem csinál mást, mint meghív egy közönséges shell-programot.

Kívülről ebből annyit lehet látni, hogy loginnév helyett egy hosszú krikszkrakszot adunk meg (gyakorlatban az ilyet nem szokás begépelni, hanem egy másik, rövidke programmal, az ún. exploit-tal küldetni el), mely után a program minden további nélkül egy command prompt-ot vág a képünkbe, amivel a behatolás sikeresen megvalósult. A módszer ellen általános védelem nincs, és mostanában nem is lesz, noha esetenként meglepően hatékony félmegoldások vannak (auditált kód, mindig méretellenőrző függvények stb.).

Social engineering

A social engineering egy nagyon trükkös dolog, mivel nulla, azaz totálisan zéró szaktudást igényel, mégis rendkívül hatékony. Szó szerint valamiféle "társadalmi mérnöki tevékenység"-et jelent, de lényegében arról van szó, hogy nem szoftveres úton, hanem társadalmi kapcsolatok útján vesszük rá a bennfenntes személyeket a szükseges adatok (elsősorban jelszavak) megadására. Magam is tanúja voltam, amikor egy teljesen nem hozzáértő ismerősöm egy ingyenes levelezőrendszeren az operátor nevet lefoglalva olyan tartalmú leveleket küldött szét számos címre, hogy a tisztelt felhasználók karbantartási célból változtassák meg jelszavaikat egy általa megadott szóra. A kliensek több, mint kétharmada egy szó, vagy bármi válasz nélkül, megtette... vannak azonban már büntetőjogilag is jelentős cselekmények is, amik azért már kilépnek a hálózatos cselekedetek kategóriájából. Ilyen lehet például különféle fontos személyeknek kiadva magunkat felhívni titkárnőket, hogy áruljanak el bizonyos jelszavakat. Ez a módszer tulajdonképpen a bitbuherálások királyának, a buffer overrun-nak a legszögesebb ellentéte, mégis vele alkotják a színvonalas törések csúcsát. Védelem, a buffer overrun-hoz hasonlóan, gyakorlatilag nincs ellene – a szervert meg lehet patch-elni, de a titkárnőt nem.

[Ha én főnök lennék, azért szívesen megpróbálnám "patch-elgetni" a titkárnőmet. :) – Tom]

Látható, hogy milyen széles tárháza van a programozási furmányoknak, és mennyire nem elég néhány klikkelés, hogy a frissen installált szerverünket ki merjük rakni az Internetre. A szoftvertechnológia fejlődése is inkább homályt teremt az egyszeri fejlesztők fejecskéjében, akik egyre kevésbé igazodnak el az egymásra épülő modulok összefonódásaiban. A biztonság egyre nehezebb követelmény.

A következő alkalommal a védelemről lesz szó.

MaXX