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
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.
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:
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.
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
The passwords were also successfully extracted from the database. The hashes can now be appropriately formatted before being cracked with either
John the Ripper.
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
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.
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.