Hallo Sabine,
Ja, auch - aber vor allem auch dann, wenn der Benutzer diese
Informationen nicht so ohne weiteres fälschen kann (deshalb
die HTTP-Header).
Ist nachvollziehbar für mich. Welche Informationen des Users machen
den Sinn um ihn zu unterscheiden? Wie gesagt bei der IP kann es ja
sein, dass ich den Benutzer dann nicht mehr erkennen würde obwohl
es der richtige ist. Ist es sinnvoll z.B. eine Kombination aus
HTTP_USER_AGENT und HTTP_ACCEPT zu nehmen?
Da ja (nach meinem bisherigen Wissenstand) eben die IP unsicher ist
und auch der Referrer gefaked sein kann, drängt sich für mich die
Frage auf - welche Informationen soll ich nehmen, die überhaupt Sinn
machen um nicht etwas zu prüfen, dass mir eigentlich nichts bringt,
weil 2 von 3 die gleichen Infos schicken.
Du hast schon ziemlich exakt erraten, was ich hier antworten will:
Je vielfältiger die Werte eines HTTP-Headers sind, desto besser eignet
er sich als zusätzliche Quelle der Konsistenz-Prüfung.
Ich würde in der Tat mit dem UserAgent anfangen - da ist die Chance,
daß ein Angreifer exakt denselben String sendet, schon ziemlich klein.
(Die Accept-Liste projeziert im Vergleich dazu deutlich schlechter.)
Wenn dieses Programm dann auch noch mit Deinen womöglich
JavaScript enthaltenden Seiten fertig werden muß, hast Du eine
nette zusätzliche Hürde aufgebaut, die nicht mit brute force,
sondern nur mit eigener Arbeit zu überwinden ist.
Warum JavaScript? In welcher Form kann mir hier Javascript etwas
bringen? Das verstehe ich nicht - als einziges sehe ich hier eine
Möglichkeit daran Besucher mit aktiviertem und deaktiviertem
Javascript zu unterscheiden? Meinst du das oder bin ich hier am
falschen Dampfer?
Wenn ich als Angreifer mit dem Erraten von URLs zwar Deine Session-ID
"brechen" kann, aber zusätzlich bestimmte Felder des HTTP-Headers auch
noch so senden muß, wie das der "belauschte" Browser tut, meiner aber
nicht kann, wäre meine nächste Idee, ein Programm wie meinen HTTP-
Tracer zu nehmen, also einen Roboter als HTTP-Client. Diesen so zu
schreiben, daß er HTTP bedienen kann, ist verhältnismäßig einfach -
wenn Deine Requests aber nur in einem Client korrekt funktionieren
würden, der JavaScript unterstützt, müßte ich einen kompletten Browser
schreiben!
Das soll nun keine Anregung sein, unbedingt JavaScript zu verwenden -
nur wenn Du das ohnehin schon tun würdest (wieso auch immer), wäre das
für den Angreifer eine zusätzliche Hürde, falls er nicht mit einem nor-
malen Browser angreifen kann, sondern einen "Eigenbau" braucht.
Sicherer kommt mir nach wie vor die Version vor, alle Schritte
mitzuprotokollieren, denn dann ist der Zugriff des Besuchers nur Ok
wenn er 5 Links mit 5 Timestamps geklickt hat, wenn er auf einen
dieser zurückspringt und nicht nur wenn der Timestamp kleiner als
der jetzige ist.
Nun könnte ich ja in der Datenbank die Timestamps eintragen, wenn er
nun auf zurück geht, habe ich den Eintrag bereits da - ich weiß also
dass er in der History zurückmaschiert ist, geht er auf vorwärts
springt er zu seinem nächsten Datensatz in der DB. Klickt er aber auf
einen Link, kommt ein neuer, noch nicht vorhandener Timestamp in der
Datenbank und ich kann alle Einträge die größer sind als der Eintrag
vor dem Klick auf den Link löschen. Sehe ich das richtig?
Genau das habe ich gemeint. Solange der innerhalb des Films nur bereits
bekannte Einträge abfährt, bleibt Dein Film erhalten. Wenn ein Request
kommt, kannst Du also prüfen, ob
a) Du den Timestamp schon in Deinem Film hast und
b) ob die dabei übertragenen Daten mit den in Deinem Film gespeicherten
übereinstimmen.
Wenn der Kunde beispielsweise die Anzahl der Waren, die er in seinen
Warenkorb legt, nachträglich ändert, dann sendet er Dir den von Deinem
Shop gelieferten Timestamp zurück, aber abweichende Daten - nun ist es
Dein Job, diese als "anders" zu erkennen und ihm als Antwort eine neue
Seite mit neuem Timestamp zu senden ... hier beginnt der "neue Ast".
(Und genau in diesem Moment kannst Du den Film "kürzen", weil der Browser
es in seiner history genau jetzt ebenfalls tut.)
Und noch eine abschließende Frage - sehr oft habe ich auf meine Idee
mit den ändernden Timestamps die Meinung gehört, dass dies nicht
sinnvoll wäre, aufgrund der vielen Einträge - Erhöhung der Ladezeiten,
Datenbank-Overflow. Datenbank-Overflow mache ich mir weniger sorgen,
da auch ich vorhabe, Einträge nach bestimmter Zeit zu löschen (z.b.
wenn letzter Timestamp der SessionID länger als 1 Stunde von now,
dann delete).
Genauso gut kannst Du den Transaktionsfilm löschen, wenn die Transaktion
erfolgreich beendet oder explizit abgebrochen worden ist.
Das passiert innerhalb des RDBMS beim "commit": Die Änderungen an den
Tabellen werden festgeschrieben, und das Rollback-Segment wird vom
Ballast der Zwischenergebnisse befreit.
Das Ganze von einer zeitlichen Komponente abhängig zu machen ist m. E.
alleine nicht die beste Lösung. Denn Du willst diese Zeit einerseits
nicht so kurz machen, daß eine Zigarettenpause Deines Kunden die Session
abbricht, aber ansonsten so kurz wie möglich, um die Menge der Daten
so klein wie möglich zu halten.
Insofern wirst Du wahrscheinlich eine Mischung aus beidem haben wollen:
a) bei definierter Beendigung einer Transaktion sofort löschen.
b) periodisch alle veralteten Einträge (einige Stunden?) aufräumen.
Wie sieht es aber mit Ladezeiten aus? Kosten mich die Abfragen ob der
Timestamp bereits vorhanden ist (evt. auch in einer Cache-Tabelle)
und der Eintrag von neuen Timestamps viel Zeit oder ist dies
vertretbar?
Innerhalb der Transaktionsfilmtabelle liegt der Primärschlüssel auf dem
Paar aus Session-ID und Timestamp - damit bekommst Du sehr performant
exakte Treffer. Und wenn Du diese Transaktionsfilmtabelle von der
zusätzlich erforderlichen dauerhaften Aufbewahrung der Transaktionen
(um dem Kunden später nachweisen zu können, wann er was gekauft hat)
trennst, hast Du
a) eine große Archiv-Tabelle, die selten geändert wird und
b) eine kleine Film-Tabelle, die ständig geändert wird.
Da diese kleine Tabelle immer mal wieder komplett leer wird, ist es
nicht schlimm, daß sie ständig geändert wird - zwar degeneriert der
Index erheblich, aber er wird ja auch immer mal wieder komplett
abgebaut.
Bei jeder Änderung des Tabelleninhalts muß der Primärschlüsselindex
mitgepflegt werden - das ist aber nicht ungewöhnlich aufwändig.
Wie ich schon zweimal erwähnt habe, würde diese Filmtabelle in etwa
das nachbilden, was eine Datenbank mit einem Rollback-Segment tut.
(Während das Transaktions-Archiv Deines Shops dann in etwa der eigent-
lichen Tabelle entspricht.)
Und so, wie eine Datenbank auf ihr eigenes Rollback-Segment performanter
zugreifen kann als auf eine echte Tabelle, könntest auch Du versuchen,
die Filmtabelle (kleiner, aber mit viel mehr Änderungen als das Archiv)
in einem performanteren Modus laufen zu lassen.
Vielleicht läßt sich diese Tabelle ja komplett im Hauptspeicher halten?
(Das wäre ein Tuning-Job für den DB-Administrator.)
Viele Grüße
Michael
P.S.: Deine Fragestellungen tendieren dazu, interessant zu sein. :-)