Sichere Softwareentwicklung – Teil 2 Pflegeanleitung für sichere Software
Will man eine Software auch sicher machen bedeutet das viel Arbeit. Es gilt Schwachstellen zu verhindern und von Beginn an einen sorgsamen Umgang mit Daten zu pflegen. Dazu gehört die Trennung von Datenverarbeitung und ihrer Darstellung ebenso wie eine konsequente Validierung von Ein- und Ausgangsdaten. Dann braucht es nur noch sichere Übertragungswege und regelmäßige Prüfroutinen. Oder fehlt da noch was?
Anbieter zum Thema

Ist eine Anwendung erst implementiert und für Nutzer zugänglich, begleitet eine Vielzahl von Ereignissen und Aktionen ihren normalen Betrieb. Wenn im Zuge der Nutzung Fehler in der Anwendung auftreten oder sich ein sicherheitsrelevanter Vorfall wie ein Hackerangriff ereignet, muss dieses Ereignis analysiert werden. Für eine erfolgreiche Post-Mortem-Analyse ist es unerlässlich, den Vorfall nachhaltig zu betrachten. Hierzu braucht es eine ausführliche Protokollierung, ein Logging der Anwendungen, Ereignisse und Benutzerinteraktionen – wobei insbesondere die Datenschutzbestimmungen zu berücksichtigen sind.
Protokollierung bringt Erkenntnis
Tritt ein Sicherheitszwischenfall ein oder kommt es zur Manipulation von Daten, sind detaillierte Analysen unerlässlich. Anderenfalls lassen sich Vorfälle nicht nachvollziehen und Angreifer nicht zuordnen. Treten Fehler in unseren Anwendungen auf und kontaktieren uns Kunden, sind Support- und Entwicklungsteams auf möglichst detaillierte Informationen angewiesen, um die Fehlerursache schnell zu identifizieren (Ursachenanalyse).
Log-Einträge (Log-Daten) stellen bei der Fehlersuche eine wichtige Informationsquelle dar und ermöglichen es uns, das Problem schneller zu analysieren.
Tipps zur Programmierung: Wichtig für die Fehleranalyse ist es festzustellen, welcher Nutzer wann welche Aktionen in unseren Anwendungen durchgeführt hat. Dies gilt insbesondere für mandantenfähige Anwendungen und SaaS-Services.
Folgende Ereignisse benötigen mindestens eine Protokollierung:
- Anmeldeversuche mit falschen Zugangsdaten
- Administratoranmeldungen und -aktivitäten
- Änderungen an Benutzerkonten und Berechtigungen
- Fehler in der Sitzungsverwaltung
- Fehler bei der Eingabewertprüfung
- Fehler innerhalb der Anwendung (z. B. Ausnahmen)
- Schreibzugriffe auf Daten innerhalb der Anwendung
- Herunterfahren, Starten und Neustarten von Anwendungen oder Systemen
Protokolleinträge brauchen ein einheitliches Format und nach Möglichkeit weitere Attribute, die für eine spätere Auswertung oder automatisierte Auswertung durch SIEM-Systeme (Security Information and Event Management) wichtig sind:
- Schwere (z. B. niedrig, mittel, hoch, kritisch, Sicherheit, Debuggen)
- Kunden-ID
- Zeitstempel
- Nutzer-ID
- IP-Adressen, HTTP-Methoden und angeforderte URLs (inkl. Parameter)
Bei der Protokollierung gelten die aktuellen Datenschutzbestimmungen (EU-DSGVO) und deren Anforderungen. Hierzu zählt auch das Informieren und das Anzeigen eines Datenschutzhinweises.
Sensible und personenbezogene Daten bleiben bei der Protokollierung außen vor. Dazu gehören z. B.: Passwörter, Verschlüsselungscodes, Gesundheitsdaten und Finanzdaten (z. B. Bankverbindung, Kreditkartendaten).
In Ausnahmefällen und nach Klärung des rechtlichen Rahmens dürfen Protokolle sensible und personenbezogene Daten aufzeichnen, jedoch nur unter Berücksichtigung der Pseudonymisierung oder der Verwendung von kryptografisch sicheren Hash-Methoden.
APIs und REST-Schnittstellen sichern
Häufig stellen Webanwendungen auch APIs sowie Teile ihrer Funktionalität über sogenannte REST-Schnittstellen bereit. Diese Schnittstellen implementieren und sichern Entwickler genauso robust wie die übrige Anwendung. Dazu gehören das Filtern und Validieren von Ein- und Ausgaben sowie das sichere und zuverlässige Abrufen und Verifizieren von Nutzern und deren Rechten. Je nachdem, welche Datenformate diese Schnittstellen verwenden (z. B. JSON oder XML), benötigen sie Filterroutinen, die spezifische Sicherheitsfunktionen für das jeweilige Format ergänzen.
Wenn APIs oder REST-Schnittstellen für Fremde zugänglich und nicht vollständig und robust in Anwendungen implementiert sind, können nicht autorisierte Nutzer Daten manipulieren oder löschen. Der unbefugte Zugriff auf Daten oder Funktionen über solche Schnittstellen kompromittiert unmittelbar die Vertraulichkeit, Integrität und Verfügbarkeit der Nutzerdaten und stellt eine Bedrohung für unsere IT-Infrastruktur dar.
Tipps für die Entwicklung: Um Angriffe über manipulierte Client-Anfragen oder manipulierte Parameter zu verhindern, filtern und prüfen Programmierer anhand einer Whitelist (Liste legitimer Werte) alle Daten eingehend. Eine restriktive Whitelist enthält nur zulässige Werte und Zeichenketten. Viele Frameworks bieten APIs und REST-Schnittstellen zum Filtern oder Whitelisting, häufig in Verbindung mit Scaffolding und der automatisierten Erstellung von Quellcode für APIs und REST-Schnittstellen. Entwickler prüfen sicherheitshalber erneut die vom Framework erstellten Filterregeln und Whitelists. TLS insbesondere mit PFS stellen sicher, dass Server und Client Daten (insbesondere wichtige Token, Anmelde- oder Sitzungsdaten) immer verschlüsselt austauschen und Dritte diese nicht abfangen und/oder manipulieren. Die Übertragungsverschlüsselung trägt damit wesentlich zur Vertraulichkeit und Integrität der Kundendaten bei.
Die Implementierung von TLS braucht ausreichend Zeit, da eine Fehlkonfiguration und andere Szenarien bewirken, dass Angreifer durch Downgrade-Angriffe auf TLS oder aufgrund fehlender Zertifikatsprüfungen trotz Übertragungsverschlüsselung Zugriff auf sensible Daten haben. Sensible Informationen wie Benutzernamen, Passwörter und Sicherheitstoken sind nicht in der URL zu codieren, damit Web-Browser-Verlauf oder unverschlüsselte Verbindungen in Serverprotokollen keine Hinweise liefern.
Methoden-Test in Eigenregie
Bereits während der Entwicklung sollten Programmierer die Funktionen und Schnittstellen auf korrektes Funktionieren und ihr Verhalten bei fehlerhaften Parametern und Eingabewerten überprüfen. Ein bewährtes Verfahren für diesen Test von Modulen sind die sogenannten Unit-Tests.
In der Prüfeinheit erstellt der Test für jede Funktion oder Methode eine Prüfroutine, die zunächst einen Ausgabezustand erzeugt (zum Beispiel Zuweisung von Variablenwerten), dann die zu testende Funktion/Methode aufruft und schließlich das Ergebnis (beispielsweise einen Ausgabewert) mit dem erwarteten oder gewünschten Verhalten vergleicht.
Es besteht die Möglichkeit, solche Unit-Tests mit Werkzeugen (bei Integration in die Entwicklungs-IDE) automatisch durchzuführen und auszuwerten. Entsprechende Werkzeuge und Frameworks gibt es für alle gängigen Programmiersprachen.
Ohne Qualitätskontrolle oder bei unzureichenden Prüfverfahren besteht die Chance, funktionale und/oder sicherheitsrelevante Fehler in unseren Anwendungen unter Umständen zu übersehen und erst im Produktivbetrieb zu bemerken. Die Komplexität der heutigen Programmcodes gestaltet die Ursachenanalyse von Problemen aufgrund von Quellcodefehlern häufig sehr schwierig. Dies gilt insbesondere dann, wenn das Fehlverhalten nicht wirklich reproduzierbar ist oder über mehrere Programmkomponenten, -klassen, -module und -funktionen hinweg auftritt.
Tipps für die Entwicklung: Bei der Speicherung von Daten im Programmcode (beispielsweise in der Datenbank) oder der Verarbeitung von Ausgabewerten ist es wichtig, die einzelnen Datenfelder und Variablen daraufhin zu überprüfen, ob die Werte gültig sind und innerhalb des erwarteten Wertebereichs liegen. Es ist ratsam, für jede Funktion einen eigenen Unit-Test zu erstellen, der prüft, ob die Funktion bei fehlerhaften Eingabedaten korrekt arbeitet und sich erwartungsgemäß verhält. Für die meisten Programmiersprachen gibt es Softwaretools und Werkzeuge zur Erstellung von Unit-Tests, die sich auch in gängige Entwicklungsumgebungen integrieren lassen.
Um Fehler frühzeitig zu erkennen und zu beheben, achten Softwareentwickler auf regelmäßige und automatische Unit-Tests (zum Bespiel bei jedem Build). Sie ermöglichen eine frühe Fehlererkennung und eine schnelle Korrektur.
Traue keiner externen und nicht selbst kontrollierten Quelle
Webanwendungen enthalten oft Inhalte aus anderen Quellen, insbesondere von Content-Providern. Der Inhalt wird meist im Quellcode referenziert und vom Web-Browser des Nutzers dynamisch geladen. Bei der Integration von Inhalten aus Drittquellen ist die Vertrauenswürdigkeit der Quelle zu klassifizieren und gegebenenfalls sind die von Dritten gelieferten Inhalte zu überprüfen oder zu filtern.
Dateien von externen Servern können mit Schadcode infiziert sein, der durch die Integration in Anwendungen die Computersysteme der Nutzer infiziert. In der Vergangenheit tauchten solche Fälle vor allem durch Malware in Online-Werbung (Malvertising) auf, die, in eine Vielzahl von Websites und Anwendungen integriert, eine große Anzahl von Computersystemen infizierte.
Wenn integrierte externe Dateien eine Bedrohung für Nutzer darstellen, kann dies auch einen Imageschaden für den Kunden nach sich ziehen. So ist die Herkunft von Schadcode für viele Nutzer nicht direkt nachvollziehbar und so problemlos mit den Kundenanwendungen in Verbindung zu bringen. Daher gilt: Alle möglichen Sicherheitsvorkehrungen treffen und integrierte externe Inhalte und Dateien sorgfältig prüfen und nur auf vertrauenswürdige Quellen zurückgreifen.
Tipps für die Entwicklung: Vor der Integration externer Inhalte steht die Überprüfung der Zuverlässigkeit und Vertrauenswürdigkeit der Quelle:
- Stammen die Inhalte von einem bekannten Anbieter (Content-Provider)?
- Ist der Content-Provider schon lange am Markt tätig?
- Gab es in der Vergangenheit Sicherheitsvorfälle im Zusammenhang mit dem Content-Provider?
Wenn möglich isolieren Entwickler externe Inhalte von der übrigen Anwendung und statten sie mit so wenig Rechten wie möglich aus. Dies erreichen Programmierer zum Beispiel durch die Verwendung von iFrames in Verbindung mit dem Sandbox-Attribut (HTML5). Auf diese Weise nehmen Anwendungen externe Inhalte in die Ansicht auf, ohne dass der Content-Provider JavaScript ausführen, URLs aufrufen oder Cookies lesen muss. Außerdem scheint es sinnvoll, vertrauenswürdige Quellen für ausführbaren JavaScript-Code explizit zu benennen (Content Security Policy). JavaScript-Code aus anderen Quellen stellt dann keine Bedrohung mehr dar, denn der Web-Browser des Nutzers führt diese nicht mehr aus.
Augen auf bei der Partnerwahl
Um Funktionalitäten in Anwendungen zu implementieren, verwenden Softwareentwickler häufig Softwarekomponenten von Drittanbietern. Bei dem Gebrauch von Programmbibliotheken, Plug-ins und Add-ons anderer Anbieter oder von Open-Source-Projekten sind diese auf ihre Robustheit und Sicherheit zu testen sowie die entsprechenden Lizenzbestimmungen zu überprüfen. Module externer Anbieter weisen manchmal technische Schwachstellen auf, die bei ihrer Integration neue zusätzliche Angriffsvektoren liefern. Auch wenn die eigenen Entwicklungen keine Schwachstellen aufweisen, besteht die Möglichkeit einer Kompromittierung des Systems durch unsichere Module und damit einer Gefahr für die Kundendaten.
Wenn externe Geräte eine Bedrohung für Nutzer darstellen, bedeutet dies auch einen Imageschaden für den Kunden. So ist die Herkunft von Schadcode für viele Nutzer nicht direkt nachvollziehbar und problemlos mit den Kundenanwendungen in Verbindung zu bringen. Softwareentwickler sollten daher alle möglichen Sicherheitsvorkehrungen treffen, alle Fremdmodule vor der Verwendung überprüfen und nur solche aus vertrauenswürdigen Quellen einsetzen.
Genauso wichtig wie die Robustheit und Sicherheit von Fremdmodulen ist die Einhaltung der entsprechenden Lizenzbestimmungen:
- Darf die Anwendung das Modul verwenden?
- Welche Folgen und Verpflichtungen ergeben sich aus der Nutzung?
Tipps für die Entwicklung: Die Vertrauenswürdigkeit der Quelle sowie die Robustheit und Sicherheit der Bibliotheken sind von dem Programmierer vor der Verwendung von Fremdmodulen zu überprüfen. Erste Hinweise finden sich oft in Foren oder Mailinglisten für die Meldung von Bugs oder Fehlern:
- Wurden in der Vergangenheit viele Fehler gemeldet?
- Gibt es bekannte Sicherheitsschwachstellen?
- Wie wurde bisher mit Fehlermeldungen und der Sicherheit umgegangen?
- Stehen regelmäßige Patches und Updates bereit?
- Befindet sich das Modul noch in der Weiterentwicklung oder liegt die Herausgabe der letzten Version schon lange zurück?
Vor dem Einsatz von Fremdmodulen prüfen Entwickler mit der Compliance Abteilung die entsprechenden Lizenzbestimmungen. Auch bei Versionsänderungen (beispielsweise nach der Aktualisierung eines Fremdmoduls) ist zu testen, ob Änderungen an der Lizenz negative Auswirkungen haben. Nur die neusten und stabilsten Versionen leisten einen sicheren Schutz. Darüber hinaus binden Softwareentwickler die Module in das Patch-Management ein, sodass die Prüfung der Aktualität der Version regelmäßig erfolgt.
Die Kombination der hier beschriebenen „Pflegeanleitung“ mit den Grundsätzen der sicheren Software-Entwicklung, die ich im vorangegangenen Artikel formuliert habe, bilden ein solides Grundgerüst für einen Einstieg in sichere Softwareentwicklung.
Über den Autor: Pierre Gronau ist Gründer und Inhaber der Gronau IT Cloud Computing GmbH und Senior IT Consultant mit umfangreicher Erfahrung als technischer Projektleiter.
(ID:46124742)