KomplexitĂ€t đŸ€œđŸ€› IT Sicherheit: 2 interessante Beispiele

BeschĂ€ftigt man sich regelmĂ€ĂŸig mit IT Sicherheitsthemen – etwa in dem man jede Woche den Security Now Podcast hört – gibt es immer wieder Momente in denen man völlig davon ĂŒberzeugt ist, dass das Internet nur von Kaugummi und Klebeband zusammengehalten wird. Aber oft sind es auch Themen, die tief in die unheimlich komplex gewordenen Infrastukturen und Technologien fĂŒhren, mit denen wir tĂ€glich hantieren. Das sind zwei Beispiele aus den letzten Wochen, die ich besonders spannend fand:

Trojan Source – UTF-8 und Tricks mit dem bidi Encoding 🔀

Aus Security Now 843: Zwei britische Forscher haben ein spannendes Paper mit dem Titel ‚Trojan Source: Invisible Vulnerabilities‚ veröffentlicht, welches im Endeffekt diese Kernaussage hat:

Bei der PrĂŒfung eines Programmcodes kann man nicht mehr davon ausgehen, dass der Code, den man vor sich auf dem Bildschirm sieht, der gleiche Code ist, der spĂ€ter vom Compiler ‚gesehen‘ und in ein Programm ĂŒbersetzt wird

So wie das Trojanische Pferd auch nicht das war, was es zu sein schien…Wenn man darĂŒber einen Moment nachdenkt zieht es einem nach und nach das Fundament unter dem FĂŒĂŸen weg, auf dem die ÜberprĂŒfung von SoftwarequalitĂ€t und -sicherheit von jeher stand:

Ein Mensch schaut sich in einem Editor den Quellcode, den ein anderer Mensch – oder inzwischen auch eine Maschine – geschrieben hat, versucht ihn zu verstehen und vergleicht ihn mit der Funktion, die der Code laut Pflichtenheft oder Eigenbeschreibung oder Stack Overflow Kommentar haben soll.

Im Paper werden nun unterschiedliche Verfahren beschrieben, wie man in Quellcode, der als Unicode gespeichert ist, subtile TĂ€uschungen einschmuggeln kann. Und dabei kommt die KomplexitĂ€t moderner Zeichensatzcodierungen, die den Anspruch haben letztlich jedes relevante Schriftsystem der Welt – und möglicherweise auch extraterrestrische – korrekt darstellen zu können, uns die Quere:

Neben vergleichsweise simplen Ticks wie dem EinfĂŒgen von breitenlosen und damit unsichtbaren Leerzeichen (Zero Width Space ZWSP), die Stringvergleiche scheitern lassen können, oder der Verwendung von Homoglyphen, die etwa zur EinfĂŒhrung alternativer Methodenaufrufe genutzt werden können, sind es die Nutzungen der Bidirectional Commands und davon gibt es einen ganzen Block:

Tabelle mit den UTF-8 Zeichen fĂŒr Richtungswechsel. Quelle: https://www.w3.org/International/questions/qa-bidi-unicode-controls

Die lassen sich sogar verschachteln und Àhnlich wie bei einem Stack in der Programmierung gibt es POP Anweisungen um Verschachtelungen wieder zu beenden und damit eine Schachtelungsebene nach oben zu gehen:

Tabelle mit den UTF-8 Zeichen fĂŒr Richtungswechsel. Quelle: https://www.w3.org/International/questions/qa-bidi-unicode-controls

Gerade mit dem Isolates, die komplette Gruppen von Zeichen als gemeinsames Element behandeln, und Kombinationen von BiDi Anweisungen lassen sich leicht FĂ€lle konstruieren, bei denen etwas, dass im Quellcodeeditor so aussieht:

...
/* Wenn SicherheitsprĂŒfung bestanden, dann return; */
if (check == true) 
     return;
else 
     throw new Exception("Keine Berechtigung!");

fĂŒr den Compiler hingegen so erscheint:

...
/* Wenn SicherheitsprĂŒfung bestanden, dann */ return;
if (check == true) 
     return;
else 
     throw new Exception("Keine Berechtigung!");

Hier wird also aus dem scheinbaren Kommentar am Ende eine Programmanweisung, die die Logik komplett aushebelt. Das solche subtilen Änderungen manchmal weitreichende Probleme verursachen, dafĂŒr ist der goto fail;-Bug ein gutes Beispiel, den Apple vor Jahren in seinem Betriebssystem hatte. Hier sah der fehlerhafte Abschnitt so aus:

if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
	goto fail;
	goto fail;

Richtig wÀre aber diese Variante gewesen:

if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
	goto fail;
goto fail;

Die dritte Zeile durfte also nicht eingerĂŒckt sein. Manchmal reicht schon ein TAB um den Unterschied zu machen und in diesem Fall gab es Vermutungen, dass vielleicht jemand dafĂŒr bezahlt worden sein könnte diesen subtilen Fehler an einer entscheidenden Stelle einzubauen. Das Risiko der Entdeckung wĂ€re gering gewesen und man hĂ€tte sich leicht damit herausreden können, dass es sich um einen Tippfehler gehandelt hat. Mit Hilfe der BiDi-Trickserei wĂ€re dieser Fehler nicht einmal bei einem sehr sorgfĂ€ltigen Code Review sichtbar gewesen.

Da die Forscher bereits reale Beispiele fĂŒr die Anwendung dieser Technik gefunden haben ist das keine rein theoretische Bedrohung. Da sich solcher Code sogar per Copy-and-Paste ĂŒbernehmen lĂ€sst sind beliebte Vorgehensweisen in der modernen Softwareentwicklung ebenfalls gefĂ€hrdet. Also noch mehr gefĂ€hrdet, als sie es immer schon waren 🙈

Was kann man tun?

GrundsĂ€tzlich wird man wohl abwarten mĂŒssen bis die Werkzeuge wie Editoren, Compilier und vielleicht auch Linter sich dieses Problems annehmen. Bis dahin gibt es vielleicht diese Faustformeln:

  • Gerade in den Quellcode eingebrachte Texte wie Kommentare und Strings sind Einstiegspunkte fĂŒr diese Art von Angriff
  • Die Auswirkung der bidi-Tricksereien enden beim nĂ€chsten Zeilenumbruch. Eine einheitliche Quellcodeformatierung, die z. B. eingebettete Kommentare nicht in der gleichen Zeile stehen lĂ€sst wie Code, kann ein paar Varianten vermutlich aushebeln
  • Bei der Nutzung von fremden Programmcodes muss man noch stĂ€rker als bisher schon auf deren QualitĂ€t achten. Was immer schon notwendig, und immer schon schwierig war

HTTP Request Smuggeling đŸ§±â›ïž

Aus Security Now 846: Auch dieses Problem wird durch KomplexitÀt verursacht, aber auf einer ganz anderen Ebene: Hier geht es darum, dass zwei oder mehr hintereinander geschaltete Webserver, die am Bedienen eines Webrequests beteiligt sind, das dabei verwendete HTTP Protokoll nicht einheitlich interpretieren.

Und im Endeffekt unterschiedliche Vorstellungen davon haben, welche Webrequests sie eigentlich gerade verarbeiten.

Dieses Problem ist kein ganz neues Problem, aber heute noch relevanter, da es inzwischen gÀngige Praxis ist, dass mehr als ein Server am Ausliefern einer Seite beteiligt ist:

  • Proxy Server werden vor den eigentlichen Applikationsserver geschaltet, um die Last zu verringern
  • Webserver wie Apache oder nginx liegen vor den Applikationsservern um TLS zu terminieren oder Loginfunktionen – z. B. Shibboleth – zu ĂŒbernehmen
  • Loadbalancer sind Netzwerkkomponenten, die die Zugriffe auf nachgelagerte Server verteilen, um Lasten gleichmĂ€ĂŸig verarbeitbar zu machen
  • Dienste wie Cloudflare bieten ihren Kunden durch vorschaltete Systeme Schutz vor Denial of Service Angriffen, die eigentlichen Server sind nicht mehr direkt erreichbar
  • Und alle denkbaren Kombinationen davon….

FĂŒr die effiziente Kommunikation zwischen diesen Servern werden verschiedene Webrequests gerne hintereinander gehĂ€ngt, damit sie sich schnell ĂŒber die gleiche Verbindung ĂŒbertragen lassen.

Aber wie schafft man es dem einen Server etwas anderes vorzugaukeln, als dem spĂ€ter drankommenden Server? In dem man die zwei Optionen, die der HTTP Standard als Mittel bietet um die LĂ€nge eines Request zu definieren – und damit bei hintereinander gehĂ€ngten Requests zu definieren, wo der eine aufhört und der andere beginnt – so trickreich nutzt, dass die beteiligten Server zu unterschiedlichen Ansichten darĂŒber gelangen, wo die Grenze zwischen zwei Requests liegt. Auch wenn es laut dem Standard eigentlich klar wĂ€re, wie vorzugehen ist:

“According to the HTTP/1.1 standards, if both Content-Length and Transfer-Encoding headers are passed, Transfer-Encoding takes precedence.”

Quelle auf Medium

Auf diese Weise kann es bei anfĂ€lligen Serverkombinationen – und laut diesem Paper sind das viele – gelingen einen Zugriff auf einen Backend Server abzusetzen, der eigentlich von den davor geschalteten Servern gefiltert werden sollte. Das kann insbesondere dann relevant sein, wenn die vorgeschalteten Server das Login- und Rechtemanagement ĂŒbernehmen.

FĂŒr eine bestimmte Variante des Request Smugglings vulnerable Serverkombinationen laut diesem Paper

Auch hier ist es nicht leicht etwas zu tun. Wie immer muss man natĂŒrlich seine Server aktuell halten, so gibt es z. B. fĂŒr Tomcat inzwischen einen Patch fĂŒr CVE-2021-33037, der auch mit HTTP Request Smuggeling zu tun hat. Aber auf das Verhalten vieler Komponenten, wie z. B. Loadbalancer, hat man wenig bis keinen Zugriff.

Eine Lösung ist es vielleicht die kritischen Entscheidungen einer Applikation – also die Rechte- und Zugriffskontrolle – möglichst weit nach hinten zu verlagern, bis in die Applikationsserver. Das nimmt einem Optimierungsmöglichkeiten, aber dafĂŒr ist der Server, der am Ende die Requests verarbeitet, auch derjenige, der entscheidet welche Requests zulĂ€ssig sind.

ihbrune

1991-1996: Studium der Naturwissenschaftlichen Informatik an der UniversitĂ€t Bielefeld. Abschluss mit der Diplomarbeit zum Thema 'Analyse von ein- und mehrdimensionalen Zeitreihen mit der Karhunen-LoĂšve- und Wavelet Transformation' || 1996-1997: Wissenschaftlicher Mitarbeiter am Lehrstuhl Prof. A. Knoll in der Technischen FakultĂ€t der UniversitĂ€t Bielefeld im Projekt 'LANeCo: Local Area Net Configuration' || 1998- 2018: TĂ€tigkeit im BIS - Bielefelder Informationssystem an der UniversitĂ€t Bielefeld || Seit Oktober 2018: Leitung der Abteilung Informationssysteme und ProzessunterstĂŒtzung im BITS