Test & Qualität Cybersecurity durch optimal verteilte statische Codeanalyse

Von Jacob Palczynski & Martin Becker 11 min Lesedauer

Anbieter zum Thema

Robuste Software ist unerlässlich für moderne sicherheitskritische Systeme, stellt jedoch oft eine Herausforderung für agile Entwicklungsteams dar. Anwender und Unternehmen wollen Schwachstellen minimieren und schnell auf Cyberangriffe reagieren können. Wird statische Codeanalyse zum richtigen Zeitpunkt, im richtigen Umfang und mit der richtigen Suchtiefe eingesetzt, kann Cybersecurity quantifiziert, schrittweise verbessert und effizient adressiert werden.

Werkzeuge für die statische Codeanalyse (SAST) sind ein wirksames Mittel, um diverse Herausforderungen der Cybersecurity in der Softwareentwicklung zu bewältigen. (Bild:  frei lizenziert /  Pixabay)
Werkzeuge für die statische Codeanalyse (SAST) sind ein wirksames Mittel, um diverse Herausforderungen der Cybersecurity in der Softwareentwicklung zu bewältigen.
(Bild: frei lizenziert / Pixabay)

Cybersecurity stellt für eingebettete Software eine wachsende Herausforderung dar, da immer mehr Hacker-Angriffe auf sie abzielen. Ziel der Cybersecurity ist es, Systeme vor deren Umgebung zu schützen, eventuelle Angriffe abzuwehren und böswillige Zugriffe zu verhindern. Kompromittiert ein Angreifer ein System, kann die funktionale Sicherheit beeinträchtigt sein. Cybersecurity ist daher eine Voraussetzung für funktionale Sicherheit.

Sicherheitskritische Software muss auch in unwahrscheinlichen Situationen korrekt funktionieren. Angreifer suchen oft aktiv und mit großem Ressourcenaufwand nach Sicherheitslücken. Damit sind die Existenz und Ausnutzbarkeit eines Fehlers maßgeblich. Böswillige Angriffe müssen somit beim Softwareentwurf ausdrücklich berücksichtigt werden.

Mehrere neuere Normen wie ISO/SAE 21434, IEC-62443 und DO- 356 definieren neue Cybersecurity-Anforderungen. Cybersecurity-Experten, die die neuen Normen umsetzen können und den technischen Hintergrund der jeweiligen Anwendung mitbringen, sind rar. Somit muss neben der Etablierung zuverlässiger Prozesse auch ein Weg gefunden werden, dieses neue Wissen an die vorhandenen Entwickler effektiv weiterzugeben. Im Ernstfall müssen Sicherheitslücken schnell geschlossen werden, um Schäden zu verhindern oder zumindest zu begrenzen. Der „neue“ Entwicklungsprozess muss also nicht nur den neuen Anforderungen genügen, sondern auch agiler sein als dies bisher der Fall war.

Softwareentwicklungsteams werden dabei mit neuen Herausforderungen durch Cybersecurity konfrontiert:

  • 1. Mit Updates muss gerechnet werden – Heute als sicher geltende Software kann bereits morgen unsicher sein. Muss ein Update entwickelt werden, wird effektiv der Entwicklungszyklus neu gestartet (siehe Abbildung 1). Kleine Ineffizienzen führen zu exponentiell höheren Kosten.
  • 2. Programmierungsrichtlinien sind unzureichend – Die CIA-Triade (Confidentiality Integrity Availability) ist integraler Bestandteil der neuen Cybersecurity-Standards. Programmierrichtlinien und die Vermeidung von gefährlichen Codemustern (CWEs) tragen erheblich zur Codequalität bei, können aber nicht garantieren, dass die Software in allen Grenzfällen zuverlässig funktioniert.
  • 3. Nachweise brauchen (Warte-)Zeit – Je strenger die Security-Anforderungen sind, desto mehr Zeit muss für die Verifikation aufgewendet werden. Jede Softwareänderung kann die Prüfergebnisse ungültig machen. Geschwindigkeit und Tiefe der Verifikationsaktivitäten müssen geschickt ausbalanciert werden.
  • 4. Wer schult die Entwickler? – Jeder Entwickler muss von Anfang an sicheren Code schreiben. Menschen können zwar gut Muster erkennen, aber es fällt ihnen schwer, gedanklich alle Eventualitäten zu berücksichtigen.

Abbildung 1: Cybersecurity erfordert regelmäßige und damit sich wiederholende Entwicklungsprozesse, hier am Beispiel des V-Modells dargestellt.(Bild:  Mathworks)
Abbildung 1: Cybersecurity erfordert regelmäßige und damit sich wiederholende Entwicklungsprozesse, hier am Beispiel des V-Modells dargestellt.
(Bild: Mathworks)

Cybersecurity erfordert also Software, die in kurzer Zeit nachweislich robust und wartbar ist. Um den Wartungsaufwand gering zu halten, müssen Entwicklungsprozesse möglichst wenig wiederholt werden, und sie sollen beendet werden, sobald ausreichende Sicherheitsnachweise vorliegen. Dazu müssen Entwickler geschult, und ihre Arbeit messbar gemacht werden. Dennoch muss es auf dem Weg dorthin Raum für Flexibilität geben, damit neue Funktionen schnell implementiert werden können. Cybersecurity muss Teil jedes Prozessschritts sein, darf aber den Softwareentwicklungsprozess nicht unnötig verlangsamen. Diese Ziele decken sich mit den Prinzipien zweier bekannter Produktionssysteme, DevOps und das Toyota Production System. Qualität soll so früh wie möglich etabliert (Shift-Left) und Entwicklungszyklen verkürzt werden. In diesem Rahmen führt Qualitätssicherung mittels statischer Codeanalyse in kürzerer Zeit zu höherer Softwarequalität.

Abbildung 2: Exemplarischer Softwareentwicklungs-Prozess. Der Anteil an nicht-wertschöpfender Zeit (Muda) überwiegt in der Regel. (Bild:  Mathworks)
Abbildung 2: Exemplarischer Softwareentwicklungs-Prozess. Der Anteil an nicht-wertschöpfender Zeit (Muda) überwiegt in der Regel.
(Bild: Mathworks)

Was macht einen effizienten Prozess aus?

Das Toyota Production System (TPS, in westlichen Kulturen auch als Lean bekannt) beschreibt Praktiken, um Qualität und Entwicklungsgeschwindigkeit mit maximaler Ressourceneffizienz in Einklang bringen. Diese Praktiken sind mittlerweile in vielen Disziplinen, wie der Softwareentwicklung, zu finden. Enge Verwandte sind hier die neueren DevOps-Ansätze, die die Erfolgsgeschichte des TPS fortsetzen.

Das zentrale Ziel des TPS ist es, unnötigem Aufwand – Muda – zu vermeiden. Als Muda wird jede Tätigkeit definiert, die aus Kundensicht nicht direkt zum Produktwert beiträgt. Der Anteil des so zu definierenden wertschöpfenden Aufwands ist typischerweise gering, wie in Abbildung 2 dargestellt. Jeder Schritt ist hier nur einmal dargestellt. Softwareentwicklung ist aber in der Regel iterativ, was Muda verstärkt.

Das TPS definiert sieben Arten von Muda, die auf Beispiele in der Softwareentwicklung übertragen werden können:

  • (M1) Überproduktion: nutzlose Funktionen
  • (M2) Wartezeit: Kompilierung
  • (M3) Transport: Datenübertragung
  • (M4) Überbearbeitung: höhere Komplexität als erforderlich
  • (M5) Großes Inventar: unfertige Arbeiten
  • (M6) Einrichtung/Benutzung der Arbeitsumgebung: Umschalten zwischen Branches im Software-Repository
  • (M7) Defekte erfordern Korrekturen, erneute Tests usw. Spät entdeckte Fehler zu korrigieren bringt hohe Kosten mit sich.

Abbildung 3: Eine optimal verteilte SAST-Toolchain.(Bild:  Mathworks)
Abbildung 3: Eine optimal verteilte SAST-Toolchain.
(Bild: Mathworks)

Updates gelten zwar per Definition als Muda, können aber dennoch unvermeidlich sein.

Wie minimiert man Muda?

Der ideale Softwareentwicklungsprozess bringt hohe Softwarequalität mit kurzen Entwicklungszyklen in Einklang und geht die oben genannten Herausforderungen für Cybersecurity an. Empfehlenswert ist eine ausgewogene Kombination aus Pre-Commit- und Post-Commit-Prüfung mittels statischer Codeanalyse. Die Pre-Commit-Analyse sollte schnell und mit begrenztem Kontext ablaufen. Ergänzt wird sie durch einen automatisierten CI-Job, der nach dem Commit abläuft. Dieser prüft den Code umfassend im Integrationskontext.

Dass dieser Ansatz sowohl sinnvoll als auch effizient ist, zeigt folgende, beispielhafte ideale Toolchain für Cybersecurity: Polyspace Bug FinderTM prüft die grundlegende Codequalität, Polyspace Code ProverTM beweist umfassend die Robustheit. Eine Übersicht zeigt die Abbildung 3 samt Erläuterung:

Tool-Auswahl (0). Polyspace Bug Finder erlaubt es, Code auf Richtlinien, CWEs und Defekte hin zu überprüfen. Die Analysen sind nicht vollständig und robust. Dafür minimiert es Wartezeiten seitens des Entwicklers (M2) durch kurze Antwortzeiten. Detaillierte Erklärungen für die identifizierten Schwachstellen reduzieren den Zeitaufwand für die Behebung von Fehlern (M7).

Polyspace as You Code bindet Polyspace Bug Finder in die Entwicklungsumgebung ein und unterstützt das automatische Aufsetzen der Analysen (M6). In die Programmierumgebung nahtlos integriert, liefert es innerhalb von Sekunden eine erste Bewertung der Codequalität und deckt schlechte Programmiermuster sowie potenzielle Sicherheitsschwachstellen rigoros auf. Durch die kontinuierliche Anwendung solcher Werkzeuge lernen Entwickler ihre Fehler kennen und haben so die Möglichkeit, diese von vornherein zu vermeiden.

Jetzt Newsletter abonnieren

Verpassen Sie nicht unsere besten Inhalte

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung. Die Einwilligungserklärung bezieht sich u. a. auf die Zusendung von redaktionellen Newslettern per E-Mail und auf den Datenabgleich zu Marketingzwecken mit ausgewählten Werbepartnern (z. B. LinkedIn, Google, Meta).

Aufklappen für Details zu Ihrer Einwilligung

Polyspace Code Prover ist ein fundiertes SAST-Werkzeug, das alle erreichbaren Programmzustände berücksichtigt, ohne Grenzfälle zu übersehen. Damit kann die Erfüllung der CIA-Triade mit fundierten Nachweisen belegt werden.

Integrationsprobleme betreffen mehrere Parteien (shared ownership, obere Halbebene in Abbildung 4). Polyspace Access ermöglicht als browsergestütztes Review-Werkzeug die gemeinsame Nutzung der Analyseergebnisse und erleichtert Diskussionen über die gefundenen Probleme. Diese können kommentiert und zugewiesen werden, auch über externe Bug-Tracking-Tools.

Abbildung 4: Optimaler Prozess: Erst die Qualität, dann die Robustheit – erst lokal, dann global. Der Großteil der Iterationen findet früh und an kleinen Einheiten statt.(Bild:  Mathworks)
Abbildung 4: Optimaler Prozess: Erst die Qualität, dann die Robustheit – erst lokal, dann global. Der Großteil der Iterationen findet früh und an kleinen Einheiten statt.
(Bild: Mathworks)

Alle Werkzeuge erlauben eine inkrementelle Überprüfung des Codes. Metadaten zu Defekten (z.B. Kommentare oder Verweisungen an die Entwickler) werden automatisch auf nachfolgende Analysen übertragen, wiederholte Review-Aktivitäten vermieden (M4). In Polyspace Access ermöglicht eine „alt/neu“-Logik, zwei beliebige Analysen zu vergleichen und dadurch Trends zu erkennen und Fehleraufkommen zeitlich einzugrenzen. Somit wird Cybersecurity messbar.

Pre-commit (1). Vor dem Commit (die untere Halbebene in der Abbildung 4) sollte nur das jeweilige Arbeitspaket des Entwicklers analysiert werden. Die Entwickler sind in ihrem „Territorium“, wo sie sofort Korrekturen vornehmen oder absichtliche Abweichungen von den Richtlinien dokumentieren können. Der Code wird idealerweise in frühen Entwicklungsphasen innerhalb der Entwicklungsumgebung des Entwicklers (z. B. Microsoft VS CodeTM) analysiert.

Polyspace as You Code wird hier eingesetzt, um schnelles Feedback über CERT-C-Verletzungen, CWEs und andere Defekte zu erhalten. Die Analyse beschränkt sich auf die aktuell bearbeiteten Dateien, sodass Entwickler nicht unnötig ausgebremst werden (M2). Der Einrichtungsaufwand ist zudem minimal, da das Tool alle notwendigen Informationen (z.B. Compiler, Include-Pfade, etc.) direkt aus der IDE bezieht (M6). Abbildung 5 zeigt, wie Polyspace as You Code den Entwickler vor einer unvollständig initialisierten Variable (abs_control_output) warnt, was eine CERT-C-Verletzung darstellt. Obwohl die Variable in den if-else-Block ab Zeile 87 geschrieben wird, decken die Prädikate nicht alle möglichen Bedingungen ab. Der Entwickler kann unmittelbar reagieren und eine potenzielle Schwachstelle vermeiden, noch während er an dem Algorithmus feilt. Darüber hinaus werden Integrationsdefekte in der IDE gezielt ausgeblendet, um eine Überbearbeitung zu verhindern (M4): Defekte, die aus externen Eingaben resultieren (z.B. Überläufe und ungültige Zeigerargumente), könnten sonst nicht ohne erheblichen Aufwand ausgewertet werden. Dazu müsste der Integrationskontext so genau wie möglich nachgebildet werden. Dies wäre aber nur sinnvoll, wenn der nachgebildete Kontext auch verifiziert würde, was effizienter im folgenden Schritt gelöst werden kann.

Falls gewünscht, kann an dieser Stelle auch eine lokale Robustheitsanalyse mit Polyspace Code ProverTM erfolgen, sobald die Qualitätsanforderungen abgedeckt sind. In einem gut strukturierten Design ist es einfacher, Grenzfälle zu erkennen und anzugehen, was die Lernkurve reduziert (M6).

Post-Commit (3). Die Integrationsanalyse liegt nicht in der Verantwortung der einzelnen Entwickler und wird daher zentral über CI-Systeme wie JenkinsTM oder ZuulTM angestoßen, welche umfassendere Analysen vornehmen. Der Aufbau der Analyse erfolgt wie bisher automatisch, diesmal durch Einbindung in Build-Systeme wie cmakeTM, bazelTM o. ä. Es müssen lediglich noch die gewünschten Prüfungen ausgewählt werden, was durch XML-Dateien geschehen kann. Mit diesem Post-Commit-Schritt erreicht man eine aktuelle, umfassende und konsistente Verifikation sämtlicher Änderungen am Code.

Sowohl die Qualität als auch die Robustheit des Codes müssen wie bisher geprüft werden. Robustheitsanalysen im Rahmen der Integration liefern den endgültigen Nachweis, erfordern aber in der Regel mehr Wartezeit als alle bis zu diesem Zeitpunkt durchgeführten Analysen. Daher sollte die Robustheitsanalyse auf der Integrationsebene als letzte Prüfung, aber dennoch regelmäßig durchgeführt werden (z. B. nächtliche Prüfungen), um späte und teure Fehler zu vermeiden.

Analysen können im CI/CD-System automatisch ausgewertet und CI-Jobs bei Nichterfüllung bestimmter Kriterien (z.B. zu viele neue Defekte oder Verletzung bestimmter CERT C-Regeln, zu komplexe Funktionen) fehlerbedingt abgebrochen werden. Das CI/CD-System dient somit als Quality Gate und kann helfen, Jidōka (Automatisierung anhalten und Grundursache für Fehler finden) anzuwenden.

Abbildung 5: Das SAST-Tool Polyspace as You Code zeigt Sicherheitsschwachstellen frühzeitig und innerhalb von Sekunden in der IDE auf (hier: Microsoft VS CodeTM. Screenshot mit Genehmigung von Microsoft).(Bild:  Microsoft)
Abbildung 5: Das SAST-Tool Polyspace as You Code zeigt Sicherheitsschwachstellen frühzeitig und innerhalb von Sekunden in der IDE auf (hier: Microsoft VS CodeTM. Screenshot mit Genehmigung von Microsoft).
(Bild: Microsoft)

Teamarbeit und interaktive Reviews (5). Die im CI/CD-System erhaltenen Ergebnisse sollten aus Effizienzgründen gut visualisiert werden und es den Entwicklern ermöglichen, gemeinsam an einer Lösung zu arbeiten. Abbildung 6 zeigt einen Integrationsfehler in Polyspace AccessTM. Das Review-System sammelt Analyseergebnisse aus den CI-Läufen und stellt für das gesamten Team die Trends, Vergleiche und Aufgabenzuweisungen zur Verfügung. Fehler werden durch interaktive Elemente leicht verständlich erklärt und müssen nicht erneut zeitaufwändig reproduziert werden. Die Abbildung zeigt eine Division durch Null in pi_utils.c, verursacht durch einen Aufruf aus einer zweiten Datei, pi_alg.c. Dem Entwickler der ersten Datei einen solchen Befund vor dem Commit zu zeigen, ist wenig sinnvoll, da hier der Kontext fehlen würde und man diese Warnung leicht als False Positive fehlinterpretieren könnte. Andererseits liefert die Integrationsanalyse ein konkretes Beispiel für das Auftreten des Fehlers und ermöglicht es den beteiligten Entwicklern, sich in der Browserschnittstelle zu treffen, sich über mögliche Maßnahmen zu verständigen und auf Wunsch ein Bug-Tracker-Ticket zu eröffnen.

Werden danach weitere Integrationsanalysen vorgenommen, überträgt Polyspace Access die Review-Informationen automatisch auf neuere Ergebnisse, um kostspielige Nacharbeitung von ein und denselben Defekten zu minimieren (M3). Darüber hinaus können Entwickler erst im Rahmen der Integrationsanalysen gefundene Probleme während ihrer frühen Analysen innerhalb der IDE ein- oder ausblenden. So können sie sich auf ihre lokalen Fehler konzentrieren und den entsprechenden Kontext für jedes Problem sehen, an dem sie gerade arbeiten, aber „alte Bekannte“ ausblenden.

Jenseits des Prozesses

Der Prozess ist jedoch nicht alles. Selbst die besten Werkzeuge und Prozesse schützen nicht vor allen Fehlern. Neben den einzelnen Entwicklern muss auch das gesamte Team sowie die Organisation dazulernen, um die Vorteile von TPS und DevOps wirklich zu nutzen. Diese zusätzlichen Grundsätze würden den Rahmen dieses Artikels sprengen. Die folgenden drei sind jedoch aufgrund ihrer Mächtigkeit nennenswert:

  • 1. Hansei und Kaizen – Zurückblicken und kontinuierlich verbessern: Auftretende Probleme müssen bis zu ihrer Ursache zurückanalysiert (ohne Schuldzuweisung) und geeignete Gegenmaßnahmen für die Zukunft festgelegt werden
  • 2. Konsensentscheidungen treffen: Nachdem das Problem identifiziert wurde, sollten alle infrage kommenden Lösungsstrategien in Betracht gezogen, alle notwendigen Daten gesammelt, und es sollte vom gesamten Team eine Lösung vereinbart werden, der sich auf Grundlage der Fakten alle anschließen.
  • 3. Teams fördern: Wertschöpfung beruht auf menschlicher Arbeit, nicht auf Prozessen. Ein erfahrenes Team ist mehr als die Summe seiner Teile. Gemeinsam stimmen sich die Mitglieder ab, lernen voneinander und verbessern sich und den Prozess kontinuierlich.
  • 4. Zusammenfassend lässt sich sagen, dass Teams ihren Prozess nicht nur definieren, sondern auch sicherstellen sollten, dass sie ihn kontinuierlich verbessern.

Fazit

Abbildung 6: Integrationsdefekte werden vom CI/CD-System an das browserbasierte Review-System weitergeleitet, wo die Entwickler die Defekte gemeinsam verwalten und zusammenarbeiten können.(Bild:  Mathworks)
Abbildung 6: Integrationsdefekte werden vom CI/CD-System an das browserbasierte Review-System weitergeleitet, wo die Entwickler die Defekte gemeinsam verwalten und zusammenarbeiten können.
(Bild: Mathworks)

Sichere Software in kurzer Zeit zu entwickeln, mag wie ein Widerspruch erscheinen. Ein gut ausgewogener Workflow kann Schwachstellen jedoch frühzeitig erkennen (Shift-Left), ohne Entwicklern und Testern zu viel aufzubürden, und deckt Programmierfehler und Schwachstellen zuverlässig auf. Der Schlüssel liegt darin, unnötigen Aufwand (Muda) zu vermeiden, wozu die Wahl der richtigen Verifikationsmethode, der richtigen Werkzeuge und des richtigen Umfangs zum jeweiligen Zeitpunkt erforderlich ist. Cybersecurity erfordert folglich einen gut koordinieren und bewusst gewählten Prozess.

Werkzeuge für die statische Codeanalyse (SAST) sind ein wirksames Mittel, um diverse Herausforderungen der Cybersecurity in der Softwareentwicklung zu bewältigen. Mit diesen Werkzeugen können Teams Sicherheitsschwachstellen automatisch und konsistent identifizieren. Eine Analyse zur Einhaltung von Programmierrichtlinien wie CERT C oder zum Auffinden bestimmter Muster reicht jedoch nicht aus, um die CIA-Triade zu erfüllen; es ist ein tieferer Nachweis der Robustheit erforderlich. Ein solcher Nachweis kann durch fundierte SAST-Tools erbracht werden und hilft, Sicherheitslücken zu schließen, welche durch Programmierrichtlinien nicht erfassbar sind. (mbf)

* *Dr. Jacob Palczynski arbeitet als Senior Training Engineer bei MathWorks. Seit über 10 Jahren teilt er seine Expertise beim Einsatz statischer Codeanalyse und der Modellverifikation und -validierung mit Teams, die sicherheitskritische eingebettete Software entwickeln. Dabei arbeitet er auch mit Kunden zusammen, deren Entwicklungsprozesse Standards zur funktionalen Sicherheit wie ISO 26262 und DO178-C folgen. Vor seiner Tätigkeit bei MathWorks hat er als wissenschaftlicher Mitarbeiter am Lehrstuhl Informatik 11 der RWTH Aachen über die Anwendung formaler Methoden im Rahmen der Verifkation und Validierung eingebetteter Software geforscht und gelehrt.

* *Martin Becker ist Senior Field Application Engineer für Verifikations- und Validierungsworkflows bei MathWorks. Er ist ein Verfechter von formalen Methoden und statischer Analyse und verfügt über mehr als 15 Jahre Erfahrung mit Embedded Systems. In seiner täglichen Arbeit unterstützt er Kunden aus einer Vielzahl von Branchen bei der effizienten Erstellung von Embedded-Software unter Einhaltung von Sicherheitsstandards. Vor seiner Tätigkeit bei MathWorks arbeitete er als Ingenieur für Luftfahrtkonzepte bei Airbus, als Forschungsingenieur bei Tata Consultancy Services und promovierte zum Dr.-Ing. auf dem Gebiet der Echtzeit-Computersysteme an der Technischen Universität München.

(ID:49861020)