Security First: Sichere Softwareentwicklung

Die Sicherheit einer Software vor der Entwicklung des Produktes selbst zu planen, bringt sowohl Effizienzvorteile als auch Kostenersparnis mit sich. Trotzdem wird das Thema Sicherheit fast immer nachrangig behandelt oder gar als Last angesehen. Wir zeigen, wie es dazu kommt und wie Sicherheitsaspekte von Beginn an in die Entwicklung integriert werden können.

Die dynamisch gewachsene Softwareentwicklung

Ein Projekt startet mit einer Idee, die umgesetzt werden soll – meistens aus dem Bedarf heraus, etwas zu verändern, zu optimieren oder eleganter zu lösen. Dieser Bedarf wird in Form der funktionalen Anforderungen sichtbar gemacht und ist oft leicht beschreibbar: Welche Informationen werden von der Software verarbeitet? Wie werden diese Informationen empfangen oder übertragen? Wie erfolgt die Berechnung und Erzeugung von Ergebnissen? Welche Schnittstellen für andere Anwendungen müssen bereitgestellt werden?

Aus ausreichend genauen Anforderungen an Schnittstellen, Komponenten, Datenflüssen und deren Zusammenspiel ergeben sich schnell Anforderungen an das generelle Design einer Lösung. So ist es beispielsweise bei einer Webanwendung wie diesem Blog naheliegend, dass ein Webserver verwendet wird, der aus einer Datenbank Inhalte über das Protokoll HTTP überträgt. Die Architektur könnte also wie folgt aussehen:

Da funktionale Anforderungen durch ihren konkreten Inhalt unmittelbar sichtbar sind, werden insbesondere in agilen Entwicklungsmodellen zunächst diese Anforderungen umgesetzt. Häufig werden hierbei schon interne Vorgaben, die auch nicht immer dokumentiert sind, berücksichtigt und damit bereits etablierte oder bekannte Lösungswege gegangen oder vorhandene Programmteile wiederverwendet.

Nachdem eine Grundfunktionalität geschaffen wurde, werden Aspekte relevant, die nicht direkt mit der Funktionalität in Verbindung stehen – die nichtfunktionalen Anforderungen. Auch hier fallen wieder diejenigen als erstes auf, die sich auf einer abstrakten Ebene noch messen lassen. Zum Beispiel können Zuverlässigkeit, Reaktionsgeschwindigkeit und auch die Effizienz mit Kennzahlen wie Erfolgsraten oder Ladezeiten gemessen werden. Die Benutzbarkeit, stark gesteuert durch Entscheidungen zur UX, wirken sich auf die Nutzerakzeptanz aus und spiegeln sich so in Kennzahlen wie der Verweil- oder Verwendungsdauer oder der Anzahl an Supportanfragen wider.

Nichtfunktionale Anforderungen umfassen allerdings auch Anforderungen, die sich nicht gut messen oder veranschaulichen lassen, wie gesetzliche Vorgaben, Branchenstandards oder Vertragsbausteine wie Service Level Agreements, die Anforderungen an die Verfügbarkeit oder Vertraulichkeit von Daten stellen. Beispielsweise fordert die Datenschutz-Grundverordnung im Artikel 32 ein „dem Risiko angemessenes Schutzniveau” bei der Verarbeitung personenbezogener Daten. Sicherheit wird bei der Verarbeitung personenbezogener Daten – oder in unzähligen anderen Situationen – schnell eine nichtfunktionale Anforderung, ohne dass eine absolute und objektive Messgröße dafür existiert. Für die Prüfung, ob eine Anforderung erfüllt ist, stellt dies allerdings ein Problem dar.

Hinzu kommt, dass Sicherheit keinen Produktfortschritt unterstützt, bei schlechter Umsetzung die UX nachteilig beeinflusst und somit oft ein Hindernis oder Kostenfaktor ohne sichtbaren Mehrwert darstellt. Daraus folgt häufig, dass Sicherheit erst sehr spät im Entwicklungsprozess berücksichtigt wird – wenn es überhaupt passiert.

In solchen Fällen ist es oft nur eine Frage der Zeit, bis doch ein Schaden entsteht – seien es empfindliche Strafen durch Datenschutzverstöße oder ein nachhaltiger Image-Schaden aufgrund eines erfolgreichen Angriffes auf die Software. Aber auch ohne einen direkten Angriff können durch eine wohlwollende Person oder einen beauftragten Penetrationstest Sicherheitslücken identifiziert werden. Manchmal finden sich hierbei eine ganze Liste an Schwachstellen. Um diese nachträglich zu beheben, müssen erfahrungsgemäß viele Ressourcen aufgewendet werden, stellenweise Prozesse etabliert und manchmal sogar tiefgehend die Architektur einer Anwendung angepasst werden – wären diese Probleme doch nur vorher aufgefallen …

Security von Anfang an mitdenken

Security wird nicht zum ersten Schritt. Zuerst einmal braucht es wieder eine Idee, die zu einem Entwicklungsprojekt wird. Es startet wieder im Design mit der Definition einer Architektur und der damit verbundenen Identifikation von Komponenten und Datenflüssen. Statt jetzt aber sofort mit der Entwicklung zu starten, wird der Designprozess erweitert, um Security by Design zu praktizieren.

Hierzu gibt es eine Vielzahl von Umsetzungsvarianten, die weit über die hier betrachtete Anfangsphase hinaus gehen. Im Folgenden gehen wir auf einzelne Elemente ein, die sich in den Praktiken des von Microsoft entwickelten Security Development Lifecycle wiederfinden.

Zentral für diesen Prozess ist erneut die Anforderungsanalyse. Gerade Anforderungen aus gesetzlichen Vorgaben müssen bekannt sein und verstanden werden. Es muss also eine Anforderungsanalyse durchgeführt werden, die über die rein funktionalen Anforderungen hinausgeht, um eine gute Grundlage für die weitere Entwicklung des Projektes zu schaffen. So ergibt sich aus der bereits benannten Datenschutz-Grundverordnung die Relevanz des „Stands der Technik”, welcher für den jeweilig konkreten Einsatzzweck ermittelt werden muss und sich anschließend in Anforderungen wiederfinden sollte.

Mit diesem zusätzlichen Wissen kann die Planung der Software- oder Systemarchitektur erweitert werden. Betrachtet man die oben abgebildete Architektur in Bezug auf die Sicherheit, ist ein Problem erkennbar: Die Verbindung zwischen Webserver und Client ist unverschlüsselt. Wird eine solche Website in einem öffentlichen Netzwerk aufgerufen, kann der Inhalt bei Übertragung beliebig verändert werden. Wenn wir den Stand der Technik beachten, ist hier die Verwendung von TLS in Form von HTTPS üblich, um die Vertraulichkeit und auch die Integrität der übertragenen Inhalte zu sichern. Solche Überlegungen führen bereits vor der ersten Zeile Code dazu, dass Sicherheitsmaßnahmen wie die Unterstützung von HTTPS berücksichtigt werden. Die Verwendung einer Webserver-Lösung, die kein TLS unterstützt, ist für unser Beispiel streng genommen erst jetzt ausgeschlossen (auch wenn solche Webserver zugegebenermaßen sehr selten geworden ist).

An dieser Stelle können wir allerdings einen Moment innehalten und eine Sache feststellen: Unser Beispiel zeigt, wie man mit nur wenigen Gedanken an Sicherheit von einer rein funktionalen Architektur zu einer Sicherheitsarchitektur kommt.

Betrachten wir nun auch die Betriebsumgebung und segmentieren die Systeme mit Firewalls, kommen wir in unserem Beispiel zu folgender Sicherheitsarchitektur:

Aufbauend auf dieser Sicherheitsarchitektur können wir die Wirksamkeit der Sicherheitsüberlegungen auf einer theoretischen Ebene prüfen. Hierzu können wir uns überlegen, welche Bedrohungen auf unsere Anwendung wirken. Abhängig von der Bedrohung können Angriffe oder Fehler auf verschiedensten Wegen einen Schaden an der Anwendung oder den darin verarbeiteten Daten bewirken. Durch das Beschreiben und Konkretisieren einer solchen Bedrohung wird diese bewertbar – im einfachsten Fall mit einer Bewertung der Schadenshöhe und Eintrittswahrscheinlichkeit, im besten Fall mit etablierten Modellen wie beispielsweise STRIDE, welche im Anschluss in verschiedenen Dimensionen analysiert werden. Unabhängig, ob ein solches Framework verwendet wird oder nicht, gilt: Mit einer strukturierten Bedrohungsmodellierung fallen mögliche Schwächen in der Sicherheitsarchitektur frühzeitig auf und können noch in der Planung behoben werden. Der gesamte Entwicklungsprozess ist dadurch effizienter und somit günstiger, als später zur Behebung solcher Feststellungen Anpassungen an einer bereits implementierten Architektur erfolgen lassen zu müssen.

Durch die Bedrohungsmodellierung sind auch mögliche Schwachstellen bekannt, die in der Entwicklung mit mehr Sorgfalt betrachtet werden müssen. Da die Sicherheit der Anwendung sehr früh im Design verankert wurde, können auch spätere Sicherheitstests gezielter geplant werden.

Neben einer generellen Betrachtung der Sicherheitsarchitektur und darauf aufbauender Maßnahmen existieren noch weitere Aspekte, die bei einer frühen Berücksichtigung zu einem erhöhten Sicherheitsniveau führen. Vor allem, da heutzutage nicht mehr jede Komponente einer Software neu entwickelt, sondern fertige Bibliotheken, Schnittstellen, Standards, Programme, Container und Dienste verwendet werden, kann eine starke Relevanz der Qualität und Sicherheit dieser Abhängigkeiten entstehen. Ein gut vorbereitetes Supply Chain Management ist dabei unerlässlich, um den Überblick über diese Abhängigkeiten zu behalten und bei Bedarf, zum Beispiel bei Bekanntwerden einer Schwachstelle, schnell zu reagieren.

Wie wichtig regelmäßige Software-Updates sind, ist mittlerweile gut bekannt. Es werden mögliche Schwachstellen behoben, bevor diese ausgenutzt werden können und die Software bleibt so auf dem aktuellen Stand der Technik. Vergleichbar dazu ist die Aktualität und Security Awareness der entwickelnden Personen eng verbunden mit der Sicherheit einer Anwendung. Diese Personen müssen einerseits wissen, wie Schwachstellen entstehen und ausgenutzt werden, und andererseits verstehen, wie diese vermieden werden können. Eine angemessene und stetige Fortbildung kann also einen zentralen Beitrag zur Sicherheit der Anwendungen leisten. Das kann über regelmäßige Schulungen und Awareness-Trainings erfolgen, aber auch durch Fachvorträge oder Wissensaneignung über Newsletter. Unabhängig vom bevorzugten Medium zur Fortbildung gilt vor allem zu beachten, dass die entwickelnden Personen regelmäßig die Zeit für solche Fortbildung benötigen.

Security war von Anfang an dabei

Durch die frühe Betrachtung von Sicherheitsaspekten sind Probleme aufzeigbar und können bereits mit Lösungen versehen werden, bevor die erste Zeile Code entstanden ist. Schwachstellen können so schon im Designprozess aufgedeckt und vermieden werden. Ebenso sind gesetzliche Vorgaben durch eine frühe Analyse von Anforderungen an den Schutz oder die Sicherheit von Informationen früh berücksichtigt. Das Risiko für eine ressourcenaufwendige Nachbesserung wird so deutlich minimiert. Beim nächsten Software-Projekt wird Security früh genug und nicht erst im Nachgang berücksichtigt.

Autor