3 Einführung in die sichere Softwareentwicklung
Die Hauptursache von Sicherheitsproblemen in Computersystemen sind Schwachstellen in der Software. Hacker nutzen Implementierungsfehler und Mängel im Softwaredesign, um ein System anzugreifen.
Softwaresysteme enthalten sowohl Implementierungsfehler (Bugs) als auch Designmängel (Design Flaws), die zu Sicherheitsrisiken werden können. Als Anwender hat man sich längst daran gewöhnt, dass Software nicht fehlerfrei ist. Gleichzeitig haben die Sicherheitsprobleme in den letzten Jahren überdurchschnittlich stark zugenommen.
Nach Gary McGraw sind die Ursachen dafür:
Connectivity: Die zunehmende Vernetzung der zumeist mobilen Computer über das Internet ermöglicht es den Hackern, Softwaresysteme von jedem Ort der Welt aus anzugreifen. Bestehende Softwarekomponenten werden als Webservices zur Verfügung gestellt, auch wenn diese nie dafür vorgesehen waren.
Extensibility: Applikationen können frei aus dem Internet geladen, Erweiterungen und Plugins auf Knopfdruck installiert werden. Webseiten und lokale Dokumente enthalten Scripts, um deren Funktionalität zu erweitern. All diese Techniken erschweren es, festzustellen, welche Software verwendet wird und ob diese fehlerfrei ist.
Complexity: Betriebssysteme, Applikationen oder auch nur Softwarebibliotheken bestehen aus Millionen von Codezeilen. Untersuchungen zeigen, dass die Fehlerwahrscheinlichkeit stark mit dem Umfang des Codes ansteigt – damit steigt auch die Anzahl der Sicherheitslücken.
Lange Zeit war das Thema Security alleine die Angelegenheit von Administratoren, die für den Betrieb von Firewalls, Intrusion-Detection-Systemen und Antivirenprogrammen zuständig waren. Es zeigt sich aber, dass dieser Ansatz nicht alleine zum Ziel führen kann. Schließlich ist es effizienter, Software zu entwickeln, die sich selbst schützen kann, indem sie weniger Angriffspunkte bietet.
3.1 Ein Prozessmodell für sichere Softwareentwicklung
Sichere Software entsteht nicht zufällig oder durch kleine Erweiterungen am fertigen Softwareprodukt. Software-Security basiert auf bewährten Methoden des Software-Engineerings. Eine wichtige Praktik des Software-Engineerings ist die Verwendung eines definierten Prozessmodells, in dem die Abfolge der einzelnen Phasen der Softwareentwicklung vorgegeben ist, um die reibungslose Erstellung eines Softwareprodukts sicherzustellen. Je nach Anwendungsbereich kommen unterschiedliche Prozessmodelle zum Einsatz. Werden diese Phasen des Prozessmodells der Reihe nach über die Projektlaufzeit verteilt, spricht man von einem Wasserfallmodell. Bei Anwendungen, bei denen sich die Anforderungen rasch ändern können, setzt man jedoch auf agile Entwicklungsmethoden. Bei agilen Prozessmodellen wird die Projektlaufzeit in gleich lange Iterationen unterteilt, wobei in jeder Iteration alle Phasen der Softwareentwicklung durchlaufen werden. Wartung und Weiterentwicklung können somit in zusätzliche Iterationen ausgelagert werden.
Nach Ian Sommerville sind die wichtigsten Phasen der Softwareentwicklung:
Analyse und Definition der Anforderungen: Die funktionalen und nicht-funktionalen Anforderungen sowie bestehende Rahmenbedingungen werden im Gespräch mit dem Kunden erarbeitet. Das Ergebnis der Anforderungsanalyse sind Use-Case-Spezifikationen, die in einem Anforderungsdokument zusammengefasst werden.
Architektur und Design: Die Struktur des Softwaresystems wird definiert. Durch Abstraktion wird die Gesamtfunktionalität auf Komponenten aufgeteilt, die über spezifizierte Schnittstellen und Protokolle interagieren. Architektur- und Designentscheidungen werden im Designdokument festgehalten, das üblicherweise auch UML-Diagramme enthält.
Implementierung und Unit Testing: Die Funktionalitäten der Komponenten werden weiter unterteilt, bis sie mit den Konstrukten einer Programmiersprache implementiert werden können. Jeder Teil der Implementierung wird mit Hilfe von Tests verifiziert. Das Ergebnis dieser Phase sind der Quellcode sowie verschiedene Konfigurationsdateien und Softwarebibliotheken, aus denen das fertige Softwaresystem automatisiert gebaut werden kann.
Systemtests: Durch Systemtests wird überprüft, ob das Softwaresystem die spezifizierten Anforderungen erfüllt. Nach einem erfolgreichen Abnahmetest wird das Softwaresystem an den Kunden ausgeliefert. Ein Protokoll der Testergebnisse dokumentiert das Ende dieser Phase.
Betrieb und Wartung: Das ist die mit Abstand längste Phase im Lebenszyklus eines Softwareprodukts. Die Software wurde installiert und ist als laufendes System im praktischen Einsatz. Im Zuge der Wartungstätigkeiten werden Fehler beseitigt, die bis dahin nicht entdeckt wurden. In diese Phase fällt auch das Hinzufügen neuer Funktionalitäten, wenn sich die Anforderungen mit der Zeit verändern (Software-Evolution).
Abbildung 3.1 Ein praktisches Prozessmodell für die Entwicklung von sicherer Software
Um ein sicheres Softwaresystem zu entwickeln, müssen mehrere sicherheitsrelevante Tätigkeiten in unterschiedlichen Phasen der Softwareentwicklung durchgeführt werden. Man hat daher die bekannten Prozessmodelle der Softwareentwicklung um konkrete Security-Aktivitäten erweitert, welche die Sicherheit in jeder Entwicklungsphase berücksichtigen. Die bekanntesten Vertreter dieser erweiterten Prozessmodelle sind der Security Development Lifecycle (SDL) von Microsoft und die Touchpoints for Software Security von Gary McGraw.
Das Prozessmodell, das in Abbildung 3.1 dargestellt ist, orientiert sich am Konzept der Touchpoints, da dieses Prozessmodell weniger strikt definiert ist und sich leichter in die Praxis überführen lässt. Die unterschiedlichen Praktiken zur Verbesserung der Softwaresicherheit basieren auf den Artefakten, die von den einzelnen Phasen des Entwicklungsprozesses erzeugt werden. Leider sind die Ressourcen in der Softwareentwicklung oft knapp bemessen, und eine vollständige Umsetzung aller notwendigen Aktivitäten ist nicht immer möglich. Daher erfolgt hier eine Priorisierung der Praktiken nach ihrer Wirksamkeit im Aufspüren von Sicherheitslücken:
Code-Review: Bei der Analyse des (Quell-)Codes versucht man, Implementierungsfehler zu finden. Im Gegensatz zum klassischen Debuggen wird dabei speziell auf Bugs geachtet, die erfahrungsgemäß zu Sicherheitslücken führen können.
Architectural Risk Analysis: Die Architektur und das Design eines Softwaresystems müssen kohärent sein und eine durchgängige Verteidigungslinie gegen Angriffe bilden. Eine Risikoanalyse versucht, Schwachstellen in dieser Struktur ausfindig zu machen.
Risk-Based Security-Tests: Security-Tests sind, technisch gesehen, Unit-, Component-, Integration- und Systemtests. Die Testfälle orientieren sich jedoch einerseits an den eingebauten Sicherheitsfunktionalitäten, andererseits an den potenziellen Schwachstellen aus der Risikoanalyse und den Angriffsmustern (Attack Patterns) von Hackern.
Penetration Testing: Man versucht, ein Softwaresystem in seiner realen Laufzeitumgebung anzugreifen. Dieser Blackbox-Ansatz ähnelt einem Hackerangriff sowohl in der Vorgehensweise als auch in der Auswahl der eingesetzten Tools.
Abuse Cases: Bei der Definition von Abuse Cases schlüpfen Entwickler in die Rolle von Hackern. Abuse Cases beschreiben das Systemverhalten während eines Angriffs. Dazu braucht es Wissen darüber, was geschützt werden muss, wie Angriffe ablaufen könnten und wie eine mögliche Verteidigung funktionieren soll.
Security Operations: Angriffe gegen ein Softwaresystem können jederzeit stattfinden. Mit Hilfe von Monitoring- und Logging-Tools können diese Aktivitäten erfasst und ausgewertet werden. Aus den analysierten Angriffsmustern können neue Verteidigungsstrategien entwickelt und in die Software integriert werden.
Da sich diese Praktiken auf die Artefakte der einzelnen Softwareentwicklungsphasen beziehen, sind sie vom verwendeten Prozessmodell weitestgehend unabhängig und können auch sehr gut zusammen mit agilen Methoden eingesetzt werden.
Die vorgeschlagene Reihenfolge der Software-Security-Praktiken kann sich im konkreten Anwendungsbereich natürlich ändern. Einen wesentlichen Einfluss auf die Reihenfolge der angewendeten Praktiken hat der Zeitpunkt, zu dem eine Security-Analyse durchgeführt wird:
...