Hi,

um dir vielleicht noch einen interessanten Denkansatz zu geben, der hier noch nicht erwähnt wurde - und etwas, dass du beim schreiben von Code durchaus im Kopf haben solltest: Das ist ein klassisches Szenario für eine 'Timing Attack'.

Wenn in Python (und den meisten anderen Sprachen) zwei strings verglichen werden, dann werden in wirklichkeit alle chars des strings nacheinander verglichen. Es wird genau genommen erst geguckt ob die strings gleich lang sind, wenn ja wird über jedes Zeichen des ersten strings iteriert und mit dem Zeichen, an gleicher stelle, des zweiten Strings verglichen. Sobald ein Zeichen abweicht wird der Vergleich beendet und als 'false' evaluiert.

userpw == passwort

ist in echt ziemlich genau das gleiche wie:

def str_equals(userpw, passwort):
    if len(userpw) != len(passwort):
        return False

    for c1, c2 in zip(userpw, passwort):
        if c1 != c2:
            return False

    return True

Gut, aber wie kann man das exploiten?
Ganz einfach: Je mehr Zeichen verglichen werden, desto länger dauert der Vergleich.

Wenn du (in deinem Fall wo das korrekte Passwort "geheim" ist) "aasd" eingegeben hättest, würde er sofort abbrechen, da die beiden strings noch nicht mal gleich lang sind. Hättest du "asddsa" eingegeben würde es schon ein bisschen länger dauern, da er zumindest das erste Zeichen vergleicht. "gehopp" würde noch länger dauern, da er erst beim vierten Zeichen abbricht.

Du kannst bruteforcen - aber anstatt blind zu raten, kannst du gucken wie lange das Programm braucht, um festzustellen, dass dein eingegebenes Passwort falsch war. Zu erst änderst du die Länge des geratenen Passworts, bis das Programm ein bisschen länger braucht um festzustellen, dass das Passwort falsch ist. Das verrät dir, dass die Länge nun stimmen muss. Dann änderst du so lange das erste Zeichen bis die Zeit noch ein bisschen länger wird, wenn das passiert weißt du, dass der erste Buchstabe richtig ist. Und so weiter.

Um zu verdeutlichen was das bedeutet: Dein Passwort "geheim" besteht aus 6 Zeichen. Würden wir ganz naiv jede mögliche Kombination ausprobieren, und es wären nur Buchstaben und Zahlen möglich, dann gäbe es 36 mögliche Zeichen. Das bedeutet 6³⁶ verschiedene Möglichkeiten (= 10314424798490535546171949056 verschiedene Passwörter). Dadurch, dass wir allerdings an jeder Stelle feststellen können ob das Zeichen richtig ist, sind es auf einmal keine 6³⁶ Möglichkeiten mehr, sondern lediglich 6*36 (= 216). Bedeutet, wir müssen im schlechtesten Fall 216 mal raten - statt 10314424798490535546171949056 mal.

Und genau das ist der Grund, warum es sichere Funktionen für stringvergleiche gibt, etwa https://docs.python.org/3/library/hmac.html#hmac.compare_digest

Viele Grüße

...zur Antwort
Weitere Inhalte können nur Nutzer sehen, die bei uns eingeloggt sind.