Október 18-án javították azt a Linux kernelhibát, amely lokálisan korlátozott privilégiumszint-emelést tesz lehetővé Linuxon és Androidon. A sebezhetőséget már aktívan ki is használják, ezért erősen javasolt a frissítés.
A probléma felfedezője Phil Oester, biztonsági kutató. Oester HTTP-forgalom elemzése után kezdett el nyomozni, mivel az általa felügyelt rendszerek némelyikében behatolás nyomaira bukkant, de néhány file-módosításon kívül semmit nem talált – a logokban sem. A nyomozás során kiderült, hogy egy bizonyos utasítás-sorrendet követve (race condition) korlátozott lokális felhasználó beleírhat privilegizált állományokba, mivel a feltételek teljesülése esetén egy read-only memóriaterület és az alatta lévő állomány egyaránt írhatóvá válik.
Race condition
A hiba egyik fele a kernel copy-on-write memóriaműveleteket kezelő részében van. Ilyen műveletek akkor jönnek létre, amikor többen is ugyanazt az adatot akarják használni. Ekkor a kernel egy pointert ad minden igénylőnek olvasási joggal anélkül, hogy másolat készülne az adatról – ez csak akkor történik meg, ha az egyik adatfelhasználó változtatni akar azon (dirty bit). Ekkor készül csak tényleges másolat, hogy a többi igénylő számára láthatatlan maradjon a változás. Igen gyakori, hogy az ilyen megosztott adatok mégsem változnak, így a programok lefutása után meg lehet mondani a kernelnek, hogyan kezelje az adott memóriaterületet, a madvise rendszerhívással. Miután az alkalmazásnak nincs szüksége már az adott memóriaterületre, a MADV_DONTNEED ajánlást továbbítja a kernel felé.
A hibaforrás második fele a minden process által saját magának írható memóriaterület. A /proc filerendszerben találhatunk meg minden információt az éppen futó folyamatokról. A futó processeknek engedélyezett a /proc/self írása, így a /proc/self/mem is, ami az adott folyamat saját memóriaterülete, így amikor írási műveletet kérünk a megosztottan használt adatra, azonnal kapunk egy másolatot a memóriába. Fontos hangsúlyozni, hogy az írás a másolatba történik, nem az eredeti állományba.
Előidézés
Amíg a fenti két különböző folyamatot egymástól szeparáltan (by design) használjuk, nincs is semmi gond. Amikor azonban egy hosszú ciklusban gyors egymásutánban felváltva kérjük ezeket a folyamatokat, elérkezünk egy olyan ponthoz, amikor az adott másolatot eldobja a kernel (MADV_DONTNEED), a folyamatunk jelzi, hogy írnánk az állományba, de a másolatra mutató pointer még nem frissült, ehelyett az eredeti állományra mutat.
coresec@Bismarck ~/Documents/CVE-2016-5195-dirtycow $ ls
total 20
-rwxr-xr-x 1 coresec coresec 13568 Oct 28 21:30 dirtycow
-rw-r--r-- 1 coresec coresec 2826 Oct 28 21:25 dirtycow.c
coresec@Bismarck ~/Documents/CVE-2016-5195-dirtycow $ sudo -s
Bismarck CVE-2016-5195-dirtycow # echo Owned by root > root.file
Bismarck CVE-2016-5195-dirtycow # ls
total 24
-rwxr-xr-x 1 coresec coresec 13568 Oct 28 21:30 dirtycow
-rw-r--r-- 1 coresec coresec 2826 Oct 28 21:25 dirtycow.c
-rw-r--r-- 1 root root 14 Oct 29 19:50 root.file
Bismarck CVE-2016-5195-dirtycow # chmod 0404 root.file
Bismarck CVE-2016-5195-dirtycow # ls
total 24
-rwxr-xr-x 1 coresec coresec 13568 Oct 28 21:30 dirtycow
-rw-r--r-- 1 coresec coresec 2826 Oct 28 21:25 dirtycow.c
-r-----r-- 1 root root 14 Oct 29 19:50 root.file
Bismarck CVE-2016-5195-dirtycow # exit
exit
coresec@Bismarck ~/Documents/CVE-2016-5195-dirtycow $ echo pwned by user > root.file
bash: root.file: Permission denied
coresec@Bismarck ~/Documents/CVE-2016-5195-dirtycow $ cat /proc/cpuinfo | grep "model name" | uniq
model name : Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
coresec@Bismarck ~/Documents/CVE-2016-5195-dirtycow $ time ./dirtycow root.file pwnedbyuser
mmap 7f5b8a391000
madvise 0
procselfmem 1100000000
real 2m32.429s
user 0m7.272s
sys 4m8.884s
coresec@Bismarck ~/Documents/CVE-2016-5195-dirtycow $ cat root.file
pwnedbyuserot
A javítás
A hiba 2007 óta található meg a kernelben, Linus írja is, hogy próbálta javítani, de aztán más probléma elvonta a figyelmét. A javítás során beiktattak egy plusz ellenőrzést, amely csak azután engedi az írási műveletet, ha a copy-on-write befejeződött és a pointer frissült.
A javítás már elérhető Red Hat, Debian, Ubuntu, CentOS, Suse, OpenSuse és CloudLinux rendszerekre is.
sh4d0w