A HUP-on már rendkívül szórakoztató eszmecsere alakult ki a legújabb Linux kernel jogosultság-kiterjesztés sebezhetőséggel kapcsolatban, én igyekeztem megállni a szócséplést, amíg legalább nagy vonalakban megértem, hogy miről is van szó :) A probléma részleteivel kapcsolatban remek összefoglaló olvasható Jason A Donenfeld blogján, én is ezt tanulmányoztam, és az alábbi összefoglaló is ez alapján születik.
Top-down megközelítéssel a probléma a 2.6.39-es Linux kernelben került bevezetésre, Linus múlt héten commitolta a javítást. Ez előtt a verzió előtt egy #ifndef kigyilkolta a sebezhető mem_write() függvényt még mielőtt lefordult volna. Ez a függvény a folyamatok memóriaterületének írását teszi lehetővé a /proc/<pid>/mem-en keresztül. A kernel 2.6.39-es változatának kiadásakor úgy gondolták, hogy a mem_write()-ba bevezetett ellenőrzések megakadályozzák a lehetőség rosszindulatú kihasználását - tévedtek (Linus szavaival: "the /proc/<pid>/mem handling really isn't very robust" :)
A csibészkedést két ellenőrzés hivatott megakadályozni, ezek közül az első azt garantálja, hogy egy folyamat csak a saját memóriaterületét írhatja. Ennek a megkerüléséhet első körben érdemes elolvasnunk az exec() manualját, ami úgy indít, hogy "[Ez a függvénycsalád] lecseréli az aktuális folyamat image-ét egy új folyamatéra". Vagyis egy SUID root binárist exec()-elve annak a memóriaterületére írhatnék, ami nekem nagyon jó lenne. Erre egy elegáns megoldás a su használata, ami megteszi azt a szívességet, hogy stderr-re egy az egyben kirakja a neki átadott érvénytelen paramétereket. A hibakimenetet egy megfelelő helyre pozicionált, /proc/self/mem-re mutató fájlleíróba irányítva öröm lesz és boldogság.
Azaz csak lenne, ugyanis van még egy ellenőrzés, ami a folyamathoz rendelt self_exec_id változó értékét ellenőrzi. Ez az érték minden egyes exec()-re egyel nő, az ellenőrző rutin pedig azt vizsgálja, hogy a memória fájlleíróját megnyitó folyamat self_exec_id-ja megegyezik-e az azt írni kívánó folyamatéval. Az előző megoldásban a su folyamat id-ja tehát magasabb lesz a leírót létrehozónál, így bukta van.
Azonban ez a korlátozás megkerülhető a feladatok "párhuzamosításával":
Először is forkoljuk magunkat, az így kapott gyerek folyamat self_exec_id-ja meg fog egyezni a miénkkel. A gyerek folyamatban hívjuk az exec()-t, amivel létrehozzuk a fájlleírót a szülő folyamat memóriájára - ezt megtehetjük, az open() ugyanis mindig engedélyezett. Ha a szülő folyamat exec()-eli a shellkódot kiköpő su-t, a fájlleírót létrehozó folyamat és a su self_exec_id-ja meg fog egyezni! A gyerek folyamat szépen visszadja a létrehozott leírót a szülőnek, aki ennek birtokában megcsinálhatja az stderr megfelelő átirányítását, így a su végül önkéntelenül beletúr a saját memóriájába.
Magátólértetődő választás a shellkódot a su exit()-jének helyére írni, hiszen ez gyakorlatilag közvetlenül a hibaüzenet (shellkód) kiírása után meg is hívódik. Probléma akkor van, ha a su-t pozíciófüggetlennek (-PIE) fordították, így a kernel alkalmazza rá az ASLR-t, mi meg nem tudjuk, hova kell írni. A népszerű disztrók többségénél ez azonban úgy tűnik, nincs így, és a szerencsésebb esetekben (SUSE?) is elképzelhető, hogy lehet találni más megfelelő SUID állományt, vagy a nyers erőhöz lehet fordulni.
Az érintett/javított disztrókról sajnos még nem találtam rendes listát. Remélem nem néztem be semmit, ha mégis, kommenteljetek, javítok! ;)
Friss: Az exploitokat meg majdnem elfelejtettem :)
- mempodipper.c (csak ezt néztem meg tüzetesebben, a többivel óvatosan!)
- sd megoldása Pythonban
- Fedorára, su helyett gpasswd-vel
eax_ 2012.01.25. 19:52:22
"Eközben a szülő folyamat exec()-eli a shellkódot kiköpő su-t, így a fájlleírót létrehozó folyamat és a su self_exec_id-ja meg fog egyezni! Végül a gyerek folyamat szépen visszadja létrehozott leírót a szülőnek, aki ennek birtokában megcsinálhatja az stderr megfelelő átirányítását, így a su végül önkéntelenül beletúr a saját memóriájába."
A szulo meg az elott kapja meg az fd-t, es csinalja meg az atiranyitast, hogy atexecelodne su-ba, utana ez mar relative nehez. :)
buherator · http://buhera.blog.hu 2012.01.25. 19:59:24
EQ · http://rycon.hu 2012.01.25. 21:49:58
buherator · http://buhera.blog.hu 2012.01.25. 22:02:05
EQ · http://rycon.hu 2012.01.25. 22:08:20
Hunger 2012.01.26. 10:14:58
Ezt is megértük. :)