본문 바로가기

malware

SQL Injections in MySQL LIMIT clause

728x90

Countless number of articles was written on the exploitation of SQL Injections. This post is dedicated to a very specific situation. When assessing the severity of SQL Injection in certain application, I encountered a problem, which I was not able to solve quickly using web search. It’s about a question if SQL injection vulnerability in the LIMIT clause in MySQL 5.x database is currently exploitable.

Example query:

Of course, important is the fact that the above query contains ORDER BY clause. In MySQL we cannot use ORDER BY before UNION. If ORDER BY was not there it would be actually very easy to exploit it simply using just UNION syntax. The problem has appeared at stackoverflow and it was discussed at sla.ckers too. Sorry no results.

So let’s look at the syntax of the SELECT in the MySQL 5 documentation

After the LIMIT clause may occur following clauses: PROCEDURE and INTO. This INTO clause is not interesting, unless the application uses a database account with permission to write files, which nowadays is rather rare situation in the wild. It turns out that it is possible to solve our problem using PROCEDURE clause.

The only stored procedure available by default in MySQL is ANALYSE  (see docs).

Let’s give it a try:

ANALYSE procedure can also take two parameters:

Does not bode us well. Let’s see whether the parameters of ANALYSE are evaluated.

gives us immediate response:

Therefore, sleep() is certainly not being called. I didn’t give up so fast and I finally found the vector:

Voilà! The above solution is based on handy known technique of so-called error based injection. If, therefore, our vulnerable web application discloses the errors of the database engine (this is a real chance, such bad practices are common), we solve the problem. What if our target doesn’t display errors? Are we still able to exploit it successfully?

It turns out that we can combine the above method with another well-known technique – time based injection. In this case, our solution will be as follows:

It works. What is interesting that using SLEEP is not possible in this case. That’s why there must be a BENCHMARK instead.

Update: As BigBear pointed out in the comment, very similar solution was actually posted earlier on rdot. Thanks!

728x90