4

This question is about a small detail in a larger school assignment. I have been struggling with this little problem for too long.

ABCTF arranged a Capture-the-Flag competition which was held earlier this year. One of the problems in this competition, was an SQL injection. This is a URL to the task description, and this is a URL to the login form which was to be injected. There is a published solution for this problem, and it looks like this:

Username: -1' union select 1,1,1,1 #

Password: 1

I need to figure out what the backend query string might look like. The simplest, most naive assumption would be

String query = "SELECT FROM user WHERE username = '" + inputA + "' AND password = '" + inputB + "';";
execute(query);

But this would produce

String query = "SELECT FROM users WHERE username = '-1' union select 1,1,1,1 #' AND password = '1';";
execute(query);

The most glaring problem with this, is that the quotes are unbalanced. Furthermore, I don't understand what output the SELECT statement would produce. As I've understood it, the "#" character is used to denote temporary tables in MS SQL Server, like "#temporary_table". I've played with other, simple statements as well, but nothing that would make sense.

Does anyone have an idea to what the backend query could look like? Any suggestion is appreciated.

2

The link states that the solution involves adding a whole new fake line via union where every value is a 1. The -1 as a username tries to make sure the query doesn't return any valid data as server side languages usually only compare the first row. An example would be the following code.

password = execute("SELECT password FROM users WHERE username = '{$username}'");
if( password != $password ) fail();
pass();

Which results in

password = execute("SELECT password FROM users WHERE username = '-1' union select 1,1,1,1 #'");
// no username called -1 means that the only row returned is the artificial row, so password = 1
if( password != 1 ) fail();
pass();

Keep in mind that there are millions of ways this code would work, ranging from only SQL to vulnerabilities in the web application. However, I found this approach most realistic.

  • Thank you! Everything is clear to me now. I didn't know you could generate a row with a SELECT statement by giving constants instead of variables as input. Does this apply to most DBMS? – Magnus Nov 3 '16 at 10:08
  • 1
    UNION is standard SQL and thus supported by most DBMS. This is also the important part - what you do is generating an inline table where every value is 1 and adding it to the existing table that you made sure is empty. You could use the variable names of the other columns to not only have a 1 but it would require you to know what the variable names of the other three columns are and which one of them is the password column. Without inside knowledge or debugging output, this is unlikely to know. – James Cameron Nov 3 '16 at 10:13
7

In MySQL, the # symbol can be used as a comment marker. Quote marks in comments don't have to balance.

Not all SQL instances run on Microsoft databases.

  • Thank you! I was quick to assume that it was MS SQL Server in the backend. It was the first result I found when trying to figure out what the "#" could be. – Magnus Nov 3 '16 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.