parasoft-logo-2018 (Parasoft)

Parasoft® Deutschland GmbH

https://de.parasoft.com

28.07.2023

Gute Software ist billiger als schlechte Software - Programmierstandards für größere SW-Sicherheit

Die Entwicklung von hochwertiger Software schafft keine Mehrkosten, sondern die Kosten sind höher, wenn man Software unzureichender Qualität entwickelt. Der Forscher Capers Jones hat nachgewiesen, dass die die typischen Kosten für Software mit jeder Phase ansteigen – vom Erstellen des Pflichtenhefts über das Programmieren bis zur Wartung. Die Herangehensweise der Teams an Qualität bestimmt, ob ihr Prozess gesund oder ‚pathologisch‘ ist.

Die Kosten mangelnder Qualität

Findet man Fehler sofort beim Schreiben des Codes, sind die Kosten relativ niedrig – beispielsweise nur ein paar Minuten Zeit des Entwicklers. Lassen sich 85% aller Defekte schon in der Entwicklungsphase beseitigen, wirkt sich dies markant auf die Kosten aus.

Laut Untersuchungen bei echten Unternehmen mit realer Software (anstelle theoretischer Modelle) kostet das Beheben von Fehlern nach der Freigabe rund 16.000 US-$ (u.U. deutlich mehr). Erfolgen die Qualitäts- und Security-Maßnahmen in einer späten Phase, sind die hier aufgedeckten Security-Probleme dem teuren Ende des Zyklus zuzurechnen. Der Aufwand dürfte etwa 15-mal so hoch sein wie beim Auffinden in frühzeitigen Security-Audits. Es ist ein nachweislich falscher Ansatz, die Software-Qualität durch Tests am Ende des Entwicklungszyklus und damit unmittelbar vor der Freigabe zu verbessern. Bei der Produktion von Waren ist klar, dass diese Methode nicht funktioniert – warum aber hält sich die fixe Idee, bei Software könnte man Qualität und Sicherheit ‚hineintesten‘?

Basierend auf den folgenden gängigen Merkmalen möchte ich behaupten, dass nahezu niemand ingenieurmäßig an die Software-Entwicklung herangeht:

·        Was die meisten Entwickler tun, ist nicht reproduzierbar. Stellt man zwei Entwicklern dieselbe Aufgabe, werden sich die Ergebnisse unterscheiden.  

·     Es fehlt an gut ausgearbeiteten ‚Best Practices‘. Software-Entwickler betrachten Programmierstandards als ein Regelwerk, auf dessen Einhaltung die Teamleitung besteht, und verkennen dabei, dass sie Wissen, Praxis und Erfahrung verkörpern. Während einem Elektroingenieur klar ist, dass Standards eine Möglichkeit sind, ein auf Anhieb sicheres Produkt zu bauen, sieht ein Softwareentwickler dagegen in einem Standard eine Restriktion, die ihn hemmt – ein ‚False Positive‘ also.

·     Fremde und uneinheitliche Entwickler-Schulung. Die Ausbildung im Bereich der Software-Entwicklung erfolgt nicht so standardisiert wie bei den Ingenieurwissenschaften. Oft liegt der Fokus auf Programmiersprachen anstelle von Standards und etablierten Praktiken.

 

Mehr Safety und Security

Codingstandards zielen darauf ab, bewährte Programmierpraktiken zu etablieren, um  funktional sicheren, zuverlässigen, prüfbaren und wartbaren Code zu schreiben. In der Regel bedeutet das, bekanntermaßen unsichere Programmierpraktiken ebenso zu vermeiden wie Code, der zu unvorhersehbarem Verhalten führen kann.

Es scheint jedoch, dass die Industrie mit diesen Programmierstandards das Ziel ein wenig aus den Augen verloren hat. So gibt es bei den Tools (z.B. statischen Analysetools) seit den vergangenen zehn Jahren eine Verlagerung: Anstelle der Aufdeckung von potenziell problematischem, unsicherem Code oder bekannten Sprach-Schwachstellen wird nach Fehlern gesucht, gleichsam als eine Art frühzeitigem Test (auch bekannt als ‚shift left‘ – also Linksverschiebung auf der Zeitachse).

Unbestritten ist die Fehlersuche wichtig. Aber ist es nicht produktiver, von Anfang an solide Software zu schreiben? Man sollte Standards ausarbeiten und durchsetzen, um das Entstehen von Defekten von vornherein zu vermeiden – und auf der Zeitachse in eine frühere Phase zu rücken.

 

Industriestandards

Industriestandards für Safety und Security wie MISRA C/C++, SEI/SANS CERT, OWASP Top 10 und CWE - Common Weakness Enumeration Top 25 sind ein enormer Arbeitsaufwand. Obwohl ihr Einsatzgebiet je nach Typ eingeschränkt ist, finden sie Anwendung in vielen Branchen, wie beispielsweise MISRA C: Dieser in 1998 ins Leben gerufene Standard ist sehr gut definiert und wird jeweils nach einigen Jahren aktualisiert. Mit der Weiterentwicklung der Sprachen C und C++ werden auch die dazugehörenden Standards weiterentwickelt. Der überaus flexible Standard berücksichtigt verschiedene Schweregrade (severity levels), und es gibt eine dokumentierte Strategie zum Behandeln und Dokumentieren von Abweichungen. Da sich die Technologie (z.B. die statische Analyse) zum Erkennen von Verletzungen der von Codierstandards aufgestellten Richtlinien weiterentwickelt, wird bei den neuesten MISRA-Versionen berücksichtigt, welche Richtlinien entscheidbar (also von Tools mit hoher Genauigkeit detektierbar) sind und welche nicht.

 

Die Rolle der statischen Analyse

Die Hauptursache mangelhafter Softwarequalität ist die unzureichende Fehlerbeseitigung – das belegen Studien. Programmierer erreichen beim Aufdecken von Defekten in ihrer eigenen Software eine Effizienz von etwa 35%. Im späteren Verlauf des Entwicklungszyklus liegt die Zahl der Mängel, von denen man hoffen kann, dass sie nach all den Designprüfungen, Peer-Reviews, Unit-Tests und Funktionstests beseitigt werden, bei etwa 75%. Bei ordnungsgemäßem und präventivem Einsatz kann die statische Analyse die Quote der eliminierten Defekte auf 85% steigern. Die meisten Unternehmen legen den Fokus beim Einsatz der statischen Analyse auf das Auffinden und zügige Beseitigen von Fehlern. Aber sie hätten zusätzliche Vorteile, wenn sie statische Analysetools nutzten, um bekannte mangelhafte Programmierpraktiken und Sprach-Features von vornherein zu vermeiden. Hier kommen jene Codierstandards ins Spiel, die mit Richtlinien und Sprach-Teilmengen unterbinden, dass gängige Defekte wie etwa Pufferüberläufe oder fehlende Initialisierungen überhaupt erst in den Code hineingeschrieben werden.

 

Vorbeugen ist besser …

Angenommen, in einem Test wird ein komplexer Pufferüberlauf-Fehler entdeckt, z.B. mit einem Dynamic Application Security Tool (DAST). Nach Auffinden und Debuggen muss ein erneuter Test folgen. Die statische Analyse mit Flow-Analyse hätte diesen Fehler vielleicht auch gefunden, je nach Komplexität der Applikation. Die Laufzeit-Fehlerdetektierung ist zwar präzise, prüft aber nur die tatsächlich ausgeführten Codezeilen. Also kann sie nur so gut sein wie die Testabdeckung. Besser wäre es, wenn ein Programmierstandard die Verwendung des Codes, der zu diesem Fehler führt, von vornherein unterbunden hätte.

 

Codierstandards wie MISRA C beschreiben nicht, wie man z.B. nicht initialisierten Speicher aufdecken kann, sondern leiten die Programmierer an, ihren Code so zu schreiben, dass ein solcher Fehler gar nicht erst vorkommt. Das ist eine deutlich ‚ingenieurmäßigere‘ Vorgehensweise: Programmieren nach bekannten und akzeptierten Standards, ganz so, wie man es im Bauwesen macht, etwa bei der Brückenkonstruktion. Hier würde man schließlich auch nicht zunächst die Brücke bauen und dann immer schwerere Lastwagen darüberfahren lassen, das Gewicht des letzten heil darübergefahrenen Lkw messen und die Brücke dann neu bauen, damit sie dieses neue Gewicht verkraftet. Welch unsinniges Vorgehen! Trotzdem erfolgt die Entwicklung von Software nicht viel anders.

 

Wendet ein Softwareteam einen Codierstandard an und nutzt die statische Analyse richtig, kann es Fehler frühzeitig erkennen und vermeiden – das ist sehr gut. Besser ist es aber, die Art und Weise zu verändern, wie das Team den Code schreibt. Ein gutes Beispiel ist die Heartbleed-Schwachstelle. Es gibt inzwischen Detektoren für genau diese Sicherheitslücke, aber man hätte auch den Code so schreiben können, dass Heartbleed niemals aufgetreten wäre. Programmierstandards verkörpern solide technische Prinzipien für das Programmieren in den jeweiligen Sprachen und bilden die Grundlage für ein vorbeugendes Konzept..

 

Autor: Arthur Hicken, Evangelist bei Parasoft

 

Arthur Hicken ist seit mehr als 25 Jahren bei Parasoft in den Bereichen Software-Security und Testautomatisierung tätig und half bei der Erforschung neuer Methoden und Techniken (darunter fünf Patente). Gleichzeitig unterstützt er die Kunden bei der Verbesserung ihrer Softwarepraktiken.