You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _posts/2025-02-21-htb-yummy.md
+14-11Lines changed: 14 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,10 +9,10 @@ toc: true
9
9
header:
10
10
teaser: "/assets/images/headers/Yummy.png"
11
11
---
12
-
"Yummy" is a hard Linux machine that starts off by finding a Local File Inclusion (LFI) vulnerability in order to find several cron job scripts. These scripts lead to a database backup script of the website's source code that leaks a secret JWT key to forge a token for the admin account on the site. The backend is vulnerable to SQL injection that gives us initial access to the machine. Further enumeration reveals the password for another user that can run a command as another user to move laterally to a developer account. This account can run`rsync` as root, which allows us to copy the root user's SSH key.
12
+
Yummy is a hard box that starts with a Restaurant web app using Caddy web service, on port 80, where an attacker finds an arbitrary file read HTTP Location header, which is not handled and sanitized properly by the default Caddy configuration. This allows an attacker to find several `cronjob` scripts that allow downloading the web app source code. Reading the source code, the web app uses JWT RSA keypairs to forge an admin token and escalate privileges on the web app. The admin panel has an SQL injection, allowing arbitrary file write over a file running periodically (`cronjob`). Improper directory permissions allow the attacker to move laterally to `www-data` and eventually a `dev` user. The `dev` user can execute`rsync`binary as root, which helps escalate privileges to root.
13
13
14
14
# Reconnaissance
15
-
Our initial port scan only shows two standard ports open, 22 and 80.
15
+
Our initial port scan only shows two ports open: SSH on port 22 and a web server on port 80. By looking at the `http-server-header`, we identify that the server is running Caddy as a reverse proxy.
16
16
17
17
```
18
18
# Nmap 7.94SVN scan initiated Sun Oct 6 14:04:12 2024 as: nmap -p- -sCV -v -oN yummy.nmap 10.129.74.97
@@ -32,15 +32,17 @@ PORT STATE SERVICE VERSION
32
32
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
33
33
```
34
34
35
-
Navigating to the website redirects us to `yummy.htb` and also displays that the version in use is **Caddy**. We add this domain to the `/etc/hosts` file and continue to explore the webpages. After creating an account and logging in, we can make a reservation.
35
+
Navigating to the website redirects us to `yummy.htb`. We add this domain to the `/etc/hosts` file and continue to explore the webpages. The website is hosting a restaurant application to manage appointments and reservations. After creating an account and logging in, we can make a new reservation.
36
36
37
37

38
38
39
39
From our dashboard, it is possible to save our reservation to a calendar file (ics) via the `save iCalendar` option.
The request makes a call to the `/export/Yummy_reservation_YYYYMMDD_hhmmss` endpoint where the date is the current timestamp of the export. This endpoint is vulnerable to LFI and we can alter the request to read arbitrary files as the `www-data` user.
43
+
The request makes a call to the `/export/Yummy_reservation_YYYYMMDD_hhmmss` endpoint where the date is the current timestamp of the export. This endpoint is vulnerable to LFI and we can alter the request to read arbitrary files as the `www-data` user. Another thing to notice is that the cookie uses a JWT token which can be decoded with tools like [CyberChef](https://gchq.github.io/CyberChef/) or [jwt.io](https://jwt.io/). Decoding the token, there's a role `customer` and fields `e` and `n` are specified, which are essential encryption exponent and modulus respectively.
44
+
45
+
Manipulating the GET request to `/export/../../etc/passwd` gives us Arbitrary File Read.
44
46
45
47

46
48
@@ -75,11 +77,12 @@ cd /var/www
75
77
/usr/bin/zip -r backupapp.zip /opt/app
76
78
```
77
79
78
-
This zip file is a backup of the original source code located in `/opt/app`. After downloading the zip and extracting it, we have the application's source code.
80
+
We can download the backed-up file from `/var/www/backupapp.zip`. This zip file is a backup of the original source code located in `/opt/app`. Once unzipped, we can view the content of `app.py`.
79
81
80
82

81
83
82
-
We can proceed to do some code analysis and see if we can spot additional vulnerabilities or credentials. The login method in `app.py` looks interesting.
84
+
We can proceed to do some code analysis and see if we can spot additional vulnerabilities or credentials. The login method in `app.py` looks interesting. The pair of RSA keys are generated in the `config/signature.py`. The validation is done in the
85
+
`middleware/verification.py`.
83
86
84
87
```python
85
88
if user:
@@ -154,7 +157,7 @@ Let's perform a search query on the admin dashboard and intercept the request wi
0 commit comments