BACKRONYM strikes back

Posted by jonas on Monday, August 31, 2015

In der Regel verlaufen unsere PHP-Minor-Updates praktisch unbemerkt; so auch unser gestriges Update von PHP 5.6.10 auf 5.6.12 - unbemerkt, bis auf einen Fall: Die PHP-Applikation eines Users weigerte sich spontan, noch eine Datenbankverbindung mit mysql_connect() aufzubauen, obwohl die Zugangsdaten mehrfach kontrolliert wirklich gestimmt haben. Die erstaunliche Meldung:

MySQL server has gone away

… und zwar bereits direkt zum Verbindungsaufbau, noch bevor der Client irgendwas an den MySQL-Server gesendet hat. Und jetzt der spannende Teil: Ein Downgrade auf PHP 5.6.10 behebt das Problem; die Verbindung kommt einwandfrei zustande.

Nach einigem Debugging stellte sich dann als Wurzel allen Übels heraus, dass die Applikation des Users die Konstante MYSQL_CLIENT_SSL beim Verbindungsaufbau angibt. Huh..? Die Verbindung zu MySQL findet über einen lokalen Socket statt (nicht über’s Netzwerk); SSL-Support haben wir an dieser Stelle, wo die Kommunikation ohnehin lokal bleibt, gar nicht mit drin. Wie hat das überhaupt jemals funktionieren können?

Die Erklärung ist: BACKRONYM, eine MySQL-Schwachstelle, die Sicherheitsforschern in den Duo Security Labs aufgefallen ist und die im zugehörigen Blogpost wie folgt skizziert wird:

no matter how hard we tried (no matter how many MYSQL_OPT_SSL_* options we set) we could not make the client enforce the use of SSL. If the server claimed not to support it, the client would happily communicate over plain old, unencrypted TCP!

Genau so hat die Applikation des betreffenden Users in der Vergangenheit dann auch funktioniert: Sie wollte gerne SSL sprechen; der Server sagte, kann ich nicht; daraufhin hat’s der Client dann fröhlich ohne SSL gemacht.

Seit PHP 5.6.11 ist genau damit aber Schluss; die BACKRONYM-Schwachstelle ist dort clientseitig geschlossen worden, was in Bug 69669 dokumentiert worden ist.

Dieser Fix betrifft aber letztlich nur PHP, konkret also den dort von uns eingesetzten “native driver”, mysqlnd. Der MySQL-Client selbst und alle gegen die MySQL-Client-Library linkenden Applikationen sind von dem Fix “verschont”, leiden also weiterhin unter dieser Schwachstelle - die zwar irrelevant für Verbindungen über den lokalen Socket ist; wer aber MySQL-Verbindungen über’s Netz zu Remote-Hosts durchführt und das mit SSL abgesichert sehen möchte, der sollte sich entsprechend vorsehen, denn ein Fix ist nicht in Sicht - oder, wie die Sicherheitsforscher es süffisant in ihrem Blogpost formulieren:

Actually, the good news is that the MySQL team has already realized his was a problem, and implemented a fix. Like, over a year ago. The bad news? The fix was only applied to MySQL 5.7.3 and later; 5.7.x is not yet even a GA release! (Also, the fix was applied to version 6.1.3 of the standalone libmysqlclient distribution). The worse news? In many cases, the “fix” is not enabled by default! So, while we haven’t collected any real data on the subject, we’re pretty confident that the vast majority of libmysqlclient users are affected by this issue.

Bei uns kommen Remote-MySQL-Verbindungen insbesondere für die Master-Slave-Verbindungen zwecks MySQL-Backup zum Tragen, auch wenn wir damit noch innerhalb des Rechenzentrums bleiben (jeder Standort hat eigene Backup-Server). Diese Verbindungen laufen aber nicht über die SSL-Implementierung von MySQL, sondern über dedizierte SSH-Tunnel pro Host.

Wessen Applikationen nun also sonst noch spontan mit dem Upgrade auf PHP 5.6.12 kaputtgegangen sein sollten: Das tut uns ausgesprochen leid, aber der Fix ist wichtig und die Verbindungskonfiguration, die mit dem Fix kaputtgeht, war auch in der Vergangenheit immer schon falsch; es war vielmehr ein Fehler, dass sie überhaupt je funktioniert hat.