Sicher durch weniger Bugs
Mark Hermeling
Mit der digitalen Transformation werden Anwendungen in allen Bereichen und Branchen zunehmend kritisch. Daten und Applikationen sind die Grundlage digitaler Geschäftsmodelle. Anforderungen an deren Sicherheit und Zuverlässigkeit werden immer komplexer. Vor allem bei der Entwicklung von Embedded-Systemen müssen damit Validierung und Verifizierung ein neues Niveau erreichen.
Das Internet of Things (IoT) ist vielleicht eines der prominentesten Beispiele dafür, wie die digitale Transformation Wirtschaft und Gesellschaft verändert. Zahllose Geräte – die Marktforscher von Gartner gehen bis zum Jahr 2020 von weltweit über 20 Milliarden IoT-Geräte aus – vernetzen Unternehmen, Maschinen und Kunden. Dabei tauschen sie auch hochsensible Daten aus. Diese Devices bilden das Rückgrat neuer Geschäftsmodelle, sie sind für digitale Unternehmen unverzichtbar. Gleichzeitig sind die IoT-Geräte aus technologischer Sicht zunächst einmal Clients, die über das Internet und andere Protokolle kommunizieren. Sie stellen also auch potenzielle Angriffsziele für Cyberkriminelle dar. Die Unternehmen haben das Problem erkannt: Laut dem Analystenhaus Juniper Research wächst der Markt für IoT-Security in den kommenden fünf Jahren um das Dreifache, die weltweiten Ausgaben werden 2023 über sechs Milliarden Dollar betragen.
Damit nehmen Sicherheit und Zuverlässigkeit in der Software-Entwicklung einen immer größeren Stellenwert ein, besonders bei den Embedded-Systemen. Denn im Gegensatz zu PC- und Server-Anwendungen lassen sich Embedded-Geräte nicht einfach so über Updates und zusätzliche Sicherheitslösungen wie Malware-Scanner absichern. Dazu sind diese Geräte in der Regel zu schmalbandig an das Internet angebunden. Zudem ist die Hardware aus Kostengründen meist nicht gerade großzügig ausgelegt und freie Ressourcen sind eher die Ausnahme. Es gilt also, den Code vor der Markteinführung so sicher und zuverlässig zu machen, dass das System kaum Angriffsfläche bietet.
Analyse aller Steuerungs- und Datenströme
Dabei nimmt die statische Code-Analyse eine zentrale Rolle innerhalb des Software Development Lifecycles (SDLC) ein. Im Gegensatz zum dynamischen Testing wird der Code bei der statischen Code-Analyse nicht ausgeführt. Tools wie CodeSonar von GrammaTech erstellen aus dem Code vielmehr ein Modell, anhand dessen alle Steuerungs- und Datenströme durchlaufen und analysiert werden. Als Modell dient die Intermediate Representation (IR), wie sie auch von Compilern erzeugt wird. Der Vorteil dieses Ansatzes ist, dass kein ausführbarer Code vorliegen muss, die statische Code-Analyse kann also bereits in einer sehr frühen Entwicklungsphase eingesetzt werden. Damit eignet sie sich auch dafür, im Rahmen agiler Entwicklungsmethoden wie Continuous Integration direkt am Entwicklerarbeitsplatz die täglichen Beiträge vor der Integration in die Mainline auf Fehler und Abweichungen von den Entwicklungsrichtlinien hin zu überprüfen. Auf dem Build-System wiederum kann die statische Analyse dabei helfen, Sicherheitslücken und Fehler frühzeitig aufzudecken, den Entwicklern Hilfe bei deren Beseitigung zu geben und so die Code-Qualität bereits von Anfang an zu verbessern. Die statische Code-Analyse eignet sich dazu, klassische Programmierfehler wie Buffer Overruns oder Null-Pointer-Dereferenzierungen zu erkennen. Auch Abweichungen von Programmierstandards, wie sie zum Beispiel in der Automobilbranche durch MISRA-C definiert sind, können problemlos gefunden werden.
Durch den Ansatz, den Code anhand eines Modells zu überprüfen, beseitigt die statische Analyse zudem eine gewichtige Schwachstelle des Testings: Im Testing wird das Programm mittels definierter Testfälle auf Fehler und korrekte Funktion überprüft. Fehler werden nur gefunden, wenn
- die betreffende Code-Stelle vom Testfall durchlaufen wird,
- der Testfall an dieser Stelle zu einer Error-Condition führt und
- diese Error-Condition das erwartete Ergebnis des Testfalls beeinflusst.
Da die statische Analyse alle Zustände berücksichtigt, die das Programm theoretisch einnehmen kann, lassen sich potenzielle Fehler mit deutlich höherer Trefferquote aufspüren. Zudem geben die Analyse-Tools den Entwicklern viele hilfreiche Informationen, die bei der Beseitigung der Fehler helfen. Programmierstandards in sicherheitskritischen Branchen, etwa DO-178 B/C in der Luftfahrt, schreiben deswegen den Einsatz dieses Verfahrens vor, viele andere Normen empfehlen es.
Fremden Code überprüfen
Eine Hürde bei der Qualitätssicherung innerhalb des SDLC stellt Code aus externen Quellen dar. Dieser liegt häufig nur in Form von Binärdateien vor. Aus wirtschaftlicher Sicht ist der Einsatz von externem Code im Rahmen des Sourcings sinnvoll: Die Entwickler können sich auf die Logik der Anwendung konzentrieren, Bibliotheken oder Datenbanken werden von Spezialisten zugeliefert. Aus Sicht der Sicherheit und Zuverlässigkeit jedoch müssen auch diese Komponenten auf Fehler und Schwachstellen hin überprüft werden. Bei Binärcode ist das jedoch nicht trivial.
Der erste Schritt der statischen Analyse ist das Disassemblieren des Binärcodes. Das Ergebnis dieses Schritts ist Assembler-Code, der nur theoretisch und mit immensem Aufwand von einem Entwickler gelesen werden kann. Bei binären Dateien ohne Debugging-Informationen oder Symboltabellen enthält der Code zudem zu wenig Informationen, um in seinen Steuerungs- und Datenflüssen nachvollziehbar zu sein. Hier sind Tools unverzichtbar, die das Disassemblieren und Analysieren des Binärcodes anhand des daraus erzeugten Modells übernehmen. Dabei gibt das Tool dem Entwickler zahlreiche Hilfen, um gefundene Fehler genau zu lokalisieren und zu verstehen. Dennoch bleibt es Assembler-Code, der Entwickler sollte also mit dieser Hardware-nahen Programmiersprache vertraut sein.
Binär-Code ist jedoch nicht per se ein Problem. Es kann durchaus auch ein Vorteil sein, wenn Bestandteile der Anwendung nur binär vorliegen. Denn im Gegensatz zur Untersuchung von strukturiertem Quellcode erzeugt die Analyse der Binaries auch Informationen, die sich aus den Quellen nicht ableiten lassen: Bei der Analyse des Binärcodes wird das Programm so betrachtet, wie es nachher wirklich in den Speicher geladen und ausgeführt wird. Dadurch lassen sich auch mögliche Probleme aufdecken, die durch die Tool-Kette mit Compiler und Linker entstehen können. Diese bleiben bei einer reinen Quellcode-Analyse – und oft auch beim dynamischen Testing – unerkannt.
Fazit
Die statische Code-Analyse kann an zahlreichen Stellen des SDLC eingesetzt werden. Da sie keinen lauffähigen Code voraussetzt, ist sie dafür prädestiniert, bereits an den Entwicklerarbeitsplätzen potenzielle Schwachstellen aufzudecken. Darüber hinaus ergänzt sie das dynamische Testing um eine analytische Methodik, die auch Fehler erkennt, welche den Testfällen unter Umständen verborgen bleiben. Hier gilt: Je früher ein Fehler innerhalb des SDLC gefunden wird, desto geringer sind Kosten und Aufwand für die Beseitigung. Zudem hilft die statische Code-Analyse dabei, wichtige Programmierstandards und -richtlinien auch in großen oder agilen Projekten durchzusetzen – und dieses auch für eventuell notwendige Zertifizierungen zu dokumentieren. Für die Entwickler und für das Unternehmen bedeutet das: Sichere und zuverlässigere Software bei einer kürzeren Time to Market.
Bitte melden Sie sich an oder erstellen Sie ein Konto, um diesen Inhalt weiter zu lesen.