The goal of this exercise is to hack web application on https://kbe.felk.cvut.cz that is vulnerable to SQL injection. The whole attack is divided into a series of tasks that build on each other. Therefore, although not mandatory, it is recommended to solve the tasks one by one in the given order.
On the main page, there is a login form that you need to pass through, without knowledge of password. As a username use your FEL login name.
Hint #1
- In the backend code, there is an SQL query verifying credentials:
SELECT username FROM users WHERE username = '$_POST[username]' AND password = SHA1('$_POST[password]' . '$salt')
. If this query returns an existing username, you are in. Otherwise, a wrong credentials warning is shown.
Hint #2
- Fill the username input (i.e. variable
$_POST[username]
) with a value such that theWHERE
clause of the query is true for your username. Pay attention to apostrophe'
characters. Use hash symbol#
to comment out an unwanted rest of the query.
As you can see, your account is not only password-protected, but also PIN-protected. Try to find out your PIN using the vulnerability from the previous task.
Hint #1
- Table
users
contains columnpin
.
Hint #2
- The
WHERE
clause can provide you a binary signal (successful login / wrong credentials).
Hint #3
- Check presence and position of individual digits [0-9] in the PIN string that is associated with your username. Use SQL AND operator in combination with SQL LIKE operator to do that.
PIN-protection didn't stop you? Easy-peasy? Well, try to defeat the next layer of protection - Time-based One-Time Password - widely used industry standard for 2-factor authentication.
Hint #1
- Steal the secret key from the database (column
secret
), insert it into e.g. Google Authenticator and generate valid OTP values. - For convenience, the secret can be copied to Google Authenticator using QR code generated as follows:
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/kbe?secret=YOUR_SECRET_KEY
. But, don't do this in real-world applications as you share the secret with a 3rd party (Google)! Moreover the requested url (including the secret) can be stored in browser's history or in (proxy)-server logs, where can be found by an attacker. Instead, use a verified library and generate QR codes locally on your server.
Hint #2
- The PIN page welcomes you with your username. Could you force it to welcome you with your secret key?
Hint #3
- Results of two SQL queries can be merged using UNION operator. Ensure that the original query result is empty and add a new query returning your secret key.
Bored of reading secret messages? Let's do some harm. What about exfiltrating all data stored in the database?
Hint #1
- Once you get in, there is another SQL injection vulnerability, which allows you to retrieve all the data easily.
Hint #2
- The pagination mechanism is based on the following SQL query:
SELECT date_time, base64_message_xor_key AS message FROM messages WHERE username = '$_SESSION[username]' LIMIT 1 OFFSET $_GET[offset]
.
Hint #3
- Modify the query via URL get parameter
offset
. Use UNION operator to add more rows to the aboveSELECT
. Note that the number of columns for both SELECTs must be the same. A dummy column can be added this way:SELECT password, 1 FROM ...
. Also, try to avoid exfiltration via the second column (i.e.base64_message_xor_key
) as the data are processed by a decryption algorithm before printing. Putting non-encrypted data there would result in a mess. SQL CONCAT function can be handy in situations when we need to join multiple columns into one.
Do you want to be able to login as a regular user? Well, then you need to know your password in addition to your PIN and SECRET. Passwords of student accounts are hashed and salted in the following inappropriate way: sha1($password . $salt)
, where $password is five characters long string consisting of lowercase letters and numbers. Write a script trying all possible combinations.
Hint
- Why does it appear in some databases of pre-hashed candidate passwords whereas your shorter password doesn't?
Hint
- Metadata about all MySQL databases are stored in special INFORMATION_SCHEMA database.
As you might have noticed, the secret messages are stored in an encrypted form in the database, but before printing they are decrypted on the backend. Since you have access to both forms of messages, try to derive the xor key used for encoding/decoding your messages.
Hint
- For derivation, use the last message (i.e.
Well, that's all...
) as it does not contain any HTML tags.