Monday, January 7, 2008

SQL injection: Getting the table names

Yep, this is a big issue. There are a few good tricks that will allow you to query for this information, especially in M$SQL. MySQL has a few small tricks as well, but this 'feature' was introduced in version 5 and is disabled on some servers.

# MySQL and the INFORMATION_SCHEMA database

Now this neat feature was introduced in MySQL 5. Its a database containing.. information about all databases, tables, colums, fields, priveleges, keys.. you name it! The best thing is, the default setting is to allow normal users read rights to this database. It CAN be disabled by a MySQL administrator, but most MySQL 5 server i have seen are 'vulnerable'.

Detailed information can be found here: http://dev.mysql.com/doc/refman/5.0/en/information-schema.html

Here is a small example from the MySQL command line: (TABLE_SCHEMA means 'database')
mysql> SELECT `TABLE_NAME` FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA` = 'mysql';
+---------------------------+
| TABLE_NAME
+---------------------------+
| columns_priv
| db
| func
| help_category
| help_keyword
| help_relation
| help_topic
| host
| proc
| procs_priv
| tables_priv
| time_zone
| time_zone_leap_second
| time_zone_name
| time_zone_transition
| time_zone_transition_type
| user
+---------------------------+
17 rows in set (0.06 sec)

I guess you get the point here.. using this method in a union select query gets you all the information you need.


# M$SQL SysObjects table

In M$SQL we have someting way better! The SysObjects table is a table containing all information about all objects created in the database. As far as i know there is no way of disabling a normal user access to this table. A simple example is:

(Look for a (U)ser table starting with 'user')
SELECT name FROM sysObjects WHERE type = 'U' AND
name LIKE 'user%'


# 'Social' engineering

If all else fails, social engineering is the place/thing to be!.. go.!..do!
This can be very tedious and its pretty hard to keep up, but it almost never fails! You can make a very educated guess about what the database tables are, if you look good enough. I usually start at a login form. If the user and password fields are named: 'user' and 'password' the database layout will probably be:

  1. Pretty default.. table is probably something like: user(s), login, account(s) etc..
  2. Database and table names are probably english
Now if the developer chose to name these fields: 'usr' and 'passwd' we should look at some other table / column names, and if these fields are in a non-english language, take it from there.. (and good luck ;)

If you have some visual feedback from your SQL injection you can query for the database() and user() values.

SELECT database(), user();

This too will give you some basic information about the developers naming standards.

If you still can't find any tables, its probably a good idea to start thinking about table prefixes. This is somewhat outdated but still often used. Now what kind of prefix are we looking for? Most of them are 3 letter combinations followed by an underscore. Acronyms for software packages or company names. Only very seldom i find a site that uses the 'tbl_' prefix. But it did happen .. once ;)
Find out the developers name, what the CMS system is called, what the site itself is called and try a few acronyms.

--------

All this guessing around might seem to be based on a whole lot of luck, but it really isn't. In my time as a security auditor i found only one single website that had such obscure table names i could not detect any user tables.

It might take you a few hours, but you will get there. Trust me. ;)

Oh and dont forget, table names are case insensitive! ;)