zurück zur Übersicht

Sichere Verwendung von APIs

sql-injection2Wie in einem früheren Artikel bereits berichtet fand im Dezember der German OWASP-Day 2015 statt. Dort wurden diverse technische und konzeptionelle Themen präsentiert, die nicht nur die Sicherheit von Webapplikationen betreffen.

In diesem Artikel möchten wir uns angelehnt an den Vortrag von Christoph Kern dem Thema sicheres Coding widmen. In “Robuste und Praktikable Ansätze zur Verhinderung von Sicherheitsdefekten“ erläuterte er, wie man API-Funktionen auf sichere Weise verwendet.

 

In folgendem Beispiel betrachten wir ein leider häufig zu findendes Konstrukt, welches Applikationen für SQL-Injection-Angriffe anfällig macht. Der SQL-Query wird durch String-Concatenation generiert:

String sql = „select * from user where username='“ + username +“‚ and password='“ + password + „‚“;

Wirksamen Schutz gegen SQL-Injection-Angriffe bietet hingegen die Verwendung von sogenannten Prepared Statements, auch Parameterized Queries genannt. Der Befehl wird mit Platzhaltern für die zu übergebenden Parameter versehen und dann vorübersetzt, wodurch er nicht mehr verändert werden kann. Bei der Übergabe der Parameter erfolgt dann eine Gültigkeitsprüfung durch das Datenbanksystem:

String selectStatement = „SELECT * FROM User WHERE userId = ? „;
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();

Jedoch ist es bei der Verwendung von Parameterized Queries zwingend notwendig, dass diese auch korrekt eingesetzt werden. Das folgende Beispiel zeigt die falsche Verwendung. Der Parameter $strUserName wird direkt in das Prepared Statement eingebettet, statt ihn wie im vorherigen Beispiel durch Aufruf der Funktion prepStmt.setString() zu übergeben. SQL-Injection ist hier trotz Verwendung eines Prepared Statements möglich:

String strUserName = request.getParameter(„Txt_UserName“);
PreparedStatement prepStmt = con.prepareStatement(„SELECT * FROM user WHERE userId = ‚+strUserName+'“);

Wie kann man aber den Quellcode von Applikationen möglichst schnell, z.B. schon während der Kompilierung, überprüfen, um sicher zu stellen, dass sichere Programmiermethoden benutzt wurden? Es gibt einige hilfreiche APIs, die Sicherheitskontrollen als Bestandteil des Build-Prozesses integrieren. Google stellt z.B. die Error Prone JAVA APIs zur Verfügung. Sollten, wie im obigen Beispiel gezeigt, Prepared Statements nicht richtig verwendet werden, weil sich dynamische Werte in dem vorzubereitenden SQL-Befehl befinden, so wird während der Kompilierung eine Fehlermeldung erzeugt:

java/com/google/…/Queries.java:194: error: [CompileTimeConstant] Noncompile-time constant expression passed to parameter with@CompileTimeConstant type annotation.“WHERE userId = ‚+strUserName+'“);

Des Weiteren werden potenziell gefährlichen Funktionen wie executeQuery(String) beschränkt und ihre Ausführung nur in bestimmten Modulen erlaubt. Stattdessen wird mit sicheren Query-Buildern gearbeitet.

In einem zweiten Beispiel hat Christoph Kern auf Cross-Site-Scripting-Attacken (XSS) hingewiesen, die wir bei unseren Tests noch öfter sehen als SQL-Injections. Eine XSS-Attacke zu verhindern ist generell schwieriger als die Verhinderung von SQL-Injections. Man muss sich auf den Output statt Input konzentrieren und verschiedene Kontexte behandeln: HTML (Entities + Attribute), URLs und Scripts. Die Nutzung von Blacklists, Whitelists und eigenen Escapings ist nicht empfohlen, da dieser Ansatz nicht ausreichend ist und umgangen werden kann. Besser geeignet ist der Einsatz sogenannter kontext-sensitiver Templates, wo beispielsweise URL- und HTML-Entitäten unterschieden werden. In diesem Zusammenhang bietet Google das Javascript-Framework JS Conformance als Bestandteil des Closure Compiler-Paketes an. Hier besteht ebenfalls die Möglichkeit den Quellcode bei der Kompilierung auf Einhaltung bestimmter Anforderungen zu überprüfen. Durch anpassbare Richtlinien lässt sich zum Beispiel der Zugriff auf unsichere DOM-APIs (z.B. innerHTML, location.href) verbieten. Stattdessen wird auf sichere Alternativen verwiesen (z.B. Strict Template; goog.dom.safe.setInnerHtml(Element, SafeHtml), goog.dom.safe.setLocationHref(Location, string|SafeUrl)). Dieser Ansatz wird in komplexen Google-Anwendungen wie Gmail und G+ genutzt, wodurch die Anzahl der XSS-Sicherheitslücken laut Google drastisch reduziert werden konnte (30 in 2012 vgl. mit 0 seit September 2013).

Eine ganze Reihe weiterer Ansätze versucht Programmierer dabei zu unterstützen, ihre Anwendungen sicherer zu entwickeln. Die Go-Programmiersprache (Golang) implementiert beispielsweise automatisches Escaping. Der HTML-Kontext wird automatisch erkannt, ohne dass der Entwickler eine zusätzliche Erweiterung nutzen muss. OWASP bietet seit einiger Zeit eine kostenlose und offene Bibliothek, die OWASP Enterprise Security API (ESAPI) an, die Entwickler bei der Nachrüstung von Sicherheitsfunktionen in bestehenden Anwendungen unterstützen soll. Bei statischen Code-Analyse werden gefährliche APIs oder die falsche Verwendung von APIs erkannt. Einige Tools wie HP Fortify bieten sogar die Möglichkeit, Entwickler in Echtzeit zu warnen, falls gefährliche oder fehleranfällige Funktionen benutzt werden.

Abschließend kann man Christoph Kern nur zustimmen. Sicheres API-Design ist wichtig und muss primär vom Entwickler einer API umgesetzt werden. Nutzer einer API sollten dies allerdings zum Kriterium für die Auswahl einer API-Library machen.

Haben Sie Fragen zum Thema Code-Analyse und sichere Anwendungsentwicklung? Kontaktieren Sie uns!


Weiterführende Links:

https://www.owasp.org/index.php/Preventing_SQL_Injection_in_Java
https://www.owasp.org/index.php/German_OWASP_Day_2015/Programm
http://errorprone.info/
https://github.com/google/closure-compiler/wiki
https://github.com/google/closure-compiler/wiki/JS-Conformance-Framework
https://golang.org/
https://www.veracode.com/blog/2013/12/golangs-context-aware-html-templates
https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API

Bild: © iT-CUBE SYSTEMS AG 2015

 

Schreibe einen Kommentar