Wenn Sie öffentliche Verkehrsmittel benutzen, gehen Sie davon aus, dass der Zug an der Haltestelle hält, die Türen sich öffnen und schließen und, falls Sie den „Stopp“-Knopf im Bus drücken, dieser Sie tatsächlich an der nächsten Station aussteigen lässt. All dies funktioniert aufgrund von – oft unausgesprochenen – Vereinbarungen, von denen wir annehmen, dass sie von anderen oder von der Technologie, auf die wir uns verlassen, eingehalten werden. Was für Ihr Land gilt, muss aber nicht unbedingt auf der ganzen Welt gültig sein.
Während es höchstwahrscheinlich ein ziemliches Chaos verursachen würde, sich im Alltag nicht auf diese Vereinbarungen zu verlassen, oder uns zumindest sehr seltsame Blicke einbringen würde, wird mir aus der paranoiden Perspektive eines an Sicherheit interessierten Menschen immer öfter bewusst, wie fragil die alltäglichen Abläufe auf der Welt sind. Und wie einfach es auf der anderen Seite ist, viele kleinere Probleme zu beheben, wenn sich unsere Annahmen als falsch herausstellen.
Implizite Annahmen sind ein Problem
Aber natürlich können Annahmen auch missbraucht werden. Wie schon mehrfach von Fernsehreportern oder Sicherheitsforschern und -trainern bewiesen wurde, ist das Betreten eines gesicherten Bereichs oder die offene Entnahme von (persönlichen) Gegenständen viel einfacher, als man glaubt! Oft reicht es schon aus, Vertrauen zu vermitteln. Vielleicht unterstützt durch passende Kleidung, z.B. durch das Tragen einer Warnweste, wenn man in einen Baustellenbereich gehen will, oder auch nur durch einen Stapel mit einem erfundenen Firmennamen, während man einen Werkzeugkasten mit sich herumträgt, der die Vorstellung unterstützt, ein Techniker zu sein. Erst kürzlich habe ich einen Fernsehbericht gesehen, in dem eine Sekretärin in aller Freundlichkeit die Fahrstuhltüren offen hielt, damit der „Techniker“ nicht das schwere IT-Equipment die Treppe hinuntertragen oder auf die nächste Kabine warten musste ...
Was für das so genannte reale Leben gilt, trifft auch auf Software und die darin modellierten Prozesse zu. Beim Schreiben von Software entpuppen sich die impliziten Annahmen manchmal als ziemliches Problem: Nur weil es keinen Sinn macht, bei einer Überweisung eine ungültige Bankverbindung anzugeben oder einen Geburtstag in der Zukunft anzugeben, heißt das nicht, dass es niemand tun würde. Die interessanteste Frage ist nicht, warum das passieren könnte, sondern wie die Anwendung damit umgehen wird. Deshalb ist es wichtig, nicht nur zu testen, ob die Anwendung mit gültigen Daten arbeitet, sondern auch, dass sie sich auf eine definierte Weise beschwert, wenn sie die Eingaben nicht wie erwartet verarbeiten kann.
Während die beiden oben genannten Beispiele nur die Frage aufwerfen, wie die Benutzereingabe validiert werden soll – und wie sie gegebenenfalls zurückgewiesen werden kann –, sind andere, mit dem Arbeitsablauf zusammenhängende Probleme schwieriger zu testen und sind vielleicht nicht so offensichtlich.
Tückische Captchas
Werfen wir einen Blick auf ein sehr einfaches, aber gängiges Beispiel: Um Spammer davon abzuhalten, ein Kontaktformular zu missbrauchen, besteht der typische Ansatz heutzutage darin, ein Captcha hinzuzufügen. Während das aus der Sicherheitsperspektive per se kein Problem ist – wir reden hier nicht über Barrierefreiheit -, erfordert es einen Workflow, der implementiert werden muss: Der Captcha-Code muss generiert werden, ebenso wie seine verzerrte visuelle Darstellung, der Code muss in einer Session gespeichert werden und er muss verifiziert werden, wenn das Formular zurück an die Anwendung gesendet wird.
Auf den ersten Blick scheint es eine gute Idee zu sein, die Codegenerierung und die Bildausgabe in einer Datei zu kombinieren. Wann immer also die Webseite mit dem geschützten Formular geladen wird, wird das Captcha-Bild mit angezeigt. Das gilt aber nur so lange, bis Sie sich entscheiden, die Bilder im Browser zu deaktivieren. Jetzt wird das Formular angezeigt, ohne dass das Captcha-Bild angefordert wird, so dass wir am Ende keinen Captcha-Code in der Benutzersitzung haben. Nach dem Absenden und abhängig von der tatsächlichen Implementierung kann es passieren, dass ein nicht vorhandener Wert aus der Session mit einem leeren Wert aus dem Formular verglichen wird. Aufgrund der Typecasting-Natur von PHP, bei der ein NULL-Wert gleich leer wäre (es sei denn, es wird ein typsicherer Vergleich verwendet), könnte die Captcha-Prüfung umgangen werden, was die Annahme verletzt, dass ein Angreifer das Captcha tatsächlich lösen müsste, um das Formular erfolgreich abzuschicken.
In einer Welt der Annahmen kann es keine wirkliche Sicherheit geben. Wenn etwas für die Geschäftslogik Ihrer Anwendung entscheidend ist, verifizieren Sie es. Verwandeln Sie eine Annahme in Wissen. Oder akzeptieren Sie die Tatsache, dass es vielleicht nicht so ist, wie Sie angenommen haben, und handeln Sie entsprechend.