Die Informationssicherheit hat Einzug in den Alltag genommen. Viele kennen jetzt Dank der Geräte und Social Media Plattformen, die sie verwenden, Techniken wie Zwei-Faktor-Authentisierung, Verschlüsselung und Software-Updates. Wenn es um die Innereien — also das Secure Design — geht, so bleiben viele Fragen offen. Was in modernen Prozessoren heutzutage vorgeht, lässt sich schwer in wenigen Worten ausdrücken. Die Fehler Meltdown und Spectre sind zwar in aller Munde, jedoch braucht man viel Vorwissen, um zu verstehen, was da genau passiert. Dazu kommt zusätzlich der Code, der in der Firmware, quasi unter dem Betriebssystem, Arbeit für Geräte wie Grafikkarten oder Netzwerkkarten verrichtet. Möchte man jetzt eine Applikation entwickeln, stellt sich die folgende Frage: Wie kann man bei der Vielzahl von Komponenten den Überblick behalten und sicher programmieren? Secure Coding, also sichere Programmiertechniken, alleine hilft ja nur beim eigenen Code. Die Antwort liegt in der Architektur des Ganzen.
Der Aufbau entscheidet beim Secure Design
Eine Anwendung beginnt niemals mit Code. Am Anfang steht immer ein Design und eine Beschreibung der Aufgaben, die eine Applikation erfüllen soll. Diese Phase ist der kritischste Teil bei der Softwareentwicklung, denn Entscheidungen, die hier getroffen werden, bestimmen meist die Zukunft des Projekts. Das bedeutet im Besonderen, dass die Grundlage für die spätere Informationssicherheit des Codes an dieser Stelle getroffen wird. Beispielsweise die Auswahl der Komponenten, die verwendeten Protokolle, notwendige Bedingungen (wie beispielsweise kryptografische Schlüssel, Anforderungen an Netzwerk und Speicher, etc.) und Kommunikation mit Drittanbietern werden in der Designphase festgeschrieben. Was bedeutet also Secure Design in diesem Zusammenhang?
Secure Design besteht aus einer Reihe von Grundlagen, die an jeder Stelle im Softwareprojekt beachtet werden. Man versucht die Angriffsfläche des Codes zu minimieren, überall sichere Defaults zu verwenden, so wenige Berechtigungen wie möglich an Konten/Komponenten zu verteilen, Sicherheitsprüfungen in allen Schichten einzubauen, Fehler sicher abzufangen, keinen fremden Diensten zu vertrauen und Aufgaben im Code zu trennen. Die Applikation muss in jeder Umgebung zuverlässig arbeiten können, ohne Schwachstellen preiszugeben. Verarbeitete Daten müssen ständig auf ihre Integrität überprüft werden. Das gilt auch für interne Prozesse wie Kommunikation mit einer Datenbank oder anderen Teilen. Entwickler und der Code dürfen zu keiner Zeit von Annahmen ausgehen, die ein Angriff negieren könnte. Dies schließt Softwarebibliotheken und Fähigkeiten von Hardware bzw. Betriebssystemen ein. Darunter fallen auch die Eigenschaften von Prozessoren, die die Klasse der Meltdown und Spectre Fehler hervorgerufen haben.
Natürlich darf man sich jetzt nicht von der Paranoia packen lassen und auf alle Features der Plattform verzichten. Man soll ja Code wiederverwenden und nicht immer das Boot neu erfinden (das Boot ist älter als das Rad). Es geht immer um Annahmen, die man trifft, wenn man programmiert. Die XML Eingabe ist vielleicht kein XML. Die Antwort des Cloud Services stammt vielleicht nicht von der angenommenen Quelle oder ist einfach falsch. Die Daten, die man vorher in die Datenbank geschrieben hat, sind möglicherweise nun falsch (weil es einen Angriff gab). Moderner Code steckt voller Annahmen. Spannend wird es, wenn diese nicht stimmen.
Mathematische Beweise für Secure Coding
Eine Möglichkeit Mehrdeutigkeiten in Spezifikationen zu vermeiden ist die Mathematik. Da Code aus der Informatik kommt und die Informatik ein Teilgebiet der Mathematik ist, lassen sich Prozesse mathematisch darstellen. Übersetzt man nun Aufgaben aus den Designdokumenten in eine mathematische Sprache, so lassen sich mit Hilfe von Werkzeugen Abläufe im Code mathematisiert darstellen und beweisen. Schafft man dies, so ist man sprichwörtlich auf der sicheren Seite. Zusätzlich eliminiert man so unklare Formulierungen, was wiederum den Entwicklerinnen hilft.
Die Formalismen sind auch ein Teil von Secure Design.
Datenbasierte Entwicklung ≠ Datenbank-Entwicklung
Wie implementiert man nun Secure Design? Da man es immer mit Daten zu tun hat, kann man bei diesen beginnen. Die Applikation soll ja mit Fehlern sichern umgehen können. Das bedeutet bei Eingabe von unsinnigen oder manipulierten Daten darf nichts Kritisches passieren. Eine Taktik ist daher, die Software mit zufällig erzeugten oder manipulierten Daten zu füttern und zu schauen was passiert. Letztlich ist das die Strategie der Testfälle, die man bei der Entwicklung oft hat, um beseitigte Fehler nicht wieder im Code zu finden. Die Technik, Systeme mit Zufallsdaten zum Stolpern zu bringen, heißt Fuzzing. Es gibt viele Werkzeuge dafür, teilweise auch schon für die Entwicklungswerkzeuge. Am besten funktioniert die Kombination aus Zufallsdaten und echten Daten, damit man über die erste Überprüfung hinwegkommt. Schließlich möchte man ja den ganzen Code testen.
Hersteller von Betriebssystemen oder Teams, die kritische Software entwickeln, verwenden diesen Ansatz schon.
Die Gewohnheiten ändern!
Informationssicherheit steht und fällt mit den Gewohnheiten des Alltags. Alles, was aktiv bedacht werden muss, geht früher oder später schief. Dasselbe gilt natürlich auch für die Softwareentwicklung. Aus diesem Grunde muss man Secure Design und Secure Coding in geeigneten Schritten in die eigenen Prozesse einbauen. Das lässt sich leider nicht mit der Lektüre einer Dokumentation oder Anleitung alleine durchführen. Empfehlenswert ist die Umsetzung in Teilschritten, begleitet durch einen Workshop für alle Entwickler. Es gibt reichhaltig Material zur Anschauung, denn das Studium von bekannten Fehlern schafft Praxisnähe und hilft den eigenen Code zu hinterfragen.
Über René Pfeiffer
René Pfeiffer ist seit 2009 als Senior Security Consultant für SEC4YOU tätig. Neben seiner selbsttändigen Tätigkeit ist der Geschäftführer der DeepSec GmbH und veranstaltet seit über 10 Jahren die DEEPSEC. Durch die Nutzung von anerkannten Methoden und seine Affinität zu IT-Security und Linux durfte er unzählige Kunden den den Branchen Industrie, Luftfahrt, Telekommunikation, Energieversorger, Pharmazie, Gesundheitswesen, Werbung, Anwaltskanzleien, NGOs, Medien, Logistik und Software-Entwicklung in Sicherheitsfragen beraten.
Fragen an René Pfeiffer zu Secure Design — Secure Coding stellen Sie bitte über unser Kontaktformular.