Die Flagge des Marasek

Dekostreifen

English

Aktuell Texte Der Comic Impressum Kalender Suche PHP-Klassen Container-Wizard main.s21

Kategorien

Buch
Computer
Computerspiele
Film
Geschichte
Gesellschaft
Idee
Kunst
Natur
Persönlich
Politik
Programmieren
Religion & Philosophie
Weblog
Weltpolitik
Weltsicht
{{login}}

Signierte Querystrings

Permalink
Vorheriger: KriegsschädenNächster: Firefly
Eingeordnet in: Programmieren

Vielleicht ist jemandem der "checksum"-Parameter aufgefallen, der in der URL meiner Seiten vorkommt. Dies ist ein MD5-Hash, der aus dem Querystring und einem geheimen Schlüssel generiert wird. Dazu wird in einer Funktion erst mal http_build_query() aus einem Array ohne Prüfsummenparameter generiert; der resultierende Querystring wird mit dem Schlüssel verbunden, ein MD5-Hash erzeugt und dem Array hinzugefügt, um einen letztendlichen Querystring zu erzeugen.

Dazu gibt es eine Funktion, die einen beliebigen Array oder $_GET überprüft, in dem es den mitgelieferten Hash mit einem neu erzeugten vergleicht. Stimmen beide Werte überein, ist der Querystring zwischen zwei HTTP-Requests nicht von dritter Stelle (dem bösen Benutzer verändert worden).

Das Problem ist, dass die GET-Parameter zwar von meiner Seite erzeugt werden, aber immer über den Umweg der Nutzerseite wieder zu meiner Seite gelangen und daher prinzipiell offen für Manipulationen sind. Bei entsprechend unvorsichtiger Programmierweise, d. h. wenn die GET-Parameter ungeprüft verwendet werden, entstehen mitunter recht drastische Sicherheitslücken, die von böswilligen Benutzern ausgenutzt werden können.

Der MD5-Hash behebt das Problem. Alleine das Skript kennt den Schlüssel und kann daraus immer wieder den Hash berechnen. Da der Nutzer den Schlüssel nicht kennt, kann er die Parameter nicht verändern, ohne dass er auffliegt. Letztlich ist, solange der Schlüssel nicht in die Hände des Gegners fällt, die Signierung die sicherste Abwehr, die ich habe. Gehe ich davon aus, dass GET-Parameter ohnehin nur von meinem Skript erzeugt werden (beispielsweise aus vertrauenswürdigen, von mir erstellten Dokumenten aus der Datenbank), kann ich die Überprüfung der Parameter fast vergessen, da ich die Gültigkeit aller Parameter zu Beginn des Skripts überprüfen kann.

Angriffszenarien

Ein Angriffspunkt wäre eine Brute Force-Attacke gegen den Schlüssel. Bei einem entsprechend kurz und einfach gewählten Schlüssel (z. B. "hund") müsste der Angreifer nur den Querystring+verschiedene Zeichenkombinationen mit einem signierten String vergleichen, bis er eine passende Kombination hat. Da ich mir den Schlüssel aber nicht merken, sondern nur irgendwo im Skript speichern muss, kann ich mir einfach eine mir ausreichend lange Zeichenkette aus /dev/urandom holen. Eine Brute-Force-Attacke ist dann nicht mehr möglich bzw. es wird wohl kaum jemand ein Rechnernetzwerk mit der Aufgabe betrauen, die GET-Parameter eines xtklassigen Weblogs zu knacken.
Ein realistischeres Angriffsszenario ist es, die Kommunikation abzuhören oder den Webserver anzugreifen, um so an den im Skript oder ausserhalb (Datenbank, Dateisystem) gespeicherten Schlüssel zu kommen.
Doch wer die Resourcen hat, um diesen Angriff durchzuführen, hat es nicht nötig, an GET-Parametern herumzufummeln, da er dann sowieso Zugriff auf alles hat.

Fehlerquellen

Das Verfahren bietet erst mal den Vorteil, dass man theoretisch an einer Stelle die Gültigkeit der Parameter überprüfen kann. Praktisch mache ich das noch nicht, da Suchmaschinen mitunter veraltete oder gar keine Prüfsummen haben, und ich dann von Suchmaschinen kommende Nutzer mitunter unberechtigt ausschliessen würde. Dies ist etwas, was man im Hinterkopf behalten sollte; vor allem sollte man es vermeiden, variable Parameter in die Liste mit aufzunehmen, etwa IP-Adresse. Das kann aber an anderen Stellen wieder hilfreich sein, dazu später.
Eine sicherheitsrelevante Fehlerquelle ist, dass man das "Waschen" von Parametern vermeiden sollte. Angenommen, ich breche das Skript bei falschen Eingaben nicht hart ab und übergebe der Signaturfunktion einen Wert direkt aus $_GET, würde dieser mitunter manipulierte Wert signiert und in Folge als gültig anerkannt. Wenn der Wert dann mitgeschleift wird, könnte er an anderer Stelle Schaden anrichten.
Daher sollte man der Signaturfunktion nur aus dem Skript neu generierte Parameter und Werte übergeben!

Anwendungen

Bilder gegen Diebstahl sichern

Variable Parameter, wie oben erwähnt, kann ich mir dort zu Nutze machen, wo ich ein Programmbestandteil nur in einem bestimmten Kontext ausführen möchte. Meine Bilder sollen beispielsweise auf dieser Seite und nicht bei dem Bilderdieb angezeigt werden, der sie direkt mit <img src="http://www.hadanite... einbindet. Natürlich sind die Bilder nicht direkt aufrufbar, sondern nur über ein Skript, dass die Bilddaten ausgibt. Dort könnte ich z.B. den HTTP-Referer überprüfen und schauen, ob es meine Seite ist - was aber unzuverlässig ist. Session Management wäre auch eine Lösung. Konkret binde ich das Bildskript mit einem Zeitstempel als Parameter ein. Im Skript besteht ein gewisses Zeitfenster, d.h. Zeit, die zwischen dem Zeitpunkt des mitgelieferten Zeitstempels und einem vom Skript generierten Zeitstempel verstrichen ist; ist der Zeitstempel des Skriptes sehr viel weiter in der Zukunft, muss ich davon ausgehen, dass das Skript nicht mehr aus meiner Seite heraus aufgerufen wurde, die Auslieferung wird verweigert.

Formulare gegen Bots schützen

Eine andere Möglichkeit wäre, dass ein Benutzer die Kommentarfunktion oder das Feedback-Formular erst nach X Seitenaufrufen nutzen kann, als Hemmnis gegen direkt aufrufende Skripte.

Anmeldevalidierung per Email

Ein typisches Verfahren zur Validierung einer bei einer Anmeldung angegeben Email-Adresse ist es, dem Nutzer eine Nachricht zuzuschicken und ihn dort auf einen speziellen Link klicken zu lassen, der seine ID enthält.
Ungesichert könnte der Benutzer die IDs in der Datenbank abschätzen und sich selbst beliebig viele gültige Anmeldungen mit falscher E-Mail generieren, mit einer Signatur wird die Manipulation erheblich erschwert.

Kommentieren

Bitte beachten: Kommentare sind nicht sofort sichtbar, sondern werden erst nach einer kurzen Prüfung freigegeben, sofern keine rechtliche Beanstandung vorliegt.
Rechtlich bedenkliche Inhalte werden entweder entschärft oder nicht veröffentlicht.

* Titel  
* Nickname  
* Kommentar