# Advent 2014 Day 21 : Otp

otp was a nice (and painful) web challenge in the advent calendar CTF 2014.

We were provided with the source code of the web application and with an URL: the objective was to successfully login to the web site to get the flag.

To log in the web application we need to submit a password, paired with the token we are provided as an hidden field in the form, and this pair of credentials is valid for 10 seconds: if the token has expired we won’t be able to log in, so what we need to do is to find a way to generate a token and exfiltrate the password generated by the application for that specific token, before it expires.

As it’s possible to observe from the source code, the query at line 31 is dynamic, so it’s possible to perform a SQL injection attack against the application.

By sending a tampered token value in the POST request, it’s possible to notice that we are facing a union based injection attack: infact if we send something like this:

token=' UNION SELECT 1;


we would be presented with the following output in the web page

It would at this point be easy to enumerate the database structure, tables and columns to exfiltrate some valid data, but it would have been too easy; at line 25 we can see

which makes this challenge a real pain. Infact, as the comment suggets, this is a really tiny yet powerful firewall, because to enumerate the database, we’d need to access the sqlite_master table, where metadata about table structure are stored, but guess what? this is filtered and we cant.

So, no table enumeration: we need to find an alternative way to exfiltrate a valid password to log in.

I’m not that good at sql injection attacks, and in fact it took me a while to figure this out, but after a lot of trial and error i learned that column names are not needed to read data from them

I’ve tried the following injection query and eventually it resulted in the last generated password correctly exfiltrated.

token=' UNION SELECT pass FROM (SELECT 1 AS expire, 2 AS pass, 3 AS token UNION SELECT * FROM otp order by token desc LIMIT 0,1);


now all i needed was to be fast enaugh to exfiltrate a valid password and login within 10 seconds.

bash and curl came to the rescue, i put togeder this dirty and terrible script that helped me to login and get the flag