In the previous part of the article, we had looked at some incidents to better understand how attackers try to find SQL injection vulnerabilities. Instead of looking for other incidents, I’ve decided to write a short introduction about testing your own application using publicly available automatic tools.
Constantly searching for vulnerabilities on your web applications and services is vital. Most of the time, such systems are exposed to the Internet and it is certain that sooner or later, someone will try to exploit their vulnerabilities.
We’ll use a popular tool called sqlmap which is capable of detecting vulnerabilities using several different methods, including blind injection. You can download the latest version of the software at http://sqlmap.org/.
Before running tests on your own app, I’d recommend you to do some practice with the tool on a site made to be vulnerable. You can find many websites to practice your hacking skills (which is a good and useful thing to do, I absolutely recommend it), for example, Google’s Gruyere project, which can be used both online or in your own environment or ITSEC Games’ bWAPP.I’ll use the latter as Gruyere doesn’t contain SQL-related vulnerabilities.
Setting up bWAPP
Alternatively, you may use bee-box, a premade environment with bWAPP in it.
After setting up your environment, you should download and extract bWAPP to your webroot. For this demonstration, I’ve extracted it to the bWAPP subfolder, therefore, the webapp is accessible at http://localhost/bWAPP/.
Next, you should configure the database access credentials. You should change the value assigned to $db_username and $db_password in /admin/settings.php.
The final step is to set up the database, which can be done by visiting /install.php (in my case, http://localhost/bWAPP/install.php) using a browser.
sqlmap was written in Python, therefore you’ll need a Python interpreter to use it. I’ll use the same VM I used for bWAPP. You’ll only need to download and extract the archive and you are ready to go.
Getting our hands dirty
Now that we set up the environment, it’s time to find some vulnerabilities. You’ll need to log in to access the vulnerable parts of bWAPP. For this you can find the default login credentials above the input fields.
After we have logged in, we’ll see a list of vulnerabilities. Let’s select a simpler one, “SQL Injection (GET/Search)”. We’ll get to the page http://localhost/bWAPP/sqli_1.php which allows us to search in a simple film database. You may find similar input fields in your own app, too.
A simple scan
Let’s search for the word “Terminator” and see the request. You may use a packet sniffer, like Wireshark or the browsers development console – the Network tab should contain the requests in an easy-to-read format.
Firstly, notice that the request URI was /sqli_1.php?title=Terminator&action=search; the string which you enter to the input field gets sent to the server in the request string, as a GET parameter.
Secondly, as I’ve mentioned, you’ll need to log in to see the vulnerable demo apps. Being a command line tool, sqlmap is not suitable to log in, so we’ll need to make bWAPP believe that the requests sent by sqlmap were sent by our browser. A good way to achieve this is called Session Hijacking. As you probably know, PHP allows to identify users and store data belonging to them using sessions. Each user is identified by a session cookie called PHPSESSID. If sqlmap sends this cookie while scanning, bWAPP will think that the requests were sent by our browser which is logged in.
In my case, the value of the Cookie header is the following.
I’ll configure sqlmap to send both PHPSESSID and security_level cookies to be sure that the webapp produces the same output as in the browser.
It’s time to find out whether one of the parameters is vulnerable. For this, you’ll need to run a command similar to this:
python sqlmap.py --url="http://localhost/bWAPP/sqli_1.php?title=Terminator&action=search" -p title --cookie="PHPSESSID=bklva5tfl14t8ec8pslldpmur4; security_level=0"
The --url option should specify the page to scan, the -p option sets which parameter should be tested for SQL injection. The values of the cookies should be set by the --cookie option.
The scans are cached. If you wish to rerun the whole scan, use the --flush-session option.
Sqlmap can recognizethe vendor of the database management system and will ask whether it should run the tests for other dialects of SQL. It will also ask if you wish to proceed the tests once it found a vulnerability. If you ask it to do so, you should get the following output.
This shows that the parameter checked is vulnerable and shows the list of possible ways to exploit this vulnerability. Sqlmap can also be used for the exploitation phase of the attack too, but for now, let’s see some more about scanning.
In some cases, parameters don’t get sent in the URI but instead, in the request body, as POST parameters. A common example for such requests is the case of login forms – this way, it is possible to avoid saving the login credentials in the browser’s history and the HTTP server’s logs. The “SQL Injection (Login Form/Hero)” example in bWAPP works as a login form. To test such forms, you’ll need to use slightly different parameters for sqlmap.
python sqlmap.py --url="http://localhost/bWAPP/sqli_3.php" --data="login=Pink&password=Floyd&form=Submit" --cookie="security_level=0; PHPSESSID=t06r9a0v52ohq3bt8t5ar2i7u4" --risk=3
Firstly, you’ll have to specify the message body using the --data parameter. By default, sqlmap sets the Content Type to be application/x-www-form-urlencoded, so you can specify the parameters the same way you would in the URI. To see any effect in such forms, you’ll often have to use OR-based injection, which has to be enabled explicitly. This can be done interactively – sqlmap should ask you during the scan whether you’d like to use higher risk value –or using the --risk=3 option.
Also, you may have noticed that I haven’t specified any parameters. By default, this means that every GET and POST parameters will get tested.
Running the test shows that both login and password fields are vulnerable for SQL injection.
You might think that although I’ve mentioned automatic vulnerability testing, things shown earlier require a lot of manual work. You’re right, but fortunately, sqlmap is capable for crawling sites and parsing their content.
Automatically testing the login form we have tested previously is as simple as adding the –forms option to the command.
python sqlmap.py --url="http://localhost/bWAPP/sqli_3.php" –forms --cookie="PHPSESSID=nthuq084aalkri93cleodfs273; security_level=0" --risk=3
For each form it founds, sqlmap asks you whether you would like to run the tests on the specific form. If you choose to scan the one with the POST data login=&password=&form=submit, you’ll find that both the login and the password fields are vulnerable, just like in the previous part but this time, the software found you the injectable fields and you didn’t need to specify any of them.
Scanning your site
Most of the time, SQL queries are involved with things other than login forms or forms at all. For example, if you read a blog, the ID of the article you are watching will probably be in your request’s URI and the content associated with that ID comes from a database.
It would be nice to be able to scan a whole site for SQL injection including links, forms and so on. Fortunately, you can do this using the --crawl option of sqlmap. You’ll need to specify a number which will give the maximal depth for the crawling. Using this option doesn’t include forms, it will try to find vulnerable parameters in URIs from links for example, but it can be used with the --forms option.
BWAPP doesn’t really have any part to crawl. Instead, I will use my development environment for the BitNinja Dashboard as target – hopefully we won’t find anything :) . You should run the scan on a local instance of your own application. Keep in mind that by sending the test requests, sqlmap may insert unwanted content into your database or make the site unreachable.Please be really careful if you decide to scan your site in its production environment.
The command to run is:
python sqlmap.py --url="http://admin-devel.bitninja.io" --flush-session --crawl=3 --forms --batch
Fortunately, the scan didn’t find any injection points on the Dashboard’s publicly available parts. Did it find anything in your app?
I can not emphasize enough the importance of regular vulnerability testing. Anyone can (and will) make mistakes during development and it is vital to find these errors before an attacker could exploit them. Automatic tools like sqlmap help you find and fix vulnerabilities in a fast and cost-effective way. You may even include such tests into your release process.
The possibilities shown here are only the tip of the iceberg. Sqlmap is able to do much more than what you have seen here and there are dozens of other tools to use for finding different kinds of vulnerabilities. I’d encourage you to take a look at these tools, try them and if you find them useful, include them into your development process.
Of course, the BitNinja will detect your attempt. Please be careful with the testing. :)
Do you already have a favorite tool? Don’t hesitate to share it!