Die Konzepte, die dem Prinzip der Linksverschiebung zugrunde liegen, sollten jedem, der sich mit der Entwicklung von sicherheitskritischen Anwendungen befasst, bereits vertraut sein, denn Standards zur funktionalen Sicherheit verlangen schon seit Jahren nach einer ähnlichen Vorgehensweise. Die folgenden bewährten Methoden haben deshalb auch bei sicherheitskritischen Anwendungen ihre Berechtigung:
Festlegung der Anforderungen bereits ganz am Anfang
Undokumentierte Anforderungen führen zu Kommunikationsfehlern auf allen Seiten und ziehen Nacharbeiten, Änderungen, Fehlerbehebungen und Sicherheitslücken nach sich. Um eine reibungslose Projektentwicklung sicherzustellen, müssen die Teammitglieder sämtliche Bestandteile des Produkts und den Ablauf seiner Entwicklung auf die gleiche Weise verstehen. Klar definierte Funktions- und Sicherheitsanforderungen tragen dazu bei, dass diese Bedingung erfüllt ist.
Derartige Anforderungen dürften für Entwickler, die nach dem V-Modell arbeiten, bereits ein komplettes System definieren, wogegen sie für DevSecOps-Entwickler lediglich eine Iteration darstellen. Dennoch bleibt das Prinzip dasselbe. Das endgültige Resultat sollte jedoch stets in klar definierten Anforderungen bestehen, sowie in einem Produktionscode, der diese Anforderungen umsetzt.
Bidirektionale Rückverfolgbarkeit gewährleisten
Bidirektionale Rückverfolgbarkeit bedeutet, dass eine Rückverfolgung sowohl in Vorwärts- als auch in Rückwärtsrichtung möglich sein muss (Bild 3). Durch Automatisierung wird dies in einer von Veränderungen geprägten Projektumgebung deutlich einfacher.
Anwenden einer sicheren Sprach-Teilmenge
Was die Entwicklung in C oder C++ betrifft, haben Studien ergeben, dass rund 80 % der Softwaredefekte auf die falsche Anwendung von rund 20 % der Sprache zurückzuführen sind. Um diesem Aspekt Rechnung zu tragen, können sich Entwickler auf Sprach-Teilmengen beschränken, die durch das strikte Untersagen problematischer Konstrukte den Safety- und den Security-Eigenschaften zugutekommen.
Zwei gängige Teilmengen sind MISRA C und CERT C vom Carnegie Mellon Software Engineering Institute (SEI). Beide helfen Entwicklern beim Erzeugen von sicherem Code. Auch wenn die Zielsetzungen beider Standards ähnlich sind, so erfolgt die Umsetzung auf unterschiedliche Weise.
Ganz allgemein führt das Entwickeln von neuem Code mit MISRA C zu weniger Codierfehlern, weil diese Teilmenge striktere, besser entscheidbare Regeln enthält, die in den Grundprinzipien definiert sind. Die Fähigkeit zur schnellen und einfachen Analyse von Software mit Bezug auf die MISRA-C-Codierstandards kann der Qualität und Konsistenz des Codes zugutekommen und den Zeitaufwand bis zum Einsatz (Deployment) verringern.
Wenn die Entwickler die Regeln da- gegen retrospektiv, d.h. auf den bereits erstellten Code anwenden müssen, kann wiederum CERT C eine pragmatische Wahl sein. Die Analyse von Code anhand von CERT C deckt gängige Programmierfehler auf, die die Ursache der meisten Attacken auf Software sind.
Die Anwendung von MISRA C oder CERT C führt zu sichererem Code, allerdings ist es nicht praktikabel, solche Standards auf manuellem Weg in einer Codebasis durchzusetzen. Benötigt wird deshalb ein statisches Analyse-Tool.
Befolgen eines Sicherheits-fokussierten Prozessstandards
In sicherheitskritischen Bereichen er- gänzen die entsprechenden Standards meist jene, die auf die funktionale Sicherheit ausgerichtet sind. Zum Beispiel ergänzt die Norm J3061 (Cybersecurity Guidebook for Cyber-Physical Vehicle Systems), an deren Stelle schon bald die Norm ISO/SAE 21434 (Road vehicles – Cybersecurity engineering) treten wird, den Standard ISO 26262 für funktionale Sicherheit der Automobilindustrie. Wenn sich eine entsprechende Notwendigkeit ergibt, lassen sich automatisierte Entwicklungswerkzeuge in die Arbeitsabläufe der Entwickler sicherheitskritischer Systeme integrieren, wobei gleichzeitig die Anforderungen bezüglich der funktionalen Sicherheit berücksichtigt werden.
Automatisierung statischer und dynamischer Prüfprozesse
Die Bezeichnung »statische Analyse« ist ein Sammelbegriff für Testregime, die eine automatisierte Inspektion von Quellcode vornehmen. Im Gegensatz dazu geht es bei der dynamischen Analyse um die tatsächliche Ausführung des Quellcodes – ganz oder abschnittsweise. Die Fokussierung solcher Techniken auf Sicherheitsaspekte resultiert in einem Static Application Security Testing (SAST) bzw. Dynamic Analysis Security Testing (DAST).
Innerhalb dieser Gruppen gibt es große Unterschiede. Zum Beispiel handelt es sich bei Penetrations-, Funktions- und Fuzz-Tests um Blackbox-DAST-Tests, die keinen Zugriff auf den Quellcode erfordern, um ihre Funktion zu erfüllen. Blackbox-DAST-Tests bilden eine Ergänzung zu Whitebox-DAST-Tests. Bei letzteren handelt es sich um Modul-, Integrations- und Systemtests, die durch eine dynamische Analyse etwaige Schwachstellen im Applikationscode aufdecken sollen.
Alle soeben beschriebenen Security-bezogenen Tools, Tests und Techniken haben ihren Platz in jedem Lebenszyklus-Modell. Im V-Modell sind sie großteils analoger Natur und ergänzen die Prozesse, die üblicherweise mit der Entwicklung von funktional sicheren Anwendungen in Verbindung gebracht werden.
Die Rückverfolgbarkeit der Anforderungen ist im Fall des V-Modells während des gesamten Entwicklungsprozesses gewährleistet, im Fall des DevSecOps-Modells auch für jede Entwicklungs-Iteration.
Einige SAST-Tools werden genutzt, um die Einhaltung von Codierstandards zu bestätigen, die Beschränkung der Komplexität auf ein Minimum sicherzustellen und zu prüfen, dass der Code gepflegt werden kann. Andere dienen dagegen zum Prüfen auf Sicherheitslücken – dies jedoch nur in dem Ausmaß, in dem solche Checks an Quellcode und ohne den Kontext einer Verarbeitungsumgebung vorgenommen werden können.
Whitebox-DAST gestattet das Prüfen von kompiliertem und ausgeführtem Code in der Anwendungsumgebung, oder besser noch auf der Zielhardware. Mithilfe der Codeabdeckungsanalyse lässt sich leichter nachweisen, dass sämtliche sicherheitsbezogenen und anderweitigen Anforderungen vom Code erfüllt werden, und dass der gesamte Code mindestens eine Anforderung erfüllt. Diese Checks können sogar bis zur Objektcode-Ebene gehen, wenn dies angesichts der Kritikalität des Systems erforderlich ist.
Robustheitsprüfungen können innerhalb der Modultestumgebung genutzt werden, um die Resilienz bestimmter Funktionen nachzuweisen – sei es isoliert oder im Kontext des jeweiligen Aufrufbaums. Die traditionellen Fuzz- und Penetrationstests als Blackbox-DAST-Methoden behalten ihre Berechtigung, dienen in diesem Kontext aber zur Bestätigung und Demonstration der Robustheit eines Systems, das auf der Basis des Security-Aspekts entwickelt wurde.
Entwickler sollten bereits vor Beginn des Softwareentwicklungsprozesses Zugang zu automatisierten Tools haben – beispielsweise zu Testsoftware, die den Entwicklungs-, Zertifizierungs- und Zulassungsprozess beschleunigen kann. Werden diese Tools genutzt, um die Arbeit während des gesamten Lebenszyklus zu unterstützen, und werden gleichzeitig die Best Practices angewandt, die mit dem Prinzip »nach links verschieben und frühzeitig testen« in Einklang stehen, so trägt dies dazu bei, die Sicherheit vernetzter Embedded-Systeme zu verbessern.
Der Autor
Mark Pitchford
verfügt über mehr als 30 Jahre Erfahrung in der Softwareentwicklung für technische Anwendungen. Er hat an vielen bedeutenden industriellen und kommerziellen Projekten in Entwicklung und Management sowohl in Großbritannien als auch international mitgearbeitet.
Seit 2001 arbeitet er mit Entwicklungsteams, die eine konforme Softwareentwicklung in sicherheitskritischen Umgebungen erreichen wollen, und arbeitet dabei mit Standards wie DO-178, IEC 61508, ISO 26262, IIRA und RAMI 4.0. Pitchford erhielt seinen Bachelor of Science von der Trent University in Nottingham und ist seit mehr als 20 Jahren zugelassener Ingenieur. Heute arbeitet er als technischer Spezialist bei LDRA.
mark.pitchford@ldra.com