FreeBSD-s intézkedések a NULL pointer dereference támadások ellen

Címkék

A FreeBSD projekt egy errata-t adott ki, amelyben arról tájékoztatja a felhasználókat, hogy bevezetésre kerül egy olyan funkció, amellyel letiltható, hogy a felhasználó 0-s címre tudjon mappelni. Ezzel korlátozható a felhasználó azon képessége, hogy a kernel NULL pointer dereference-eket privilégium-szint emelésre tudja felhasználni.

A C programozási nyelvben az "address 0"-t vagy NULL-t allokálatlan memória kifejezésére használják. NULL (értékű) pointer feloldása (dereference - a memória területhez való hozzáférés a pointer-en keresztül) gyakori programozási hiba. Ez akkor következhet be, amikor a programozó anélkül használja a mutatót, hogy a használat előtt megfelelően ellenőrizné, hogy annak értéke nem NULL. A NULL pointer feloldása normális esetben user processz esetén segmentation fault-on keresztül a végrehajtás befejezésével, kernelben pedig page fault panic-kal jár.

A legtöbb architektúrán a FreeBSD kernel két részre osztja a processz virtuális memória címtartományt: kernel és user részekre. Ez a megvalósítás javítja a rendszerhívás-teljesítményt. Azonban ebben a megoldásban a 0-s cím az user által kontrollált virtuális címtartományba kerül. Ha a kernel egy bug folytán egy NULL pointer-t old fel, akkor egy rosszindulatú processz, amely kódot vagy adatot mappelt a 0-s címre, képes lehet manipulálni a kernel viselkedését.

Például, ha egy rosszindulatú processz a 0-s címre mappel kódot, majd triggerel egy kernel bugot amelynek következtében NULL pointer feloldásra kerül sor, akkor a kernel ahelyett, hogy pánikolna, a kódot fogja végrehajtani kernel privilégiumokkal.

Hogy ez elkerülhető legyen, a FreeBSD bevezeti a 'security.bsd.map_at_zero' sysctl változót, amellyel letiltható, hogy a felhasználó a 0-s címre mappeljen.

A FreeBSD 8-ban és az azután kiadott verziókban ez a funkció már be lesz kapcsolva. A FreeBSD 7-ben, és az azt megelőző verziókban ez a funkció ki van kapcsolva. A bekapcsolásához a 'security.bsd.map_at_zero' sysctl értéket 0-ra kell állítani.

Extrém esetekben ritkán előfordulhat, hogy bizonyos alkalmazások a 0-s címre akarnak mappelni. Gondos tesztelés szükséges e funkció engedélyezése előtt, kiváltképp, ha valaki virtuális gép és emulációs technológiákat, vagy régebbi a.out formátumú binárisokat használ.

A részletek az errata-ban.

Hozzászólások

Itt volt az ideje. A Linux kernelben 2007 októbere óta ott van hasonló céllal a vm.mmap_min_addr

--
trey @ gépház

Mármint hogy az egész elképzelésre érted, ugye? A semminél talán azért többet.

Julien Tinnes ezt írta róla:

"Of course, this doesn't solve the complete issue of "to userland pointer dereferences" and it also breaks the somewhat useful feature of being able to map the first pages (this breaks Dosemu for instance), but in practice this has been effective enough to make exploitation of many vulnerabilities harder or impossible."

--
trey @ gépház

>amelynek következtében NULL pointer feloldásra kerül sor, akkor a kernel ahelyett, hogy pánikolna, a >kódot fogja végrehajtani kernel privilégiumokkal.

Nem ertem, elvileg attol fuggetlenul kene tovabbra is panikolnia hogy eppen mi van az adott teruleten, nem?

Miert kellene?
Azert panikol, mert nem mappelt memoriara hivatkozik, ezert jon a pagefault, amire meg a panic (linuxon nem is panic, csak oops).
Ha a juzer map-eli, akkor mar egy teljesen legalis memoriahozzaferes lesz - igy mukodnek azok a syscall-ok is, ahol pointert adsz at.

--
Fontos feladatot soha ne bizz olyan gepre, amit egyedul is fel tudsz emelni!

Például, ha egy rosszindulatú processz a 0-s címre mappel kódot, majd triggerel egy kernel bugot amelynek következtében NULL pointer feloldásra kerül sor, akkor a kernel ahelyett, hogy pánikolna, a kódot fogja végrehajtani kernel privilégiumokkal

Gondolom altalaban ennel azert bonyolultabb kihasznalni egy null pointer dereference-t, mert a null pointer valoszinuleg nem rogton egy fuggveny pointerkent lesz ertelmezve, hogy azonnal esz nelkul odaugorjon a mi kodunkra a proci.
Peldanak okaert ebben az exploitban is a hibasan feloldott null pointer egy strukturara mutat, aminek az egyik pointer tipusu eleme altal mutatott ertekehez hozzavagyol 1-et a kod (tobbek kozott ennek mar nem szabadna lefutnia). Ezert spender abba a pointer tipusu elembe (a null pointer altal mutatott strukturaban) a tun device mmap muvelethez tartozo fuggvenypointer cimet irja, igy ahhoz vagyolja hozza az 1-et a kod - alapbol a tun device mmap muveletehez tartozo fuggvenypointer 0, mert a tun device-t nem lehet mmap-polni. Ezek utan amikor bemmapolja a tun device-t, az atirt fuggvenypointernek hala az 1-es cimre ugrik a proci (0 vagy 1 = 1), oda viszont addigra spender mar egy ugroutasitast tett a sajat fo kodjara, ami aztan azt csinal amit akar.

- Use the Source Luke ! -

Változó, a Linux sendpage bug ami 2.4 és 2.6 kerneleket is érintette az pl. ha jól emlékszem pont közvetlen fv. ptr. volt, ahogy a régebbi FreeBSD 6.x/7.x protosw bug is.

És persze vannak olyan ptr. deref. bugok, amelyek nem használhatók ki másra, csak DoS-re, annál szoktak egyesek kalimpálni a fórumban, hogy dehisz csak 3 soros...

nezd en nem tudtam, hogy azt a hibat te talaltad, azt hittem azt csinaltad mint spender, hogy lattad a javitast es irtal a hibara egy exploitot - utobbi, leven az exploit nem tul bonyolult, nem nagy szam, szemben azzal ha tenyleg te szurod ki a hibat. Tevedtem (ezt mar akkor is belattam), bocsanat.

- Use the Source Luke ! -

Ott tévedsz, hogy a hiba megtalálása nem feltétlenül nehezebb, mint a kihasználása. Sőt, a probléma értelmezése és exploitálása sok esetben jóval nehezebb, mint a megtalálása (ezt a fuzzeres bugvadászok - akik napi szinten több ezret képesek találni - is megerősíthetik ;). Az általad linkelt exploitnál is az volt a "nagy szám", hogy megnézve a forráskódot a hiba nem látszott kihasználhatónak privilégium szerzésre (10-ből 10 "security expert" el is ment mellette), közben mégis kihasználható és ezt bizonyította spender. Persze utólag már könnyen okos az ember.

De hogy kicsit jobban ontopicabb legyek és ezzel talán inkább megérted a mondanivalómat: Próbáld meg privilégium szerzésre kihasználni a FreeBSD swapgs kernel bugot. Nem kellett megtalálnod, megtette már más és pontosan le van írva a probléma is, úgyhogy biztos nem lesz nehéz innentől már exploitot írni rá... ;)

en pedig az "azt csinaltad mint spender" reszre reagaltam, mert azt probaltad kifejezni, hogy spender egyszeruen csak 'mas bugjaval probalt ekeskedni', nem volt benne semmi "nagy szam". A PoC exploitommal nem is erdemes egy mondatban sem emliteni, mert az csak tesztelesi cellal kerult ki (bele is van irva nagy betukkel), amikor lattam, hogy nem lesz belole mar tobb DoS-nel.

De akik ismernek jobban, azok tudjak, hogy szoktam erre mondani egy hasonlatot... A buveszetnel es illuziokeltesnel is csak addig "nagy szam" a produkcio, amig nem ismeri a nezo a 'titkot'. Amikor megtudja pedig csak legyint, hogy "csak ennyi?"

Igy van ez IT Sec temaban is, ezert nem erdemes elarulni ezeket a titkokat... (Ahogy en se teszem meg az eredeti topickal kapcsolatban es nem arulok el egy titkot a FreeBSD intezkedese kapcsan, majd idovel biztos megteszi mas)

A kernel és a user két különböző térben fut? Ha igen, akkor miért a user 0-s címre ugrik?