Analyse des globalen und lokalen Datenflusses: Entscheidend für die Sicherheit von ABAP-Code

Unternehmen, die SAP-Anwendungen einsetzen, nehmen in den meisten Fällen umfangreiche Anpassungen vor, um ihre Geschäftsprozesse innerhalb der SAP-Technologie abbilden zu können. Diese Anpassungen umfassen letztlich Millionen von Zeilen ABAP-Code, der von Menschen entwickelt wurde und unter anderem Sicherheitslücken enthalten kann.
Um die Sicherheit des von Unternehmen erstellten Codes zu gewährleisten, ist eine Lösung entscheidend, die sich in den Entwicklungszyklus integrieren lässt, sodass Schwachstellen bereits in einer frühen Entwicklungsphase erkannt werden und deren Behebung deutlich kostengünstiger ist als die Durchführung von Bewertungen in der Produktionsumgebung.
Bei der Suche nach solchen Schwachstellen ist es stets entscheidend, ob bestimmte Datentypen durch Benutzereingaben manipuliert werden können und ob diese Benutzereingaben vor ihrer Verwendung als Eingabe für den Code nicht oder nicht ausreichend validiert werden. Einige typische Schwachstellen, die daraus entstehen können, sind:
- SQL-Injection
- Code-Injektion
- Verzeichnisdurchlauf
- OS-Befehlsinjektion
Wenn Sie diese Art von Schwachstellen (sowie andere) aufdecken möchten, muss das Sicherheitsprodukt, das die Prüfung durchführt, eine Datenflussanalyse durchführen, um festzustellen, ob Benutzereingaben als Eingabe für dynamischen Code verwendet werden, ohne zuvor validiert worden zu sein.
Das beliebteste Tool zur ABAP-Code-Sicherheit, Control Code ABAP“ (C4CA) von Onapsis, kann von Entwicklern bei Bedarf in der ABAP Workbench (SE80) oder im ABAP Development Toolkit (ADT) aufgerufen werden. C4CA bietet Entwicklern im ADT zudem Unterstützung in Echtzeit. Die meisten Kunden führen während des Release-Prozesses eines Objekts auch automatische Prüfungen durch, um sicherzustellen, dass jedes Objekt mindestens einmal geprüft wird und keine (oder keine unbefugten) Sicherheitslücken in die Produktion gelangen können.
Auf dem Markt für die Sicherheitsanalyse von ABAP-Code gibt es einige Tools, die auch eine Datenflussanalyse durchführen und dabei alle nach außen gerichteten Schnittstellen als potenzielle Benutzereingaben betrachten. Diese Tools unterscheiden sich jedoch hinsichtlich des Umfangs ihrer Datenflussanalyse und der Genauigkeit bei der Identifizierung tatsächlicher Benutzereingaben. Dieser Unterschied hat erhebliche Auswirkungen auf die Rate der falsch-negativen und falsch-positiven Ergebnisse.
Analyse des lokalen Datenflusses
Um Schwachstellen wie SQL-, Code- oder Befehlsinjektionen sowie Verzeichnisüberquerungen zu erkennen, ist es entscheidend, den Datenfluss zwischen jeder nach außen exponierten Schnittstelle und dem dynamischen Teil des Codes zu analysieren. Das erste Beispiel zeigt ein Szenario, in dem der Eingabeparameter iv_param eines Funktionsbausteins nicht direkt an den dynamischen Code-Teil übergeben wird. Eine Datenflussanalyse erkennt, dass der Wert von iv_param lv_param zugewiesen wird und lv_param als Eingabe im dynamischen Code verwendet wird.

Um Fehlalarme zu vermeiden, ist zudem eine Datenflussanalyse erforderlich. Das folgende Beispiel sollte keinen Befund generieren, da es erkennt, dass der Wert des Eingabeparameters `iv_param` überprüft wird, bevor er in die dynamische Anweisung einfließt:

In der Praxis kann der Datenfluss recht komplex sein. Die oben genannte Überprüfung könnte in einen anderen Funktionsbaustein integriert werden:

Einige auf dem Markt erhältliche Tools führen eine lokale Datenflussanalyse durch. Eine lokale Datenflussanalyse kann die Absicherung nur erkennen, wenn der aufgerufene Funktionsbaustein Z_PROCESS_PARAM zur selben Kompilierungseinheit (hier: Funktionsgruppe) gehört wie der aufrufende Funktionsbaustein Z_DYN_CODE. Mit anderen Worten:
Bei einer lokalen Datenflussanalyse stellen alle direkt oder indirekt aufgerufenen Module, die nicht zur selben Kompilierungseinheit gehören wie das betreffende Modul, blinde Flecken dar!
Im besten Fall führen die Einschränkungen einer lokalen Datenflussanalyse zu Fehlalarmen. Es besteht jedoch auch die Gefahr von Fehlentscheidungen.
Ein falsches negatives Ergebnis kann auftreten, wenn sich der dynamische Code in einem aufgerufenen Modul befindet, das nicht zum Scan-Bereich gehört. Im folgenden Beispiel wird das Programm Z_CALLER auf Schwachstellen überprüft. Das Programm selbst enthält keinen dynamischen Code, der aufgerufene Funktionsbaustein Z_DYN_CODE jedoch schon; schlimmer noch: Sein Eingabeparameter wird durch Benutzereingaben im aufrufenden Programm Z_CALLER bereitgestellt.

Da der Funktionsbaustein nicht zur selben Kompilierungseinheit gehört, wird sein Inhalt nicht im lokalen Datenfluss analysiert und die kritische Situation wird nicht erkannt!
Man könnte annehmen, dass das Problem im Funktionsbaustein Z_DYN_CODE bereits früher entdeckt worden wäre, da ein aufgerufener Funktionsbaustein zuvor bereits separat geprüft worden sein muss (z. B. weil er zuvor in das QA- und/oder das Produktivsystem transportiert wurde). Hier stehen wir jedoch vor einem allgemeinen Problem der lokalen Datenflussanalyse.
Wenn ich Module anderer Entwickler, Abteilungen oder Unternehmen integriere, bin ich darauf angewiesen, dass andere entscheiden, ob ein festgestellter Fehler als kritisch eingestuft wird oder nicht.
Eine solche Entscheidung wird im Release-Prozess durchgesetzt, da Transporte in der Regel blockiert werden, wenn Fehlerbefunde weder behoben noch von einer autorisierten Person akzeptiert werden. Ein häufig anzutreffender Ansatz zur Entscheidungsfindung ist der Beginn einer manuellen globalen Datenflussanalyse. Wird für ein Modul eine potenzielle Injektionsschwachstelle gemeldet, werden alle Verbraucher dieses Moduls manuell auf mögliche Exploits überprüft. Wenn die Verbraucher nur „sichere“ Werte für die kritischen Eingabeparameter liefern, gilt das Modul selbst als „sicher“ und die gemeldete Schwachstelle wird akzeptiert:

Im obigen Beispiel wird der Befund bezüglich der potenziellen Injection-Schwachstelle im Funktionsbaustein Z_DYN_CODE akzeptiert, da der Verbraucher Z_CALLER_ABC genau einen festen Wert bereitstellt und der Verbraucher Z_CALLER_DEF die Benutzereingabe validiert, bevor sie an Z_DYN_CODE übergeben wird. Dieser Ansatz ignoriert völlig, dass es in Zukunft neue Konsumenten wie das Programm Z_CALLER geben könnte, die (unbeabsichtigt oder absichtlich) unsichere oder nicht validierte Eingabewerte an Z_DYN_CODE übergeben könnten.
In einer idealen Welt sollten Entwickler natürlich nur externe Module aufrufen, die für die öffentliche Nutzung freigegeben sind (APIs, SAP-BAPIs usw.). Bei den Sicherheitsüberlegungen für solche Module wird in der Regel berücksichtigt, dass es eine unvorhersehbare Anzahl von (unkontrollierbaren) Nutzern geben könnte und daher das (B)API-Modul selbst für die Sicherheit sorgen muss.
Nicht veröffentlichte externe Module können inkompatiblen Änderungen unterliegen oder ohne Vorwarnung gelöscht werden. Wie oben dargelegt, besteht im Zusammenhang mit diesen Modulen zudem ein Sicherheitsrisiko, da Sicherheitsentscheidungen häufig auf der Grundlage ihrer aktuellen Nutzer getroffen werden.
Ein bekanntes Beispiel hierfür ist SAP. Die Onapsis Research Labs melden Onapsis Research Labs Sicherheitslücken in nicht-RFC-fähigen Funktionsbausteinen oder in Klassenmethoden. Die meisten dieser gemeldeten Sicherheitslücken werden letztendlich von SAP zurückgewiesen und nicht behoben. Der Grund für die Zurückweisung ist immer derselbe:
„Wir haben alle unsere internen SAP-Nutzer überprüft und festgestellt, dass diese ausschließlich sichere und/oder validierte Werte an das Berichtsmodul übermitteln. Da das Modul nicht für Kunden freigegeben ist und nicht von außen aufgerufen werden kann, erfolgt jeder Verweis darauf im kundeneigenen Code auf eigenes Risiko des Kunden, und der Nutzer ist dafür verantwortlich, geeignete Maßnahmen zur Gewährleistung der Sicherheit zu ergreifen.“
Im Gegensatz zu RFC-fähigen Funktionsbausteinen berücksichtigt SAP hier nicht das Risiko eines gezielten Angriffs. Daher ist es für einen Insider-Angreifer ein Leichtes, einen anfälligen Report in die Produktionsumgebung einzuschleusen, ohne von Tools bemerkt zu werden, die Prüfungen mittels lokaler control durchführen. Er muss lediglich einen dieser anfälligen SAP-Funktionsbausteine identifizieren und aufrufen, die dynamischen Code bereitstellen:

Globale Datenfluss
Mithilfe einer patentierten Technologie führt die C4CA-Lösung von Onapsis eine globale Datenflussanalyse durch. Eine globale Datenflussanalyse berücksichtigt alle aufgerufenen Module, unabhängig davon, ob diese zur gleichen Kompilierungseinheit wie der Verbraucher gehören oder nicht. Dadurch wird die Anzahl der Fehlalarme und der übersehenen Fehler deutlich reduziert. Ein weiterer wichtiger Aspekt der globalen Datenflussanalyse ist, dass sie eine wesentlich detailliertere Verwaltung der Fundstellen ermöglicht.
Ein Injection-Befund in C4CA wird eindeutig durch die Quelle der Daten identifiziert, die dem dynamischen Code und dem Datensenke zur Verfügung gestellt werden – also durch die Quellcodezeile des dynamischen Codes. Es können mehrere Datenquellen mit derselben Datensenke verbunden sein. Tools, die eine lokale Datenflussanalyse durchführen, interpretieren genau eine Stelle als Datenquelle, in der Regel einen Eingabewert in der Schnittstelle des geprüften Moduls.
Beispiel:
Immer wenn das anfällige Modul Z_DYN_CODE als Teil seiner Kompilierungseinheit gescannt wird, wird seine Anfälligkeit erkannt und durch die rot markierten Quellcodezeilen eindeutig gekennzeichnet. Dies geschieht unabhängig von etwaigen bestehenden Nutzern.

Im Gegensatz zu anderen Tools berücksichtigt C4CA bei der Einstufung des Befunds, dass es sich lediglich um eine potenzielle Injection-Sicherheitslücke handelt.
Sollte in Zukunft ein Schwachstellen-Scan für einen neuen Kunden durchgeführt werden, wird im Rahmen einer globalen Datenflussanalyse das aufgerufene Modul Z_DYN_CODE erneut überprüft, unabhängig davon, ob es zur selben Kompilierungseinheit gehört oder nicht und unabhängig davon, ob jemand den vorherigen Befund beim Scan von Z_DYN_CODE akzeptiert hat oder nicht.
Zwei Beispiele, die zu neuen individuellen Erkenntnissen führen:


Beim Scannen des Programms Z_CALLER_VUL1 erkennt C4CA eine eindeutige Injection-Schwachstelle, da der dynamische Code in Z_DYN_CODE eindeutig auf Benutzereingaben in Z_CALLER_VUL1 basiert. C4CA generiert daher einen neuen Befund und stuft diesen als „Flaw“ ein. Der Autor des Programms kann nun entweder den Eigentümer des Funktionsbausteins Z_DYN_CODE benachrichtigen und um eine Abhilfe bitten oder er kann vor dem Aufruf von Z_DYN_CODE eine eigene Abhilfe im Programm implementieren. Dasselbe gilt für die Methode Z_CALLER_VUL2.
Zusammenfassung
Tools zur Codesicherheit müssen eine Datenflussanalyse durchführen, um Schwachstellen wie SQL-Injection, OS-Command-Injection, Code-Injection und Directory Traversal zu identifizieren.
Die marktführende Lösung Onapsis C4CA und andere auf dem Markt erhältliche Tools verfolgen unterschiedliche Ansätze hinsichtlich dieser Datenflussanalyse und der daraus resultierenden Ergebnisverwaltung. Während einige Tools lediglich eine lokale Datenflussanalyse durchführen, führt C4CA optional eine globale Datenflussanalyse durch.
Eine lokale Datenflussanalyse ist ein akzeptabler Ansatz, sofern potenzielle Schwachstellen stets umgehend behoben werden. Die Entscheidung, eine potenzielle Schwachstelle zu akzeptieren, darf niemals allein auf der Grundlage einer Überprüfung der aktuellen Nutzer getroffen werden. Zukünftige Nutzer könnten das anfällige Modul auf unsichere Weise aufrufen, sei es aus Unkenntnis oder in böswilliger Absicht.
Die globale Datenflussanalyse von Onapsis C4CA stellt sicher, dass jeder neu eingeführte Datenflusspfad – beispielsweise durch einen neuen oder geänderten Verbraucher – erneut vollständig analysiert wird, sodass der Verantwortliche des Verbrauchers über kritische Situationen informiert wird und eigene Abhilfemaßnahmen einleiten kann.
