SQL Injection Fundamentals
Database Enumeration
MySQL Fingerprinting
As we cover MySQL
in this module, let us fingerprint MySQL
databases. The following queries and their output will tell us that we are dealing with MySQL
:
SELECT @@version
When we have full query output
MySQL Version 'i.e. 10.3.22-MariaDB-1ubuntu1
'
In MSSQL it returns MSSQL version. Error with other DBMS.
SELECT POW(1,1)
When we only have numeric output
1
Error with other DBMS
SELECT SLEEP(5)
Blind/No Output
Delays page response for 5 seconds and returns 0
.
Will not delay response with other DBMS
INFORMATION_SCHEMA Database
To pull data from tables using UNION SELECT
, we need to properly form our SELECT
queries. To do so, we need the following information:
List of databases
List of tables within each database
List of columns within each table
With the above information, we can form our SELECT
statement to dump data from any column in any table within any database inside the DBMS. This is where we can utilize the INFORMATION_SCHEMA
Database.
So, to reference a table present in another DB, we can use the dot ‘.
’ operator. For example, to SELECT
a table users
present in a database named my_database
, we can use:
SCHEMATA
We can find the current database with the SELECT database()
query
TABLES
To find all tables within a database, we can use the TABLES
table in the INFORMATION_SCHEMA
Database.
COLUMNS
Practical Examples
Get DB name
Get Tables From DB name
Get Columns From DB Name (at least used with tables with 1 column)
Reading Files
Privileges
Reading data is much more common than writing data, which is strictly reserved for privileged users in modern DBMSes, as it can lead to system exploitation, as we will see. For example, in MySQL
, the DB user must have the FILE
privilege to load a file's content into a table and then dump data from that table and read files. So, let us start by gathering data about our user privileges within the database to decide whether we will read and/or write files to the back-end server.
DB User
While we do not necessarily need database administrator (DBA) privileges to read data, this is becoming more required in modern DBMSes, as only DBA are given such privileges. The same applies to other common databases. If we do have DBA privileges, then it is much more probable that we have file-read privileges. If we do not, then we have to check our privileges to see what we can do. To be able to find our current DB user, we can use any of the following queries:
User Privileges
First of all, we can test if we have super admin privileges with the following query:
We can also dump other privileges we have directly from the schema, with the following query:
From here, we can add WHERE grantee="'root'@'localhost'"
to only show our current user root
privileges.
We see that the FILE
privilege is listed for our user, enabling us to read files and potentially even write files. Thus, we can proceed with attempting to read files.
LOAD_FILE
Writing Files
Write File Privileges
To be able to write files to the back-end server using a MySQL database, we require three things:
User with
FILE
privilege enabledMySQL global
secure_file_priv
variable not enabledWrite access to the location we want to write to on the back-end server
secure_file_priv
Otherwise, if a certain directory is set, we can only read from the folder specified by the variable.
On the other hand, NULL
means we cannot read/write from any directory.
MariaDB has this variable set to empty by default, which lets us read/write to any file if the user has the FILE
privilege. However, MySQL
uses /var/lib/mysql-files
as the default folder.
However, as we are using a UNION
injection, we have to get the value using a SELECT
statement. This shouldn't be a problem, as all variables and most configurations' are stored within the INFORMATION_SCHEMA
database.
SELECT INTO OUTFILE
Writing Files through SQL Injection
Let's try writing a text file to the webroot and verify if we have write permissions.
Writing a Web Shell
Having confirmed write permissions, we can go ahead and write a PHP web shell to the webroot folder. We can write the following PHP webshell to be able to execute commands directly on the back-end server:
Once again, we don't see any errors, which means the file write probably worked. This can be verified by browsing to the /shell.php
file and executing commands via the 0
parameter, with ?0=id
in our URL:
Last updated