Red Siege Challenge 2022

1 minute read

Challenge 1 - Unlocked Doors

These guys keep pretending they don’t exist and aren’t letting you join their club. See if you can let yourself in.

My initial thought was to try and perform an SQL injection attack in the login form to see if there was a way to access the authorized member IDs and their pins. Because form sanitization is done on the client-side, rather than the server, we can modify the HTML to disable the min and max number checks to input our SQLi statement.

1<input type="number" name="member_id" id="member_id" min="1000000" max="9999999" class="form-control mb-3" placeholder="Member ID" required="">

We can change this to:

1<input type="text" name="member_id" id="member_id" min="1000000" max="9999999" class="form-control mb-3" placeholder="Member ID" required="">

Then, we can input any string into the form without it telling us it needs to be a seven digit member ID. Putting " or ""=" in as the member ID did not work as an SQLi attack, but it did provide some valuable information. It seems the website is running “Werkzeug powered traceback interpreter.” which shows Python tracebacks for Flask applications. There is one useful line in this traceback;

1File "/app/app.py", line 22, in index
2  if str(hash(int(member_id) * 1337) % 10000) != pin or len(member_id) != 7:
3ValueError: invalid literal for int() with base 10: '" or ""="'

Here we have the check for access to the website. If the member ID is not seven digits, or if member_id*1337%10000 != pin, then access will be denied. So, we can simply use any 7 digit number and plug it into that equation to find the pin. For example, when ID = 1234567, we can do (1234567*1337)%10000 and the pin will be 6079.