Fragen? Antworten! Siehe auch: Alternativlos
Ich erwähne das, weil das aus meiner Sicht der Grund ist, wieso dieser Code es bis in OpenSSL geschafft hat. Wenn jemand da den reinkommenden Code auditiert, guckt der nach den hochriskanten Bugs. Und nach der langläufigen Einschätzung, die so bei Entwicklern vertreten wird, ist out of bounds read halt viel weniger riskant als andere Bug-Klassen. Ich kann mir gut vorstellen, dass der Auditor einfach nicht nach der Art von Bug geguckt hat. Der hat memcpy gesehen, und hat dann kurz geprüft, dass vorher genug alloziert wurde und das keinen Buffer Overflow gibt, und dann hat der das durchgewunken.
Normalerweise ist es nur meine Aufgabe, Bugs zu finden. Ich bin nicht dafür zuständig, dass die auch gefixt werden. Aber trotzdem kriege ich natürlich regelmäßig mit, wenn die Entwickler dann Bugs schließen, weil sie das Risiko für zu gering halten. Wenn es mal organisatorische Zwänge gibt, dass Bugs gefixt werden müssen, beziehen die sich normalerweise nur auf "wichtige" Bugs wie Buffer Overflows. Und auch da kommt es häufiger vor, dass Entwickler sich weigern, sowas zu fixen, wenn man ihnen keinen Exploit zeigt.
Wenn ich meine Zeit damit verbringe, einen Exploit zu schreiben, finde ich aber keine Bugs in der Zeit. Daher wird das im Normalfall nicht passieren. Wenn Entwickler einen Exploit sehen wollen, geht es nicht um den Bug, sondern das ist der Versuch, den Bug loszuwerden, ohne ihn fixen zu müssen, indem der Gegenseite eine massive Bringschuld aufgebürdet wird. Schon der Einspruch des Entwicklers kostet ihn (mich sowieso) im Allgemeinen deutlich mehr Aufwand, als das Fixen des Bugs gekostet hätte.
Warum schreibe ich das hier alles? Weil ich darauf hinweisen möchte, dass das System im Moment kaputt ist. Die Perspektive von Entwicklern auf Bugs müsste sein: You file it, we fix it. Und zwar sofort. Keine Rückfragen, kein Gezeter, kein Prokrastinieren. Alle Bugs werden sofort gefixt. Wir reden ja hier von professionellen Entwicklern. Die kriegen Geld dafür, ordentlichen Code zu schreiben. Wenn es da einen Defekt gibt, wird der sofort gefixt. Fertig. Und zwar unabhängig davon, ob das jetzt ein Security-Problem ist oder "nur" Defense in Depth. Egal ob man das Szenario für realistisch hält oder nicht.
Einige Firmen haben das mit Incentive-Programmen herbeizuführen versucht. Sowas wie "es gibt Bonus, wenn man höchstens soundsoviele Bugs hat". Das führt leider dazu, dass einige Entwickler einfach alle einkommenden Bugs sofort als ungültig schließen, damit sie nicht in die Statistik gelangen. So einfach ist es halt nicht.
Und bei Open Source ist das natürlich noch mal schwieriger, Qualitätsstandards einzuhalten, wenn du niemandem damit drohen kannst, dass er gefeuert wird, wenn er sich nicht zusammenreißt.
Ein technisches Detail habe ich noch. OpenSSL hat seinen eigenen Allokator gebaut. Theo de Raadt (der Mann hinter OpenBSD) regt sich schön darüber auf, erwähnt aber nur die halbe Problematik. Eigentlich nur ein Viertel. Der Grund, wieso OpenSSL einen eigenen Allokator gebaut hat, ist — so vermute ich jedenfalls — OpenBSD. OpenBSD scheißt auf Performance und macht ihr malloc dafür richtig doll langsam. Auf der Plus-Seite segfaultet das dann sofort, wenn jemand was falsch macht. Kann man vertreten, aber dann sieht das halt in Benchmarks so aus, als sei OpenSSL furchtbar langsam. OpenSSL hatte jetzt zwei Möglichkeiten. Sie hätten mal ihren Code entkernen können, damit der nicht so viel malloc und free aufruft. Das wäre die gute Variante gewesen. OpenSSL hat aber lieber getrickst und sich einen eigenen Allokator gebaut und damit, wie Theo kritisiert, die Sicherheitsvorteile des OpenBSD-Allokators aufgegeben.
Die andere Hälfte der Medaille ist, dass der OpenSSL-Allokator vom System größere Blöcke Speicher anfordert, und dann innerhalb von denen selber fummelt. Das heißt aber, wenn ich jetzt 64k Speicher leaken kann, die aus einem dieser Blöcke kommen, dass da nur OpenSSL-Daten drin sind. Keine anderen Daten, die jemand anderes im Prozess alloziert hat. Das ist es, was diesen Bug so tödlich macht. Ihr habt vielleicht die Speicherdumps gesehen, die gerade so rumfliegen. Das ist der Grund, wieso da immer gleich so saftige Daten drinstehen wie unverschlüsselte HTTP-Dumps mit den Cookies und Passwörtern.
Update: Einen noch. Ich kriege hier gerade von einigen Leuten Flak, weil ich den Namen des Entwicklers gebloggt habe. Als ob der vorher nicht dran gestanden hätte an dem git-Checkout. Ist das legitim, den als Schuldigen zu nennen? Ich finde: Ja. Denn die Entwickler müssen endlich chirurgisch von der Idee befreit werden, dass Fehler halt unvermeidbar sind, und daher ist das nicht so wichtig, dass ich hier ordentlich arbeite. Es geht hier nicht um Shaming, sondern darum, dass alle sehen: Das hat ein Typ wie du und ich geschrieben, und hier hat ein anderer Typ wie du und ich das durchgewunken. Wenn die das falsch machen, muss ich vielleicht auch mein Verhalten ändern? Ja, müssen wir. Alle von uns.
Wir reden hier von einer der zentralen Sicherheits-Komponenten auf der Welt. Es ist völlig unakzeptabel, dass so ein Ranz-Code bei OpenSSL submitted wird. Es ist auch völlig unakzeptabel, dass OpenSSL das dann nicht merkt und diesen Ranz-Code eingecheckt hat. Und es ist völlig unakzeptabel, dass diese Tretmine da jetzt seit Jahren in der Codebasis herumgammelte, und es keiner gemerkt hat. Wir haben hier ein massives Prozess-Problem, und dem müssen wir uns stellen. Das hat mit Shaming nichts zu tun. Millionen von Menschen verlassen sich auf diese Software. Da checkt man nicht mal eben kurz was ein, wird schon gutgehen. Die Wartung von OpenSSL sollte mit einer ähnlichen Verantwortung verbunden sein wie das Warten von Flugzeugen oder Atomkraftwerken. Wir haben schlicht keine Entschuldigungen dafür, dass es soweit kommen konnte.
Natürlich konnte ich auch an dem T-Systems-Joke nicht vorbeigehen, das seht ihr sicher ein. :-)