Andreas: Hacker-Angriff auf geschützen HTTP-Bereich erkennen

Hallo!
Nachdem wir unten (http://forum.de.selfhtml.org/?m=74095&t=13386) sehr ausführlich über die Sicherheit eines hauptsächlich über Sessions geschützen HTTP-Bereich diskutiert haben, ist jetzt noch die Frage offen, wie man einen Hackerangriff darauf erkennt, und nicht tagelang über ein Script 'probiert' werden kann.

Auf alle Fälle werde ich SSL verwenden, dann einen eingeloggten Besucher in einer Session registrieren, und gleichzeitig einen Cookie mit Timestamp und evtl. noch einer Information speichern, diese natürlich auch in der Session für die Kontrolle auf jeder geschützen Seite, und darüber hinaus noch den User-Agent auf jeder Seite kontrolliere. Ich habe mit einen Augen noch keinen sich über eine Session verändernden User-Agent gesehen!

Das besagte Problem ist jetzt - wie erkenne ich es, ob sich ein Hacker(oder besser Cracker) versucht einzuloggen - wenn man das so nennen kann :-).
Erstmal - kann man noch andere Angriffe als Brute-Force berücksichtigen? Aber auch die Brute-Force Angriffe sind nicht unbedingt leicht zu erkennen, oder? Man könnte ja einfach die mißlungenen Versuche loggen, und wenn das in 1 Minute mehr als 10 sind dann IP direkt abwehren. Nur kann man ja die IP zwischen den einzelnen Zugriffen über Proxies doch ändern, oder? Und wie könnte ich das erkennen bzw. verhindern?
Vielleicht über den User-Agent, wenn da in 1 Minute 50 mal der gleiche steht, dann Ende?
Wie würdet Ihr das machen und was sollte ich Eurer Meinung nach noch berücksichtigen?

Viele Grüße
Andreas

  1. Erstmal - kann man noch andere Angriffe als Brute-Force berücksichtigen? Aber auch die Brute-Force Angriffe sind nicht unbedingt leicht zu erkennen, oder? Man könnte ja einfach die mißlungenen Versuche loggen, und wenn das in 1 Minute mehr als 10 sind dann IP direkt abwehren. Nur kann man ja die IP zwischen den einzelnen Zugriffen über Proxies doch ändern, oder? Und wie könnte ich das erkennen bzw. verhindern?

    Das wäre aber mühsam, wenn ich für jeden Zugriff den Proxy wechseln müßte - Brute Force muß ja sehr schnell sein, sonst hat's gar keinen Sinn.
    Brute Force erkennt und blockt man am besten über Logfiles und den Provider.
    Einen sicheren Schutz kriegst Du auch ganz leicht:
    1. Session ID mitführen.
    2. Session ID plus geheimen String nehmen, MD5 davon und auch mitführen.

    So müßte jemand die Session ID (bei PHP glaube ich 128 bit) _und_ den Secret Key (kannst ja auch noch mal 128 bit lang machen) erraten - per Brute Force keine Chance. Wir reden hier ja vom Web, da kannste nicht 1 Milliarde Schlüssel pro Sekunde durchprobieren.

    1. Hi!

      Das wäre aber mühsam, wenn ich für jeden Zugriff den Proxy wechseln müßte - Brute Force muß ja sehr schnell sein, sonst hat's gar keinen Sinn.
      Brute Force erkennt und blockt man am besten über Logfiles und den Provider.
      Einen sicheren Schutz kriegst Du auch ganz leicht:

      1. Session ID mitführen.

      was meinst Du mit mitführen?

      1. Session ID plus geheimen String nehmen, MD5 davon und auch mitführen.

      Wenn ich die SessionID verlängere hat mir Sven vorgerechnet, das es zar deutlich schwieriger wird, aber selbst die sessionID alleine ist schon schwer genug zu knacken!

      So müßte jemand die Session ID (bei PHP glaube ich 128 bit) _und_ den Secret Key (kannst ja auch noch mal 128 bit lang machen) erraten - per Brute Force keine Chance. Wir reden hier ja vom Web, da kannste nicht 1 Milliarde Schlüssel pro Sekunde durchprobieren.

      Ja, aber ich denke auch nicht, das jemand per Brute-Force probieren wird die SessionID zu knacken, sondern eher das Passwort oder Benutzername der Login-Seite! Kann ich irgendwie sicherstellen, das die das Script mit der login-Überprüfung nur definitiv nur eingaben von meiner Eingabeseite zuläßt? Referer ist ja nicht sicher, und alles was mir einfiele könnte man sehr einfach nachbilden und stünde auch im html-Code. Über $_POST ist das doch auch nicht sichergestellt, das trifft doch auf jeden POST Request zu, oder?

      Also logge gene ich direkt sessions mit, nicht erst bei der Anmeldung, und logge IP, SessionID, User-Agent und Zeitpunkt, dann kann ich gucken ob gleiche Session ID, oder Kombination aus IP und SessionID, oder ähnliches, und wenn bestimmt eGrenzwerte überschritten werden, wird IP, SessionID gesperrt. Oder? Was sagt Ihr dazu?

      Grüße
      Andreas

  2. Moin,

    Nachdem wir unten (http://forum.de.selfhtml.org/?m=74095&t=13386) sehr ausführlich über die Sicherheit eines hauptsächlich über Sessions geschützen HTTP-Bereich diskutiert haben, ist jetzt noch die Frage offen, wie man einen Hackerangriff darauf erkennt, und nicht tagelang über ein Script 'probiert' werden kann.

    Traditionellerweise fügt man einfach ein sleep(3) (evt. auch mit anderen Werten für 3) ein, wenn man feststellt dass das Passwort falsch ist. Wenn deine Passwörter so gewählt sind, dass sie sich mit einem Versuch alle 3 Sekunden in annehmbarer Zeit brute forcen lassen, dann hast du was falsch gemacht.

    Immer wieder schön ist es auch, die Anzahl fehlgeschlagener Versuche pro Benutzernamen zu speichern und die Zwangspause Stück-für-Stück zu erhöhen, bzw. den Benutzernamen nach einer festgelegten Zahl an Fehlversuchen (bei T-Online beispielsweise soweit ich weiss 9) für einen Tag ganz und gar zu sperren, unabhängig vom Passwort. (Sinnvollerweise macht man das nicht mit dem Administratoraccount, aber der hat eh ein sicheres Passwort zu haben)

    Eventuell musst du dann auch zu einem erfolgreichen Login eine kleine Zwangspause einführen damit man nicht erfolgreich/erfolglos allein schon an der Zeitdauer bis zur Antwort unterscheiden kann.

    Eine Art lockfile anzulegen, um parallele Einlogversuche (zumindest für den gleichen Benutzername) zu verhindern ist sicher auch nicht falsch.

    --
    Henryk Plötz
    Grüße aus Berlin

    1. hi!

      Traditionellerweise fügt man einfach ein sleep(3) (evt. auch mit anderen Werten für 3) ein, wenn man feststellt dass das Passwort falsch ist. Wenn deine Passwörter so gewählt sind, dass sie sich mit einem Versuch alle 3 Sekunden in annehmbarer Zeit brute forcen lassen, dann hast du was falsch gemacht.

      stimmt, da hatte ich auch schon dran gedacht, das ist wohl das beste.

      Immer wieder schön ist es auch, die Anzahl fehlgeschlagener Versuche pro Benutzernamen zu speichern und die Zwangspause Stück-für-Stück zu erhöhen, bzw. den Benutzernamen nach einer festgelegten Zahl an Fehlversuchen (bei T-Online beispielsweise soweit ich weiss 9) für einen Tag ganz und gar zu sperren, unabhängig vom Passwort. (Sinnvollerweise macht man das nicht mit dem Administratoraccount, aber der hat eh ein sicheres Passwort zu haben)

      Ja, aber da ist das Problem, wie erkenne ich einen "2. versuch"? Viele User haben über Poxies schonmal die gleiche IP. Und dann? Sperrst Du alle User mit der IP? Cookies allgemein, oder SessionID wird wohl kein brute-force script mit zurück schicken, also auch nutzlos. Das einzige was mit noch einfile, wäre der "auch manipulierbare) User-Agent in Kombination mit IP und noch irgendeinem sicheren merkmal. Aber auch das ist nicht wirklich gut. Das ist mal wieder dasselbe Problem wie, wie im Thread mit dem schützen des Bereiches überhaupt aufgetaucht war, Clients wiederzuerkennen.

      Eventuell musst du dann auch zu einem erfolgreichen Login eine kleine Zwangspause einführen damit man nicht erfolgreich/erfolglos allein schon an der Zeitdauer bis zur Antwort unterscheiden kann.

      Hm? verestehe ich nicht. Was ist daran so schlimm, wenn man das unterscheiden kann? Ändert doch nichts an der Sicherheit, oder? Sonst würde ich evtl sleep() direkt am Anfang einfügen, da wird das dann immer ausgeführt, nur was brächte das?

      Eine Art lockfile anzulegen, um parallele Einlogversuche (zumindest für den gleichen Benutzername) zu verhindern ist sicher auch nicht falsch.

      Das ist gut, eingegebenen Benutzernamen loggen. So weit ich weiß funktionieren die meisten Programme so, dass zu einem bestimmten Benutzernamen per brute-force Passwörter probiert werden. Dann häte man ja einträge mit immer demselben Passwort.

      Und wie sollte man dann reagieren? Unterschiedlich ob es ein existierender Benutzername ist, oder nicht? Was könnte man überhaupt noch machen? IP sperren geht wohl nicht, und wenn der keine SesionID oder Cookie hat, kann man da schlecht irgendwas sperren, außer den Benutzername, wenn der existiert. Aber die idee mit sleep() ist wirklich gut, könnte man ja wirklich bei zu vielen vergeblichen Versuchen von einer IP oder mit einem Username weiter hochsetzen.

      Grüße
      -- Andreas

      --
      Henryk Plötz
      Grüße aus Berlin

      1. Moin,

        Ja, aber da ist das Problem, wie erkenne ich einen "2. versuch"?

        Da wiederhole ich mich ungern aber:

        Immer wieder schön ist es auch, die Anzahl fehlgeschlagener Versuche _pro_Benutzernamen_ zu speichern

        Alles was ich angesprochen habe gilt pro Benutzername, anders gibt das keinen Sinn.

        Hm? verestehe ich nicht. Was ist daran so schlimm, wenn man das unterscheiden kann?

        Naja, man könnte sonst das Brute Forcen um etwa den Faktor 3 beschleunigen: Kommt nach 1 Sekunde keine positive Antwort, muss davon ausgegangen werden, dass das Passwort falsch war, also nochmal probieren. Das erschlägt man dann mit lockfiles gleich mit. Im Nachhinein überlege ich mir grade, dass man die sowieso haben will, ansonsten kommt einer auf die Idee soviele gleichzeitige Einloggversuche zu starten, wie Server gleichzeitig verfügbar sind (soweit ich weiss standardmäßig etwa 150 beim Apache). Auf diese Weise könnte man glatt 150 verschiedene Passwörter pro 3 Sekunden (alle Zahlen natürlich je nach Konfiguration) ausprobieren. (Das würde der Admin aber sehr schnell bemerken, da der normale Serverbetrieb davon stark beeinträchtigt werden würde). Achja, die maximale Fehlversuchszahl würde das auch verhindern.

        Das ist gut, eingegebenen Benutzernamen loggen. So weit ich weiß funktionieren die meisten Programme so, dass zu einem bestimmten Benutzernamen per brute-force Passwörter probiert werden. Dann häte man ja einträge mit immer demselben Passwort.

        Alles andere wäre auch sinnfrei.

        Und wie sollte man dann reagieren? Unterschiedlich ob es ein existierender Benutzername ist, oder nicht?

        Blöde Idee[tm], da man so evt. an die Information ob ein bestimmter Benutzername existiert oder nicht kommen könnte. Die Reaktion auf Benutzername existiert nicht und Passwort für den Benutzernamen ist falsch muss exakt identisch sein. Daher werden die Fehlermeldungen üblicherweise als "Die Passwort/Benutzername-Kombination existiert nicht." (oder ähnlich) formuliert. Das liegt nicht etwa an der Faulheit der Programmierer.

        Aber die idee mit sleep() ist wirklich gut, könnte man ja wirklich bei zu vielen vergeblichen Versuchen von einer IP oder mit einem Username weiter hochsetzen.

        Das schrieb ich ja in meinem vorhergehenden Posting. Nach IP zu sperren ist übrigens keine so gute Idee, da das bei Proxies schonmal zu Problemen führen kann: die Wahrscheinlichkeit dass sich x Benutzer hinter der gleichen IP sitzen, und nahezu gleichzeitig einloggen wollen ist je nach System das geschützt werden soll so niedrig nicht. Etwa wenn in der Schule die Internetverbindung für den Rest der Stunde für persönliche Zwecke freigegeben wird und alle sich gleichzeitig bei GMX einloggen wollen.

        --
        Henryk Plötz
        Grüße aus Berlin