Kontinuierliche Risikoanalyse und Securitybewertung von Architekturen
von Christian Schneider
Threat Modeling bzw. Bedrohungsmodellierung von IT-Systemen bezeichnet die Analyse einer Architektur vor dem Hintergrund möglicher Risiken. Ziel ist es, bereits in einer frühen Designphase mögliche Schwachstellen oder Angriffspunkte zu identifizieren. Diese können zum Beispiel unverschlüsselte Kommunikationspfade, fehlende starke Authentisierung, fehlende Propagation der Nutzeridentität ins Backend zwecks Berechtigungsprüfung, fehlende Härtung und Kapselung, mögliche Injection-Schwachstellen sowie viele weitere Schwachstellen sein.
Mittels der Anwendung von Security-Controls (also z. B. Themen wie Verschlüsselung, Validierung, Authentisierung, Kapselung etc.) wird die Eintrittswahrscheinlichkeit oder Ausnutzbarkeit der identifizierten Schwachstellen auf ein akzeptables Niveau abgesenkt. Man spricht hierbei auch von einer Mitigation. Somit dient Bedrohungsmodellierung auch der Ableitung von Security-Requirements im Rahmen der Entstehung einer Software. Ein weiterer Nutzen von Bedrohungsmodellierung ist es, die Menge der zu tragenden Restrisiken zu erkennen und abzuschätzen, ob diese in Summe tatsächlich tragbar sind. Im Optimalfall erhält man ein ausgeglichenes Niveau von zu adressierenden Risiken und zu übernehmenden Restrisiken inkl. einem sauber dokumentierten Weg dorthin.
Aber auch bei Änderungen an einer bestehenden Architektur oder größeren neuen Releases ist es angebracht, dass Bedrohungsmodelle auf diese Änderungen hin angepasst werden, um gegebenenfalls neue Risiken zu erkennen und rechtzeitig mitigieren zu können. Somit gehört Bedrohungsmodellierung als ein Teil der Security zu einem kontinuierlichen Prozess, anstatt dass es sich nur um eine einmalige Aktion handelt.
Vergleicht man Bedrohungsmodellierung mit anderen Disziplinen innerhalb der Security, so stellt man oft fest, dass diese Chance auf frühzeitige Verbesserung der Sicherheitseigenschaften einer Architektur leider deutlich weniger Anwendung findet als zum Beispiel Penetrationstests. Dabei stellen Pentests erst die allerletzte Chance vor einem Go-live dar, die gröbsten Sicherheitslücken in einer Außensicht (Blackbox) zu finden. Die Innensicht auf der Architekturebene wird hierbei oftmals nicht mit betrachtet. Selbstverständlich sind Pentests ebenfalls wichtig und finden Schwachstellen, die eine Bedrohungsmodellierung in der Entstehung nicht hätte verhindern können, jedoch muss man es auch andersherum betrachten: Bedrohungsmodellierung findet Schwachstellen in der Architektur, die ein Pentest nicht so gut finden kann. Diese kommen oftmals im Rahmen der „Post-Exploitation“ zum Tragen – also dann, wenn Angreifer über eine erste Sicherheitslücke bereits den Fuß in der Tür haben und dann weitere Architekturschwachstellen im Inneren ausnutzen.
Threat Modeling – wie?
Zur Durchführung von Bedrohungsmodellierung gibt es eigentlich so gut wie keine festgelegten Rahmen oder Einschränkungen. Jede an der Entstehung von Software beteiligte Rolle kann durch das Hinterfragen der Sicherheitseigenschaften mögliches Verbesserungspotenzial identifizieren. Auf den Punkt bringt es das Threat Modeling Manifesto, das auf einer hohen Abstraktionsebene Bedrohungsmodellierung beschreibt [1]. Es geht laut des Manifests darum, sich selbst vier Schlüsselfragen zu stellen:
-
Woran arbeiten wir?
-
Was kann schiefgehen?
-
Was werden wir dagegen tun?
-
Haben wir unsere Arbeit gut genug gemacht?
Wenn man nun versucht, diese Fragen in einen Prozess zu überführen, dann benötigen wir für Punkt 1 ein Modell, das die zu entstehende Architektur beschreibt. Für Punkt 2 sind mögliche Szenarien von Angriffen von außen sowie von innen auf dieses Modell hin anzuwenden, oftmals unter Einbeziehung von securityerfahrenen Personen oder standardisierten Verfahren. Punkt 3 stellt das Ableiten von Security-Requirements aus den Ergebnissen aus Punkt 2 dar. Abschließend kann Punkt 4 als eine Art Feedback-Loop betrachtet werden, in dem die übrig gebliebenen Restrisiken dahingehend bewertet werden, ob sie tragbar sind („Arbeit gut genug gemacht“) oder nicht, und ob man eine weitere Iteration durchführt.
Ein solcher Prozess lässt sich in Teams auf viele Arten umsetzen, mal mehr formalisiert und auch mal eher informell. Zum Beispiel kann man regelmäßig Security-Architektur-Workshops abhalten, in denen die Architektur und ihre Datenflüsse auf dem Whiteboard analysiert werden. Andere Unternehmen bevorzugen das Ausfüllen von Fragenkatalogen, die sich manchmal jedoch in Richtung entwicklerunfreundlicher Makro-lastiger „Excel-Tapeten“ bewegen können, wenn man nicht aufpasst. Wieder andere Teams nutzen Karten bzw. Kartenspiele wie zum Beispiel das Elevation-of-Privilege-Kartenset [2] von Adam Shostack, dem Autor eines der wichtigsten Bücher zum Thema Threat Modeling [3].
Vielen dieser Handwerkszeuge liegen bestimmte Verfahren zugrunde, mit denen Angriffe auf Architekturen simuliert werden. Eines der am häufigsten verwendeten Verfahren hierzu ist STRIDE [4], das von Microsoft entwickelt und im Rahmen des Security Development Lifecycles (SDL) [5] in der Anforderungs- und Entwurfsphase Anwendung findet. Hierzu werden an eine Architektur und ihre Datenflüsse Risiken aus den folgenden sechs Kategorien angelegt und Gegenmaßnahmen abgeleitet:
-
Spoofing (Identitätsverschleierung)
-
Tampering (Manipulation)
-
Repudiation (Verleugnung)
-
Information disclosure (Verletzung der Privatsphäre oder Datenpanne)
-
Denial of service (Verweigerung des Dienstes)
-
Elevation of privilege (Rechteausweitung)
Parallel dazu gibt es noch einige weitere [6], teils weniger verbreitete oder stärker spezialisierte Verfahren. Zum Beispiel bietet PASTA (Process for Attack Simulation and Threat Analysis) [7] ein stärker angreiferbezogenes Verfahren zur Sicherheitsanalyse von Architekturen.
Das kostenlos zur Verfügung gestellte Microsoft Threat Modeling Tool (Abb. 1), das ein grafisches Modellieren mit automatischer Ableitung von Risiken unterstützt, nutzt STRIDE als grundlegendes Verfahren [8].
Bei größeren Modellen zeigt sich aufgrund des Diagram-First-Ansatzes jedoch eine etwas schwierigere Handhabung, hiermit noch optisch gute Modelle zu erstellen. Davon abgesehen ist es aber recht leicht, bei kleineren Modellen entsprechend schnell erste Ergebnisse zu erzielen. In der Bewertung der Ergebnisse sind oftmals noch securityerfahrene Personen hinzuzuziehen, da die dem Werkzeug zugrunde liegenden Regelwerke je nach Modellinput doch recht abstrakte Risiken mit einem teilweise auch höheren False-Positive-Anteil erzeugen. Schneller und einfacher nachvollziehbar als viele Excel-Tapeten zur fragebogenbasierten Risikoableitung aus einer Architektur ist es aber auf jeden Fall.
Auch das Open Web Application Security Project (OWASP) bietet mit dem OWASP Threat Dragon ein diagrammbasiertes Werkzeug zur Erstellung von Bedrohungsmodellen an [9].
Wer eher komplett ohne regelbasierte Ableitung von Risiken arbeiten möchte und sich stärker im diagrammbasierten Ansatz sieht, sollte sich unbedingt die Draw.io Stencils zum Thema Threat Modeling von Michael Henriksen ansehen [10]. Diese sind – gepaart mit den kartenbasierten Verfahren – eine gute Variante, um Threat Modeling Workshops in Entwicklungsteams durchzuführen.
Herausforderungen in agilen Projekten
Nachdem wir nun das Wozu und das Wie von Threat Modeling betrachtet haben, stellt sich die eigentliche Herausforderung: die möglichst nahtlose Integration der Verfahren und Werkzeuge in den Entwicklungsprozess und die Organisation.
Das nach Möglichkeit nachhaltig und kontinuierlich abzubilden, gestaltet sich besonders in agilen Entwicklungsorganisationen nicht immer einfach und effektiv. Oftmals wird, wenn überhaupt, eine Bedrohungsmodellierung nur initial im Rahmen des ersten Go-live durchgeführt (eventuell, weil es von der zentralen Securityabteilung im Rahmen einer Freigabe gefordert wird). Hierzu eignen sich alle vorgenannten Varianten zur Durchführung von Bedrohungsmodellierung sehr gut. Danach jedoch wird das Modell, gerade in den Diagram-First-Ansätzen, nur unzureichend an die weitere Entwicklung der Architektur in den kommenden Sprints angepasst.
Aber nicht nur die reduziertere Bereitschaft, sich im Rahmen eines jeden Sprints der Pflege abschreckend anmutender Excel-Tapeten anzunehmen oder in großen Modellen am diagrammbasierten grafischen Tool die eigenen, teils künstlerischen Fähigkeiten bzgl. überlappungsfreier Datenflüsse auf neue Ebenen zu heben, sorgt für eine stetige Erosion des Threat Models: Auch die nicht immer gegebene Verfügbarkeit von securityerfahren Personen, um im Rahmen eines jeden Sprints die Änderungen zu bewerten, sorgt für eine fortschreitende Abweichung des Modells von der Realität.
Zusammengefasst lässt sich vermuten, dass klassische Bedrohungsmodellierung, so wie sie in vielen Unternehmen als Teil eines (eventuell verpflichtenden) Prozesses gelebt wird, nicht gut zum Tooling der Entwicklungsteams passt und der Prozess sich mit agilen Vorgehensweisen und deren schnellen und häufigen Rollouts eher reibt, als dass er sich integriert.
Lösungsansatz Dev(Sec)Ops
Vor einer ähnlichen Herausforderung zur Integration von Securityelementen in einen agilen Entwicklungsprozess und dessen Sprints standen auch die klassischen Themen Securityreview (meist auf Codeebene durch Codereviews durchgeführt) und Securitytest (meist auf Testsystemen am Ende durch Pentests durchgeführt). Hier war das Problem ähnlich gelagert: Es ist nicht möglich, diese tiefe Form der Prüfung in jedem Sprint durchzuführen, gleichwohl hat jeder Sprint das Potenzial, aus Versehen eine gravierende Sicherheitslücke einzubauen, die dann unentdeckt live geht.
Dieses Integrationsproblem wurde geschickt durch die Kombination von Automation und Indikatoren gelöst: Mittlerweile gibt es eine große Menge an Werkzeugen, die gewisse Securityscans als Baseline-Checks automatisieren können. Seien es statische Codeanalysen, dynamische Scans, Prüfung von Abhängigkeiten oder auch Kombinationen daraus. Hierfür steht der Begriff DevSecOps, der die Integration von automatisierten Baseline-Checks gewisser Securityeigenschaften im Rahmen von DevOps definiert. Persönlich gehe ich davon aus, dass man in nicht allzu ferner Zukunft wieder nur noch von DevOps spricht, da dieser Begriff selbstverständlich die Integration von Securityanteilen beinhaltet. Solange diese Selbstverständlichkeit noch nicht gegeben ist, heißt es noch eine Weile lang DevSecOps, damit man sieht, dass etwas fehlt, wenn man keine Securitychecks in DevOps integriert hat.
So weit, so gut mit diesem Vergleich zum Thema Automation und kontinuierlicher Baseline-Checks. Aber was ist mit den Indikatoren gemeint? Grundsätzlich lässt sich sagen, dass, egal wie viel Aufwand wir betreiben, es immer gewisse Themen gibt, die sich im Securitybereich durch Automation nicht vollständig erledigen lassen. Genau hier greifen dann die Indikatoren: Wenn zum Beispiel die Architektur grundlegend geändert wurde oder zentrale sicherheitsrelevante Aspekte einer Anwendung (wie Authentisierung/Autorisierung) verändert, sensitive Bereiche (wie Payment) erweitert oder weitere ähnliche Indikatoren getriggert wurden, sollten eine Review und ein Pentest stattfinden. Somit hat die klassische Dev(Sec)Ops-Welt es gemeistert, den Großteil an Prüfungen als Baseline-Checks zu automatisieren und klare Indikatoren zu definieren, wann zusätzliche menschliche Prüfungen durch Securityexperten vonnöten sind.
Diesen erfolgreichen Kompromiss zwischen Automation im DevOps-Sinne und individueller Durchführung von Tiefenprüfungen können wir auch auf das Thema Bedrohungsmodellierung übertragen und damit hoffentlich einiges an Reibung aus den vorgenannten Integrationswegen herausnehmen: Durch möglichst einfache Pflege des Architekturmodells und der Datenflüsse ohne große Wechsel im Tooling lassen sich auch kleinere Änderungen im Rahmen eines jeden Sprints schnell im Modell abbilden. Durch stärker automatisierte Ableitung von Risiken aus einem Architekturmodell reduziert sich auch die Abhängigkeit auf securityerfahrene Personen in jedem Sprint. Leider setzt das, um nicht zu viele False Positives zu erzeugen, auch eine eher technische als fachliche Modellierung voraus. Somit ist das Ziel, diese Modellierung auf technischer Ebene dorthin zu verlagern, wo das Wissen über die konkrete Technik (im Sinne von verwendeten Technologien, Protokollen, Authentisierungsverfahren etc.) vorhanden ist: zum Entwicklungsteam. Bestenfalls direkt aus der IDE heraus.
Threat Models as something like Code?
Wenn man den hohen Grad an Automation im Bereich Dev(Sec)Ops betrachtet, sieht man mit Dingen wie Pipeline as Code und auch, in Richtung Laufzeitumgebung schauend, mit Infrastructure as Code vorherrschende Paradigmen. Hierbei ist der Begriff Code teilweise weit gefasst und er meint oftmals sogar deklarative Definitionen, in denen beschrieben wird, wie eine Laufzeitumgebung oder eine CI/CD Pipeline aufgesetzt wird. Wie wäre es, wenn man versucht, Threat Models als Code oder etwas Ähnliches wie Code zu erstellen? Welche Vor- und welche Nachteile ergäben sich daraus?
Als Vorteil kann z. B. die direkte Editierbarkeit in IDEs genannt werden, sodass Entwicklungsteams (dort, wo das Detailwissen über die Technologien vorhanden ist) direkt ohne Medienbruch die neuen Ergänzungen im Threat Model einarbeiten können. Damit einher geht die direkte Möglichkeit des Eincheckens in den Source Tree zum Projekt (oder an anderer Stelle) und eine sauber historisierte und dank Diffing/Merging gute Form des gemeinsamen Bearbeitens im Team. Auch die Testbarkeit/Verifikation von Modellen ist damit relativ einfach.
Selbstverständlich ergeben sich auch mögliche Nachteile einer Threat-Model-as-Code-Idee: Die Erstellung und Pflege der Modelle als Code ist eventuell für Nichtentwicklungsteams nicht so einfach. Durch den direkten Fokus auf die Details, ohne direkt mit einem grafischen Modell zu beginnen, geht oftmals der Blick auf das große Ganze verloren und man droht sich zu verzetteln oder übermodelliert zu haben.
Diese (sicherlich nicht komplett vollständigen) Listen an Vor- und Nachteilen betrachtend, kann der Versuch, möglichst viele Vorteile mit möglichst wenigen Nachteilen zu einer Lösung zu verbinden, in der Definition von Threat Models in Form einer IDE-editierbaren deklarativen Beschreibung münden. Zum Beispiel bietet YAML als sehr einfache, menschenlesbare Deklaration von Inhalten die Vorteile der guten Editierbarkeit in IDEs (inkl. Linting, Auto-Completion etc.) und kann direkt eingecheckt und gedifft werden. Gleichermaßen hat YAML aber etwas weniger Nachteile in Bezug auf Komplexität gegenüber Code. Zudem sind gerade im DevOps-Bereich viele deklarativ gelöste Themen in YAML umgesetzt.
Open Source Agile Threat Modeling Toolkit „Threagile“
Aus den vorgenannten Überlegungen ist das Open-Source-Werkzeug Threagile [11] entstanden, an dessen Entwicklung der Autor dieses Artikels mitwirkt: Als Agile Threat Modeling Toolkit versucht Threagile das Thema Bedrohungsmodellierung mehr in Richtung Entwicklungsteams zu bringen, ohne dabei Medienbrüche in der Modellerstellung und -pflege hervorzurufen. Verfügbar ist es als Docker-Container auf Docker Hub [12] sowie die Quellen des unter der MIT-Lizenz veröffentlichten Open-Source-Projekts auf GitHub [13]. Vorgestellt wurde das Projekt einer breiteren Öffentlichkeit im Rahmen des ersten Release auf den Konferenzen Black Hat Arsenal USA 2020 sowie DEF CON AppSec Village 2020. Im Rahmen einer Keynote auf der DevOpsCon Berlin 2021 wurde das Konzept einer entwicklerfreundlicheren agilen Bedrohungsmodellierung mittels Threagile präsentiert. Dieser Teil des Artikels widmet sich der Verwendung von Threagile als einer Ausprägung der vorgenannten Ansätze und zeigt mögliche Vorteile sowie weitere Alternativen auf.
In Threagile erstellt man ein Threat Model als YAML-Datei mit folgenden Inhalten. Dank eines vorhandenen YAML-Schemas und Text Expansion Snippets, das in die IDE der Wahl importiert werden kann, gestaltet sich das Editieren mitsamt Auto-Completion und Fehlererkennung sehr einfach.
Data Assets
Hiermit beschreibt man die unterschiedlichen Kategorien von Daten, die man in dem zu modellierenden System verarbeitet. Es geht nur um die groben Kategorien, z. B. Reportingdaten, Abrechnungsdaten, Kundendaten oder dergleichen. Konkrete Datentypen und Attribute wären viel zu detailliert. Vielmehr geht es hierbei um die Bewertung der Datenklassen bezüglich der drei klassischen Schutzziele Vertraulichkeit (Confidentiality), Integrität (Integrity) und Verfügbarkeit (Availability).
Listing 1: Beispiel eines „Data Assets“ im Modell
Customer Contracts:
id: customer-contracts
description: Customer Contracts (PDF)
usage: business
quantity: many
confidentiality: confidential
integrity: critical
availability: operational
justification_cia_rating: >
Contract data might contain financial data as well as personally identifiable information (PII). The integrity and availability of contract data is required for clearing payment disputes.
origin: Customer
owner: Example Company XYZ
tags:
Nach der freien Festlegung eines einleitenden Titels in der ersten Zeile (er wird für die Report-Erzeugung verwendet) bekommt jedes Data Asset eine ID, um es in der Modelldatei an anderen Stellen referenzieren zu können (Listing 1). Zu den Punkten usage, quantity, confidentiality, integrity und availability gibt es entsprechende Enum-Werte, aus denen man im Modell auswählen kann. Die restlichen Punkte sind deskriptiver Natur und dienen Dokumentationszwecken in den generierten Reports.
Technical Assets
Hiermit beschreibt man die technischen Komponenten, also die klassischen Kästchen, die man auf ein Whiteboard malen würde, wenn man versucht, die Architektur visuell darzustellen. Die Abstraktionsstufe hängt davon ab, ob es ein direkter Bestandteil der eigenen Architektur ist (dann lieber detaillierter) oder ob es ein Umsystem oder eine Endnutzerkomponente (Browser) etc. ist (dann eher nur kontextgebend abstrakter).
Listing 2: Beispiel eines Technical Assets im Modell
Apache Webserver:
id: apache-webserver
description: Apache Webserver hosting the portal code and client-side code
type: process
usage: business
used_as_client_by_human: false
out_of_scope: false
justification_out_of_scope:
size: application
technology: web-server
internet: false
machine: container
encryption: none
multi_tenant: false
redundant: false
custom_developed_parts: true
data_assets_stored:
owner: Example Company XYZ
tags:
Auch hier bekommt jedes Technical Asset nach der freien Festlegung eines einleitenden Titels in der ersten Zeile wieder eine id zwecks Referenzierbarkeit im Modell (Listing 2). Der Großteil der restlichen Eigenschaften beschreibt die verwendete Technologie (hier gibt es eine große Liste zur Auswahl) sowie weitere sicherheitsrelevante Eigenschaften, jeweils mit einer hinterlegten Auswahlmöglichkeit.
Selbstverständlich existieren Technical Assets in einem Modell nicht einfach grundlos: Entweder verarbeiten und/oder speichern sie Daten. Somit hat jedes Technical Asset auch noch die Möglichkeit, Data Assets, die sie verarbeiten und/oder speichern anhand ihrer ID zu referenzieren.
Communication Links
Da zu einer Bedrohungsmodellierung auch die Betrachtung der Datenflüsse gehört, hat jedes Technical Asset die Möglichkeit, ausgehende Kommunikationsverbindungen anzugeben: Die beginnen jeweils mit einem freien Text als Titel des Datenflusses und referenzieren auf ein Technical Asset anhand dessen id als target.
Listing 3: Beispiel eines ausgehenden Communication Links an einem „Technical Asset“
... ... ... ... ... ... # unterhalb eines „Technical Assets”:
communication_links:
ERP System Traffic:
target: erp-system
description: Link to the ERP system
protocol: https
authentication: token
authorization: technical-user
vpn: false
ip_filtered: false
readonly: false
usage: business
data_assets_sent:
- customer-operational-data
- internal-business-data
data_assets_received:
- customer-contracts
tags:
Hierbei wird mit protocol eine Auswahl aus einer langen Liste an möglichen Protokollen getroffen (die weiter unten beschriebenen Risk Rules erkennen anhand der Protokolle z. B., ob eine Transportverschlüsselung vorhanden ist oder nicht). Ebenso wird eine Auswahl aus verschiedenen Formen der Authentisierung und Autorisierung getroffen sowie die gesendeten und empfangen Data Assets anhand ihrer ID referenziert.
Wer sich nun fragt, was mit eingehenden Kommunikationsverbindungen ist: Diese werden als ausgehende Kommunikationsverbindungen der aufrufenden Gegenseite modelliert. Hierdurch wird im Modell erzwungen, dass man immer den Kontext der Aufrufer mitmodelliert, wie z. B. den Browser der User oder die Mobile-App im Smartphone oder das Umsystem (als out-of-scope gesetzt), das einen aufruft. Hierdurch erhält man die gesamte Kette an Kommunikationsverbindungen und möglichen Risiken.
Trust Boundaries
Zu guter Letzt benötigt eine vernünftige Bedrohungsmodellierung noch die Definition der Vertrauensgrenzen, die Gruppen von Technical Assets bilden und diese gegenüber anderen Gruppen isolieren – sozusagen die großen Rahmen um die vielen Kästchen: In einer klassischen Architektur im eigenen Rechenzentrum ist das zum Beispiel ein VLAN oder eine DMZ, die netzwerktechnisch das Backend segmentiert. In Cloud-Umgebungen kann das auch als Security-Group definiert werden, in Container-Umgebungen als Network Policy. Letztendlich geht es darum, im Rahmen der Modellanalyse festzustellen, wenn eine Kommunikationsbeziehung über eine Vertrauensgrenze hinweggeht, da dann möglicherweise Risiken bzw. Bedrohungen entstehen können, die durch Security-Controls (wie Verschlüsselung, Authentisierung etc.) abzusichern sind.
Listing 4: Beispiel einer Trust Boundary im Modell
ERP DMZ:
id: erp-dmz
description: ERP DMZ
type: network-cloud-security-group
technical_assets_inside:
- erp-system
- contract-fileserver
- sql-database
trust_boundaries_nested:
tags:
Nach der Auswahl des Typs der Trust Boundary aus einer Liste möglicher Varianten wird per id auf die in ihr vorhandenen Technical Assets referenziert (Listing 4). Für den Fall tiefer verschachtelter Vertrauensgrenzen (zum Beispiel in der großen Vertrauensgrenze Cloud dann noch unterschiedliche Security-Groups und in einigen wiederum Network Policies auf Ebene der Container-Platform) kann man aus einer Trust Boundary noch weitere Nested Trust Boundaries anhand ihrer ID referenzieren.
Risk Rules
So weit, so gut: Wir haben ein Modell – immerhin. Wenn wir uns das in der Einleitung referenzierte Threat Modeling Manifesto anschauen, haben wir damit die erste von vier Schlüsselfragen („Woran arbeiten wir?“) beantwortet. Nun steht die zweite Schlüsselfrage an: „Was kann schiefgehen?“
Zur Identifikation möglicher sicherheitstechnischer Schwachstellen in der Architektur („Was kann schiefgehen?“) werden in klassischen Workshops zur Bedrohungsmodellierung am Whiteboard, meist unter Einbezug von securityerfahrenen Personen, viele mögliche Angriffsszenarien in der Theorie verprobt bzw. simuliert und Gegenmaßnahmen erfragt oder als zu implementieren definiert. Diese Simulation von Szenarien ist meist methodenorientiert (STRIDE, PASTA etc.) und bezieht auch bestimmte, eventuell unbeachtete Ausgangssituationen mit ein, z. B.: „Was wäre, wenn Angreifer diese Komponente bereits übernommen haben?“
Durch das Durchspielen von tiefgreifenden Angriffsszenarien auf Ebene der Architektur, das man als Whiteboard Hacking bezeichnet, entsteht eine mehrschichtige Härtung der Architektur von innen heraus. Das wird auch als das Grundprinzip sicherer Softwareentwicklung definiert (Defense in Depth) und bietet Gegenwehr gegen sich ansonsten tief verankernde und mittels Techniken wie Lateral Movement auf weitere Systeme durchschlagende Angriffe.
Solche Architekturanalysen lassen sich nicht komplett automatisieren (das wäre zu leicht), da sie immer eine gewisse Portion Erfahrung und Kontextverständnis benötigen, um vorher nicht beachtete mögliche Angriffsszenarien zu erkennen. Somit wird es immer Bedarf an dieser Form von Threat-Modeling-Workshops am Whiteboard geben. Gleichwohl kommen in diesen Workshops neben den höchst individuellen Szenarien auch immer wieder die gleichen Basisthemen auf, die sich sehr gut in einer automatischen Prüfung auf ein Architekturmodell anwenden lassen.
Genau dort setzt Agile Threat Modeling an: Es versucht durch kontinuierliche (entwicklerfreundliche) Modellpflege, diese wiederkehrenden Risiken in einer Architektur automatisiert als Teil des agilen Entwicklungsprozesses zu erkennen. Damit ließe sich Threat Modeling, in einer Baseline-Check-Form, als Teil eines DevSecOps-Prozesses etablieren. Je technischer das Modell erstellt wurde, desto genauer (im Sinne von „false-positive-freier“) können Regeln es auswerten und präzise mögliche Risiken erkennen. Im Optimalfall findet damit eine Securityanalyse des lebenden Architekturmodells als Baseline-Check im Rahmen von DevSecOps-Prozessen statt, sodass die individuellen Threat-Modeling-Workshops nur noch bei größeren oder kritischeren Architekturänderungen notwendig sind.
Threagile, das Open-Source-Agile-Threat-Modeling-Toolkit [11], versucht viele dieser automatisiert erkennbaren Risiken im Architekturmodell (definiert durch die YAML-Datei) mittels Risk Rules (Kasten: „Risk-Rule-Beispiele“) zu identifizieren: Ein stetig wachsendes Set von built-in Risk Rules versucht je Regel, auf den Modellgraph (bestehend aus Komponenten und ihrer Datenflüsse) angewendet, diejenigen Stellen zu identifizieren, die ein sicherheitstechnisches Risiko bergen.
Risk-Rule-Beispiele
Beispiel zur Identifikation von Server-Side-Request-Forgery-Risiken
Zur Identifikation von möglichen SSRF-Risiken in der Architektur iteriert diese Risk Rule über alle Technical Assets im Modell, die weder Client noch transitive Komponenten wie Load Balancer sind. Danach werden je Technical Asset alle ausgehenden Communication Links verfolgt und diejenigen, die ein Webprotokoll als Protokollangabe im Modell besitzen, herangezogen. Diese Technical Assets erhalten dann ein mögliches SSRF-Risiko im Report. Um ebenfalls als Teil dieser Risk Rule den „Blast Radius“ zu bestimmen, also die möglichen Ziele eines SSRF-Angriffs mittels der identifizierten Komponente, werden alle (auch nicht durch diese Komponente direkt aufgerufenen) Ziele innerhalb der gleichen Netzwerk-Trust-Boundary im Modell ermittelt, die per Webprotokoll erreichbar wären, ergänzt um Metadata Services im Fall von Cloud-Umgebungen. Die Data Assets der betroffenen Zielkomponenten werden als potenziell gefährdet im Report aufgenommen. Die Kritikalität des identifizierten SSRF-Risikos an der betroffenen Quellkomponente wird anhand der höchsten modellierten Vertraulichkeitseinstufung dieser betroffenen Data Assets bestimmt.
Beispiel zur Identifikation fehlender durchgehender Identity Propagation
Um in Architekturmodellen zu erkennen, wenn im Backend die Absicherung von (Micro)Services nicht ausreichend stark ist, wird mittels dieser Risk Rule über alle Technical Assets iteriert, die in der Lage sind, Requests für Endbenutzer zu verarbeiten (z. B. Web Services, Webanwendungen etc.) und eine hohe Sensitivitätseinstufung haben oder als Multimandatenkomponente im YAML-File modelliert wurden. Dann werden für jedes dieser Technical Assets dessen eingehende Communication Links (ausgehend von Technical Assets mit der Möglichkeit zur Propagation von Tokens) ermittelt, die mit einer Authentisierung im Modell versehen wurden. Wenn diese Communication Links als Autorisierung im Modell nicht Enduser Identity Propagation besitzen, wird das Risiko einer Missing Enduser Identity Propagation für diesen Communication Link in den Report mit aufgenommen. Hierdurch lassen sich die Stellen im Modell identifizieren, die aufgrund ihres sensitiven Ratings und etwaiger Risiken des mandantenübergreifenden Datenabzugs eine durchgehende Berechtigungsprüfung in den (Micro)Services durchführen und hierzu per Token auch die Identity des Endusers erhalten sollten (zwecks Berechtigungsprüfung auf Datenebene gegenüber den Requests/Anfragen).
Beispiel zur Identifikation möglicher LDAP-Injection-Risiken
Um einen Eindruck zu bekommen, wie sich solche Risk Rules in Code dann tatsächlich abbilden, ist in Abbildung 2 ein Screenshot der Risk Rule zur Identifikation von potenziellen LDAP-Injection-Risiken zu sehen.
Built-in sowie Custom Risk Rules in Threagile werden in der von Google mitentwickelten Open-Source-Programmiersprache Go geschrieben, die eine recht einfache und intuitive Syntax besitzt, sodass die Hürde zur Entwicklung eigener Risk Rules relativ gering ist.
Um eine der vielen built-in Risk Rules zu veranschaulichen und daran nachvollziehen zu können, wie durch eine technisch detaillierte Modellierung Schwachstellen in einer Architektur automatisiert erkennbar sind, sei das Beispiel der Regel zur Erkennung von Server-Side-Request-Forgery-(SSRF-)Sicherheitslücken [14] gezeigt: Diese besonders in Cloud-Umgebungen gefährliche Sicherheitslücke ist ein oftmals unterschätztes Einfallstor für eine tiefere Verankerung von Angriffen auf eine Architektur (siehe z. B. den erfolgreichen Capital One Hack auf über 100 Millionen Consumer-Kreditanträge via SSRF-Sicherheitslücke einer Komponente mit Zugriff auf die AWS Metadata Services (IMDS) [15], die gemeldeten SSRF-Sicherheitslücken in der Google Cloud [16], die gemeldete SSRF-Sicherheitslücke in GitLab [17] sowie die in der Breite ausgenutzte Zero-Day-SSRF-Sicherheitslücke in Microsoft Exchange [18]).
Diese Auszüge aus den in Threagile enthaltenen Risk Rules zeigen, wie durch technische Modellierung im YAML-File mit Angabe verwendeter Technologien und Protokolle Risk Rules mit weniger False Positives gezielter mögliche Architekturrisiken erkennen können. Ebenso gibt es einen Eindruck, wie detailliert ein Modell mittels Risk Rules analysiert werden kann. Das gilt entsprechend auch für eigene Custom Risk Rules. Die stetig wachsende Liste von built-in Risk Rules umfasst derzeit 42 solcher Regeln (Tabelle 1).
Liste von built-in Risk-Rules | ||
---|---|---|
accidental-secret-leak | missing-hardening | sql-nosql-injection |
code-backdooring | missing-identity-propagation | unchecked-deployment |
container-baseimage-backdooring | missing-identity-provider-isolation | unencrypted-asset |
container-platform-escape | missing-identity-store | unencrypted-communication |
cross-site-request-forgery | missing-network-segmentation | unguarded-access-from-internet |
cross-site-scripting | missing-vault-isolation | unguarded-direct-datastore-access |
dos-risky-access-across-trust-boundary | missing-vault | unnecessary-communication-link |
incomplete-model | missing-waf | unnecessary-data-asset |
ldap-injection | mixed-targets-on-shared-runtime | unnecessary-data-transfer |
missing-authentication-second-factor | path-traversal | unnecessary-technical-asset |
missing-authentication | push-instead-of-pull-deployment | untrusted-deserialization |
missing-build-infrastructure | search-query-injection | wrong-communication-link-content |
missing-cloud-hardening | server-side-request-forgery | wrong-trust-boundary-content |
missing-file-validation | service-registry-poisoning | xml-external-entity |
Tabelle 1: Liste von built-in Risk Rules
Über ein entsprechendes Plug-in-Interface lassen sich auch individuelle Custom Risk Rules entwickeln, die mit Hilfe von vom Threagile-API bereitgestellten Convenience-Methoden recht einfach den Modellgraph navigieren können. Hierdurch lassen sich zum Beispiel unternehmensindividuelle Policies auf die Modelle anwenden und etwaige Abweichungen feststellen – mitsamt der Ausgabe von Verbesserungsempfehlungen: Jede Risk Rule beinhaltet auch Metadaten, die die Risiken entsprechend einordnen (z. B. nach STRIDE, CWE oder betroffener Rolle im SDLC). Mittels Textbausteinen je Risk Rule werden die Prüfschritte bzw. Mitigationsempfehlungen für die Entwickler aufgeführt, um das Risiko passend abzuschwächen.
Ergebnisse der Sicherheitsanalyse und Empfehlungen zur Absicherung
Kommen wir nun zur dritten Schlüsselfrage aus dem Threat Modeling Manifesto: „Was werden wir dagegen tun?“ Hierzu braucht es passgenaue Empfehlungen zur Absicherung für die jeweiligen Zielgruppen wie Architektur, Entwicklung, Betrieb etc.
Ein Threagile Run lässt sich (selbstverständlich komplett offline) entweder per Kommandozeile (CLI) oder als REST-Server durchführen (wenn man Threagile im Servermodus startet). Aus einem Threagile Run kommen einige Artefakte heraus, die versuchen, die Informationen passend aufbereitet zu liefern.
Datenflussdiagramm
Als erstes Artefakt wird ein Datenflussdiagramm der Architektur mittels Autolayout aus dem YAML-File erzeugt. Das ist besonders wichtig, damit wir im Rahmen der Modellerstellung frühzeitig erkennen, wie die Architektur aussieht und ob wir eventuell eine Komponente in eine falsche Zone gehängt oder eine Kommunikationsverbindung falsch gezogen haben. Dieses generierte Bild ist quasi das, was wir ansonsten auf einem Whiteboard oder in einem grafisch orientierten Werkzeug gemalt hätten.
In den Abbildungen 3 und 4 sind jeweils aus den YAML-Modellen generierte Datenflussdiagramme von einem kleinen und mittleren Beispielmodell zu sehen. Die Formen und Farben in den erzeugten Diagrammen besitzen eine Semantik und geben bereits erste Hinweise bzgl. der Verteilung von Risiken.
Als Kollateralnutzen entsteht hierdurch eine laufend aktuell gehaltene Architekturdokumentation, die auch bei so mancher systemübergreifender Fehleranalyse hilfreich sein kann, da man nun klar sieht, wer mit wem über welche Schnittstellen kommuniziert. Weiterhin dienen solche Datenflussdiagramme auch als Input für die ab und zu dennoch stattfindenden klassischen Workshops zur Bedrohungsmodellierung. Da der Input in diese Diagramme aus der Entwicklung durch die laufende Modellpflege in den jeweiligen YAML-Files der Projekte stattfindet, entsprechen die erzeugten Architekturdokumente sehr stark der „Wahrheit“ auf Implementierungsebene.
Risikoreport (PDF) mit Mitigationsempfehlungen
Das erzeugte Report-PDF listet die identifizierten Risiken aus Perspektive der jeweiligen Technical Assets auf – zusätzlich gegliedert nach Risikotyp (Abb. 5). Pro Risikotyp werden entsprechende Mitigationsempfehlungen genannt sowie zusätzlich auf das passende OWASP Cheat Sheet bzw. Kapitel aus dem OWASP ASVS/CSVS (Application Security Standards der OWASP) verlinkt, um Entwicklungsteams direkt anwendbare Hinweise auf Implementierungsebene zu geben.
Trackingdokument (Excel)
Um sich bei häufigerem Arbeiten mit Threagile einen direkten Überblick verschaffen zu können, wird eine Excel-Tabelle generiert, die die identifizierten Risiken inkl. Status und betroffenem Technical Asset sowie weiteren Informationen auflistet (Abb. 6).
JSON-Export zur Integration in DevOps-Prozesse
Durch das CLI sowie den REST-Server-Modus sind zwei flexible Integrationsmöglichkeiten in einer DevOps-Automation gegeben. Wer lieber mit GitHub-Workflows baut, findet ebenfalls eine Threagile GitHub Action, die nach einem Push eines Threat-Model-YAML-Files Threagile ausführt und die Ergebnisse mit ablegt [19]. Neben den eher für Menschen gedachten Outputartefakten (Report, Excel etc.) können die ermittelten Risiken auch als JSON ausgeben werden. Hiermit wäre es zum Beispiel leicht, CI/CD-Pipelines entsprechend abbrechen zu lassen, wenn neue kritische Risiken identifiziert wurden, die noch nicht als behandelt markiert wurden.
Tracking der Risiken
Nun haben wir drei der vier Schlüsselfragen aus dem Threat Modeling Manifesto durch einen werkzeuggestützten Prozess behandelt. Bleibt nun noch die vierte Frage übrig: „Haben wir unsere Arbeit gut genug gemacht?“
Hierzu benötigen wir ein Tracking der Mitigation identifizierter Risiken: Dieses findet bei Threagile direkt in der YAML-Datei des Modells statt. Jedes identifizierte Risiko hat eine sprechende eindeutige ID, die im Report, Excel sowie JSON auftaucht. Anhand dieser ID besteht die Möglichkeit, im Modell einen Status und weitere Trackinginfos nachzuhalten. Folgende Status stehen hierbei zur Verfügung: unchecked (das ist der Default), in-discussion, accepted, in-progress, mitigated, false-positive. Somit lassen sich neben dem Fortschritt der Risikobehandlung auch die akzeptierten Risiken dokumentieren, wenn zum Beispiel der Aufwand nicht in einem passenden Verhältnis zum Nutzen steht oder das Risiko aufgrund der geringen Auswirkungen auch einfach toleriert werden kann. In der klassischen Bedrohungsmodellierung bezeichnet man diese übrig gebliebenen Risiken als sogenannte „Restrisiken“.
Um die vierte Schlüsselfrage passend beantworten zu können, müssen diese Restrisiken dahingehend betrachtet werden, ob man sie so annehmen kann, oder ob eine weitere Mitigation bestimmter Risiken notwendig ist. Hierzu bieten der Report und das Tracking-Excel passende Sichten (Abb. 7).
Automation von Modelländerungen
Besonders in größeren Unternehmen gibt es oftmals wiederkehrende identische Aufgaben in Bedrohungsmodellen, z. B. das Hinzufügen der Build Pipeline (bzgl. Risiken wie Supply Chain Attacks), das Integrieren eines Vaults in eine Architektur oder auch die Anbindung modellierter Komponenten an einen Identity Provider im Modell, um nur einige wenige zu nennen. Diese wiederkehrenden Modellanpassungen bieten sich daher dafür an, automatisiert zu werden.
Mittels Model Macros können solche Anpassungen am YAML-Modell in Wizard-ähnlichen geführten Dialogen durchgeführt werden: Hierbei liest das Model Macro das YAML-Modell ein, fragt die modellierenden Benutzer nach für das Macro notwendigem Input und führt die Modellanpassung entsprechend den Antworten durch. Danach kann wieder weiter manuell am Modell gearbeitet werden.
Und was ist mit den Workshops?
Diese sollten selbstverständlich immer noch stattfinden, nur halt nicht mehr so oft, sondern eher nur bei zentralen Änderungen an der Architektur oder größeren Releases. Es wird immer mögliche Schwachstellen bzw. Risiken geben, die nur mit der Fachlogik vertraute Menschen erkennen können.
Um diese individuell identifizierten Risiken auch innerhalb des gleichen Risk-Tracking-Prozesses bewerten und laufen zu lassen, können sie direkt im YAML-File des Bedrohungsmodells mit erfasst werden: Je Kategorie werden Metadaten eingetragen (damit es im Report auch passend mit Details erscheinen kann) und je identifiziertem Risiko der Verweis, auf welche Komponente(n) es sich am ehesten bezieht.
Weitere Model-as-Code-Ansätze
Im Bereich der „Threat Model as Code“-Ansätze gibt es noch weitere interessante Vertreter: Als ein hervorstechendes Beispiel sei pytm erwähnt, mit dem man Threat Models statt deklarativ direkt in Python-Code schreibt [20]. Neben Datenflussdiagrammen generiert pytm auch Sequenzdiagramme und leitet Risiken anhand von in JSON definierten Regeln aus dem Python-Modellinput ab.
Wünschenswerte Effekte
Nachdem wir nun alle vier Schlüsselfragen aus dem Threat Modeling Manifesto betrachtet und anhand eines Open-Source-Werkzeugs eine beispielhafte Umsetzung gesehen haben, stellt sich die Frage: Was sind die möglichen positiven Effekte aus der werkzeuggestützten Integration von Threat Modeling in agile Entwicklungsprozesse?
Mittels der kontinuierlichen Pflege des Modellinputs auf Ebene der Entwicklung besteht die Möglichkeit, dass Sicherheitsrisiken in einer Architektur früher erkannt werden, insbesondere wenn eine Integration des werkzeuggestützten Verfahrens in DevOps-Prozesse stattfindet. Als nützlicher Seiteneffekt entsteht eine detaillierte Dokumentation der in einem Unternehmen entstehenden Architekturen, bis auf Ebene der Datenflüsse und Protokolle. Durch die Erstellung von Custom Risk Rules können unternehmensindividuelle Policies auf Modellebene geprüft und Abweichungen erkannt werden. Im Optimalfall ist damit Security weniger ein Bottleneck in Bezug auf agile Prozesse und kann durch einen Baseline-Check-Ansatz dennoch bestimmte Sicherheitsrisiken auf Ebene von Architekturen frühzeitig adressieren.
Christian Schneider ist als freiberuflicher Security Architect, Whitehat-Hacker und Trainer tätig. Er unterstützt Unternehmen im Bereich der IT-Security durch Pentests und Security Architecture Consulting sowie Teams bei der Einführung von DevSecOps und Agile Threat Modeling. In dieser Rolle ist er regelmäßig als Trainer tätig und spricht auf namhaften nationalen sowie internationalen Konferenzen.
Links & Literatur
[1] Threat Modeling Manifesto: https://www.threatmodelingmanifesto.org
[2] „Elevation of Privilege” Threat Modeling Kartenset: https://github.com/adamshostack/eop
[3] Shostack, Adam: „Threat Modeling. Designing for Security“, Wiley, 2014: https://threatmodelingbook.com
[4] STRIDE Modell von Sicherheitsrisiken: https://de.wikipedia.org/wiki/STRIDE_(IT-Sicherheit)
[5] Security Development Lifecycle (SDL): https://de.wikipedia.org/wiki/Security_Development_Lifecycle
[6] Verfahren zur Bedrohungsmodellierung: https://en.wikipedia.org/wiki/Threat_model
[7] PASTA – Process for Attack Simulation and Threat Analysis: https://owasp.org/www-pdf-archive/AppSecEU2012_PASTA.pdf
[8] Microsoft Threat Modeling Tool: https://docs.microsoft.com/de-de/azure/security/develop/threat-modeling-tool
[9] OWASP Threat Dragon Tool: https://owasp.org/www-project-threat-dragon/
[10] Draw.io Threat Modeling Stencils: https://michenriksen.com/blog/drawio-for-threat-modeling/
[11] Threagile – Open-Source Agile Threat Modeling Toolkit: https://threagile.io
[12] Threagile auf Docker Hub: https://hub.docker.com/r/threagile/threagile
[13] Source Code von Threagile auf GitHub: https://github.com/threagile
[14] Definition und Absicherung von Server-Side-Request-Forgery-(SSRF-)Sicherheitslücken: https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html
[15] Maliziös ausgenutzte SSRF-Sicherheitslücke – Capital One Hack: https://krebsonsecurity.com/2019/08/what-we-can-learn-from-the-capital-one-hack/
[16] Mehrere gemeldete high-risk SSRF-Sicherheitslücken in der Google Cloud: https://security.googleblog.com/2021/03/announcing-winners-of-2020-gcp-vrp-prize.html
[17] Gemeldete high-risk SSRF-Sicherheitslücke in GitLab: https://portswigger.net/daily-swig/gitlab-fixes-serious-ssrf-flaw-that-exposed-orgs-internal-servers
[18] Out-of-Band Zero-Day Patch einer in der Breite ausgenutzten SSRF-Sicherheitslücke in Microsoft Exchange: https://redmondmag.com/articles/2021/03/02/exchange-server-zero-day-patches.aspx
[19] Threagile GitHub Workflow Action Example: https://github.com/Threagile/github-integration-example
[20] pytm – Threat Models als Python-Code: https://github.com/izar/pytm