Auf der Suche nach Security-orientierten Codierstandards stoßen Entwickler auf verschiedene Quellen – von Cert Coding über Owasp und CWE bis zu einer Vielzahl unterschiedlicher Empfehlungen und Best Practices. Hinzu kommen zahlreiche fachspezifische Standards wie Misra, Autosar sowie eine ganze Familie von Standards auf Basis der Norm IEC 61508. Es ist eine echte Herausforderung mit diesem Umfang an Informationen umzugehen und diejenigen Codierstandards herauszufinden, die für das jeweils anstehende Projekt am besten geeignet sind. Noch gravierender wird sie, wenn Programmierer sie mitten im Softwareentwicklungs-Lebenszyklus bewältigen müssen, wenn sie also bestehende Software so anpassen müssen, dass sie einem dieser Standards entspricht.

Von CVE bis zu den CWE Top 25

Eckdaten

Je nach Anwendungen müssen Entwickler unterschiedliche Codierstandards wählen. Dieser Artikel stellt einige Standards vor und gibt Entwicklern eine kurze Hilfestellung bei der Wahl des richtigen Standards.

Im Jahr 1999 begann die Mitre-Organisation mit der Dokumentierung bekannter Software-Sicherheitslücken in der CVE-Liste (Common Vulnerabilities and Exposures). Bestand die Liste zunächst nur aus 321 Einträgen, enthält sie im September 2018 mehr als 100.000 Einträge und wird von 92 CVE Numbering Authorities (CNAs) gepflegt. Auch heute findet sie noch weithin Anwendung und wird von vielen Organisationen empfohlen.

Mit dem Anwachsen der CVE-Liste ergab sich die Notwendigkeit, ihre Einträge je nach Problemtyp in Gruppen einzuteilen, um die Ursachen vieler gängigen Probleme besser zu verstehen und geeignete Maßnahmen für die Vermeidung ähnlicher Probleme in der Zukunft zu treffen. Dazu begann Mitre mit der Kategorisierung der bekannten Probleme. Hieraus ging das Plover-Dokument (Preliminary List of Vulnerability Examples for Researchers) hervor, und durch Zusammenführung dieser Arbeit mit anderen Forschungsarbeiten entstand die CWE-Liste (Common Weakness Enumeration) als eine formelle Aufstellung der verschiedenen Arten von Software-Schwachstellen.

Tabelle 1: Designs and Coding Standards von IEC 61508-3.

Tabelle 1: Designs and Coding Standards von IEC 61508-3 Parasoft

Version 3.1 der CWE-Liste enthält etwa 700 Arten von Schwachstellen, die in 250 Kategorien und Views eingeteilt sind. Wegen der hohen Anzahl führt die CWE zusammen mit dem SANS Institute eine Liste der 25 gefährlichsten Softwarefehler, also die am weitesten verbreiteten und kritischsten Fehler, die zu gravierenden Schwachstellen in Software führen können. Auf den ersten Plätzen dieser Top-25-Liste finden sich:

1. CWE-89: Unkorrekte Neutralisierung spezieller Elemente, die in einem SQL-Befehl verwendet werden (SQL Injection).

2. CWE-78: Unkorrekte Neutralisierung spezieller Elemente, die in einem Betriebssystem-Befehl verwendet werden (OS Command Injection).

3. CWE-120: Kopieren in den Puffer, ohne die Größe des Eingabewerts zu prüfen (klassischer Pufferüberlauf).

Standards für funktionale Sicherheit (Safety)

Um die funktionale Sicherheit von elektrischen, elektronischen und programmierbaren, elektronischen, sicherheitsrelevanten Systemen zu gewährleisten, entwickelte die International Electrotechnical Commission (IEC) für alle Anwendungsgebiete die Norm IEC 61508. Sie deckt sämtliche Aspekte eines Computersystems ab. Teil 3 befasst sich gezielt mit dem Softwareteil des Systems und enthält eine Vielzahl von Anforderungen für sämtliche Phasen des Softwareentwicklungs-Lebenszyklus. Die IEC 61508-3 enthält eine Liste von Techniken, die die IEC für die Softwareverifikation empfiehlt, darunter die explizite und dringende Empfehlung der statischen Analyse für die höheren Sicherheitsstufen (Safety Integrity Level; SIL).

In der Tabelle „Designs and Coding Standards von IEC 61508-3“ zeigt die Normungsorganisation verschiedene Softwaredesign-Techniken und gibt Empfehlungen, welche sich für bestimmte SILs eignen. Hierbei steht ein R für Recommended und ein HR für Highly Recommended, also empfohlen und dringend empfohlen (Tabelle 1).

Bei der IEC 61508 handelt es sich um eine universelle Norm, die in unterschiedlichen Branchen Anwendung findet. Daneben gibt es auch aber auf bestimmte Einsatzgebiete ausgerichtete Normen wie beispielsweise:

  • Luftfahrt: DO-178C / ED-12C
  • Automobil: ISO 26262
  • Eisenbahn: IEC 62279 / EN 50128
  • Kernkraftwerke: IEC 61513
Tabelle 2: Aufgrund der hohen Anzahl und zur besseren Orientierung teilen die Normungsorganisationen die Regeln in den Standards meist in mehrere Kategorien.

Tabelle 2: Aufgrund der hohen Anzahl und zur besseren Orientierung teilen die Normungsorganisationen die Regeln in den Standards meist in mehrere Kategorien. Parasoft

Diese Normen zielen zwar auf die spezifischen Besonderheiten eines bestimmten Gebiets ab, jedoch ist der Grundgedanke recht ähnlich. Alle nämlich verlangen neben anderen Verifikationstechniken auch die Anwendung der statischen Analyse am entwickelten Code. Außerdem bieten sie allgemeine Richtlinien hinsichtlich der zu ergreifenden Maßnahmen, lassen aber gleichzeitig einen breiten Interpretationsspielraum. Normalerweise benennen sie auch keine bestimmten Codierungskonventionen oder Codierstandards, die Entwickler oder Programmierer anwenden sollen, allerdings erwähnt die ISO-26262 Misra C als Beispiel einer Codierrichtlinie für die Programmiersprache C.

Sichere Codierstandards aufstellen

Das Schreiben von sicherem Code bedeutet, dass der geschriebene Code nicht angreifbar ist, also keine potenziell ausnutzbaren Schwachstellen oder Sicherheitslücken aufweist. Zudem muss der geschriebene Code einerseits gewisse sichere Muster aufweisen, andererseits zugleich unsichere Muster vermeiden. Diese Muster unterscheiden sich von einer Programmiersprache zur anderen und es gibt es keine Standardregeln, deren Befolgung die Sicherheit der Software garantiert. Einige verbreitet eingesetzte Codierstandards tragen dem Safety-Aspekt Rechnung:

  • Für die C-Sprache: Misra C und SEI Cert C
  • Für die Sprache C++: Misra C++, JSF AV C++, SEI Cert C++, Autosar C++

Damit Programmierer sich leichter zurechtfinden, teilen die Normungsorganisationen die Regeln in den Standards normalerweise in mehrere Kategorien, denn die Zahl der Regeln in den einzelnen Standards kann recht umfangreich sein, wie Tabelle 2 zeigt.

Best Practices

Sobald man an die Absicherung eines Codes geht, kommt es auf die richtige Wahl an. Benötigt die Software eine Zertifizierung nach einem bestimmten Functional-Safety-Standard, ist die erste Entscheidung bereits gefällt. Ungeachtet dessen müssen Programmierer aber über die Codierstandards oder die Teilmenge des Standards entscheiden, den die entwickelte Software zwingend einzuhalten hat. Dies kann einer der zuvor erwähnten Standards sein.

Im nächsten Schritt müssen Programmierer dann ein geeignetes statisches Analysetool auswählen, denn es ist nicht möglich, die Einhaltung all dieser Regeln manuell zu verifizieren. Der Markt bietet hier verschiedene Hersteller mit sowohl quelloffenen als auch kommerziell statischen Analysetools. Die folgenden Auswahlkriterien sollten Anwender beachten:

  • Wird der gewählte Codierstandard von dem Tool ganz oder teilweise unterstützt?
  • Wenn der betreffende Funktionssicherheits-Standard die Tool-Qualifikation verlangt, ist zu fragen, ob das Tool zertifiziert ist und ob es das Qualification-Kit bietet.
  • Kann das Tool die Analyse-Reports in der für die Konformitätsanalyse benötigten Form vorlegen?
  • Kann es die Analyse-Reports in einer für die Entwickler leicht lesbaren Form erzeugen?
  • Lässt sich das Tool einwandfrei in die verwendeten IDEs, Build- und CI-Systeme integrieren?
  • Gestattet es eine selektive Analyse von neuem, geändertem oder bestehendem Code?
  • Unterstützt das Tool eine flexible Konfiguration der Analyse?
  • Nutzt das Tool Risk-Scoring-Algorithmen als Hilfestellung beim Priorisieren der gefundenen Defekte?
Tabelle 3: Entwickler können gefundene Fehler anhand der CERT-C und CERT-C++Regeln priorisieren.

Tabelle 3: Entwickler können gefundene Fehler anhand der Cert-C- und Cert-C++Regeln priorisieren. Parasoft

Zudem betreibt die CWE Community zusätzlich das Compatibility-and-Effectiveness-Programm. Dabei handelt es sich um einen formellen Prüf- und Evaluierungsprozess für ein Produkt oder einen Service. Derzeit umfasst die Liste mit Produkten und Services 55 Einträge, die als Officially CWE-Compatible gelten. Kommt das gewählte Tool in dieser Liste vor, dann ist sichergestellt, dass es die finale Stufe des formellen CWE-Compatibility-Programms der Mitre-Organisation erreicht hat.

Sind der Codierstandard und die erforderlichen Tools bestimmt, sollte die weitere Arbeit für die von Grund auf neu gestarteten Softwareprojekte einfach sein: Programmierer müssen das Tool in das CI-System integrieren und sicherstellen, dass kein Defekt unberücksichtigt bleibt.

In aller Regel aber müssen Programmierer Codierstandards auch für Software durchsetzen, die sich bereits in der Entwicklung befindet. Dann kann das blinde Ausführen der Analyse mit der gesamten Codebasis zu hunderten von Defektmeldungen führen, die in ihrer Gesamtheit schwierig zu handhaben sind. Glücklicherweise stehen mehrere Techniken zur Verfügung, um diesen Vorgang zu vereinfachen.

Hier empfiehlt es sich, sich zunächst auf den neu geschriebenen oder modifizierten Code zu konzentrieren, da dies gewährleistet, dass nach Einrichtung des Codierstandards zumindest keine neuen Defekte entstehen. Es hat sich auch bewährt, die gemeldeten Defekte nach Wichtigkeit einzuordnen, sodass Programmierer die gravierendsten Fehler zuerst beheben können. Zum Beispiel gibt es für die Cert-C- und Cert-C++-Regeln eine Risikobewertung, die eine einfache Priorisierung der gefundenen Defekte gestattet (Tabelle 3). Hilfreich ist auch eine nach Priorität geordnete Liste der Defekte im Verbund mit der konfigurierbaren Liste der durchzusetzenden Regeln, um sich zunächst auf die Regeln mit dem höchsten Schweregrad zu konzentrieren und die Zahl der Regeln auszuweiten, nachdem die gravierendsten Defekte behoben sind.

Am wichtigsten ist es allerdings sicherzustellen, dass sich geeignete Maßnahmen des Entwicklungsteams an die Analyse anschließen. Selbst noch so gute Berichte der statischen Analyse sind nutzlos, wenn Entwickler sie nicht zum Reparieren des Codes nutzen, um Softwareprodukte hervorzubringen, die in Sachen Safety und Security besser sind.