ix.0711.118-122 09.06.2011 14:07 Uhr Seite 118 SAP-Security PRAXIS Sicherheitslöcher in eigenem ABAP-Code stopfen Abdichtservice Sebastian Schinzel, Frederik Weidemann, Andreas Wiegenstein, Markus Schumacher SAP-Anwender, die ihre ERP-Systeme mit eigenen ABAPAnwendungen erweitern, produzieren dabei aus Unkenntnis oft große Sicherheitslecks. Für Angreifer steht damit das Tor zu den unternehmenswichtigen Daten weit offen. Es gibt jedoch Möglichkeiten, den unerlaubten Zutritt effektiv zu unterbinden. E in Großteil von SAPs Standardanwendungen ist in der proprietären Programmiersprache ABAP geschrieben und wird im Quelltext an die Kunden ausgeliefert. Nahezu jedes Unternehmen erweitert diese Anwendungen durch eigenen ABAP-Code oder entwickelt Funktionen komplett neu. Nicht selten betrifft das weit über die Hälfte aller Applikationen in einem SAP-System. Die Sicherheit der Komponenten liegt damit nicht mehr vollständig in der Hand des Anbieters. Das Entwickeln eigener Anwendungen mit SAP-Frameworks ist also eine verantwortungsvolle Aufgabe, wenn man sich vor Augen führt, welche Da- ten das zentrale ERP-System üblicherweise verarbeitet. Ob Gehalts-, Bewerber-, Personal- und Vertriebsdaten oder die Finanzbuchhaltung: SAP bietet für nahezu alle kritischen Geschäftsbereiche entsprechende Module. Komplexität ist hier ein nicht zu unterschätzender Faktor (Abbildungˇ1). Im SAP-Umfeld steht der Begriff „Sicherheit“ meist für ein korrektes Berechtigungskonzept, manchmal für die sichere Konfiguration, er umfasst jedoch nur selten Aspekte der Softwareentwicklung. Eine saubere Konfiguration hilft jedoch wenig, wenn Sicherheitslücken im selbst geschriebenen Code klaffen. Und korrekte Berechtigungen nützen 118 ebenfalls nicht viel, wenn das eigene Programm sie nicht oder nur unzureichend prüft. Es ist bekannt, dass selbst geschriebene ABAP-Anwendungen prinzipiell anfällig sind für Standardangriffe via Directory Traversal, SQL Injection und Command Execution [1]. Einige der weit über 300 ABAP-Befehle erfordern in dieser Hinsicht besondere Aufmerksamkeit. Die Zahl der von SAP veröffentlichten Patches hat Ende des vergangenen Jahres deutlich zugenommen. Zurückzuführen ist diese Phänomen auf neue Methoden und Werkzeuge der Qualitätssicherung, zum Beispiel auf verbesserte Code Scans. Bei Tests findet man regelmäßig viele Lücken im ABAP-Code. Angreifern fällt es daher meist nicht schwer, unbefugt in das System einzudringen und sich vorbei an den übrigen Sicherheitsmaßnahmen Zugang zu Kundendaten zu verschaffen. Der Artikel beschreibt einige typische Fehler und wie man sie abstellt. Das Ganze basiert auf einem Auszug aus der BIZEC APP11, einer aktuellen Liste der größten Risiken in der ABAP-Entwicklung (siehe www.bi zec.org oder iX-Link). ABAP Command Injection ABAP gewährt ähnliche Freiheiten wie Java oder Python. Das beinhaltet den vollständigen Schreib- und Lesezugriff auf Geschäftsdaten, das Ausführen von Betriebssystemkommandos sowie das Lesen und Schreiben von Dateien auf dem Applikationsserver. Folglich ist ein Benutzer, der im produktiven System die Entwicklungsberechtigung hat, mit einem Notfalladministrator vergleichbar – er kann sich beliebige Rechte verschaffen. Es sollte also grundsätzlich niemand die Möglichkeit haben, direkt im Produktivsystem zu programmieren. Die Sprache bietet mehrere Möglichkeiten, Quellcode dynamisch zur Laufzeit zu generieren, zu kompilieren und auszuführen, ohne dass dazu eine spezielle Berechtigung notwendig wäre. Über das Kommando INSERT REPORT lässt sich beispielsweise ABAP-Code erstellen und ändern. Entwickler und Beratungshäuser nutzen die dynamische Programmierung gern, um generische, wiederverwendbare Programme zu schreiben oder um mit wenigen Zeilen Code komplexe Probleme zu lösen. iX 7/2011 © Copyright by Heise Zeitschriften Verlag ix.0711.118-122 09.06.2011 14:07 Uhr Seite 119 Gefährlich wird das, wenn es erlaubt ist, Benutzereingaben in den Quellcode einzufügen. Entwickler übersehen oft, dass ein Angreifer über geschickte Eingaben ebenfalls eigenen Quellcode ausführen kann. Um solche Lecks abzudichten, sollte man beim Entwickeln kundenspezifischer Anwendungen darauf achten, dass der Quellcode statisch bleibt und sich nicht zur Laufzeit manipulieren lässt. Directory Traversal Zahlreiche ABAP-Anwendungen verarbeiten Dateien unterschiedlicher Herkunft auf SAPs NetWeaver Application Server. Sie können das Ergebnis eines im Hintergrund ausgeführten Batch Jobs sein; es können Dokumente sein, die auf dem Server vorgehalten und zum Beispiel via SAP GUI geladen werden oder auch Attachments aus einer Onlinebewerbung. Eine Directory-Traversal-Schwachstelle liegt vor, wenn ein Angreifer durch Manipulation der Benutzereingabe auf eine nicht dafür vorgesehene Datei zugreifen kann. Von außen betrachtet sieht ein Angriff in der ABAP-Welt nicht anders aus als in anderen Programmiersprachen. Es gibt allerdings viele Möglichkeiten, sich gegen Attacken zu wappnen. Das Programm in Listingˇ1 ist anfällig für Directory-TraversalAngriffe. Der Benutzer muss einen Dateinamen angeben, der sich unterhalb des Verzeichnisses /tmp befindet. Sofern er die notwendige Berechtigung hat, wird anschließend der Dateiinhalt in der SAP GUI ausgegeben. Benutzt ein Angreifer eine relative Dateiangabe mit „../“, kann er auf Dateien in anderen Verzeichnissen zugreifen. In der Vergangenheit erlaubte ABAPs Kernel beispielsweise auch den Umgang mit den Zertifikatsdateien im Applikationsserver ohne eine zusätzliche administra- Direct UIs SAP GUI ABAP-System DB BSP ABAPCode Integrated ITS Web Dynpro ABAP Indirect UIs Files DB 3rd Party Java Applications JCO Files J2EE/Portal Web Dynpro Java Integrated ITS Direct UIs Die zahlreichen technischen Protokolle und Schnittstellen, über die ein ABAP-System mit der Außenwelt kommuniziert, bieten reichlich Angriffsfläche (Abb.ˇ1). tive Benutzerüberprüfung (siehe Kasten „SAP-Sicherheitshinweise“). Es gibt zwei Schutzansätze, die die Verantwortlichen kombinieren sollten: via Konfiguration sowie über das Programm. Zunächst zur Konfigurationsseite. Bei jedem Aufruf des Kommandos OPEN DATASET prüft der ABAP-Kernel zunächst automatisch das Berechtigungsobjekt S_DATASET. Es nimmt historisch bedingt nur 40 Zeichen auf, in der Regel fehlt dort der Platz, um eine Kombination aus vollständigem Pfad und Dateinamen abzulegen. Daher setzen Kunden häufig eine Wildcard ein, die sämtliche Dateien freigibt. Ein weiterer Berechtigungsschutz ist über die Tabelle SPTH möglich. Hier lassen sich unspezifisch für einzelne Verzeichnisse Lese- und Schreibberechtigungen einstellen oder global verbieten. In der Spalte FSBRGRU kann man zusätzlich eine Berechtigungsgruppe festlegen, die der Benutzer über das Objekt S_PATH zugewiesen bekommt. Via S_PATH lässt sich somit der Zugriff auf einzelne Verzeichnisse per Berechtigungskonfiguration steuern. BSP Integrated ITS Web Dynpro ABAP Der am einfachsten einzurichtende Schutz ist das Unterbinden oder die Kontrolle der Eingaben. Lässt man beispielsweise nur Dateien bestehend aus Buchstaben und Ziffern zu, erübrigt sich ein Angriff, da dafür benötigte Zeichen wie „.“ oder „/“ nicht erlaubt sind. Für die Fälle, in denen das nicht ausreicht, gibt es seit Dezember 2010 einen neuen zentralen Funktionsbaustein namens FILE_VALIDATE_NAME in der Funktionsgruppe SFIL. Zunächst muss der Administrator über die Transaktion FILE für physische Verzeichnisse sogenannte logische Namen vergeben. Er kann anschließend via FILE_ VALIDATE_NAME prüfen, ob ein vom Benutzer angegebener physischer Pfad innerhalb des logisch konfigurierten Pfades liegt. Hierzu normalisiert das Kommando die Eingabe, das heißt, es löst relative Pfade in absolute auf. Anschließend erfolgt die Berechtigungsprüfung. Um ein adäquates Schutzniveau zu erreichen, muss die Funktion vor OPEN DATASET aufgerufen werden. Wenn ein Fehler auftritt, bestimmt der Aufrufer, wie mit ihm umzugehen ist. Der alleinige Aufruf der Funktion Directory Traversal x-TRACT ● Jedes ABAP-System beherbergt zahllose selbst geschriebene Anwendungen, die potenziell anfällig sind für Standardangriffe wie Command Injection. ● Am besten schließt man die üblichen Sicherheitslücken schon beim Design des Programms aus. Später nach Fehlern zu fahnden, kann extrem aufwendig sein. ● Da ABAP eine komplexe Programmiersprache ist, und die sichere Programmierung hier noch in den Kinderschuhen steckt, dürften künftig noch etliche neue Schwachstellen aufgedeckt werden. REPORT ZFW_DIR_TRAV_EXMPL. DATA: content TYPE string, fileprefix TYPE string VALUE '/tmp/'. PARAMETERS: filename TYPE string LOWER CASE DEFAULT 'test'. CONCATENATE fileprefix filename into filename. OPEN DATASET filename FOR INPUT IN TEXT MODE ENCODING DEFAULT. DO. READ DATASET filename INTO content. WRITE: / content. IF sy-subrc <> 0. EXIT. ENDIF. ENDDO. CLOSE DATASET filename. 119 iX 7/2011 © Copyright by Heise Zeitschriften Verlag ix.0711.118-122 09.06.2011 14:07 Uhr Seite 120 SAP-Security PRAXIS PBO Berechtigung SAP GUI ! ! PAI DynproAblauflogik ABAP-Programm ABAP Klassische Kommunikation zwischen SAP GUI und ABAP-Server: Letzterer sendet Informationen über Aussehen und Funktionen des Dynpros an das GUI (Abb.ˇ2). ohne Behandlung des Rückgabewerts hat keinen Abbruch zur Folge und bietet somit auch keinen ausreichenden Schutz. Schwachstellen im SAP GUI Das SAP GUI ist die traditionelle grafische Benutzerschnittstelle, ein proprietärer Fat Client. Entwickler können in ABAP mit relativ wenig Aufwand Reports und Formulare erstellen (sogenannte Dynpros) und im GUI anzeigen. Abbildungˇ2 zeigt die klassische ClientServer-Kommunikation zwischen GUI und Server. Letzterer sendet Informationen über Aussehen und Funktionen des Dynpros an das GUI. Vor dem Senden wird das Ereignis Process Before Output (PBO) ausgeführt, in dem der Entwickler beispielsweise Knöpfe oder Felder ausgrauen oder unsichtbar ma- SAPSicherheitshinweise Wer diese Hinweise lesen will, muss Zugang zu SAPs Marktplatz haben (https:// service.sap.com/notes). Hinweisˇ1497104:ˇZugriff auf PSE-Dateien durch zusätzlichen AUTHORITYCHECK schützen Hinweisˇ1497003:ˇPotenzielle Directory Traversals in Anwendungen Hinweisˇ1520356:ˇSQL Injections vermeiden Hinweisˇ1487337:ˇEscaping für dynamische Programmierung CL_ABAP_DYN_ PRG Hinweisˇ1502272:ˇFunktionsbaustein zum Escaping von Quotes chen kann. Bestätigt der Benutzer seine Eingabe, werden die Daten zusammen mit dem sogenannten OK_CODE des Buttons an den Server übermittelt, der dann das Ereignis Process After Input (PAI) anstößt. Hier darf der Entwickler eigenen Code gemäß des übermittelten OK_CODE ausführen. Das Beispiel in Abbildungˇ3 ist einer realen Schwachstelle nachempfunden, die bei der Sicherheitsuntersuchung einer produktiven, eigenentwickelten ABAP-Anwendung gefunden wurde. Der erste Button ist mit dem OK_ CODE knopf1 verknüpft, der zweite mit dem OK_CODE knopf2. Der Programmierer möchte, dass nur Administratoren den zweiten Knopf benutzen dürfen, da er beispielsweise vertrauliche LogEinträge anzeigt. Eine Routine im PBO kontrolliert, ob der angemeldete Benutzer Administrationsrechte hat. Wenn nicht, erscheint der zweite Knopf in Grau, normale Anwender können ihn also nicht anklicken. Nicht bedacht hat der Entwickler jedoch, dass man in einer SAP-GUIAnwendung beliebige OK_CODEs an Dynpros senden kann. Gibt ein Benutzer ohne Administrationsrechte eine bestimmte Zeichenkette in das Transaktionsfeld ein (links oben in Abbildungˇ3), wird ein entsprechender OK_ CODE an das ABAP-Programm übergeben, obwohl sich der zweite Knopf nicht drücken lässt. Da das ABAPProgramm im PAI keine Berechtigungsprüfung durchführt, reagiert es so, als ob jemand den zweiten Knopf betätigt hätte – unabhängig davon, ob er sichtbar ist oder nicht. Es reicht demnach nicht, Berechtigungen nur im PBO eines Dynpros zu prüfen und entsprechende Elemente zu deaktivieren. Zwar lässt sich die Anwendung so besser bedienen, sicher ist sie dadurch jedoch nicht. Um zu garantieren, dass Benutzer nur erlaubte Aktionen ausführen können, muss eine weitere Berechtigungsprüfung im PAI stattfinden. SQL Injection SAP stellt eine eigene Datenbankschnittstelle namens Open SQL zur Verfügung. Spezielle SQL-ähnliche ABAP-Befehle gewähren datenbankunabhängig den Zugriff auf Tabellen im ABAP-Dictionary. Intern werden die Open-SQL-Anweisungen nahezu vollständig in Prepared Statements umgewandelt, bevor die eigentliche Anfra- 120 ge an die Datenbank startet. Daher verhält sich eine SQL Injection in ABAP nicht wie das klassische Pendant in anderen Programmiersprachen. Technisch korrekt handelt es sich um eine Prepared Statement Injection. Open SQL erlaubt die dynamische Angabe von Tabellen, Feldern und WHEREBedingungen über Klammern: REPORT ZSQLINJ. DATA: fields TYPE string. PARAMETERS: timezone TYPE string DEFAULT 'CET'. CONCATENATE `TZONE = '` timezone `'` — INTO fields. UPDATE USR02 SET (fields) WHERE bname = sy-uname. Das Programm liest aus dem SAP GUI die eingegebene Zeitzone aus und setzt eine neue für den angemeldeten Benutzer in der Benutzertabelle USR02 über den Open-SQL-Befehl UPDATE. Hier hat der Entwickler übersehen, dass ein Angreifer über die Variable timezone auch auf andere Felder zugreifen kann. Er nutzt dabei die Tatsache, dass sich über diese Variable nicht nur ein Wert für die Zeitzone übergeben lässt, sondern eine Liste von Feldname-WertTupeln, die in der Datenbanktabelle eingetragen werden. Der Angreifer kann somit nicht nur die Zeitzone ändern, sondern auch beliebige andere Felder. Rein technisch wäre auch eine klassische SQL Injection möglich. In der Praxis verwenden SAP-Anwender jedoch kaum natives SQL. Eingaben sorgfältig prüfen Den einfachsten Schutz bietet das vollständige Prüfen der Eingabe. Sind beispielsweise ausschließlich alphanumerische Zeichen erlaubt, ist zunächst kein Angriff möglich. Dieses als Eingabevalidierung bekannte Prinzip reicht jedoch nicht immer aus. Wenn der Benutzer Sonderzeichen eingeben darf, muss sie der Entwickler so behandeln, dass die Datenbank sie nicht als Teil des SQL-Kommandos interpretiert. Dieses Vorgehen nennt man Ausgabecodierung oder Escaping. Zu beachten ist, dass ABAP sowohl „`“ als auch „’“ für die String- beziehungsweise CharacterArray-Terminierung nutzt. Im Oktober 2010 hat SAP erstmalig eine Menge von Funktionen für unterschiedliche Releases bereitgestellt, mit deren Hilfe Entwickler Sonderzeichen in Benutzereingaben codieren können. In neueren SAP-Versionen hilft die iX 7/2011 © Copyright by Heise Zeitschriften Verlag ix.0711.118-122 09.06.2011 14:07 Uhr Seite 121 121 iX 7/2011 © Copyright by Heise Zeitschriften Verlag ix.0711.118-122 09.06.2011 14:07 Uhr Seite 122 SAP-Security PRAXIS Ein ausgegrauter Knopf kann bei falscher Programmierung trotzdem gedrückt werden, wenn der Benutzer eine bestimmten Zeichenfolge in das Eingabefeld einträgt (Abb.ˇ3). Klasse CL_ABAP_DYN_PRG, für solche kleiner als Version 6.20 existieren die Funktionsbausteine RS_ESCAPE_ QUOTES, RS_CHECK_VARIABLE und RS_CHECK_WHITELIST_TAB. Zu beachten ist, dass Escaping nur bei WHERE-Bedingungen und Feldern hilft. Wenn das System die Eingabe als Tabelle interpretiert (wie bei SELECTˇ*ˇFROM (table) INTO itab) muss die Validierungsroutine sicherstellen, dass ein Angreifer keine bösartigen Eingaben an die Datenbank senden kann. Entdecken von Sicherheitslücken Abschließend stellt sich die Frage, wie man kritische Stellen im Code aufspürt. Möchte man beispielsweise nach Command-Injection-Einfallstoren suchen, bietet sich die Transaktion SE80 an. Das geht folgendermaßen: Transaktion öffnen und zum gewünschten Programm navigieren. Dann auf das Fernglassymbol in der Symbolleiste klicken. Nun das gesuchte ABAP-Kommando eingeben (hier INSERT REPORT). Nach Anklicken des grünen Hakens wird das Suchergebnis angezeigt. Für jeden Treffer muss der Programmierer nun prüfen, ob der erste Parameter Benutzereingaben enthält. Dazu untersucht er den Datenfluss des betroffenen Parameters rückwärts und schaut, ob Eingaben in die Variable kopiert werden. Inhalte aus der Datenbank waren übrigens ursprünglich oft ebenfalls Benutzereingaben, die auch ein Angreifer über eine andere Anwendung eingefügt haben könnte. Wenn der Quellcode das Kommando INSERT REPORT enthält und der erste Parameter Benutzereingaben, dann hat man eine Schwachstelle gefunden, über die sich die Sicherheitsmechanismen des SAP-Servers mit hoher Wahrscheinlichkeit vollständig aushebeln lassen. INSERT REPORT ist ein selten genutzter Befehl, er dürfte wohl kaum mehr als ein paar Dutzend Mal auftauchen. Dennoch ist der Suchaufwand erheblich, da ein SAP-System üblicherweise Hunderte oder gar Tausende eigenentwickelte Programme enthält. Die Suche kann zwar über das Programm RS_ABAP_SOURCE_SCAN im Hintergrund laufen, der Datenfluss muss jedoch trotzdem analysiert werden. Wer im Quellcode nach DirectoryTraversal-Schwachstellen fahndet, dürfte feststellen, dass beispielsweise das ABAP-Kommando OPEN DATASET unter Umständen mehrere Hundert oder Tausend Male vorkommt. Ein manueller Audit ist also nicht durchführbar. SAP liefert den CodeInspector als freies Werkzeug aus, das sich über die Transaktion SCI aufrufen lässt und Quellcode auf Qualitäts-, Performanceund Sicherheitsschwachstellen abklopft. Zwar kann das Tool einen ganzen Namensraum nach bestimmten ABAPKommandos durchforsten, es ersetzt allerdings ebenfalls nicht die Datenflussanalyse und kann daher nicht herausfinden, ob Benutzereingaben in einem gefährlichen ABAP-Kommando verwendet werden. Der Aufwand, sämtliche OPEN-DATASET-Kommandos zu auditieren, ist somit kaum geringer als manuell über die Transaktion SE80. Bisher gibt es als Alternative nur das kommerzielle Werkzeug CodeProfiler, das große Mengen von ABAP-Quellcode nach Schwachstellen durchsucht und direkt ausnutzbare, das heißt mit Benutzereingaben erreichbare Stellen priorisiert. Damit reduziert sich die Anzahl potenzieller Lecks erfahrungsgemäß von Tausenden auf einige Dutzend, was eine manuelle Code-Prüfung zulässt. Früherkennung hilft am besten Selbstverständlich sollte man es erst gar nicht so weit kommen lassen und potenzielle Angriffspunkte schon bei der Entwicklung ausschließen. Dazu ist es sinnvoll, Sicherheitsanforderungen für die Anwendungen zu formulieren und daraus eine Entwicklungsrichtlinie abzuleiten. Zu beachten ist, dass SAP mehrere Programmier-Frameworks im Portfolio hat, die jeweils unterschiedliche Anforderungen an das sichere Entwickeln stellen. ABAP-Sicherheitsex- 122 perten schon in der Architekturphase einzuschalten, ist also keine schlechte Idee. Damit die Programmierer alles richtig umsetzen können, benötigen sie entsprechende Schulungen. Für externe Entwickler sollte das Einhalten der Richtlinie als Abnahmekriterium vertraglich festgehalten werden. Und ABAP-Sicherheitstrainings sind ein guter Qualifikationsnachweis. Dass alle Anwendungen, bevor sie in den Produktivbetrieb gehen, gründlich getestet werden müssen, versteht sich von selbst. Sichere Softwareentwicklung mit ABAP ist eine vergleichsweise junge Disziplin, andere Programmiersprachen sind in dieser Hinsicht weiter. In nächster Zeit dürften aufgrund der Komplexität der Sprache weitere Schwachstellenmuster und Angriffe bekannt werden. Sicherheitsanforderungen, Richtlinien und Tests müssen also immer auf dem neuesten Stand sein. (jd) SEBASTIAN SCHINZEL UND FREDERIK WEIDEMANN arbeiten als Berater bei der Virtual Forge GmbH in Heidelberg. ANDREAS WIEGENSTEIN UND DR. MARKUS SCHUMACHER sind Geschäftsführer der Virtual Forge GmbH. Literatur [1] Wiegenstein, Schumacher, Schinzel, Weidemann; Sichere ABAP-Programmierung; SAP Press 2009 Alle Links: www.ix.de/ix1107118 x iX 7/2011 © Copyright by Heise Zeitschriften Verlag