Jeder, der MySQL auf einem mit dem Internet verbundenen Computer betreibt, sollte diesen Abschnitt lesen, um die häufigsten sicherheitsspezifischen Fehler zu vermeiden.
In unserer Beschreibung zur Sicherheit wollen wir die Notwendigkeit betonen, den gesamten Serverhost (und nicht nur den MySQL-Server) gegen alle möglichen Angriffe zu schützen: Lauschangriffe, Modifikationen, Wiedergabe und DoS (Denial of Service, Dienstablehnung). Wir werden an dieser Stelle nicht alle Aspekte der Verfügbarkeit und Fehlertoleranz behandeln.
MySQL benutzt ein Sicherheitssystem, welches auf ACLs (Access Control Lists, Zugriffssteuerungslisten) basiert, für alle Verbindungen, Abfragen und anderen Operationen, die Benutzer durchzuführen versuchen können. Ferner unterstützt werden SSL-verschlüsselte Verbindungen zwischen MySQL-Clients und -Servern. Viele der hier beschriebenen Konzepte sind keineswegs MySQL-spezifisch, sondern gelten vielmehr für fast alle gängigen Anwendungen.
Wenn Sie MySQL ausführen, befolgen Sie, sofern irgendwie möglich, die folgenden Richtlinien:
Gewähren Sie niemals irgendjemandem
(mit Ausnahme von MySQL-root
-Konten)
Zugang zur Tabelle user
in der
mysql
-Datenbank! Dies ist
entscheidend. Das verschlüsselte
Passwort ist das echte Passwort in MySQL. Jeder,
der das Passwort kennt, welches in der Tabelle
user
aufgeführt ist, und Zugang zu dem
für das betreffende Konto gelisteten Host hat,
kann sich problemlos als dieser
Benutzer anmelden.
Machen Sie sich mit dem MySQL-Zugriffsberechtigungssystem
vertraut. Die Anweisungen GRANT
und
REVOKE
werden zur Steuerung des Zugriffs
auf MySQL verwendet. Gewähren Sie nie mehr Berechtigungen
als notwendig. Gewähren Sie Berechtigungen niemals allen
Hosts.
Checkliste:
Geben Sie mysql -u root
ein. Wenn Sie
mit dem Server erfolgreich eine Verbindung herstellen
können, ohne nach einem Passwort gefragt worden zu
sein, dann kann jede Person als MySQL-Benutzer
root
eine solche Verbindung mit Ihrem
MySQL-Server herstellen und hat nachfolgend alle
Berechtigungen! Lesen Sie noch einmal die
MySQL-Installationsanleitung und achten Sie dabei
insbesondere auf Informationen zur Einstellung eines
root
-Passworts. Siehe auch
Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“.
Überprüfen Sie mithilfe der Anweisung SHOW
GRANTS
, welche Konten worauf zugreifen
können. Entfernen Sie dann nicht erforderliche
Berechtigungen mit der
REVOKE
-Anweisung.
Speichern Sie Passwörter nicht unverschlüsselt in Ihrer
Datenbank. Wenn der Computer in die Hände eines Angreifers
fällt, kann dieser die Passwortliste lesen und die
Passwörter verwenden. Verwenden Sie stattdessen
MD5()
, SHA1()
oder
eine andere unidirektionale Hashing-Funktion und speichern
Sie den Hash-Wert.
Wählen Sie keine Passwörter aus Wörterbüchern aus. Es gibt Spezialprogramme zum Knacken von Passwörtern. Sogar Passwörter wie „fisch98“ sind ziemlich schlecht. Wesentlich besser ist „duaxg98“: Dieses Passwort enthält zwar auch das Wort „fisch“, jedoch wurde jeder Buchstabe auf einer QWERTZ-Standardtastatur durch die Taste zu seiner Linken ersetzt. Eine andere Methode, ein Passwort zu verwenden, besteht darin, die jeweils ersten Buchstaben jedes Wortes eines Satzes zu benutzen; so wird etwa aus „Hoch auf dem gelben Wagen“ ganz einfach das Passwort „HadgW“. Dieses Passwort ist vergleichsweise einfach zu merken und einzugeben, aber für jemanden, der den Satz gar nicht kennt, schwer zu erraten.
Schaffen Sie eine Firewall an. Diese schützt Sie vor mindestens 50 Prozent aller Sicherheitslücken in jeder beliebigen Software. Setzen Sie MySQL hinter die Firewall oder in eine DMZ (De-Militarized Zone, entmilitarisierte Zone).
Checkliste:
Scannen Sie Ihre Ports aus dem Internet heraus mithilfe
eines Tools wie nmap
. MySQL verwendet
standardmäßig Port 3306. Dieser Port sollte für nicht
vertrauenswürdige Hosts nicht zugänglich sein. Eine
weitere einfache Möglichkeit zu prüfen, ob Ihr
MySQL-Port offen ist oder nicht, besteht darin, den
folgenden Befehl an einem entfernten System einzugeben.
Hierbei ist server_host
der
Hostname oder die IP-Nummer des Hosts, auf dem Ihr
MySQL-Server ausgeführt wird:
shell> telnet server_host
3306
Wenn Sie eine Verbindung erhalten und einige sinnlose Zeichen angezeigt werden, ist der Port geöffnet; Sie sollten ihn dann umgehend mit Ihrer Firewall oder Ihrem Router schließen, es sei denn, es gäbe einen guten Grund dafür, dass der Port offen ist. Wenn telnet hängt oder die Verbindung abgewiesen wird, dann ist der Port gesperrt – so soll es sein.
Schenken Sie Daten, die von Benutzern Ihrer Anwendungen
eingegeben wurden, kein Vertrauen. Benutzer können Ihren
Code überlisten, indem Sie Sonderzeichen oder Zeichenfolgen
mit vorangestelltem Escape-Zeichen in Webformulare, URLs
oder andere Eingabemöglichkeiten der von Ihnen erstellten
Anwendungen eintragen. Sie müssen sicherstellen, dass Ihre
Anwendung auch dann sicher bleibt, wenn ein Benutzer so
etwas wie „; DROP DATABASE
mysql;
“ eingibt. Dies ist natürlich ein
Extrembeispiel, aber große Sicherheitslücken oder
umfangreiche Datenverlust können die Folge sein, wenn
Hacker ähnliche Methoden verwenden und Sie nicht darauf
vorbereitet sind.
Ein häufiger Fehler besteht darin, nur String-Datenwerte zu
schützen. Denken Sie daran, auch numerische Daten
abzusichern. Wenn eine Anwendung eine Abfrage wie
SELECT * FROM table WHERE ID=234
erzeugt,
weil ein Benutzer den Wert 234
eingegeben
hat, dann kann der Benutzer auch den Wert 234 OR
1=1
eingeben; hierauf generiert die Anwendung die
Abfrage SELECT * FROM table WHERE ID=234 OR
1=1
. Folge ist, dass der Server jeden Datensatz in
der Tabelle abruft. Mithin wird jeder Datensatz angezeigt,
zudem wird der Server extrem belastet. Die einfachste
Möglichkeit, sich vor diesem Angriffstyp zu schützen,
besteht darin, numerische Konstanten in Anführungszeichen
zu setzen: SELECT * FROM table WHERE
ID='234'
. Gibt nämlich der Benutzer zusätzliche
Daten an, so werden sie alle Teil des Strings. In einem
numerischen Kontext wandelt MySQL diesen String automatisch
in eine Zahl um und entfernt alle nachfolgenden
nichtnumerischen Zeichen.
Manche Leute gehen davon aus, dass eine Datenbank, die nur öffentlich verfügbare Daten enthält, nicht geschützt werden muss. Das stimmt nicht. Auch wenn jeder Datensatz in der Datenbank angezeigt werden dürfte, sollten Sie sich trotzdem etwa gegen DoS-Angriffe schützen (z. B. jene, die auf der im vorigen Absatz beschriebenen Methode basieren und den Server dazu bringen, Ressourcen zu vergeuden). Andernfalls kann Ihr Server für legitime Benutzer unerreichbar werden.
Checkliste:
Geben Sie einfache und doppelte Anführungszeichen
(‘'
’ bzw.
‘"
’) in all Ihre
Webformulare ein. Wird irgendein MySQL-Fehler
ausgegeben, dann untersuchen Sie das Problem umgehend.
Versuchen Sie, dynamische URLs durch Hinzufügen von
%22
(‘"
’),
%23
(‘#
’) und
%27
(‘'
’) zu modifizieren.
Versuchen Sie, die Datentypen in dynamischen URLs von numerischen auf Zeichentypen umzustellen, indem Sie die in den obigen Beispielen verwendeten Zeichen eingeben. Ihre Anwendung sollte gegen solche und ähnliche Angriffe gewappnet sein.
Geben Sie Buchstaben, Leer- und Sonderzeichen statt Ziffern in numerische Felder ein. Ihre Anwendung sollte diese Zeichen entfernen, bevor Sie sie an MySQL übergibt, oder andernfalls einen Fehler erzeugen. Die Übergabe ungeprüfter Werte an MySQL ist extrem gefährlich!
Überprüfen Sie die Daten, bevor Sie sie an MySQL übergeben.
Lassen Sie Ihre Anwendung eine Verbindung mit der Datenbank unter Verwendung eines anderen Benutzernamens als desjenigen herstellen, den Sie für administrative Zwecke verwenden. Geben Sie Ihren Anwendungen nicht mehr Zugriffsberechtigungen als notwendig.
Viele APIs stellen eine Methode bereit, um Sonderzeichen in Datenwerten zu kennzeichnen. Richtig verwendet, verhindert dies, dass Anwendungsbenutzer Werte eingeben können, die eine Erzeugung von Anweisungen durch die Anwendung verursachen könnten, welche einen anderen Effekt als von Ihnen erwünscht hervorrufen:
MySQL-C-API: Verwenden Sie den API-Aufruf
mysql_real_escape_string()
.
MySQL++: Verwenden Sie die Modifizierer
escape
und quote
für Abfrage-Streams.
PHP: Verwenden Sie die Funktion
mysql_escape_string()
, die auf der
gleichnamigen Funktion in der MySQL-C-API basiert. (Bei
PHP vor Version 4.0.3 benutzen Sie stattdessen
addslashes()
.) In PHP 5 können Sie
die Erweiterung mysqli
einsetzen, die
das verbesserte MySQL-Authentifizierungsprotokoll und
Passwörter ebenso unterstützt wie vorbereitete
Anweisungen mit Platzhaltern.
Perl DBI: Verwenden Sie die Methode
quote()
oder Platzhalter.
Ruby DBI: Verwenden Sie Platzhalter.
Java JDBC: Verwenden Sie ein
PreparedStatement
-Objekt und
Platzhalter.
Andere Programmierschnittstellen weisen möglicherweise ähnliche Funktionalitäten auf.
Übertragen Sie keine unverschlüsselten Daten über das Internet. Auf solche Daten kann jeder zugreifen, der die Zeit und die Fähigkeiten hat, sie abzufangen und für eigene Zwecke zu verwenden. Verwenden Sie stattdessen ein verschlüsseltes Protokoll wie SSL oder SSH. MySQL unterstützt interne SSL-Verbindungen ab Version 4.0. Eine andere Methode besteht in der Verwendung der SSH-Portweiterleitung, mit der man einen verschlüsselten (und komprimierten) Kommunikationstunnel einrichten kann.
Machen Sie sich mit den Hilfsprogrammen tcpdump und strings vertraut. In den meisten Fällen können Sie durch Absetzen eines Befehls wie des folgenden überprüfen, ob MySQL-Datenströme unverschlüsselt sind:
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
(Das funktioniert unter Linux und sollte mit kleinen Anpassungen auf unter anderen Betriebssystemen laufen.) Warnung: Wenn Sie keine Klartextdaten sehen, bedeutet dies nicht notwendigerweise, dass die Daten tatsächlich verschlüsselt sind. Sofern Sie ein hohes Maß an Sicherheit benötigen, sollten Sie sich an einen Sicherheitsexperten wenden.
Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.