Obwohl Cybersicherheit von Computer- und Embedded-Systemen stets verbessert wird, ereignen sich dauernd neue Sicherheitsvorfälle. Robuste Software ist entscheidend für Cybersecurity. Darum ist es umso wichtiger, wie sie entsteht. Die Prinzipien des High Assurance Security Engineering können helfen.
Eine Hauptursache für Cybersicherheitsverletzungen ist, dass versucht wird, Sicherheit nachträglich in ein System einzubauen, das nicht für Sicherheit konzipiert wurde. Aber das funktioniert nicht. Stattdessen muss von Anfang an die Sicherheit des eingebetteten Systems mitgedacht werden. Dies geschieht hauptsächlich durch die Auswahl der richtigen Softwarearchitektur und die Einhaltung des richtigen Entwicklungsprozesses. Bei Produkten, für die höchste Sicherheit vorgeschrieben ist, ist eine Reihe von Prinzipien zu finden, die auf die Softwarearchitektur und den Entwicklungsprozess angewendet werden und die nachweislich zu hochsicherer Software führen.
Bereits seit vielen Jahren wird über Softwarefehler und potenziell schwerwiegende Probleme in sicherheitsrelevanten Anwendungen gesprochen [1].
Es gibt einige Beispiele für solche Fehler und die daraus resultierenden Probleme:
➔ Buffer Overflow: Im Jahr 1988 war ein Pufferüberlauf im Berkeley-Unix-Finger-Daemon die Grundlage für den ersten Internet-Wurm namens »Morris Worm«. Dieser Wurm infizierte innerhalb eines einzigen Tages mehrere 1.000 Computer, indem er einen Puffer- überlauf im Code der Funktion gets() ausnutzte.
➔ Fehlende Bereichsprüfung: 1995 konnte eine fehlende Bereichsprüfung im Fehlerbehandlungscode des IP-Fragmentation-Reassembly-Code ausgenutzt werden, um einen Ping of Death durchzuführen. Ein Computer konnte ausgeschaltet werden, indem ein bestimmtes, ungültiges Ping-Paket von einem beliebigen Ort aus dem Internet gesendet wurde.
➔ Wiederverwendung von bestehendem Code: Ein weiterer Softwarefehler, der zu schweren finanziellen Verlusten führte, ereignete sich am 4. Juni 1996 beim Jungfernflug der Ariane-5-Rakete. Der Fehler trat in einem Code auf, der vom Ariane-4-System wiederverwendet wurde, von dem bekannt war, dass es korrekt funktionierte. Dieser Code war jedoch nicht für die viel höhere Geschwindigkeit der Ariane 5 ausgelegt. In diesem Code kam es zu einer falschen Umwandlung eines 64-bit-Gleitkommawertes in eine 16-bit-Festkommazahl mit Vorzeichen. Dies führte zu einem Überlauf, der den Flugcomputer zum Absturz brachte. Infolgedessen fielen auch das Back-up-System und der Hauptcomputer aus und ein Sicherheitssystem ließ die Rakete etwa 40 Sekunden nach dem Start explodieren.
➔ Division durch Null: Auf dem Lenkwaffenkreuzer USS Yorktown gab 1997 ein Mitglied der Besatzung versehentlich eine Null als Datenwert in die Datenbank ein. Dies führte zu einer Division durch Null und einer Abfolge von Ereignissen, die alle Maschinen im Netzwerk zum Absturz brachten und den Ausfall des Antriebssystems des Schiffes verursachten. Das Schiff lag 2 Stunden und 45 Minuten lang tot im Wasser, weil die Software den eingegebenen Wert nicht überprüft hatte.
Obwohl solche Probleme und deren Ursachen seit Langem bekannt sind, gibt es nach wie vor regelmäßig Sicherheitsprobleme beziehungsweise Berichte über Sicherheitslücken:
➔ Im Chrome-Browser wurde eine neue 0-Day-Sicherheitslücke gefunden, die Angriffe auf den jeweiligen Computer ermöglicht. Die neue ausgenutzte Schwachstelle betrifft nicht nur Chrome, sondern auch der Firefox-Browser ist für denselben Fehler anfällig, der als CVE-2023-5217 verfolgt wird. Er befindet sich in einer weit verbreiteten Code-Bibliothek für die Verarbeitung von Mediendateien, insbesondere solchen im VP8-Format.
➔ Die USA und Japan haben herausgefunden, dass chinesische Hacker Cisco-Router mit einem Backdoor versehen haben. Der gemeinsame Bericht stammt vom FBI, der NSA, der CISA sowie der NISC und NPA, die erklären, dass eine staatlich geförderte Hackergruppe in Netzwerkgeräte internationaler Niederlassungen eindringt, um in die Netzwerke der Unternehmenszentralen zu gelangen.
➔ Es gab einen Cyberangriff auf den Internationalen Strafgerichtshof in Den Haag, bei dem sensible Dokumente gestohlen wurden. Es war nicht bekannt, wer hinter dem Vorfall steckte. Es gibt jedoch Spekulationen, dass der Vorfall mit den laufenden Ermittlungen des IStGH gegen Wladimir Putin wegen angeblicher Kriegsverbrechen im Krieg mit der Ukraine zusammenhängen könnte.
➔ Hacker infiltrierten sechs Monate lang ein Stromnetz in einem ungenannten asiatischen Land, bevor sie entdeckt wurden. Sie setzten Keylogger ein und löschten Protokolldaten, um ihre Spuren zu verwischen.
➔ Mehrere Krankenhäuser in vier US-Bundesstaaten haben ihre Notdienste eingestellt, nachdem Hacker an Thanksgiving Ardent Health Services angegriffen, ihre Computernetzwerke lahmgelegt und eine Lösegeldzahlung gefordert hatten.
➔ Chinesische Hacker stahlen Chipdesigns von einem großen niederländischen Halbleiterunternehmen. Sie hatten über zwei Jahre lang, von Ende 2017 bis Anfang 2020, Zugang. Die Hacker haben, Berichten zufolge, geistiges Eigentum gestohlen, darunter auch komplette Chipdesigns.
➔ Der ehemalige Chief Operating Officer einer Firma für Netzwerk-Cybersicherheit hat sich schuldig bekannt, zwei Krankenhäuser gehackt zu haben. Er hackte die Krankenhäuser, um dem Sicherheitsunternehmen Aufträge zu verschaffen.
In vielen Bereichen ist immer noch anfällige Software zu finden, sogar in Bereichen, die besonders geschützt sein müssten. Um dies zu verhindern, sollte Sicherheit ganzheitlich angegangen werden. Dafür braucht es eine Kategorisierung der Angriffsarten: Angriffe von außen oder innen sowie Angriffe über das Netzwerk oder physische Angriffe über direkten Gerätezugriff. Ein ganzheitlicher Sicherheitsansatz sollte sich immer auf das Ergebnis der Bedrohungsanalyse stützen, die gleich zu Beginn des Projekts durchgeführt werden muss. Sie sollte sich mit allen Bereichen befassen, die das Produkt, seine Verwendung und seine Herstellung umgeben. In den meisten Fällen umfassen diese Bereiche den Entwicklungsprozess, die Hardware- und Softwarearchitektur, die kryptografischen Methoden, die Schlüssel- und Zertifikatsverwaltung, den Herstellungsprozess vom Lieferanten bis zum Endprodukt sowie die Wartung und Pflege einschließlich Software-Updates.
Ein Blick auf den Entwicklungsprozess sowie die Systemarchitektur zeigt, dass es vor allem um Maßnahmen geht, die die Anzahl der Schwachstellen in einem System reduzieren oder deren negative Auswirkungen vollständig beseitigen. Sind beispielsweise gespeicherte und übermittelte Daten durch Verschlüsselung gesichert, müssen die Daten dennoch irgendwann unverschlüsselt verarbeitet werden. Wenn es in diesem Fall nur eine einzige Schwachstelle im System gibt, die einem Angreifer Zugang zu diesem unverschlüsselten Speicher geben könnte, ist in diesem Fall das Konzept der Verschlüsselung sinnlos. Daher ist es wichtig, die sensiblen Daten durch eine strikte und zuverlässige Trennung von anfälligen Softwarekomponenten zu isolieren. Eine bewährte Methode zur Erreichung dieses Ziels ist die Anwendung der Prinzipien des High Assurance Security Engineering.
Um sichere Software zu implementieren, bedarf es eines zuverlässigen Software-Engineering-Ansatzes wie etwa das High Assurance Software Engineering. Sie verlangen, dass bei der Softwareentwicklung folgende fünf Regeln Anwendung finden:
➔ Minimierung der Komplexität (Minimization of Complexity): Das Ziel dieser Regel ist es, eine einfache und kleine Implementierung der erforderlichen Funktionalität zu finden, die den Umfang des Codes auf das Wesentliche reduziert. Dadurch wird auch die Menge an kritischem Code reduziert, bei dem eine Fehlfunktion zu schwerwiegenden Folgen führen könnte. Ein HTTP-v1.1-konformer Webserver kann zum Beispiel mit etwa 300 Quellcodezeilen (Source Lines of Code, SLOC) geschrieben werden. Im Vergleich dazu hat der Apache-Webserver etwa 80.000 SLOC [2]. Oder auch ein Journaling-Dateisystem mit 2.000 SLOC im Vergleich zum etablierten JFS, das aus fast 30.000 SLOC besteht [2].
Eine Verringerung der Menge an kritischem Code kann auch dadurch erreicht werden, dass der potenziell gefährliche Code an einer Stelle untergebracht wird, an der eine Fehlfunktion unkritisch ist. Auf einem Betriebssystem mit monolithischem Kernel laufen beispielsweise die meisten Treiber und Protokollstapel, wie TCP/IP, im Supervisor-Modus der CPU (Bild 1 links). Im Falle eines Fehlers im Code des Treibers oder des Stacks kann das gesamte System betroffen sein und zusammenbrechen. Wenn dieser Code jedoch im Benutzermodus der CPU läuft, wie es in einem Mikrokernel-basierten Betriebssystem der Fall ist (Bild 1 rechts), ist ein Fehler in einer dieser Softwarekomponenten viel weniger kritisch, da nur der betroffene Prozess abstürzen kann und nicht der zugrunde liegende Kernel oder andere Prozesse.
➔ Geringstes Privileg (Least Privilege): Es ist gängige Praxis, ein System so zugestalten, dass es Softwarekomponenten den Zugriff auf alle oder die meisten verfügbaren Ressourcen des Systems ermöglicht. Dies ist beispielsweise bei Dateien oder Nachrichten aus dem Netzwerk der Fall. In vielen Fällen ist jeder Prozess in einem System berechtigt, neue Prozesse zu starten oder zumindest Code auszuführen. Die Tatsache, dass jeder Task über all diese Privilegien verfügt, macht Pufferüberläufe so gefährlich. Um die Sicherheit zu erhöhen, sollte jede Komponente nur die Berechtigungen haben, die unbedingt erforderlich sind, um ihre Arbeit korrekt auszuführen. Das bedeutet auch, dass es sinnvoller ist, Rechte oder Privilegien durch weiße Listen zu definieren, anstatt kritische Rechte durch schwarze Listen auszuschließen. Es ist sinnvoll, eine obligatorische Zugriffskontrolle zu implementieren, bei der die Zugriffsrechte eines Objekts nicht durch das Objekt oder seinen Besitzer definiert werden, sondern durch klar vordefinierte Regeln, die vom Betriebssystemkernel strikt eingehalten werden.
➔ Komponentisierung (Componentization): Ein weiteres wichtiges Designkonzept für High Assurance Software ist die Aufteilung des gesamten Softwaresystems in kleine und verständliche Komponenten. Jeder Komponente sollte mindestens ein hauptverantwortlicher Ingenieur zugewiesen sein, der die gesamte Komponente kennt und versteht.
Sicherheitsrelevante Komponenten müssen vom Rest des Systems getrennt werden und ihre Schnittstellen müssen klar definiert und über- prüfbar sein. Die Vorteile dieses Ansat- zes sind Testbarkeit, Auditierbarkeit, Datenisolierung und gegebenenfalls Schadensbegrenzung. Bei einer sicheren Netzwerktransaktion sorgt diese Architektur dafür, dass der Kommunikations-Stack und der Treibercode nur verschlüsselte Daten sehen (Bild 2). Selbst wenn sie gehackt werden, erhalten sie also niemals Zugriff auf die ursprünglichen Klardaten, und die Daten können nicht von Hackern gestohlen oder verändert werden.
➔ Sicherer Entwicklungsprozess (Secure Development Process): Je nachdem, um welche Art von Sicherheitsanwendung es sich handelt, muss bereits ein Prozess gemäß dem jeweiligen Sicherheitsstandard oder der Vorgaben einer Behörde implementiert werden. Dies betrifft insbesondere Bereiche wie Konfigurationsmanagement, Codierungsstandards, Tests und Design sowie Schwachstellenbewertung und Gefahrenanalyse. Die Common Criteria (ISO/IEC 15408) sind ein internationaler Standard für die IT-Sicherheitsevaluierung, der schon seit Langem existiert. Ab der Evaluierungsstufe 5 (Evaluation Assurance Level, EAL) ist es erforderlich, formale und halbformale Methoden zu verwenden, um das geforderte Sicherheitsniveau nachzuweisen. Diese Anforderung muss sehr früh im Softwareentwicklungsprozess berücksichtigt werden. Im Laufe der Zeit haben sich weitere Sicherheitsstandards herausgebildet, wie zum Beispiel der ISO/SAE 21434, der einen Prozess vorschreibt, aber nicht beschreibt, und der sich auf UNECE R 155 bezieht. Darüber hinaus existieren noch weitere relevante Standards, wie etwa IEC62443 oder ISO 27001, was die Auswahl des zu befolgenden Standards verkomplizieren kann.
➔ Validierung durch unabhängige Experten (Independent Expert Validation): EineSoftware, die nach solchen Prinzipien entwickelt wurde und bestimmte Sicherheitsstandards erfüllen müsste, muss dennoch validiert werden. Ein Ansatz dafür könnten interne Audits sein, was aber dazu führen kann, dass die tatsächlichen Prüfungen beeinflusst und nicht vertrauenswürdig sind. Um das Vertrauen in die Bewertung zu erhöhen, ist es sinnvoll, die Bewertung oder Prüfung durch eine unabhängige Organisation gemäß dem jeweiligen Standard durchführen zu lassen. Auf der Grundlage des Ergebnisses dieser Bewertung zertifiziert oder genehmigt eine Zertifizierungsstelle die Komponente oder das gesamte Produkt nach einer bestimmten Stufe. Nur wenn die erforderliche Zertifizierung der Software durchgeführt wurde, sind die versprochenen Eigenschaften des Softwareprodukts garantiert.
Diese Prinzipien wurden bei der Entwicklung von hochsicheren Softwareprodukten eingesetzt, die wertvolle Vermögenswerte im Bereich der Avionik, des Militärs oder auf Regierungsebene schützen.