SQL Injection: Gezielte Maßnahmen statt Block Lists

Seite 3: Bessere Alternative

Inhaltsverzeichnis

Schnell zeigt sich, dass Block Lists ein Fass ohne Boden sind. Eine vermeintlich einfache Lösung entpuppt sich oft als komplexes Gebilde, das schwer zu warten ist und unübersichtlich wird.

Sollte man daran festhalten, ist schwer einschätzbar, ob man nicht etwas vergessen oder übersehen hat und damit das Tor für eine gefährliche Sicherheitslücke offen ist.

Daher empfiehlt es sich, Schutzmaßnahmen in folgender Reihenfolge zu erwägen – auch, aber nicht nur gegen SQL Injection:

  1. Härtetests der genutzten Umgebung und Verwenden der dort mitgegebenen Befehle, die Schutzvorkehrungen treffen
  2. Coding Vorgaben, Reviews und Schulungen und
  3. Bereinigen der Eingaben, auf die Werte die tatsächlich gefragt sind.

Speziell zum Sichern gegen SQL Injection helfen

  1. Der Einsatz von Prepared Statements, wo sie möglich sind und
  2. Allow Lists (ehemals Whitelists) in Ausnahmefällen.

Details dazu finden sich im OWASP SQL Injection Prevention Cheat Sheet und unter How to prevent SQL Injection - Portswigger.

Zunächst sollten Teams analysieren, in welchem Umfeld sich die Entwicklung befindet: Was kann die oberste Schicht? Hält das eingesetzte Framework beziehungsweise die Programmiersprache ausgewählten Härtetests stand? Dazu gehört ein Blick auf die Anzahl der regelmäßigen Contributors, GitHub-Stars, Menge an CVEs und Pressemeldungen über einen bestimmten Zeitraum, um die Reife des Projekts zu bewerten. Unter anderem bietet sich der Open Hub von Synopsys als Recherchequelle zu Open-Source-Projekten an. Je nach Ergebnis stellt sich die Frage, ob ein Wechsel des Frameworks in Betracht zu ziehen ist.

Die Recherchen sollten möglichst früh im Projektverlauf erfolgen und der Einsatz der Tools im Anschluss regelmäßig beispielsweise durch Pentests wieder auf den Prüfstand gebracht werden. Aus Security-Sicht sollte der Blick darauf gerichtet sein, welche Sicherheitsfunktionen ein Framework an Bordmitteln mitbringt. Konkret bietet das für die Beispielanwendung genutzte Spring-Framework Funktionen zum Erzeugen von JPA-Queries (Java Persistence API).

Optional<User> optional = userRepository.findById(id);

Selbst wenn eine sichere Umgebung nun zur Option steht, kann es sein, dass der Entwickler oder die Entwicklerin aus sicherem Code ausbrechen. Das passiert gerade am Anfang der Karriere, eventuell weil keine anderen Vorgehensweisen bekannt sind – in diesem Falle etwa durch Zusammensetzen einer unsicheren SQL Query. Hier helfen Coding-Vorgaben, Reviews und Schulungen, um die jeweilige Person an die Hand zu nehmen und gleichzeitig die Codequalität zu heben.

Allgemein hilft gegen viele Sicherheitslücken in Webanwendungen, nur die Eingaben zu erlauben, die tatsächlich von ihrer Bedeutung passen. Wenn beispielsweise für eine ID etwas anderes als ein ganzzahliger positiver Wert auftaucht, sollte die Anwendung die Eingabe mit einem Fehler quittieren.

Als Faustregel gilt: Zum Vermeiden von SQL Injection ist der Einsatz von Prepared Statements immer das erste und beste Mittel der Wahl.

In der Demoanwendung sieht das beispielsweise über Java Persistence Query Language (JPQL) folgendermaßen aus:

String jpql = "select username from User where id = :id";
  TypedQuery<String> q = 
    em.createQuery(jpql, String.class).
    setParameter("id",Integer.parseInt(id));
return q.getResultList().get(0);

Prepared Statements lassen sich jedoch nicht in allen Teilen einer Query nutzen, sondern nur dort, wo Daten erscheinen, inklusive der WHERE-Klausel und Werten in einem INSERT- oder UPDATE-Statement. Bereiche wie Spalten- und Tabellennamen oder die ORDER BY-Klausel sind ausgenommen.

In einem solchen Fall bietet es sich an die Logik zu überdenken oder auf Allow Lists zurückzugreifen. Eine Allow List definiert im Gegensatz zu einer Block List Eingaben, die erlaubt sind, und verwirft alles andere. Da Spalten- und Tabellennamen in der Regel bekannt sind, bieten sich Enums an. Damit schrumpft der Bereich der zusammengesetzten Strings zu einem festen Set.

Als Ergänzung gibt es noch weitere Schritte, die einsetzbar sind: Stored Procedures erlauben es, Datenbankcode zu kapseln und dadurch weniger Einblick zu geben. Allerdings sind dabei erneut Prepared Statements das Mittel der Wahl. Zudem ist ein Zugriff auf die Datenbank und Expertise in dem Bereich unabdingbar. Beispielsweise führen manche Datenbanken den Code mit Erstellerrechten aus – ähnlich einem suid-Bit in Unix-Systemen –, was bei einem Ausbruch dazu führt, dass Angreifer direkt DB-Administratorenrechte haben könnten.

Ein Datenbank-Administrator sollte die Accounts auf ihre jeweiligen Rollen mit Befehlen und Rechten einschränken, sodass in einem bestimmten Kontext nur das wirklich Notwendige erlaubt ist. Das verringert den Spielraum für potenzielle Angriffe.

Die Entwicklung kann eine zweite Verteidigungslinie für den Fall aufziehen, dass ein Angriff die erste Schutzmaßnahme umgeht. Beispielsweise bietet es sich an, zusätzlich zu Prepared Statements auf Allow Listing zu setzen.

Zumindest erwähnt sei noch die Option, alle Zeichen der Nutzereingabe zu escapen: Immer wenn eine Escape-Sequenz auf ein Zeichen möglich ist, kommt sie zum Einsatz. Der Autor rät grundsätzlich davon ab, denn das Vorgehen entschärft zwar den Eingabestring, ist aber durchaus fehleranfällig. Daher ist es nur eine Notlösung zur kurzeitigen Absicherung, wenn sich die zuvor genannten Methoden nicht umsetzen lassen.

Leider bleiben SQL Injection ein Gefahr für Webanwendungen. Viele Maßnahmen helfen nur oberflächlich und lassen sich durch geschickte Gegenmaßnahmen aushebeln. Block Lists stellen ein Fass ohne Boden dar, das regelmäßiges Flicken der Lücken erfordert.

Die sicherste Methode zum Absichern von Webanwendungen ist der Einsatz von Prepared Statements. Wer zusätzliche Sicherheit sucht, ist mit Allow Lists gut beraten.

Matthias Altmann
ist Softwareentwickler und IT-Security-Experte bei der Micromata GmbH, wo er gemeinsam mit seinen Kollegen den Bereich IT-Sicherheit betreut und fortentwickelt. Er ist außerdem Mitbegründer und Organisator des IT-Security-Meetups Kassel, einem Netzwerk von IT-Security-Enthusiasten, die sich dem fachlichen Austausch zum Thema verschrieben haben.

(rme)