Warum der aktuelle MySQL-Exploit hier nicht greift
Gestern lief ein MySQL-Exploit durch meine Kommunikationskanäle durch. CVE-2016-6662 spricht von einer remote ausnutzbaren Lücke, die Code mit root-Rechten auf der Maschine ausführen kann. Betroffen sind alle Versionen von MySQL. Das ist ein GAU. Ein Super-GAU wäre es, wenn noch die Authentisierung wegfallen würde. Bei einer Überprüfung zeigten sich drei Gründe, warum mich das trotzdem nicht betrifft.
Funktionsweise
CVE-2016-6662 ist schnell erklärt.
Ein lokaler Benutzer legt eine shared Library mit dem gewünschten Schadcode im Dateisystem an einer Stelle ab, wo er Zugriff hat. I.d.R. wird das das /tmp-Verzeichnis oder sein Home-Verzeichnis sein.
Als nächstes meldet sich der Nutzer beim MySQL-Server an und lenkt die Ausgabe eines Logfiles auf den wohl bekannten Dateinamen einer Config-Datei des MySQL-Servers um. In dieses Logfile (also die Ini-Datei) schreibt er rein, dass die soeben abgelegte shared Library geladen werden soll. Alle Schreibzugriffe des MySQL-Servers erfolgen unter den Rechten des Daemon, nicht unter den Rechten des angemeldeten Nutzers. Der MySQL-Login muss nicht mal als Nutzer im Betriebssystem existieren.
Beim Restart des MySQL-Servers sorgt das mysqld_safe Startscript dafür, dass die Library mit root-Rechten geladen wird, bevor der Server die Rechte abgibt. Damit wird dann der vom Nutzer stammende Code unter root-Rechten ausgeführt.
Produktionseinsatz
Unser Setup ist produktiv, d.h. für Experimente durch die Nutzer besteht wenig Spielraum. Unser Setup stammt nicht aus einer Distribution, sondern ist im Laufe der Zeit organisch gewachsen. In diesem Fall ist das ein Vorteil.
Gegen das Ablegen von Dateien kann man nichts tun, denn genau das ist eine der Aufgaben, die der Server für den Nutzer erfüllen soll. In dem Fall z.B. ein Webhosting. Nehmen wir also an, der Nutzer hat den Schadcode auf dem Server abgelegt.
Das Überschreiben vorhandener INI-Dateien ist dem MySQL-Server nicht möglich, da bei uns diese Dateien dem administrierenden Nutzer root gehören. Damit scheidet das Überschreiben als Angriffsvektor schon mal aus.
Natürlich könnte der Angriff darüber erfolgen, dass eine andere INI-Datei erzeugt wird, die der Server beim Start parsen wird. Da gibt es einige Plätze, die in einen typischen MySQL-Server einkompiliert werden. Die Frage ist also, ob es klappen würde. Probieren wir das mal aus:
mysql> SELECT 'malicious config entry' INTO OUTFILE '/var/lib/mysql/my.cnf'; ERROR 1045 (28000): Access denied for user 'test'@'localhost' (using password: YES)
Ohja. Der MySQL-Nutzer hat gar nicht die Rechte für diesen Angriff! Aber es gab da ja noch andere Ideen:
mysql> set global general_log_file='/var/lib/mysql/my.cnf'; ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation
Schon wieder nichts?! Einen hab ich noch:
mysql> CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf > AFTER INSERT ON `active_table` FOR EACH ROW begin end; ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation
Für einen typischen shared-Hosting Kunden haben sich damit die Möglichkeiten des Angriffs erschöpft.
Aber nehmen wir mal an, es gäbe trotzdem eine Chance, eine INI-Datei zu beeinflussen. Dann würde bei uns nicht das Startscript mysqld_safe zum Zuge kommen, sondern ein eigenes Startscript, dass zuerst die Rechte wechselt und dann den MySQL-Server aufruft. Damit ist ausgeschlossen, dass der Schadcode mit Root-Rechten laufen könnte.
Fazit
Ende gut, alles gut? Nein, diese Art von Angriff zeigt, wie wichtig es ist, zwischen administrativen Aufgaben und Produktionsaufgaben zu unterscheiden. Das Problem wird erst dann relevant, wenn z.B. durch eine Distribution die Bequemlichkeit für den Anwender im Vordergrund steht. Oder wenn man den meist gelesenen Blog-Posts folgt und das Rechtesystem außer Kraft setzt.
Wie oft ich schon gelesen habe, dass SELinux ausgeschaltet werden muss anstelle die Regeln richtig zu setzen kann ich nicht mehr an zwei Händen abzählen.
1 Kommentare