>  NEWS & PROJEKTE > Sichere Softwareentwicklung

Sichere Softwareentwicklung


Sicherheitsanforderungen im Kontext sicherer Softwareentwicklung


Zu Beginn eines Softwareprojekts steht die Anforderungsanalyse. In diesem Kontext ist es von Bedeutung, von Anfang an die Sicherheitsanforderungen (SA) mitzuberücksichtigen. Ein frühes Mitdenken an dieser Stelle kann helfen, spätere kostspielige und aufwendige Nacharbeiten und Änderungen zu verhindern.  Sicherheitsanforderungen sind nicht-funktionale (teilweise auch funktionale) Anforderungen, die Sicherheitsziele formalisieren, ohne jedoch vorzugeben, wie diese Ziele erreicht werden sollen.


Eine wichtige Bezugsquelle für SA ist der ISO-15408 Standard, auch „Common Criteria (CC)“ genannt. Der Standard definiert Sicherheitseigenschaften und deren Prüfung von IT-Systemen. Auch gesetzliche Rahmenbedingungen können als Quelle für SA dienen. Sicherheitsanforderungen können durch folgende Prozessschritte erhoben werden:



  1. Identifikation von Schutzzielen: Im Allgemeinen handelt es sich hierbei um die Ziele Vertraulichkeit, Integrität und Verfügbarkeit. Diese sind sehr pauschal und müssen für den konkreten Anwendungsfall noch spezifiziert werden.
  2. Funktionale Anforderungen definieren: Zu Beginn der Security Requirements Engineering (SRE) werden zunächst die funktionalen Anforderungen an ein System erhoben. Dieser Schritt wird im Rahmen des „normalen“ Requirements Engineerings durchgeführt. Die funktionalen Anforderungen werden als Grundlage für die weiteren Schritte benötigt.
  3. Abstraktes (High Level) Architekturdiagramm erstellen: Dieses erweist sich bei der Identifizierung von Misuse Cases als hilfreich. So können Schwachstellen auf Architekturebene leichter erkannt werden. Außerdem wird dadurch das System in seinem Anwendungsbereich bzw. Kontext betrachtet. Dadurch wird die Wahrscheinlichkeit gesenkt, dass einige bedeutende Misuse Cases nicht identifiziert werden.
  4. Assets und Ressourcen identifizieren und bewerten/gewichten: Damit Schutzmaßnahmen implementiert werden können, muss zunächst klar sein, was in welchem Maße geschützt werden muss. Hierzu werden die schützenswerten Assets identifiziert und priorisiert. Assets können bspw. Nutzerdaten, geheime Konstruktionspläne oder auch der Ruf eines Unternehmens sein.
  5. Nutzer und Angreifer identifizieren: Durch die Identifikation der rechtmäßigen Nutzer der Software oder des Systems können im weiteren Vorgehen leichter die potenziellen Angreifer verifiziert werden. Hierbei können zum Beispiel für die Nutzer jeweils äquivalente Missbrauchsnutzer identifiziert werden. Dabei wird auch über die potenziellen Interessen und Fähigkeiten der Angreifer nachgedacht.
  6. Bedrohungen identifizieren/Risikoanalyse: Nachdem die schützenswerten Assets und Angreifer gefunden sind, werden mögliche Angriffe auf diese Güter verifiziert. Dabei spielen das Risiko eines Angriffs und das erwartete Schadensausmaß eine wichtige Rolle bei der Implementierung von Gegenmaßnahmen.
  7. Misuse Cases: Äquivalent zur Identifikation von Use Cases werden Misuse Cases identifiziert, welche das Verhalten des Systems im Angriffsfall beschreiben. Aus den Misuse Cases lassen sich dann Anforderungen an das System ableiten, deren Erfüllung die Durchführung der Misuse Cases verhindert oder zumindest stark erschwert.


Sichere Softwarearchitektur


Nachdem die Sicherheitsanforderungen erhoben wurden, kann mit der nächsten Phase der sicheren Softwareentwicklung begonnen werden, nämlich mit der Planung des Designs. Da hierbei die zuvor definierten Sicherheitsanforderungen berücksichtigt werden müssen, erfolgt dieser Prozessschritt nach dem Security Requirements Engineering. Überlegungen zur Sicherheit in der Entwurfsphase sind wichtig, da die Wahl eines Architekturansatzes die Erfüllung der Sicherheitsanforderungen erleichtern, aber auch erschweren oder gar verhindern kann. Sicherheitslücken, die aufgrund von fehlerhaftem Design entstehen, können in den seltensten Fällen durch kleinere Programmieränderungen behoben werden. Stattdessen muss das Design geändert werden, was wiederum größere Softwareänderungen nach sich ziehen kann. Wichtige Hilfsmittel für sicheres Design sind Secure Design Patterns und Secure Design Principles.


Secure Design Patterns sind Muster, um häufig wiederkehrende Sicherheitsprobleme auf ähnliche Art zu lösen. Neben Security Patterns gibt es die etwas allgemeineren und abstrakteren Secure Design Principles, die Denkansätze zu sicherer Softwarearchitektur darstellen.


Sicheres Design – Security Pattern: Beispiel


Ein Beispiel für ein Security Pattern ist das “föderierte Identitätsmanagement”.


Die Benutzerverwaltung wird in vielen Anwendungen benötigt, um bspw. Berechtigungen zu realisieren. Bei der Realisierung der Benutzerverwaltung ist es empfehlenswert, in Bezug auf die Benutzerverwaltung nicht auf ein selbstentwickeltes Konzept zu bauen. Stattdessen können Identitätsprovider wie Google (“Föderation”) eingebunden werden, sofern keine maßgeschneiderte und individuelle Nutzerverwaltung benötigt wird. Der Fokus kann vollständig auf die Funktionalität gelegt werden, während das Identitätsmanagement ausgelagert wird.


Sicheres Design – Security Principle: Beispiel


Dieses Prinzip fordert die Ausstattung einer Programmfunktionalität mit nur den Rechten, die für die Erledigung der Aufgaben zwingend notwendig sind. So werden die Missbrauchsmöglichkeiten und deren Auswirkungen begrenzt.


Bedrohungsmodellierung


Sobald eine erste, grobe Architekturskizze existiert, kann mit der Bedrohungsmodellierung, im Englischen  „Threat Modelling“, gestartet werden. Sie sollte deshalb möglichst früh durchgeführt werden, da die Ergebnisse unter anderem weitere Sicherheitsanforderungen sein können, die bei der Architekturplanung berücksichtigt werden müssen. Dabei handelt es sich nicht um eine scharf abtrennbare Phase. Stattdessen finden sich einzelne Aktionen des Threat Modelling auch in anderen Phasen der sicheren Softwareentwicklung wieder. Das Ziel der Methode ist es, mögliche Angriffsvektoren zu finden, zu gewichten, zu priorisieren und anschließend Gegenmaßnahmen zu identifizieren.


Threat Modelling sollte in einem Team aus Architekten, Entwicklern und Stakeholdern durchgeführt werden, um somit ein gemeinsames Verständnis der schützenswerten Assets und Risiken zu erreichen. Durch Threat Modelling werden die besonders schwerwiegenden und in der Beseitigung kostspieligen Designfehler einer Software aufgedeckt. Die folgende Abbildung zeigt die einzelnen Phasen der Bedrohungsmodellierung.


 


Nachdem die schützenswerten Assets identifiziert wurden, wird eine grobe Architekturübersicht erstellt. Hierbei liegt der Fokus auf den Datenflüssen und der Datenhaltung, auf deren Grundlage sich Vertrauensgrenzen ziehen lassen. Vertrauensgrenzen befinden sich dort, wo Daten einen bestimmten Kontext nicht verlassen oder aber ausschließlich über eine Kommunikationsschnittstelle ausgetauscht werden.


Anschließend wird das System an den Vertrauensgrenzen aufgetrennt und kleinere Architekturübersichten für die einzelnen Teile erstellt, um auch Schwachstellen innerhalb der Vertrauensgrenzen aufzudecken. Nachfolgend wird durch Brainstorming von Architekten und Entwicklern versucht, Angriffspunkte zu finden. Es ist hilfreich, sich bei der Identifizierung der Bedrohungen an Angriffsklassen zu orientieren. Diese Angriffsklassen werden beispielsweise durch Modelle wie STRIDE vorgegeben.


Für die Dokumentation der im Brainstorming identifizierten Bedrohungen eignet sich besonders eine Exceltabelle, in der unter anderem die Bedrohung, der Angreifer und die Schnittstelle, an der sie existiert, festgehalten werden. Die einzelnen Bedrohungen müssen anschließend bewertet werden, damit eine Priorisierung möglich ist. Zur Bewertung einer Angriffsmöglichkeit empfiehlt sich die Nutzung der OWASP Risk Rating Methode.


Im letzten Schritt werden dann noch Gegenmaßnahmen gesucht und weitere Sicherheitsanforderungen ermittelt, die bei Erfüllung die Ausnutzung der Schwachstellen verhindern.


Sichere Programmierung


Während sich die vorangegangenen Abschnitte eher mit Prozessschritten außerhalb der Programmierung befassen, soll in diesem Abschnitt beispielhaft auf wichtige Schwachstellenmuster bei der Implementierung von Software eingegangen werden. Außerdem werden Programmiertechniken vorgestellt, die dazu beitragen, zuvor identifizierte Schwachstellenmuster zu vermeiden.



  • Unsicherer Umgang mit Ein- und Ausgaben: Dieses Muster ist besonders häufig im Webumfeld anzutreffen, da bösartige Eingaben über die durch das Internet erreichbare Benutzerschnittstelle besonders leicht zu tätigen sind. Die Eingaben werden hierbei von der Anwendung aufgrund mangelnder Validierung als Befehle interpretiert, wodurch Angriffe auf die Software (Bsp. SQL Injection) oder die Benutzer (Bsp. Cross-Site-Scripting) möglich sind.
  • Unsicherer Umgang mit dem Speicher: Schwachstellen, die auf dieses Muster zurückzuführen sind, beruhen auf einer Manipulation des Speichers. Diese Ursache ist oftmals auf den leichtsinnigen Umgang mit dem Speicher durch den Entwickler zurückzuführen. So ist bspw. bei mangelnder Prüfung bei der Adressierung von Speichern eine Änderung der Rücksprungadresse und somit ein Ausbrechen aus der Programmlogik möglich. Anzutreffen sind derartige Lücken meist in Programmiersprachen, die eine Speicherverwaltung durch den Programmierer erlauben, wie C, C++ und C#. Ein Beispiel für eine derartige Lücke ist der Buffer-Overflow.


Techniken für sichere Programmierung



  • Input Validierung und Output Sanitisierung: Überprüfung und Säuberung aller Ein- und Ausgaben (am besten nach dem Whitelisting Prinzip)
  • Sichere Funktionen und Sprachen: Es sollte möglichst auf Programmiersprachen zurückgegriffen werden, die keine Pointerarithmetik und manuelle Speicherverwaltung erlauben. Andernfalls müssen bei Speicheroperationen zumindest sichere Funktionen verwendet werden.
  • Code Review: Das Review sollte nicht von den gleichen Entwicklern durchgeführt werden, die den Code selbst geschrieben haben. Der Fokus sollte dabei auf die korrekte Implementierung von Sicherheitsmechanismen wie Authentifizierung, Datenvalidierung, Errorhandling, Logging und Verschlüsselung gelegt werden.


Security Testing


Am Ende des Softwareentwicklungszyklus sollte die entwickelte Anwendung auf ihre Sicherheit getestet werden. Hierbei werden verschiedene Sicherheitstests durchgeführt. Selbige sind sehr häufig Negativtests, da mit ihnen die Abwesenheit von Sicherheitslücken nachgewiesen werden soll. Aufgrund der Natur von Negativtests ist eine vollständige Testabdeckung unmöglich zu erreichen. Der Nachweis der Nichtangreifbarkeit kann daher nicht erbracht werden. Es kann nachgewiesen werden, dass keine Schwachstellen unter bestimmten Bedingungen existieren, nicht jedoch, dass überhaupt keine existieren.


Zu Beginn müssen Sicherheitstestfälle definiert werden. Das Ableiten von Sicherheitstests aus Misuse cases ist eine effektive Vorgehensweise. Eine Dokumentation der definierten Testfälle zur späteren Bewertung der Kritikalität derselben ist notwendig.


Um Schwachstellen in der entwickelten Software aufzuspüren, werden häufig Hacking-Techniken aus Angreifersicht angewandt. Oftmals wird das Ziel solcher Penetrationstests vorher definiert (z. B. Stehlen von Nutzerdaten aus der Datenbank). Es wird alles an Ergebnissen und „findings“ erfasst, was im Zuge dieses Prozesses auffällt. Bei Penetrationstests wird zwischen Blackbox- und Whitebox-Tests unterschieden.


Blackbox-Tests zeichnen sich dadurch aus, dass Angreifer nichts über Innereien eines Systems oder einer Software erfahren, was die Tests näher an die Realität herankommen lässt. Diese sind oft schnell durchführbar und haben einen vergleichsweise hohen Wirkungsgrad. Bei einem Whitebox Assessment wird zunächst die Dokumentation mit besonderem Augenmerk auf Sicherheitsaspekte begutachtet und dabei eine Liste möglicher Angriffsvektoren erstellt. Unter Zuhilfenahme des Quellcodes werden die Angriffe geplant, ausgenutzt und dokumentiert.


Die Vorteile von Whitebox-Tests im Vergleich zu Blackbox-Tests sind eine höhere Genauigkeit und eine stärkere Aussagekraft hinsichtlich des Schutzes gegen informierte, professionelle Hacker sowie Qualität von Code und Design bezüglich Sicherheit.


Über den Autor


Martin Wagner ist als Berater im Bereich Software-Engineering bei der ADVISORI FTC GmbH tätig. Neben der Entwicklung passgenauer Softwarelösungen für Kunden befasste er sich in seiner Bachelorarbeit mit dem Thema Sicherheit im Softwareentwicklungsprozess.


Unsere Leistungen im Bereich „sichere Softwareentwicklung“


Wir bei ADVISORI verfügen über fundierte Kompetenzen in der sicheren Softwareentwicklung. Wir bringen das entsprechende Prozesswissen mit, um Ihnen bei der Umstellung Ihres Entwicklungsprozesses nach erkannten Sicherheitsstandards zu helfen.
Unsere Leistungen im Überblick:



  • Analyse des derzeitigen Prozesses
  • Umstrukturierung des Prozesses und Ausrichtung auf Sicherheit in der Entwicklung
  • Unterstützung bei der Einführung von Tools, die in diesem Zusammenhang hilfreich sein können (z. B. SonarCloud)


Sprechen Sie uns gerne hierzu an: https://www.advisori.de/kontakt/


Weitere News

Scroll to Top