Webapplikationen mit Unterstützung von XML 
Navigation:Inhalt ->
3 Webapplikationen ->
3.4 Webapplikationen im Detail
Neues und Änderungen
<< Vorheriges Kapitel | Nächstes Kapitel >>

3.4 Webapplikationen im Detail

3.4.1 Allgemeines
3.4.2 Datenübertragung zwischen Client und Server
3.4.3 Daten Push
3.4.4 HTML-Formulare
3.4.5 Benutzerauthentifizierung
3.4.6 Autorisation
3.4.7 Statusloses HTTP
3.4.8 Sitzungsmanagement

3.4.1 Allgemeines

Webapplikationen unterscheiden sich in einigen Punkten sehr deutlich von herkömmlichen Computeranwendungen, die nicht im Browser, sondern auf der (grafischen) Benutzeroberfläche eines Betriebssystems laufen. Im Folgenden wird auf die Besonderheiten von Webapplikationen eingegangen.



3.4.2 Datenübertragung zwischen Client und Server

Der Webbrowser kommuniziert mit dem Webserver über HTTP. Dieses Protokoll baut wiederum auf TCP/IP und verwendet üblicherweise den TCP-Port 80. HTTP stellt einige Methoden zur Verfügung, mit Hilfe derer der Webbrowser Daten an den Webserver senden kann bzw. von diesem erhält [Fielding 1999]:

Die wichtigsten Methoden sind GET und POST. Eine GET-Anfrage sendet der Webbrowser, wenn er eine bestimmte Webseite (bzw. eine beliebige Datei: Bild, Textdatei, PDF-Datei, etc.) vom Server erhalten will. Eine POST-Anfrage wird üblicherweise an den Server gesendet, wenn Daten aus einem Formular an den Server übermittelt werden sollen. Dabei werden die Formulardaten direkt bei der POST-Anfrage mitgesendet. Diese können dann vom Programm, das am Server die gewünschte Webseite erzeugt41, verarbeitet werden. Bis zu einer gewissen Größe der Daten können sie allerdings auch mit einer GET-Anfrage als Teil der URL an den Server übermittelt werden.

Dieser Teil der URL wird Query-String genannt. Der Query-String wird von der Ressourcen-Angabe innerhalb der URL durch ein Fragezeichen ("?") getrennt. Die einzelnen Parameter innerhalb des Query-Strings werden durch das kaufmännische Und ('&', engl: Ampersand) getrennt.

Der Query-String wird aber nicht nur verwendet, wenn ein Formular mittels GET abgesendet wird und dabei der Browser den Query-String generiert. Er kann auch direkt im HTML-Quelltext bei URLs (Links, Bild-Quellen, ...) angegeben werden. Ein Programm am Server, das eine bestimmte Webseite generiert, kann daher auch den Query-String in den URLs beeinflussen.

Zu beachten ist dabei, dass das '&'-Zeichen nicht nur im normalen Text einer HTML-Seite, sondern auch in der URL mit dem Ausdruck '&amp;' quotiert werden muss. (Siehe: [W3C-Validator 2002].) Das Fragezeichen, das den Query-String einleitet, bleibt dagegen unqotiert. In die Adresszeile des Browsers muss auch das '&'-Zeichen unquotiert eingegeben werden.

http://www.domain.com/

http://www.domain.com/?id=2&amp;page=3
Beispiel 17: Beispiele von URLs mit und ohne Query-Strings, wie sie im Quelltext einer HTML-Seite angegeben werden müssen.

Im Query-String müssen aber nicht nur das '&'-Zeichen quotiert werden, sondern alle Sonderzeichen. Dies kann üblicherweise einfach mit eigenen Funktionen der Webprogrammiersprachen (PHP, ASP, JSP, etc.) erreicht werden.42

Wie man leicht erkennen kann, werden im Web die Daten (als Webseiten, bzw. in Webseiten verpackt) hauptsächlich vom Server zum Webbrowser übertragen. Der Browser sendet an den Server meist nur die Information, welche Seite der Server als nächstes an den Browser zurücksenden soll. Müssen zusätzliche Informationen vom Browser an den Server gesendet werden, so können diese einerseits im Query-String, andererseits bei Formularen auch mit einer POST-Anfrage gesendet werden.

Formulardaten sind Daten, die vom Benutzer selbst eingegeben wurden. Daten im Query-String werden nicht vom Benutzer eingegeben, sondern schon beim Generieren einer Seite vorgegeben. Somit werden diese Daten zuerst vom Webserver zum Webbrowser gesendet. Der Benutzer kann dann einen Link auswählen und somit werden bestimmte Daten wieder zurück an den Server gesendet. Bei der Generierung der nächsten Seite, können diese Daten dann weiterverwendet werden.

Ein Beispiel: Auf einer Produktübersichtseite befinden sich Links zu den einzelnen Produkten. Diese haben folgende Form: product.php?id=1, product.php?id=2, usw. Klickt der Benutzer auf einen solchen Link, wird die Seite product.php aufgerufen. Das Programm, das für deren Generierung zuständig ist, kann die Variable 'id' aus dem Query-String herauslesen, Informationen zum entsprechenden Produkt aus der Datenbank laden und diese auf der Webseite ausgeben.

Die Webprogrammiersprachen bieten Funktionen bzw. meist assoziative Arrays an, mit Hilfe derer man auf die Daten im Query-String, bzw. auf die Daten, die via Formular per POST gesendet wurden, sehr einfach zugreifen kann.

Server-Variablen

Der Webbrowser sendet bei jeder Anfrage (GET, POST) zusätzliche Informationen mit. Diese können von den Programmen, die am Server laufen, um die angeforderten Seiten zu erzeugen, ausgewertet werden. Die interessanten Variablen sind:

Es gibt eine Menge weiterer Variablen, auf die Programme am Server zugreifen können, die aber entweder für die Programmierung weniger wichtig sind oder nicht vom Client, sondern vom Server kommen. Die Variablen werden meist als Servervariablen oder Umgebungsvariablen (engl.: Environment variables) bezeichnet.43

Nachladen von Daten

Ein Problem bei der Kommunikation zwischen Server und Client ist, dass die Daten vom Server nur immer als komplette Webseiten an den Webbrowser übertragen werden können. Die Webseiten können unter Umständen sehr groß werden, sodass ein neuer Übertragungsvorgang einige Zeit in Anspruch nehmen kann. Angenommen, es sollte innerhalb eines größeren, hierarchischen Verzeichnisses eine bestimmte Kategorie ausgewählt werden. Bei einer herkömmlichen Anwendung könnte man folgendermaßen vorgehen: Zuerst können nur die Kategorien der ersten Stufe ausgewählt werden. Hat der Benutzer dies getan, werden deren Unterkategorien geladen und können im nächsten Schritt ausgewählt werden. Dies wiederholt sich solange, bis der Benutzer zur gewünschten Unterkartegorie gelangt ist.

Bei einer Webapplikation ist es nicht möglich, nur die Nutzdaten (hier Kategorien) zu übertragen. Bis zu einer gewissen Größe des Verzeichnisses wäre es möglich, das gesamte Verzeichnis in die Webseite zu verpacken und die hierarchische Auswahl mit Javascript zu ermöglichen. Ist das Verzeichnis zu groß, kann nur so vorgegangen werden, dass bei jeder Auswahl eine neue Webseite mit der ausgewählten (Unter-)Kategorie geladen wird. Je nach Geschwindigkeit der Netzverbindung kann das um einiges langsamer sein.

Als Ausweg könnte auch der Einsatz von Frames oder IFrames44 erwogen werden. In diesen Frames kann dann eine ganz einfache Webseite nur als Rahmen für die gewünschten Daten fungieren. Diese Webseiten sind daher klein und können schneller geladen werden. Es kann dann allerdings zu relativ komplexen Konstruktionen auch mit Javascript kommen. Dabei ist die Kompatibilität mit allen Browsern genau zu untersuchen.



3.4.3 Daten Push

Wenn Daten zwischen Webbrowser und Webserver übertragen werden, passiert das immer auf Anfrage des Browsers. Er fragt beim Server an, um die Daten zu erhalten (pull, engl. für ziehen). Was ist aber, wenn die Anwendung, die am Server läuft, dem Benutzer etwas mitteilen will. Ein Beispiel wäre ein Nachrichtensystem (oft auch Ticket-System genannt). D.h., ein Benutzer kann anderen Benutzern Nachrichten senden, oder bei kritischen Systemzuständen kann die Anwendung von sich aus bestimmte Benutzer benachrichtigen. Dazu sollte aber die Anwendung selbst in der Lage sein, den Benutzer zu informieren. Der Server sollte also von sich aus etwas an den Browser senden (push, engl. für stoßen).

Solange der Benutzer ständig mit der Anwendung arbeitet, und laufend neue Webseiten abruft, ist das kein allzu großes Problem. Jedes Mal, wenn eine Seite generiert wird, prüft das Programm (in der Datenbank), ob eine Nachricht für den Benutzer vorliegt, und weist dann in einem bestimmten Bereich der Webseite den Benutzer darauf hin. Was ist allerdings, wenn der Benutzer gerade nicht aktiv die Webapplikation benutzt, also laufend neue Webseiten vom Server abruft?

Frames und automatisches Aktualisieren

Eine Möglichkeit wäre, auf der Webseite Frames zu verwenden und in einem kleinen Bereich eine kleine Webseite zu laden. Diese Webseite wird mit dem "Meta-Refresh"-Tag im Kopf (HTML-Header) ständig neu geladen. Mit folgendem HTML-Code kann erreicht werden, dass alle 60 Sekunden die Seite 'checkformsg.php' aktualisiert wird.

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <title>Text des Titels</title>
 <meta http-equiv="Refresh" content="60;url=checkformsg.php" />
</head>
<body>
 ...
</body>
</html>
Beispiel 18: XHTML-Quelltext einer Webseite, die alle 60 Sekunden automatisch neu geladen wird.

Das Programm, das diese Seite generiert, prüft, ob eine Nachricht vorliegt und präsentiert diese gegebenenfalls in geeigneter Weise auf der Webseite. Bei wichtigen Nachrichten könnte durchaus auch ein Popup-Fenster erscheinen oder ein kurzer Signalton abgespielt werden.

Ein Problem an dieser Methode ist, dass ständig abgefragt wird (engl. Fachbegriff: Polling). Bei vielen Clients werden dabei das Netzwerk und der Server zusätzlich belastet. Das nächste Problem ist, dass die Benachrichtigung nicht in Echtzeit erfolgt, sondern nur in gewissen Abständen. Je kürzer die Abstände zwischen dem neuen Laden der Seite, desto schneller die Benachrichtigung, aber desto größer die Belastung für den Server.

Das größere Problem an dem Verfahren ist allerdings, dass es leicht ausfallen kann. Sobald nämlich einmal ein Problem mit der Verbindung zum Server oder mit dem Server selbst (z.B. Überlastung) besteht, kann die Seite nicht geladen werden und der Kreis des ständigen neuen Ladens wird unterbrochen.

Externer Benachrichtigungsdienst

Wenn die Benutzer nicht nur mit der Webapplikation alleine arbeiten, sondern z.B. auch mit E-Mail oder mit einem so genannten Instant-Messaging-Programm (ICQ www.icq.com, AIM www.aim.com, MSN Messenger messenger.msn.at, etc.), können diese verwendet werden, um den Benutzer auf neue Nachrichten und Ähnliches hinzuweisen.

Angenommen es trifft eine Nachricht für einen Benutzer ein, so kann eine E-Mail an diesen Benutzer gesendet werden, entweder mit dem Inhalt der Nachricht, oder mit einem Link, wo er die Nachricht findet. Klickt der Benutzer auf diesen Link, gelangt er auf die entsprechende Seite mit der Nachricht und kann dort weiterarbeiten.

E-Mails werden aber oft ebenfalls nicht in Echtzeit versendet bzw. nicht ständig abgefragt. Falls es schneller gehen sollte, kann man den Einsatz eines Instant-Messaging-Programms erwägen. Sie bieten üblicherweise ein API mit Hilfe dessen man automatisiert Nachrichten versenden kann.

Der Vorteil dieser Methode ist, dass nicht ständig auf neue Nachrichten abgefragt werden muss, sondern beim Eintreffen einer neuen Nachricht nur einmal eine E-Mail oder eine Nachricht für ein Instant-Messaging-Programm versendet werden muss. Nachteilig ist, dass ein zusätzliches Programm vorausgesetzt wird. Je nach verwendetem Programm kann es nötig sein, sich auf ein bestimmtes Betriebssystem festzulegen.



3.4.4 HTML-Formulare

HTML-Formulare erlauben es, dem Benutzer Daten einzugeben und diese dann an den Webserver zu senden. Programme, die dort laufen, können die Daten weiterverarbeiten. Die Steuerelemente innerhalb der HTML-Formulare sind: Einzeilige und mehrzeilige Textfelder, einzeilige und mehrzeilige Auswahlelemente, Radiobuttons, Checkboxen und Klickbuttons. Im XHTML-Quelltext sehen HTML-Formulare beispielsweise folgendermaßen aus:

<form name="example" action="processform.php" method="post">
 Einzeiliges Textfeld:<br />
 <input name="firstname" type="text" size="20" maxlength="30" 
        value="Peter" />
 <br /><br />
 Mehrzeiliges Textfeld:<br />
 <textarea name="biography" cols="50" rows="10" wrap="virtual">
  Geboren 1970...
 </textarea>
 <br /><br />
 Drop-Down Auswahlbox (einzeilig):<br />
 <select name="country">
  <option value="AUT" selected="selected">&Ouml;sterreich</option>
  <option value="GER">Deutschland</option>
 </select>
 <br /><br />
 Radiobuttons:<br />
 <input type="radio" name="gender" value="female">Weiblich<br />
 <input type="radio" name="gender" value="male" 
        selected="selected">M&auml;nnlich<br />
 <br /><br />
 Checkboxen:<br /> 
 <input type="checkbox" name="kids" value="yes">Kinder<br />
 <input type="hidden" name="userid" value="123456" />
 <br /><br />
 Button zum Absenden:<br /> 
 <input type="submit" value="Absenden" />
</form>
Beispiel 19: XHTML-Formular mit Formularelementen.
45

Innerhalb des Form-Tags können nicht nur Formularelemente enthalten sein, sondern annähernd beliebige andere HTML-Elemente. Dadurch können die Formularelemente mit HTML-Elementen positioniert werden. Z.B. mit Tabellen.

Formularelemente haben üblicherweise einen Namen (Attribut: "name"). Über den Namen können die Programme, die die Formulardaten erhalten, entscheiden, von welchem Feld die Daten kommen. Auch Javascriptprogramme nutzen die Namen zum Zugriff auf die Elemente. Zusätzlich haben sie meist einen Wert (Attribut: "value"). Hier steht der Inhalt des Feldes oder der Wert des gerade selektierten Eintrags. Alle Formularelemente können mit CSS-Angaben formatiert werden (Größe, Farbe, Schriftart, etc.).

Textfelder

Sie dienen zur Eingabe von Text. Sie können sowohl einzeilig oder auch mehrzeilig sein. Sie können mit einem Text vorbelegt werden. Besondere Textfelder dienen zur Eingabe von Passwörtern. Es gibt auch Nur-Lese-Textfelder (Read only).

Auswahlfelder

Auswahlfelder können einzeilig sein, dann erfolgt die Auswahl per so genannter "Dropdownliste". Sind sie mehrzeilig, können sie auch so definiert werden, dass mehr als ein Eintrag ausgewählt werden kann. Einträge können dabei vorselektiert werden.

Radiobuttons

Sie dienen dazu, eine von mehreren Optionen auszuwählen. Sie haben dabei dieselbe Funktionalität wie Auswahlfelder mit einer Selektierungsmöglichkeit. Eine Option einer Auswahlgruppe sollte immer vorselektiert sein. Ansonsten kann es passieren, dass ein Formular abgesendet wird, ohne dass eine Option ausgewählt wurde.

Checkboxen

Checkboxen sind Ja/Nein-Felder (angekreuzt/leer). Sind mehrere Checkboxen vorhanden, können beliebig viele angekreuzt sein. Sie entsprechen dann mehrzeiligen Auswahlboxen mit mehreren Selektierungsmöglichkeiten.

Versteckte Felder

HTML-Formulare können nicht nur die sichtbaren Elemente, wie Textfelder Auswahlboxen, Radiobuttons, Checkboxen und Klickbuttons haben, sondern auch versteckte Felder (engl.: Hidden fields). Diese Formularelemente haben - wie alle Formularelemente - einen Namen, dem ein Wert zugewiesen wird. Der Wert wird üblicherweise schon bei der Generierung des Quelltextes für das Formular am Server gesetzt. Er könnte aber auch - wie bei anderen Elementen auch - mit Hilfe von Javascript am Webbrowser verändert werden.

Ganz verstecken lassen sich aber auch versteckte Felder nicht. Da der Wert des Feldes üblicherweise bei Generierung der Seite gesetzt wird, ist er im HTML-Quelltext enthalten. Sieht man sich den Quelltext im Browser an, so kann man auch den Wert des versteckten Feldes erkennen.

Formulardesign

Formulare sind die primäre Schnittstelle zwischen Benutzer und der Webapplikation. Es ist daher besonders wichtig, Formulare effizient und übersichtlich zu gestalten.

Der durchschnittliche Besucher wird Anwendungen im Internet hauptsächlich mit der Maus bedienen. Es ist also hauptsächlich auf einen übersichtlichen und selbsterklärenden Aufbau zu achten.

Für so genannte "Power-User" gelten aber zusätzliche Kriterien. Die Anwendung sollte schnell und effizient bedient werden. Das setzt auch eine Tastaturunterstützung voraus. Die wichtigste Taste dabei ist die Tabulatortaste. Mit ihr kann von Formularelement zu Formularelement navigiert werden. Allerdings ist die Reihenfolge bestimmt durch die Reihenfolge im Quelltext. Außerdem werden auch normale Links mit der Tabulatortaste angesprungen. Dabei kann sich vor allem bei der Verwendung von Tabellen für die Positionierung der Formularelemente eine unlogische Aktivierungsreihenfolge ergeben.

Ein Beispiel: Bei einem Anmelde-Formular sollte zuerst der Benutzername, dann das Passwort und zuletzt der Absende-Button aktiviert werden, wenn man mit der Tabulatortaste von Element zu Element wechselt. Man sieht aber immer wieder Anmelde-Formulare, wo sich links oben das Feld für den Benutzernamen befindet, rechts daneben der Anmelde-Button und links unten das Passwort-Feld. Gibt man den Benutzernamen ein und drückt die Tabulatortaste, so wird der Anmelde-Button aktiv. Erst durch ein zweites Drücken der Tabulatortaste kommt man zum Passwort-Feld. Oft sind auch normale Text-Links zwischen Formularelementen zu finden, die den Bearbeitungsfluss stören.

Falls es sich nicht vermeiden lässt, die Formulare so aufzubauen, dass die Reihenfolge der Elemente automatisch intuitiv ist, kann die Tabulator-Reihenfolge explizit bestimmt werden. Formularelemente können dazu mit dem Attribut "tabindex" versehen werden.

Zusätzlich können Formularelementen Tastenkürzel (engl.: Hot keys) zugewiesen werden. Dadurch kann man mit der "Alt"-Taste und dem Tastenkürzel zu den entsprechenden Formularelementen springen.46 Das benötigte Attribut heißt "accesskey".



3.4.5 Benutzerauthentifizierung

Bei einer Webapplikation muss üblicherweise zuerst der Benutzer authentifiziert werden. Der Webserver muss wissen, an welchen Benutzer er eine bestimmte Seite sendet, damit er sie entsprechend generieren kann. Unterschiedliche Benutzer haben eventuell unterschiedliche Rechte, die festlegen, welche Aktionen durchgeführt werden dürfen und welche nicht.

Die Authentifizierung erfolgt bei Webapplikationen fast ausschließlich mit einer Benutzerkennung und zugehörigem Passwort. Biometrische Authentifizierungsverfahren, wie Fingerabdruckssensoren, Irisscanner, Gesichtserkennungsprogramme etc. stecken noch in den Kinderschuhen und können meist leicht umgangen werden. [Thalheim 2002]

Die Benutzerkennung kann eine Kundennummer, der Name des Benutzers, ein Kürzel, die E-Mail-Adresse oder eine vom Benutzer beliebig gewählte Kennung sein. Bei Anwendungen im Web, ist die letzte Möglichkeit mit relativ großem Freiraum in der Wahl der Kennung vorzuziehen, damit die Benutzer eine wählen können, die sie auch bereits bei anderen Webseiten verwenden. Kein Benutzer wird sich 20 verschiedene kryptische Kundennummern zum Anmelden (Login) bei diversen Seiten merken.

Passwörter

Ähnliches gilt auch für Passwörter. Für kritische Anwendungen müssen natürlich verschiedene und besonders sichere Passwörter verwendet werden. Dies gilt insbesondere für Benutzerkonten beim Arbeitgeber, Universitäten, Internet Banking, etc. Aber es ist fast unmöglich, für jede (weniger kritische) Webseite eigene Passwörter zu verwenden. Es ist auch nicht zielführend, den Benutzern vorzuschreiben, dass sie sehr oft ihre Passwörter ändern sollen. Daher gehen viele Benutzer dazu über,einfache Passwörter zu verwenden. Die Benutzer sollten darauf hingewiesen werden, dass sichere Passwörter aus mindestens sechs, besser acht Zeichen bestehen, wobei sowohl Groß- als auch Kleinbuchstaben, Ziffern und Sonderzeichen enthalten sein sollten. Vor allem sollten sie aber keine Wörter in irgendeiner Sprache enthalten.

Benutzerpasswörter sollten nur verschlüsselt abgespeichert werden. Es wäre zwar oft zweckmäßig, wenn der Administrator durch einen schnellen Blick auf die Passwörter im Klartext unsichere erkennen und diejenigen Benutzer informieren könnte. Allerdings ist es nicht sehr anständig, die Passwörter anderer Benutzer auszuspionieren. Außerdem haben oft viele Personen Zugriff auf einen Server bzw. auf die Datenbank (wo die Passwörter zumeist abgespeichert sind). Außerdem sind Server nie vor einem Einbruch von außen sicher. Sind die Passwörter nicht verschlüsselt, könnten Unbefugte Zugang zu einer großen Menge von Benutzerkennungen und Passwörtern kommen. Je nach Wichtigkeit der Anwendung haben zumindest einige Benutzer diese Passwörter auch für andere Benutzerkonten verwendet. [Brauch 2002] Hinweise zum Finden von sicheren Passwörtern findet man z.B. unter www.uni-giessen.de/hrz/kommuni/passwortmerkblatt.html oder www.mathematik.uni-ulm.de/admin/passwd.html.)

Einwegverschlüsselung

Die Verschlüsselung der Passwörter sollte mit bewährten Algorithmen erfolgen. Geeignete Funktionen stellen die Webprogrammiersprachen ebenfalls zur Verfügung. Üblicherweise wird eine Einwegverschlüsselung angewendet. Dabei wird das Passwort verschlüsselt und so in der Datenbank gespeichert. Bei der Überprüfung wird das eingegebene Passwort ebenso verschlüsselt. Dieses verschlüsselte Passwort und das in der Datenbank befindliche verschlüsselte Passwort werden dann verglichen. Typische Verschlüsselungsalgorithmen hierfür sind MD547 oder SHA-1 [Rivest 1992] [FIPS 1995]. Alternativ könnte auch ein Hash-Algorithmus, der zusätzlich mit einem geheimen Schlüssel versehen wird, (engl.: keyed hash) zum Verschlüsseln verwendet werden. (Beispielsweise: HMAC-MD5, HMAC-SHA-1 [Krawczyk 1997]. MAC steht dabei für "Message Authentication Code" oder auf Deutsch Nachrichtenauthentifizierungscode.)

Unsicherer Übertragungsweg

Das Problem hierbei ist allerdings, dass das Passwort in das Eingabefeld im HTML-Formular am Client-Rechner eingegeben wird. Dann wird es über ein HTTP-POST an den Webserver gesendet. HTTP ist allerdings nicht verschlüsselt. Das Passwort kann also leicht auf dem Weg vom Client zum Server ausspioniert werden. Für Sicherheitskritische Anwendungen insbesondere im Internet eignet sich diese Vorgehensweise also nicht.

Eine Idee wäre, das Passwort vor dem Senden mittels Javascript zu verschlüsseln. Aber auch das alleine ist zuwenig. Der Server erwartet dann ein verschlüsseltes Passwort. Hat jemand das verschlüsselte Passwort auf dem Weg vom Client zum Server aufgezeichnet, kann er sich direkt mit dem verschlüsselten Passwort anmelden (einloggen). Der Server muss daher beim Erzeugen der Anmelde-Seite (Login-Seite) auch eine zufällig erzeugte ID an den Webbrowser senden. Diese ID wird dann gemeinsam mit dem eingegebenen und verschlüsselten Passwort an den Server mittels HTTP-POST geschickt. Der Server akzeptiert allerdings nur eine Kombination aus ID und gültigem Passwort. Wird dieselbe Kombination von einem Angreifer ein zweites Mal benutzt, ist sie nicht mehr gültig. Will sich ein Benutzer neu anmelden, so muss er die Anmelde-Seite neu laden. Dadurch erhält er eine neue ID, die dann wieder mit dem eingegebenen und verschlüsselten Passwort an den Server gesendet wird und einmal gültig ist.48

Das Problem an dieser Methode ist, dass Javascript von sich aus keine MD5-Veschlüsselungsfunktion bietet. Eine Implementierung der MD5-Funktion in Javascript findet man unter: pajhome.org.uk/crypt/md5/md5src.html.

SSL

Es stellt sich aber die Frage, wann es sinnvoll ist, solchen Aufwand bei der Übertragung des Passwortes zu treiben. Üblicherweise bei sicherheitskritischen Anwendungen. Hier sollte dann aber nicht nur der Anmeldevorgang, sondern die gesamte Kommunikation (Webseiten, Formularinhalte) sicher sein. Dafür eignet sich die Verwendung von SSL, wie im Kapitel 2.6.2 Secure Socket Layer und Transport Layer Security beschrieben.

Automatische Anmeldung

Bei weniger sicherheitskritischen Anwendungen kann es praktisch sein, dass ein Benutzer automatisch angemeldet (eingeloggt) wird, sobald er eine Seite besucht. Dies funktioniert mit Hilfe von so genannten Cookies.

Cookies

Ein Programm, das auf dem Webserver läuft und eine Seite für einen Webbrowser erzeugt, kann im HTTP-Kopfbereich (HTTP-Header) diese Cookies mit an den Broser senden. Jedes Cookie hat einen Namen, dem ein Wert zugewiesen wird. Diese Cookies werden dann unter der Verwaltung des Browsers auf dem Rechner des Benutzers gespeichert. Dabei wird auch mitgespeichert, von welcher Domain diese Cookies kommen. Fordert der Webbrowser später eine neue Webseite von einer bestimmten Domain an, dann sendet der Browser bei der Anfrage (GET, POST) die Cookies, die zu dieser Domain gehören, mit an den Webserver. Ein Programm auf dem Webserver kann diese Cookies wieder auslesen. Damit können Daten von einem Seitenabruf auf einer Domain zu einem anderem Seitenabruf auf derselben Domain übertragen werden.

Beim Erzeugen der Cookies kann man auch angeben, wie lange das Cookie gültig sein soll. Wird kein Gültigkeitsdatum angegeben so spricht man von einem so genannten Sitzungscookie (Sessioncookie). Das ist solange aktiv, als der Webbrowser geöffnet ist.

Wenn die Webapplikation nun beim Anmelden ein dauerhaftes Cookie setzt, das den Benutzer identifiziert, kann dieser beim nächsten Besuch wiedererkannt und so automatisch angemeldet werden.

Cookies sind üblicherweise rechnerbezogen. Bei mehrbenutzerfähigen Betriebssystemen bzw. Browsern auch benutzerbezogen. Wenn verschiedene Benutzer mit demselben Rechner bzw. mit demselben Benutzerkonto arbeiten, ist daher die Verwendung kritisch. Angenommen ein Benutzer meldet sich auf einem öffentlichen Computer an und es wird ein dauerhaftes Cookie gesetzt. Wenn sich der Benutzer nicht abmeldet (ausloggt), wodurch dauerhafte Cookies gelöscht werden sollen, bleibt das Cookie bestehen. Besucht bzw. benützt nun ein anderer Benutzer die Webseite bzw. Webapplikation, ist er automatisch als der zuvor angemeldete Benutzer angemeldet.

Da das automatische Anmelden mit Cookies grundsätzlich nicht sehr sicher ist, ist der Inhalt des Cookies, der den Benutzer bei der automatischen Anmeldung wieder erkennt, nicht allzu kritisch. Allerdings sollte es nicht das Passwort enthalten. Cookies sind nämlich als Textdateien auf dem Rechner gespeichert oder direkt über den Browser abrufbar. Es ist also nicht schwer den Inhalt von Cookies auszulesen. Beispielsweise wenn jemand kurz den Rechner verlässt, könnte das Cookie mit dem Passwort schnell gefunden werden.

Dass sich in diesem Fall jemand anderer am eigenen Rechner bei einer Webseite oder Webapplikation mit automatischer Anmeldung und bei gesetztem Cookie anmeldet, kann sowieso nicht verhindert werden. Daher ist diese Vorgehensweise nicht zu empfehlen. Außerdem sollte beim Ändern des Passwortes immer auch das alte Passwort abgefragt werden. Sonst könnte jemand leicht während der Abwesenheit das Passwort ändern und hätte dann unter Umständen später auf einem anderen Rechner genügend Zeit für böswillige Aktivitäten.



3.4.6 Autorisation

Ist die Authentizität des Benutzers einmal festgestellt, muss ermittelt werden, welche Berechtigungen der angemeldete Benutzer hat. Diesen Vorgang nennt man Autorisation. Je nach Berechtigungen kann ein Benutzer bestimmte Informationen sehen, bzw. bestimmte Aktionen durchführen. Beispielsweise kann ein Administrator zusätzliche Menüpunkte zum Ändern bestimmter Informationen sehen, die ein normaler Benutzer nicht sieht. Zu gewissen Seiten (z.B. Administrationsbereich) dürfen bestimmte Benutzer gar keinen Zugriff haben. Dabei genügt es nicht, nur darauf zu vertrauen, dass der Benutzer nicht auf solche Seiten gelangt, weil er keine Links dorthin findet. Solche URLs können oft leicht herausgefunden werden. Es müssen daher die Rechte wirklich bei jeder Seite überprüft werden.

Üblicherweise gibt es beim Rechte-Management verschiedene Gruppen mit bestimmten Rechten. Benutzer können dann Mitglied einer oder auch mehrerer Gruppen sein.



3.4.7 Statusloses HTTP

Aus Sicht des Webservers läuft eine Seitenabfrage eines Webbrowsers folgendermaßen ab: Der Server erhält eine GET- oder eine POST-Anfrage, analysiert diese, startet eventuell ein Programm, das die gewünschte Seite erzeugt, oder lädt sie direkt von der Festplatte oder aus einem Zwischenspeicher und sendet sie zurück an den Webbrowser. Damit ist dieser Transfer für den Server abgeschlossen. Üblicherweise greifen viele verschiedene Webbrowser von vielen verschiedenen Rechnern auf den Webserver zu. Dabei gibt es für den Webserver keine Möglichkeit, mit Hilfe von HTTP einen Zusammenhang zwischen zwei verschiedenen Anfragen ein und desselben Webbrowser (bzw. Rechner oder Benutzer) herzustellen. Anders ausgedrückt: Der Server hat keine Status-Information vom Webbrowser. Mit HTTP ist es also nicht möglich, einen Zugriff eines Browsers einem eventuell zuvor getätigten Zugriff am selben Server zuzuordnen.

Warum das ein Problem ist, und wie man dieses Problem umgehen kann, wird im nächsten Kapitel 3.4.8 Sitzungsmanagement diskutiert.



3.4.8 Sitzungsmanagement

Ein Besuch einer Webseite (einer Domain) oder die Benutzung einer Webapplikation durch einen Benutzer wird als Sitzung (engl.: Session) bezeichnet. Dabei kann der Benutzer angemeldet sein oder nicht. Während einer Sitzung kann der Benutzer verschiedene Einzelseiten besuchen und Formulare ausfüllen und absenden.

Das Problem dabei ist, dass bei jedem Seitenaufruf der Benutzer wiedererkannt werden muss. Ein Beispiel: Auf den Seiten eines Online-Shops, wie beispielsweise Amazon.de, befinden sich gleichzeitig hunderte oder tausende Besucher. Diese können sich Waren ansehen und auch welche in den virtuellen Warenkorb legen. Später können sie jeweils ihren Warenkorb ansehen und die Waren im Warenkorb kaufen. Das Programm, das am Webserver läuft, muss daher wissen, welcher Warenkorb zu dem Besucher gehört, der gerade eine Ware dort hinein gibt, oder sich diesen ansieht.

Wie im Kapitel 3.4.7 Statusloses HTTP angeführt, gibt es beim HTTP-Protokoll keine Statusinformationen über eine Sitzung. Jeder Seitenaufruf ist für sich abgeschlossen. Es ist nicht möglich festzustellen, ob derjenige Besucher, der gerade die Seite X anfordert, vorher die Seite Y angefordert hat, oder ob Seite Y von einem anderen Benutzer angefordert wurde.

Was man benötigt, sind so genannte Sitzungsdaten (engl.: Session data), die genau einer Sitzung und damit genau einem Benutzer zugeordnet werden können. Beim obigen Beispiel mit dem Online-Shop würde in diesen Sitzungsdaten zumindest der Warenkorb oder eine Identifikationsnummer des Warenkorbs stehen.

Es wird daher ein Mechanismus benötigt, mit dem man entweder einen Benutzer eindeutig wieder erkennen kann, oder Daten von einer Webseite, die ein Benutzer aufgerufen hat, zur nächsten Webseite, die dieser Benutzer betrachtet, zu übertragen. Oder genauer: Vom Programm am Webserver, das eine Webseite für einen Benutzer erzeugt zum Programm, das die nächste Webseite für diesen Benutzer erzeugt.

Im Folgenden seien einige Möglichkeiten angeführt.

IP-Adressen

IP-Adressen funktionieren nicht als eindeutiges Identifizierungsmerkmal für einen bestimmten Benutzer. Man könnte zwar meinen, dass jeder Benutzer einen Rechner mit einer IP-Adresse verwendet und man anhand dieser einen Benutzer identifizieren kann. Bis zu einem gewissen Grad geht das. Es wird auch z.B. bei Zugriffszählern verwendet, um eine ungefähre Vorstellung zu erhalten, wie viele verschiedene Besucher zugegriffen haben. Aber die IP-Adressen sind weder eindeutig noch können sie - auch während einer Sitzung - eindeutig einem Benutzer zugewiesen werden.

Eindeutig sind sie deswegen nicht in jedem Fall, weil es erstens Benutzer gibt, die über einen Proxy-Server auf Webseiten zugreifen und zweitens gibt es Rechner in lokalen Netzwerken, die gar keine öffentlichen IPs haben, aber trotzdem auf das Internet zugreifen können.

Proxy-Server sind Server, die Webseiten bzw. andere Webinhalte, wie beispielsweise Bilder, zwischenspeichern. Greift ein Browser über einen Proxy auf eine Webseite zu, prüft der Proxy zuerst, ob er diese Seite nicht schon kürzlich geladen hat und sie im eigenen Zwischenspeicher enthalten ist. Wenn ja, kann er sie sofort ausliefern. Wenn nicht, dann lädt er sie vom Server, der die angeforderte URL enthält und speichert sie gegebenenfalls zwischen. Provider sparen sich dadurch unter Umständen viel Datentransfer, der sonst teuer zu bezahlen wäre. Allerdings funktioniert das Zwischenspeichern bei dynamischen bzw. personalisierten Seiten, wie z.B. bei einem Online-Shop, nicht. Auch bei nicht personalisierten Seiten, die häufig geändert werden, kann es problematisch sein, falls dann ein Benutzer noch den veralteten Inhalt vom Proxy enthält.

Das Problem für die Webapplikation ist allerdings, dass sie nur die IP-Adresse des Proxy-Servers sieht. So können hunderte oder tausende Besucher scheinbar dieselbe IP-Adresse haben, da sie den gleichen Proxy verwenden.

Ähnlich stellt sich die Situation dar, wenn in einem lokalen Netzwerk private IP-Adressen verwendet werden.49 Da die 4 Byte langen IPv4-Adressen (Internet Protocol Version 4 Adressen) schon knapp werden, können nicht alle Rechner in Firmen und Organisationen, aber auch in Privathaushalten, öffentliche IP-Adressen erhalten. Daher wurden private IP-Adressen reserviert, die im Internet nicht vergeben sind. Nur ein Computer im lokalen Netzwerk hat auch eine Verbindung zum Internet. Dieser hat also zwei Netz-Schnittstellen (z.B. Netzwerkkarten) mit jeweils einer öffentlichen und einer privaten IP-Adresse. Dieser Rechner sorgt dafür, dass alle Rechner im lokalen Netzwerk mit dem Internet kommunizieren können.50

Greift nun ein Rechner im privaten Netzwerk auf einen Webserver zu, sieht das Programm, das die Seite zurückliefern soll, wieder nur die IP jenes Rechners, der mit dem Internet direkt verbunden ist. Alle privaten Rechner haben daher dieselbe IP-Adresse.

Bis jetzt wurden Fälle diskutiert, wo mehrere Besucher dieselbe IP-Adresse haben. Möglich ist es allerdings auch umgekehrt. Ein Großteil der privaten Internetbenutzer haben Internetzugänge mit dynamischen (im Gegensatz zu fixen) IP-Adressen. Dabei wird dem Benutzer bei jedem Verbindungsaufbau zum Internet eine IP-Adresse aus dem Pool des Providers zugewiesen. Hier bleibt die IP-Adresse aber zumindest über einen gewissen Zeitraum konstant.

Noch problematischer wird es bei manchen Providern, wie z.B. AOL (www.aol.com), die ebenfalls Proxy-Server einsetzen. Bei AOL gibt es allerdings mehrere und diese werden nicht fix zugeordnet. Bei jeder Abfrage einer Webseite wird dann zufällig ein Proxy-Server verwendet. Dadurch kann ein Benutzer während einer Sitzung ständig ändernde IP-Adressen erhalten.51

Zusammenfassend lässt sich sagen, dass IP-Adressen kein ausreichendes Kriterium sind, um Benutzer eindeutig wiederzuerkennen.

Query-String

Der Query-String ist ein Teil der URL. Er wird durch ein Fragezeichen (?) von der Ressource-Angabe (Webseite, Verzeichnis, Grafik, ...) getrennt. Er kann nicht nur - wie oben bereits erwähnt - automatisch vom Browser erzeugt werden, um Namen von Formularelementen und deren Inhalte an den Server zu übertragen, sondern kann auch selbst, wie eine normale URL, zusammengestellt werden. Der Query-String wird dann gemeinsam mit der URL an den Webserver übertragen. Das Programm am Webserver kann diesen Query-String analysieren.

Somit ist es möglich, Daten von Webseite zu Webseite zu übertragen. Diese Möglichkeit kann ausgenützt werden, um eine so genannte Session-ID von einer Webseite zur nächsten weiterzuleiten. Die Session-ID ist eine eindeutige Zeichenkette, die die Sitzung und damit den Benutzer identifiziert.

Ruft ein Besucher eine Webseite auf, untersucht das Programm, das die Webseite erzeugt, den Query-String. Ist darin keine Session-ID enthalten (beim ersten Zugriff auf diese Domain bzw. Webapplikation), so wird diese erzeugt. Sie wird nun intern abgespeichert (z.B. in einer Datenbank). Weiters wird die Session-ID an jeden internen Link angehängt. Interne Links sind Links innerhalb der Webseite (Domain) oder der Webapplikation. Um wieder auf das Beispiel mit dem Online-Shop zurückzukommen, hier ein Beispiel eines solchen Links:

<a href="warenkorb.php?sid=ASwd455glk32sDDr3">Warenkorb ansehen</a>
Beispiel 20: Generierter Quelltext eines Links mit angehängter Session-ID.

Dabei steht "sid" für Session-ID. Wird auf diesen Link geklickt, so überträgt der Browser diesen inklusive Query-String mit der Session-ID an den Webserver. Das Programm, das dort die Webseite "warenkorb.php" erzeugt, kann den Query-String auswerten und die Session-ID ermitteln. Diese Session-ID ist mit einem bestimmten Warenkorb in der Datenbank verknüpft. Dieser kann dann auf der Seite ausgegeben werden. Außerdem werden wiederum allen internen Links dieser Seite die Session-ID im Query-String angehängt.

Session-IDs im Query-String bringen allerdings einige Gefahren mit sich. Sie sind als Teil der URL in der Adresszeile des Browsers bzw. im Quelltext der Webseite sichtbar und können sehr leicht manipuliert werden. Völlig unbrauchbar wäre etwa ein einfaches Durchnummerieren der Sitzungen bzw. Besucher. Dann müsste ein potentieller Angreifer nur einige Nummern ausprobieren, um eine gültige zu finden. Es ist daher auch klar, dass eine Session-ID nicht unbegrenzt gültig sein darf. Session-IDs sollen nach einer bestimmten Zeit ungültig werden (Session-Timeout). Je sicherheitskritischer eine Anwendung ist, desto kürzer sollte dieses Timeout sein. Beim Online-Banking ist es teilweise oft nur fünf bis zehn Minuten. Erfolgt in dieser Zeit kein Seitenabruf, muss man sich wieder neu anmelden.

Manche Webprogrammiersprachen erzeugen selbstständig Session-IDs oder stellen Funktionen zur Verfügung, mit denen man diese erstellen kann. Sonst wendet man die oben bereits erwähnten Hash-Funktionen (SHA-1, MD5, HMAC-MD5, HMAC-SHA-1, etc.) auf eine Zufallszahl an. Die Zufallszahl muss dabei so zufällig wie möglich und genügend lang sein. Wird z.B. die Zeit als Initialisierungswert für den Zufallszahlengenerator verwendet, ist das denkbar schlecht: Es könnte jemand automatisiert plausible Zeitpunkte durchprobieren, damit den Zufallszahlengenerator initialisieren, die Zufallszahl ebenfalls mit denselben Algorithmus verschlüsseln und so auf dieselbe Session-ID kommen. Es könnte aber z.B. die Zeit (je kleiner die Auflösung desto besser: z.B. Mikrosekunden) und die ID des aktuell laufenden Prozesses gemeinsam verwendet werden.

Wie in Kapitel 3.4.5 Benutzerauthentifizierung über die Übertragung des Passwortes schon besprochen, kann auch die Session-ID, wie auch der Rest der Anfrage an den Webserver, und die zurückgesendete Webseite auf dem Weg zum und vom Server relativ leicht ausspioniert werden. Bei wichtigen Daten muss daher SSL eingesetzt werden.

Aber es gibt noch viel einfachere Angriffsmethoden auf diese Session-IDs. Die Session-ID könnte z.B. einfach abgeschrieben und auf einem anderen Rechner verwendet werden. Für das Programm am Webserver macht es keinen Unterschied, von welchem Rechner die Seite mit der gültigen Session-ID abgerufen wurde.

Dies ist vor allem dann zu beachten, wenn Links (URLs) häufig weitergegeben werden, wie das etwa bei Online-Shops der Fall ist. Ist ein Besucher angemeldet und sendet einer anderen Person beispielsweise einen Link zu einem bestimmten Produkt, enthält dieser Link auch die Session-ID. Die andere Person kann somit die Sitzung des ursprünglichen Besuchers übernehmen. Amazon.de verhindert das dadurch, dass es zusätzlich die Sessions-ID mit Cookies gegenprüft. Sind Cookies deaktiviert, können Sitzungen allerdings übernommen werden. Um in diesem Fall Missbrauch zu verhindern, verlangt Amazon.de bei wichtige Aktionen (z.B.: Bestellung absenden) trotzdem die E-Mail-Adresse und das Passwort.

Viel hinterhältiger ist folgende Angriffsmöglichkeit, mit der viele webbasierte E-Mail-Provider zu kämpfen hatten.52 Das Problem dabei ist die Variable "HTTP_REFERER". Das ist eine Variable, die ein Webbrowser üblicherweise mitsendet, wenn er vom Webserver eine Seite anfordert. Sie enthält die URL der Seite, von der auf die aktuelle Seite gelinkt wurde (Referer). Eine Webseite enthält üblicherweise nicht nur interne Links, sondern auch externe (Webapplikationen oft relativ wenige). Die URL der Seite enthält die Session-ID im Query-String. Klickt nun der Benutzer auf den externen Link, so wird in der "HTTP_REFERER"-Variable die URL an den Server, wo der externe Link hinzeigt, übertragen. Damit wird erstens die Session-ID in die Log-Files dieses fremden Servers geschrieben. Zweitens kann das Programm, das die Webseite auf dem fremden Server erzeugt, die Session-ID aus der "HTTP_REFERER"-Variable ermitteln.

Aufgepasst muss ebenso auf Bilder auf der eigenen Webseite werden, die von einem fremden Server geladen werden. Auf diese muss nicht einmal geklickt werden. Trotzdem wird die URL über die Referer-Variable an den fremden Server übertragen.

Diese Dinge (externe Links, externe Bilder), sind insbesondere dann genau zu analysieren, wenn Benutzer selbst solche Links zu Seiten oder Bilder eingeben können, die dann in einer Webseite angezeigt werden. Beispielsweise bei Online-Diskussionsforen oder wie in den oben angeführten Fällen bei den webbasierten E-Mail-Providern.

Was kann dagegen gemacht werden? Erstens sollten die Session-IDs möglichst kurz gültig sein. Je schneller eine Sitzung ungültig ist, desto weniger Zeit hat ein potentieller Angreifer, eine ermittelte Session-ID auszutesten. Eine zu kurze Gültigkeitsdauer ist allerdings wieder lästig für den Benutzer. Wurde diese Zeit zwischen zwei Seitenaufrufen überschritten, ist die Sitzung ungültig geworden. War er vorher angemeldet, muss er sich neu anmelden. Wenn nicht, sind die Aktionen, die bis jetzt gesetzt wurden, verloren. (Z.B. Warenkorb ist wieder leer.)

In manchen Fällen könnte es auch sinnvoll sein, die IP-Adresse mit in die Session-ID zu verschlüsseln (oder in die Datenbank zu den Sitzungsdaten zu speichern) und jedes Mal überprüfen, ob die IP-Adresse, von der die aktuelle Anfrage kommt, mit der übereinstimmt, die beim Erstellen der Session-ID verwendet wurde. Damit kann großteils verhindert werden, dass eine Session-ID auf verschiedenen Rechnern funktioniert. Wenn aber, wie oben beschrieben, mehrere Rechner für den Webserver dieselbe IP-Adresse haben (Proxy oder NAT), dann wirkt dieser Sicherheitsmechanismus nicht. Wenn der Provider so wie AOL dem Benutzer laufend verschiedene IP-Adressen zuweist, dann ist die Session-ID bzw. die IP ständig ungültig und ein Arbeiten mit der Webapplikation nicht möglich.

Eine zusätzliche Hürde wäre es, die Browseridentifikation, die jeder Webbrowser an den Server sendet, in die Session-ID mit einzubauen. Über die Variable "HTTP_USER_AGENT" kann diese ausgelesen werden und enthält Name und Version vom Browser und vom Betriebssystem. Haben zwei Rechner allerdings dasselbe Betriebssystem und denselben Browser (wie es z.B. innerhalb einer Organisation sehr oft der Fall ist), dann wirkt diese Vorgehensweise nicht.

Der einzig sichere, aber aufwändige und umständliche Weg wäre, bei jedem Seitenaufruf eine neue Session-ID zu erzeugen und an die internen Links anzuhängen. Damit wäre die Session-ID in der "HTTP-REFERER"-Varible schon wieder ungültig, wenn auf einen externen Link geklickt wird oder ein Bild von einem fremden Server geladen wird. Ein Problem mit dieser Lösung ist das ständige Erzeugen einer neuen Session-ID, die jedes Mal neu in die Datenbank geschrieben werden muss. Weiters führt dann die Verwendung der Browser-History (Zurück-Button, Vorwärts-Button) zu großen Problemen: Geht ein Benutzer eine Seite zurück, dann wird diese Seite meist aus dem Browser-Cache gelesen. Das heißt, dass alle Links auf dieser Seite noch die alte, mittlerweile ungültige, Session-ID im Query-String enthalten. Wird auf so einen Link geklickt, führt das zu einem Fehler, weil die Session-ID ungültig ist. Man könnte natürlich mit Hilfe von Javascript die Zurück- und Vorwärts-Buttons sperren. Das kann allerdings durch Deaktivieren von Javascript umgangen werden. Vor allem aber ist das ein schwerer Verstoß gegen die Usability-Regeln. Man nimmt dem Benutzer sehr wichtige Navigationsmöglichkeiten.

Ein sinnvoller Mittelweg wäre, dass Seiten, die entweder externe Links enthalten, oder Bilder von fremden Servern, eine solche "Einmal"-Session-ID verwenden. Alle anderen Seiten können die normale Session-ID verwenden.

Versteckte Formularfelder

Alternativ könnte für die Übertragung der Session-ID bei kritischen Seiten (die also externe Links und fremde Bilder enthalten) mit einem versteckten Formularelement erfolgen. (Siehe Kapitel 3.4.4 HTML-Formulare.)

Links müssten dann als Formulare ausgeführt werden. Wird das Formular mittels POST an den Server gesendet, scheint das versteckte Feld, wie auch die anderen Formulardaten, nicht in der URL auf. Es kann daher auch nicht, wie der Query-String, über externe Links oder Bilder an fremde Server übertragen werde.

Eine echte Alternative zum Übertragen der Session-ID mit dem Query-String ist aber das Übertragen in einem versteckten Feld nicht. Alle internen Links müssten dann nämlich Formulare sein. Formulare werden aber üblicherweise mit Klickbuttons gesendet. Normale Links funktionieren nicht so einfach.

Neben den bekannten (meist grauen) Klickbuttons können auch Grafiken als Buttons verwendet werden. Mit Hilfe von Javascript könnten auch herkömmliche Links ein Formular absenden. Man kann aber schwer jeden Link als Grafik ausführen und bei Links auf Javascript zu vertrauen ist ebenfalls nicht empfehlenswert. Somit eignet sich diese Möglichkeiten nur in Einzelfällen. Beispielsweise wie oben bereits erwähnt, wenn die Übertragung per Query-String zu unsicher wäre. Im Folgenden ein Code-Beispiel eines Formulars mit einem verstecktem Element.

<form name="sample" method="post" action="processform.php">
  <input type="hidden" name="sid" value="ae43DF4543Se" />
  <input type="submit" name="button" value="Weiter" />
</form>  
Beispiel 21: Quelltext eines HTML-Formulars mit einem versteckten Feld (hidden field) und einem Klick-Button.

Cookies

Die letzte Möglichkeit, die Session-ID von einer Seite zur nächsten zu übertragen, sind Cookies. Das Programm am Webserver sendet die Session-ID als Cookie mit der Webseite an den Webbrowser. Dieser speichert sie und sendet sie zurück an den Webserver, sobald wieder eine Seite von derselben Domain abgerufen wurde. Aus der Sicht des Programmierers haben Cookies nur den Nachteil, dass sie vom Benutzer deaktiviert werden können. Sind Cookies am Browser deaktiviert, speichert er diese nicht und übergibt sie auch nicht an den Webserver.

Es sollten Session-IDs nur dann mit Cookies weitergereicht werden, wenn entweder Cookies vorausgesetzt werden können (etwa im Intranet), oder wenn die Webseite auch ohne Cookie (also ohne Sitzung, also ohne Anmeldung) benutzbar ist, und eine Anmeldung nur einen Mehrwert bringt. Ein Online-Shop sollte es sich nicht leisten, Besucher, die keine Cookies akzeptieren, vom Kaufen auszusperren.

Wieso haben Benutzer Cookies deaktiviert? Die Firma Netscape hatte die Cookie-Spezifikation vorgestellt. Daraufhin erschien ein Artikel im amerikanischen Computer Magazin "Byte", der die Cookies als großes Sicherheitsproblem darstellte, da der Autor die Spezifikation missverstanden hatte. Trotz einer Revidierung in der nächsten Ausgabe verbreitete sich dieses Gerücht sehr schnell.

Cookies sind theoretisch sicher. In der Praxis allerdings nicht immer. Normalerweise sollte ein Programm, das eine Webseite für eine bestimmte Domain generiert, vom Browser ausschließlich Cookies erhalten, die ein Programm derselben Domain erzeugt hat. Gefahr lauert dann, wenn ein Cookie einem fremden Server übermittelt wird, der einer anderen Domain angehört, als der Server, der das Cookie ursprünglich gesetzt hat.

Der erste Angriffspunkt sind Sicherheitslücken im verwendetem Webbrowser. Solch Lücken werden laufend - nicht nur beim besonders anfälligen Internet Explorer - gefunden. Informiert man sich allerdings regelmäßig über die entdeckten Sicherheitslücken, und aktualisiert die Software entsprechend, sollte die Gefahr relativ gering sein, da Angriffsprogramme, die diese Sicherheitslücken ausnützen, meist erst einige Zeit nach der Veröffentlichung der Lücken auftauchen. Auch viele Viren mit enormen Verbreitungsrad nutzen meist Sicherheitslücken aus, die schon Monate bekannt sind.

Der zweite Angriffspunkt ist das so genannte Cross Site Scripting (CSS oder XSS). Wie im Kapitel 3.5 Sicherheitsrisiken bei Webapplikationen genauer beschrieben, handelt es sich dabei um Fehler bzw. mangelnde Sorgfalt beim Programmieren. Dadurch ist es für einen Angreifer möglich z.B. Javascript Code auf der Webseite ausführen zu lassen, der Cookie-Inhalte an beliebige andere Server überträgt.

Bei der dritte Angriffsmethode - dem so genannten "DNS Spoofing" - wird der Browser durch falsche Einträge in den DNS-Servern auf einen fremden Server umgeleitet. Somit kommuniziert der Browser unwissentlich mit einem fremden Server. Dabei werden dann auch eventuell für diese Domain vorhandene Cookies an den Angreifer gesendet. DNS-Spoofing ist allerdings technisch sehr anspruchsvoll bzw. meist ebenfalls nur wegen Sicherheitslücken in den Implementierungen der Systemsoftware möglich. [BSI 2003]

Ein weiterer Angriffspunkt ist die eigene Festplatte, auf der zumindest die dauerhaften Cookies gespeichert sind und ausgelesen werden können. Auch die Sitzungscookies, die sich üblicherweise nur im Arbeitsspeicher befinden, während der Browser ausgeführt wird, können mit geeigneten Programmen ausgelesen werden (Programm 'Winhex' [Curphey 2002]). Dieser Angriffspunkt kann etwa ausgenutzt werden, wenn ein Benutzer kurz den Arbeitsplatz verlässt.

Der Angriffspunkt, der allen versendeten Daten bei Webapplikationen - und somit auch den Cookies - gemein ist, ist der Übertragungsweg. Hier hilft nur die Verwendung von SSL. Beim Setzen von Cookies, kann ein Attribut (secure) gesetzt werden, das verhindert, dass ein Cookie über eine nicht sichere Verbindung gesendet wird. Es wird dann nur übertragen, wenn eine SSL-Verbindung besteht.

Um sichergehen zu können, dass es zu keinen Sicherheitsproblemen mit Cookies kommt, muss die eingesetzte Software immer am aktuelle Stand sein und die Webapplikation sehr sorgfältig auf mögliche Sicherheitslücken in der Implementierung untersucht werden. Bei kritischen Anwendungen muss natürlich auf SSL gesetzt werden.

Auch wenn es möglich ist, Cookies sicher einzusetzen, lässt sich eines nicht abstreiten: Cookies wurden und werden dazu benutzt, Benutzerprofile zu erstellen und anhand dieser beispielsweise gezielte Werbung einzublenden. Firmen wie DoubleClick haben auf sehr vielen Seiten ihre Werbebanner platziert. Ebenso wie Webseiten können auch Grafiken (in diesem Fall Werbebanner) dynamisch (mit einem Programm) generiert werden. Bei der Generierung können genauso Cookies gesetzt und bereits gesetzte wieder ausgelesen werden.

DoubleClick weiß natürlich, auf welcher Domain ein bestimmter Banner angezeigt wird. Somit kann die Firma für einen Benutzer - identifiziert durch eine ID - ein Profil aufbauen, in dem verzeichnet ist, welche Seiten bevorzugt besucht werden, und dem entsprechende Werbung anzeigen. Die Profile sind hier allerdings noch anonym. Es gibt keine Zuordnung zu einem Namen einer Person.

DoubleClick wollte ihre Profile mit personenbezogenen Daten einer anderen Firma verknüpfen, allerdings haben sich dagegen sogar die US-amerikanischen Verbraucherschützer gewehrt. [Heise News 2000]

Schutzlos ausgeliefert sind die Web-Benutzer dem allerdings nicht, auch wenn man Cookies grundsätzlich erlaubt. Die Werbebanner von solchen großen Werbefirmen werden nämlich üblicherweise von der Domain der Werbefirma aus geladen, und nicht von der Domain, auf der sich der Besucher gerade befindet. Die meisten Browser erlauben es, Cookies nur für die primäre Domain, also von der die Webseite (HTML-Code) kommt, zu erlauben. Von Elementen, die von anderen Domains kommen (Bilder, Frames), werden dagegen keine Cookies akzeptiert. Beim Internet Explorer ab Version 6.0 ist das sogar die Voreinstellung.

Für Werbefirmen ist das natürlich ein großer Nachteil. Viele Webseiten müssen durch Werbung finanziert werden. Die Internetwerbung funktioniert aber grundsätzlich nicht sehr gut. Durch Cookies kann man relativ einfach verhindern, dass ein Besucher zu oft hintereinander dieselbe Werbung sieht, womit sie insgesamt effizienter wird. Werden Cookis von fremden Domains nicht mehr erlaubt, ist es ungleich aufwändiger, festzustellen, welche Werbebanner einem Besucher schon gezeigt wurden und welche nicht.

Sitzung - Authentifizierung

Sitzungsverwaltung und Authentifizierung sind zwei unterschiedliche Dinge. Eine Sitzung kann sowohl ohne als auch nach einer zuvor durchgeführten Authentifizierung eingeführt werden. Eine Authentifizierung ohne Sitzung macht meist wenig Sinn. Außer es wird nur für eine Webseite (bzw. Aktion) die Identität des Benutzers benötigt. Eine Webseite, die Cookie-basierte Sitzungen verwendet, könnte bei Aktionen, die die Authentizität des Benutzers voraussetzen, immer auch Benutzeridentifikation und Passwort abfragen. Z.B. ein Online-Diskussionsforum, bei dem auch Benutzer ohne Cookies, die also nicht angemeldet sind, Einträge unter ihren Benutzernamen schreiben, indem sie diesen und ein Passwort beim Eintragen angeben.

Folgerungen

Es gibt kein ideales Verfahren zum Sitzungsmanagement. Mit Cookies handelt man sich die wenigsten Probleme bzw. Nebeneffekte ein, allerdings besteht das große Problem, dass nicht alle Benutzer Cookies aktiviert haben.

Idealerweise setzt man Cookies ein, wo es möglich ist und verwendet die Query-String-Methode sonst. Wenn letztere zu Sicherheitslücken führen könnte, kann man je nach Problem nur einmal gültige Session-IDs, versteckte Formular-Felder oder zusätzliche Authentifizierung einsetzen.

Fremde Sitzungen

Wie bereits angesprochen, kommt es je nach Webseite bzw. Webapplikation mehr oder weniger häufig vor, dass Links innerhalb einer Sitzung an andere Benutzer bzw. Rechner weitergegeben werden. Natürlich sollte dabei verhindert werden, dass die Sitzung ebenfalls weitergegeben wird. Bei der Verwendung von Cookies ist das kein Problem, da die Cookies Rechner- oder Benutzer-bezogen sind. Beim Austausch eines Links können sie nicht mitübergeben werden. Bei Session-IDs im Query-String ist das allerdings möglich und kann höchstens durch Session-IDs, die nur einmal gültig sind, verhindert werden.

Wenn feststeht, dass eine Session übernommen wurde, stellt sich aber die nächste Frage: Was tun mit der fremden Sitzung? Das hängt einerseits von der Applikation, andererseits vom Benutzer ab. Wird die Query-String-Methode verwendet, sollte der Benutzer wenn möglich abgemeldet werden. Wie oben angeführt, kann nicht immer festgestellt werden, ob das eine fremde Sitzung ist. Normalerweise sollte dann ein Anmeldeformular erscheinen, mit dem sich der Benutzer anmelden kann. In manchen Fällen ist es aber auch sinnvoll, die angeforderte Seite zu zeigen, allerdings nicht personalisiert. Beispielsweise, wenn der Link auf ein Produkt in einem Online-Shop übertragen wurde, oder der Link auf einen Eintrag in einem Diskussionsforum, das auch ohne Anmeldung zugänglich ist.

Wenn Cookies verwendet werden, könnte es unter Umständen sein, dass der Benutzer, der den Link von der fremden Sitzung erhält, selbst auf dieser Seite angemeldet ist und sogar noch ein Cookie mit seiner Session-ID oder für seine automatische Anmeldung besitzt. Dann könnte dieser Benutzer automatisch eingeloggt und die Seite, auf die der übermittelte Link zeigt - für den neuen Benutzer personalisiert - angezeigt werden. Vorausgesetzt, er besitzt die Rechte, diese Seite zu sehen. In allen anderen Fällen sollte eine Fehlermeldung oder eine Anmelde-Aufforderung erscheinen.



41Oft ein so genanntes "Script". Vgl. Kapitel 2.4.5 Programmierumgebungen für Webapplikationen.

42Typischer Name dieser Funktionen: urlencode().

43In Perl stehen die Servervariablen im assoziative Array '%ENV'. In PHP kann man sich mit phpinfo(); einen Überblick ausgeben lassen.

44IFrames sind in Webseiten eingebettete Frames.

45Eine schöne Übersicht über alle Möglichkeiten für Formulare findet man z.B. unter selfhtml.teamone.de/html/formulare/index.htm.

46Je nach Tastatur, Betriebssystem und Browser müssen anstatt der "Alt"-Taste andere Tasten verwendet werden.

47Der MD5 Hash-Algorithmus ist nicht mehr 100% sicher. Wie in [Dobbertin 1996] dargelegt wurde, ist es in relativ kurzer Zeit unter bestimmten Voraussetzungen möglich, zu einer Nachricht eine andere Nachricht zu finden, die denselben MD5-Hash-Wert ergibt. Man spricht in diesem Zusammenhang von so genannten Kollisionen. Momentan besteht allerdings noch keine unmittelbare Gefahr für die Sicherheit bei der Verwendung von MD5. Trotzdem empfiehlt Dobbertin MD5 in Zukunft nicht mehr zu verwenden, wenn ein kollisionsfreier Hash-Algorithmus gefordert ist. Es empfiehlt sich stattdessen der Einsatz von SHA-1, HMAC-SHA-1, etc.

48Auf diese Problematik ist der Autor beim Lesen der Besucher-Kommentare der PHP-MD5-Funktion gestoßen: www.php.net/manual/en/function.md5.php. Ebenso sind hier Hinweise darauf zu finden: perl-md5-login.sourceforge.net/.

49Näheres zu privaten IP-Adressen findet man unter www.uni-karlsruhe.de/Uni/RZ/Netze/priv-ip.html.

50Üblicherweise wird dieser Vorgang als Network Address Translation (NAT) bezeichnet. Im Windows 2000 oder Windows XP ist es als Internetverbindugsfreigabe (engl. Internet Connection Sharing, kurz ICS) bekannt. Bei Linux heißt es meist IP-Masquerading.

51Siehe: webmaster.info.aol.com/proxyinfo.html.

52Siehe: www.heise.de/newsticker/data/hob-18.07.00-000/.

Nächstes Kapitel >>
Zum Seitenanfang diplomarbeit_o a-t schmiderer d-o-t cc2003-04-25