Wizer CTF #7: Login Page

Link to challenge: CTF #7


In this pretty tricky challenge, we identify two vulnerabilities, which should be used in order to capture the flag. The first one is an SQL Injection (a.k.a. SQLi), and the second is the use of a weak hashing algorithm, which is a specific case of Cryptographic Failure.

Description of code

Our code presents an innocent login page (https://chal7.vercel.app/), which is using a login API endpoint. The developer used MYSQL and ran a query to select a matching user & password. To prevent certain issues, the developer then ran another query to verify that the row returned indeed includes the originally specified username and password. General Note, you might notice that the received JSON format is somewhat strange, it is basically a name/value array; the developer here used an easy way to transform an HTML form which is posted directly to the backend into a JSON format, likely the most common and convenient data transport format. This is typically done using something like the following command:
`var formData = JSON.stringify($(document.forms[0]).serializeArray());`.

What’s wrong with that approach?

Looking at the query, we can quickly identify an SQL Injection, which basically can be exploited by altering the username to inject unintended SQL into it. With that said, to capture the flag, it is not enough to exploit that vuln since the login process validates that the correct user row come first (at [0] position of the result). However, using the second weakness, which is the use of MD5 hashed passwords, an attacker could break in and impersonate an admin.

What would a successful SQLi & Weak Cypher attack look like in this case?

Once attackers realize that it's possible to exploit the SQLi vuln, they could invoke an API call to retrieve all the other users in the database, including their password. An attacker could send something like `"isaac' union all select * from users where '1'='1"` as the username (which in this case is sent within Array[0].value), then in return, they would get a list of all the users with their hashed passwords.
It is then easy to see who is an `admin` by looking at the `type` field of the returned list. The last step is to grab the MD5 hashed password and find a rainbow table or a free online search tool (such as CrackStation) to translate the MD5 back into the password and boom! the attacker can now login as an admin. An MD5 is a hash algorithm, which means that it's generally not decryptable, in other words, it's a `one way ticket` encryption. However, over the years, hackers created long lists of passwords (a.k.a. rainbow tables) with their MD5 source password, which is being used to crack mainly weaker passwords.

Side note: some players succeeded in creating a situation, using the SQLi vuln only, making the client code show that `issac` is an admin. This solution wasn't accepted by the system, for the simple reason that even if the client side `thinks` you're an admin, the server state still sees your user type and that's not considered a full impersonation.

So what?

SQLi is always very bad to have, even if you assume that you've encrypted everything properly. In this case it provides a crack with which the attacker can use another vuln to take over an admin account. Oftentimes, in the wild, an attacker won't use only a single vuln, and will likely combine techniques in order to get to the crown jewels the desire.

Attackers would not easily give up when they see some encrypted or hashed values, in many cases those could be bypassed or brute-forced into clear text values. Impersonating an admin could mean serious harm for the business, or yet again another step in a more sophisticated attack plan.

Main Takeaways:

Code Wizer!