Skip to content

Websecurity - Logikfehler vermeiden

Das große Problem beim Vermeiden von Logikfehlern ist das gleiche wie bei der Suche danach: Es gibt so viele Möglichkeiten, einen Logikfehler in die Webanwendung ein zu bauen, dass es keine allgemeingültige Regel zu ihrer Vermeidung gibt. Oder vielleicht doch: Arbeiten Sie immer äußerst konzentriert und vorsichtig. Was das Problem mitunter aber auch nicht löst.

Einige Grundregeln

Es gibt einige "Good Practices", die das Entstehen von Logikfehlern zumindest erschweren. Und nebenbei auch noch das manch anderer Schwachstelle:

Dokumentieren Sie ausführlich

Zuallererst dokumentieren Sie jeden Aspekt des Designs der Webanwendung so ausführlich und eindeutig, dass auch ein Außenstehender ihn versteht. Achten Sie besonders darauf, dass alle Annahmen dokumentiert sind.

Kommentieren Sie auch den Sourcecode ausführlich und eindeutig. Die folgenden Informationen sind unbedingt notwendig:

  • Welchem Zweck dient der Code, und wie soll er verwendet werden?
  • Von welche Annahmen außerhalb der direkten Kontrolle des Codes wird ausgegangen?
  • Von welchen anderen Komponenten wird der Code verwendet?

Mal ein uraltes Beispiel aus meiner Studienzeit: Während eines Praktikums arbeiteten wir in zwei Gruppen an einem Modula-2-Programm. Beim Zusammenfügen beider Teile stürzte das Ergebnis ab. Die Ursache: Ein nicht initialisierter Pointer, mit dem der Code der zweiten Gruppe aufgerufen wurde.

Während die erste Gruppe davon ausging, die zweite würde den Pointer nach dem Aufruf ihres Codes initialisieren, ging die zweite davon aus, der Code würde mit einem bereits initialisierten Pointer aufgerufen. Und wenn man versucht, Daten in einen nicht initialisierten Pointer zu schreiben, bleibt dem Programm nichts anderes übrig als zu kapitulieren. Über die Initialisierung der Pointer war zwischen den Gruppen nie gesprochen worden. Die erste Gruppe hat die Pointer immer in den Prozeduren initialisiert, die zweite die Pointer immer initialisiert übergeben. Was innerhalb der jeweiligen Teile wunderbar funktionierte, wurde beim Zusammenfügen zum Problem.

Prüfen Sie Design und Code auf Logikfehler

Wenn Sie das Design auf Schwachstellen prüfen, achten Sie auch auf die dabei gemachten Annahmen. Unter welchen Umständen kann gegen diese Annahmen verstoßen werden? Kann ein Benutzer und damit ein potentieller Angreifer gezielt gegen eine Annahme verstoßen?

Beim Prüfen des Codes achten Sie vor allem auf zwei Punkte, um Logikfehler zu vermeiden:

  1. Wie geht der Code mit unerwarteten Benutzeraktionen und -eingaben um?
  2. Gibt es beim Zusammenspiel zwischen den verschiedenen Code-Komponenten und Funktionen mögliche Nebeneffekte? Was passiert, wenn eine Komponente einen Fehler auslöst oder unerwartete Ergebnisse liefert?

Vorsicht beim Verarbeiten der Requests!

Der Client bestimmt die Request-Reihenfolge

Denken Sie immer daran, dass ein Angreifer die Requests ganz nach Belieben manipulieren kann. Insbesondere kann er natürlich bei Skripten, die in einer bestimmten Reihenfolge aufgerufen werden sollen, diese Reihenfolge ändern oder Skripte ganz überspringen.

Nur weil zum Beispiel in einem Webshop erst der Warenkorb und danach das Skript zum Abschluss der Bestellung aufgerufen wird, muss deshalb noch lange nicht auch das normalerweise dazwischen liegende Skript zur Eingabe der Zahlungsart etc. aufgerufen worden sein.

Der Client bestimmt die Request-Inhalte

Außerdem können natürlich auch die Parameter nach Belieben manipuliert werden. Ein Angreifer kann eigentlich nicht vorhandene Parameter hinzufügen, vorhandene entfernen oder ändern oder auch die Art der Übertragung manipulieren. Betrachten wir für letzteres ein Beispiel in PHP:

function keineSQLInjection($eingabe) {
   // Prüft die Eingabe auf SQL-Injection-Code und liefert TRUE zurück,
   // wenn kein Angriff erkannt wurde.
   ...
}

function eintragen($wert) {
   // Trägt den Wert $wert in die Datenbank ein
   ...
}

...

if ( keineSQLInjection($_REQUEST["Parameter"]) ) {
   // Kein SQL-Injection-Code im Parameter
   ...
   eintragen($_GET["Parameter"]);
   ...
}

In PHP gibt es die globalen Variablen $_GET, $_POST und $_COOKIE für die GET-, POST- und Cookie-Parameter sowie $_REQUEST, in der der Reihe nach die GET-, POST- und Cookie-Parameter eingetragen werden (früher immer in dieser Reihenfolge, inzwischen kann die Reihenfolge auch konfiguriert werden). Dabei werden vorhandene Werte von danach eingetragenen Werten gleichen Namens überschrieben.

Betrachten wir nun das Beispiel und gehen mal davon aus, dass für $_REQUEST die alte Default-Reihenfolge gilt. Ein Angreifer überträgt nun als GET-Parameter Code für SQL-Injection und als POST-Parameter oder Cookie einen harmlosen Wert. Dieser harmlose Wert überschreibt in $_REQUEST den SQL-Injection-Code aus dem GET-Parameter, so dass keineSQLInjection($_REQUEST["Parameter"]) TRUE zurück liefert. In die Datenbank eingetragen wird jedoch der Wert aus dem GET-Parameter, so dass es zur SQL Injection kommt.

Dieses Beispiel sieht sehr konstruiert aus, und das ist es auch. Tatsächlich kommen solche Fehler aber immer wieder vor, ggf. auch in anderer Konstellation und natürlich nicht nur im Fall von SQL Injection.

Escapen Sie gründlich!

Wenn Sie Eingaben escapen, achten Sie darauf, auch das Escape-Zeichen selbst zu escapen (siehe Beispiel 6). Achten Sie bei der Abwehr von SQL-Injection-Angriffen auf Konsistenz: Nutzen Sie möglichst immer Prepared Statements mit parametriesierten Aufrufen, notfalls reicht auch das Escapen der Eingaben. Aber vermeiden Sie es, beide Verfahren zu mischen. Es besteht die Gefahr, dass SQL-Injection-Code in die Datenbank gelangt und bei der späteren Verwendung ausgeführt wird (SQL Injection 2. Ordnung).

Brauchen Sie negative Eingaben?

Wenn die Webanwendung mit Zahlenwerten arbeitet und daraus Entscheidungen ableitet, prüfen Sie alle Eingaben gründlich. Werden keine negativen Werte als Eingaben benötigt, akzeptieren Sie auch keine.

Vorsicht beim Aktualisieren von Session-Daten

Wenn Sie Session-Daten auf Grund von vom Benutzer gelieferten Daten aktualisieren, achten Sie auf mögliche Nebenwirkungen (siehe Beispiel 2). Mitunter gibt es Nebeneffekte in Funktionen, die mit der aktuellen Aufgabe überhaupt nichts zu tun haben.

Vorsicht bei der Authentifizierung und Autorisierung

Seien Sie bei der Implementierung der Authentifizierung besonders vorsichtig. Die Beispiele 1, 2 3 und 4 zeigen nur einige Möglichkeiten für Logikfehler.

Alle Entscheidungen über die Identität eines Benutzers und seine Autorisierung müssen immer auf Grundlage der Daten in der Session und auf dem Server getroffen werden. Verwenden Sie keinesfalls Daten aus dem Requests als Grundlage für eine Entscheidung. Insbesondere die Tatsache, dass ein Request überhaupt geschickt wurde, besagt rein gar nichts darüber aus, dass der Benutzer dazu befugt ist, ihn auch auszuführen.

Vorsicht beim Implementieren von Suchfunktionen

Wenn Sie eine Suchfunktion implementieren, die für verschiedene Benutzergruppen unterschiedliche Ergebnisse liefert, achten Sie darauf, dass Sie einem Benutzer nicht versehentlich etwas verraten, was er nicht wissen soll. Eine Fehlermeldung wie "Sie dürfen auf das Profil von James Bond nicht zugreifen. Bitte melden Sie sich mit den nötigen Rechten an!" verrät dem Benutzer zumindest schon mal, dass James Bond überhaupt ein Profil hat, es einen entsprechenden Benutzer also gibt.

Und damit ist das Thema "Logikfehler in Webanwendungen" auch beendet. Zumindest vorerst. Bis neue Entwicklungen eine Fortsetzung notwendig machen. Was früher oder später sicher der Fall sein wird.

Womit es in der nächsten Folge weiter geht, habe ich noch nicht entschieden.

Carsten Eilers


Übersicht über alle Artikel zum Thema

Neue Angriffe auf Webanwendungen über Clickjacking und Cookies
Websecurity - XSS-Angriffe über XML
Websecurity - Angriffe über Logikfehler
Websecurity - Angriffe über Logikfehler, Teil 2
Websecurity - Logikfehler in der Authentifizierung
Websecurity - Logikfehler in der Authentifizierung und auf der Flucht
Websecurity - Logikfehler finden
Websecurity - Logikfehler vermeiden

Trackbacks

Dipl.-Inform. Carsten Eilers am : Die IoT Top 10, #2: Unsichere Authentifizierung/Autorisierung, Teil 18

Vorschau anzeigen
Weiter geht es mit der Beschreibung der gefährlichsten Schwachstellen in den Geräten des IoT gemäß den Top IoT Vulnerabilities von OWASP. Zur Zeit sind wir beim Punkt 2: "Insufficient Authentication/Authorization". Die ve