Softwareentwicklung mit Language-Theoretic Security (LANGSEC)

Das IoT-Paradigma — die Vernetzung von traditionell nicht netzwerkfähigen Geräten aus den Bereichen Verbraucher, Gewerbe, Industrie und Infrastruktur mit dem Internet — verspricht Komfort, Produktivitäts- und Effizienzsteigerungen. IoT ist ein recht junges Feld, doch das Wachstum im letzten Jahrzehnt war so enorm, dass man davon ausgehen kann, dass es bereits mehr IoT-Geräte als Menschen gibt

Ælla Chiana Moskopp — Security Consultant

30. September 2024

Warum IoT-Sicherheit wichtig ist

Das IoT-Paradigma — die Vernetzung von traditionell nicht netzwerkfähigen Geräten aus den Bereichen Verbraucher, Gewerbe, Industrie und Infrastruktur mit dem Internet — verspricht Komfort, Produktivitäts- und Effizienzsteigerungen. IoT ist ein recht junges Feld, doch das Wachstum im letzten Jahrzehnt war so enorm, dass man davon ausgehen kann, dass es bereits mehr IoT-Geräte als Menschen gibt

Die Verbindung des virtuellen Raums mit der physischen Welt bringt jedoch auch neue Bedrohungen mit sich: Mit dem Internet verbundene Smart Homes, medizinische Geräte sowie Fabriksteuerungs- und Überwachungssysteme können Online-Angriffe in Bedrohungen für Privatsphäre, Eigentum, das menschliche Wohlbefinden, Produktionsprozesse und — durch Denial-of-Service-Angriffe — die Infrastruktur des Internets selbst verwandeln. Geräte sind ständig eingeschaltet und im schlimmsten Fall unverwaltet und unbeaufsichtigt, sodass erfolgreiche Angriffe schwerer zu erkennen sind als auf einer gängigen Computerplattform.

Hardware-Komponenten von Geräten wie Waschmaschinen oder Mikrowellen müssen Vorschriften entsprechen und werden strengen Tests unterzogen. Leider kann man das Gleiche nicht für die Software sagen, die auf durchschnittlichen IoT-Geräten läuft: Eine Umfrage von 2014 unter Führungskräften zeigte, dass Sicherheit die größte Sorge bei der Einführung von IoT-Technologie ist. Mit der zunehmenden Verbreitung seitdem ist es allgemein bekannt, dass jedes als „smart“ vermarktete Gerät (z. B. Fernseher, Steckdosen, Glühbirnen) IT-Sicherheitsrisiken darstellen kann – nicht nur für Endnutzer und Anbieter, sondern auch für die Gesellschaft im weiteren Sinne, wenn Gesundheits- oder andere kritische Infrastrukturen betroffen sind. Da es bis vor kurzem keine effektiven Vorschriften für Software-Sicherheit gab, mussten Unternehmen, die IoT-Geräte entwickeln (wie grandcentrix), eigene Sicherheitsstandards definieren und etablieren. Während Verordnungen wie der Cyber Resilience Act der Europäischen Union und Normen wie ETSI EN 303 645 („Cyber Security for Consumer Internet of Things") mittlerweile Mindestanforderungen an die IoT-Sicherheit festlegen, sind die Details der Systemarchitektur und der Softwareentwicklungsprozesse nicht streng reguliert, sodass Unternehmen selbst entscheiden müssen, wie sie diese Sicherheitsziele erreichen.

Sicherheit im IoT-Kontext bedeutet hauptsächlich, dass ein Gerät genau so funktioniert, wie es von legitimen Benutzern erwartet wird. Dies ist keine Eigenschaft, die zu einem beliebigen Zeitpunkt während der Entwicklung hinzugefügt werden kann — sie muss Teil des Prozesses sein. Eine bekannte Technik, die bei grandcentrix praktiziert wird, ist das Vier-Augen-Prinzip: Neuer Code wird nur akzeptiert, wenn ein:e Kolleg:in ihn genehmigt. Weitere Techniken sind Test Driven Development, bei der Tests vor der Implementierung erstellt werden, sowie Threat Modeling, bei der potenzielle Bedrohungen analysiert und priorisiert werden. In diesem Artikel wird ein weniger bekannter Ansatz zur Anwendung von Sprachphilosophie auf Code- und Datenformate erklärt, der als „Language-Theoretic Security“ (LANGSEC) bezeichnet wird.

Validierung vor Business Logic

Eine zentrale Erkenntnis von LANGSEC ist, dass fast alle Software Daten konsumiert und darauf reagiert, wobei die Eingabedaten den Programmzustand ähnlich wie eine Programmiersprache steuern, die nur grob spezifiziert ist. Erfahrene Entwickler:innen raten oft dazu, „Eingabedaten nicht zu vertrauen“, aber das ist selten umsetzbar — oft herrscht keine Einigkeit darüber, was „vertrauenswürdig“ bedeutet. Mangels strenger Richtlinien fügen die meisten Entwickler:innen Ad-hoc-Überprüfungen hinzu, ob die Daten ihren Erwartungen entsprechen, bevor der Code basierend auf diesen Daten irgendetwas tut. Manchmal jedoch lassen Entwickler:innen diese Überprüfungen aus, in der Annahme, dass Systembibliotheken oder der näher an der Business Logic befindliche Code die Validierung übernehmen.

Ein LANGSEC-Praktiker nennt eine solche Mischung aus Eingabevalidierung und Geschäftslogik einen „Shotgun Parser“ und klassifiziert ihn als gefährliches Antimuster: Möglicherweise sicherheitskritische Validierungen sind im gesamten Code verteilt wie die Kugeln einer Schrotflinte. Es könnte durchaus sein, dass alle Eingaben angemessen behandelt werden — aber es ist viel schwieriger, als eigentlich notwendig zu verstehen, was der resultierende Code bei beliebigen Eingaben tun wird. Die Prüfung eines mittelgroßen Shotgun Parsers kann Stunden dauern.

Einige gängige Sicherheitsprobleme entstehen dadurch, dass das mentale Modell der Entwickler:innen nicht mit dem Verhalten des Shotgun-Parsers übereinstimmt. Glücklicherweise ist es möglich, nicht nur dieses Antipattern zu vermeiden, sondern eine ganze Kategorie von Fehlern zu eliminieren: Dies lässt sich erreichen, indem man eine Grammatik für Eingabesprachen fordert und diese von den für die Implementierung verantwortlichen Entwickler:innen absegnen lässt, bevor irgendwelcher Code geschrieben wird. Die Software muss Eingabedaten gegen eine Grammatik überprüfen und bei ungültigen Eingaben abbrechen, sodass der nach einem Validierungsschritt ausgeführte Code nur noch gültige Daten verarbeiten muss; er ist leichter zu verstehen und wird durch eine Application Firewall geschützt. Der Validierungsschritt darf niemals versuchen, Daten zu „bereinigen“, da dies zu neuen Schwachstellen führen kann.

Ein Beispiel: Für einen Server, der über JSON mit mobilen Apps kommuniziert, müssen Backend-Entwickler:innen und Entwickler:innen mobiler Apps (Android und iOS) sich auf ein JSON-Schema einigen. Wenn ein solcher Server zusätzlich MQTT-Daten von IoT-Geräten empfängt, muss eine ähnliche formalisierte Vereinbarung zwischen Backend- und Embedded-Entwickler:innen bestehen.

Durch die Berücksichtigung von LANGSEC-Prinzipien in der Entwicklung bei grandcentrix stellten wir fest, dass solche Vereinbarungen nicht nur die Softwaresicherheit verbessern, sondern auch die Unit Testing und Integration Testing erleichtern: Mit maschinenlesbaren Grammatiken ist es trivial, auch sehr komplexe fiktive Datensätze für Tests und Fuzzing-Zwecke zu generieren. Falls Implementierungen voneinander abweichen, einigen sich die Entwickler:innen fast sofort darauf, welche Teile geändert werden müssen.

Vermeidung komplexer Eingabesprachen

Offensichtlich kann der LANGSEC-Ansatz die Entwicklung nur beschleunigen, wenn die Grammatik der Eingabedaten bekannt ist, bevor die Implementierung beginnt – aus demselben Grund, warum ein Shotgun Parser schwer zu überprüfen ist: Eine formale Spezifikation eines Datenformats aus existierendem Code oder Beispieldaten zu erarbeiten kann lange dauern – selbst wenn alles gut dokumentiert ist. Alle, die jemals eine Neu-Implementation, die sich auch im Fehlerfall genau wie das ursprüngliche Programm verhält, schreiben musste, werden dies wahrscheinlich bestätigen.

Ein weiteres Risiko besteht darin, dass die implizite Grammatik – inhärent in bestehendem Code oder Daten – möglicherweise zu komplex ist, um überhaupt validiert zu werden. Formale Sprachtheorie besagt, dass die Komplexität von Sprachen bestimmt, wie schwierig es ist, bestimmte Probleme zu lösen. Für Sprachen mit einer Grammatikkomplexität oberhalb eines Grenzwerts sind einige Eigenschaften unentscheidbar. Das Halteproblem zum Beispiel bedeutet, dass es für die meisten Programmiersprachen kein Programm geben kann, das bestimmen kann, ob ein anderes Programm jemals anhalten wird. Es ist also nicht notwendigerweise die Schuld von Entwickler:innen, wenn Ihr PC ein sich drehender Wasserball oder eine Sanduhr anzeigt, sondern eine Folge eines Naturgesetzes.

Bei hinreichend komplexen Sprachen kann die Interpretation von Daten vom Kontext abhängen. Dies kann zu Parser Differentials führen – Programme oder sogar Teile eines Programms können Daten unter Umständen unterschiedlich interpretieren. Solche Missverständnisse können bedeutende sicherheitsrelevante Folgen haben: Nachrichten, die von einem Teil eines Systems als unbedenklich angesehen werden, könnten bei einem anderen Teil bösartiges Verhalten auslösen. Notwendigerweise ist mindestens eine Implementierung fehlerhaft. Man muss jedoch anerkennen, dass diese Art von Fehlern in der Regel keine schlechten Entscheidungen von Entwickler:innen widerspiegelt: Bei einer Grammatik, die komplex genug ist, kann es unmöglich sein zu bestimmen, ob eine Implementierung der Spezifikation entspricht.

Man muss sich nur die Sicherheitsbilanz von Webbrowsern ansehen, um zu verstehen, was komplexe Eingabesprachen sicherheitstechnisch bedeuten: Während Sicherheitsprobleme im Zusammenhang mit HTML recht selten sind, sind Sicherheitslücken im Zusammenhang mit dem komplexeren JavaScript häufig. Trotz großer Investitionen von Unternehmen wie Apple, Google oder Microsoft scheint es, dass kein Maß an Tests oder Überprüfungen solche Probleme dauerhaft beheben kann: Kein Browser wird jemals in der Lage sein, allen bösartigen Javascript-Code zu erkennen.

Im Gegensatz zur Intuition vieler Entwickler:innen ist es leicht, versehentlich ein Datenformat zu entwerfen, das die Validierung erschwert: Stellen Sie sich ein Datenformat mit zwei Listen von Eigenschaften für IoT-Geräte vor – eine Liste, die Geräte-IDs und Sensordaten für jedes Gerät enthält, und die andere Liste mit Einträgen für Geräte-IDs und deren Besitzer. Eine Datei in diesem Format ist nur dann gültig, wenn beide Listen genau die gleiche Länge haben und genau einen Eintrag für jede Geräte-ID in der jeweils anderen Liste enthalten. Stellen Sie sich nun ein anderes Datenformat mit einer einzigen Liste vor, deren Einträge Geräte-IDs, Sensordaten und Besitzer enthalten. Für den letzteren Fall ist die Validierung viel einfacher. Tatsächlich ist es unmöglich, ein JSON-Schema für das erste Format zu schreiben – obwohl beide genau die gleichen Informationen enthalten.

Folgt man dem LANGSEC-Ansatz, bedeutet dies, die Komplexität der Grammatik einer Eingabesprache unter dem Grenzwert zu halten, ab dem die Validierung unpraktisch oder sogar unmöglich wird, und im Allgemeinen so gering wie möglich zu halten. Das am ehesten zu bevorzugende Datenformat ist eines, das durch einen regulären Ausdruck validiert werden kann. Die Anforderung, dass alle JSON-Daten, die ein Programm verarbeitet oder erzeugt, einem JSON-Schema entsprechen, kann auch dazu beitragen, dass die Komplexität nicht gefährlich hoch wird. Einige Programmiersprachen sind für die Datenvalidierung viel nützlicher als andere: Vor etwa fünf Jahren verwendeten viele grandcentrix-Projekte die Programmiersprache Elixir, die sog. “Guard Clauses” enthält. Diese Funktionalität ermöglicht es Entwickler:innen, Grammatiken für zulässige Funktionsargumente oder Switch-Anweisungen zu definieren. Elixirs Guard Clauses sind jedoch begrenzt, sodass komplexe Grammatiken von vornherein nicht spezifiziert werden können.

Entwickler:innen LANGSEC bewusst machen

Im Gegensatz zum Vier-Augen-Prinzip kann die Entwicklung unter Berücksichtigung von LANGSEC-Prinzipien nicht leicht durch automatisierte Tools umgesetzt werden. Andererseits haben diejenigen, die Informatik oder Linguistik bzw. Philosophie studiert haben, in der Regel den theoretischen Hintergrund, um die Konzepte sofort zu verstehen. Ähnlich wie bei Test-Driven Development können Entwickler:innen den LANGSEC-Ansatz leicht ausprobieren und selbst erleben, wie er die Softwareentwicklung beeinflusst.

Immer wenn ich andere Entwickler:innen bei grandcentrix berate, bitte ich sie, zwei wichtige LANGSEC-Papers zu lesen, bevor wir gemeinsam Code schreiben. Ich habe noch keinen effektiveren Weg gefunden, was für mich für die hohe Qualität dieser Arbeiten bestätigt.

Natürlich ist LANGSEC wie alle Techniken, die die Softwaresicherheit und -zuverlässigkeit verbessern, kein Allheilmittel – es kann keine Probleme in der zugrunde liegenden Hardware wie SPECTRE lösen. Trotzdem ist LANGSEC ein wesentlicher Bestandteil einer „Defense in Depth“-Strategie.

Geschäftliche Zwänge können Entwickler:innen in eine ähnliche Situation wie Browseranbieter bringen: Wann immer Drittsysteme Daten ausgeben, die nicht validierbar sind, und diese Systeme nicht geändert werden können, kann LANGSEC Entwicklern nur helfen, wenn sie sich damit trösten, dass ihre Aufgabe möglicherweise unmöglich ist, perfekt zu erfüllen.

Ich vergleiche die LANGSEC-bewusste Entwicklung gerne mit der Verwendung von Handdesinfektionsmitteln oder Desinfektionsmitteln in Krankenhäusern: Es ist eine einfache, kostengünstige und wirksame Maßnahme, aber ihr Erfolg hängt von der Wachsamkeit aller Beteiligten ab. Wie bei vielen anderen vorbeugenden Maßnahmen ist Erfolg meist unsichtbar.