Eigenes Passwort in Python "hacken"?
Hallo,
Ich habe hier:
#Variablen zuteilen
passwort = "geheim"
userpw = ""
while userpw != passwort: #Whileschleife
print("Passwort: ")
userpw = input()
if userpw == passwort: #If-Verzweigung
print("Das Passwort ist richtig! ")
break
...ein ganz einfaches Programm in Python geschrieben, welches dich so lange nach einem Passwort fragt, bis es richtig ist. Nun meine Frage:
Kann man, und wenn ja wie, ein anderes Programm in Python schreiben welches probiert das Passwort zu hacken? Entweder mit einem Dictionary, oder mit Brute-Force. Oder anders?
Danke schonmal:)
2 Antworten
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
Aus meinen Buch "Hacken mit Python und Kali-Linux":
import sys, hashlib, time
ts = time.time()
if len(sys.argv) != 3:
print("USAGE:")
print("./" + sys.argv[0] + " [HASHFILE] [WORDLIST] \n")
sys.exit()
hashes = []
with open(sys.argv[1], "r") as hashfile:
for line in hashfile:
hashes.append(line.strip())
print("Start cracking ...")
with open(sys.argv[2], "r") as wordlist:
for line in wordlist:
line = line.strip('\n')
md5_hash = hashlib.md5(line.encode()).hexdigest()
if md5_hash in hashes:
print(md5_hash + " == " + line)
td = time.time() - ts
print("Done in " + str(td) + " sec.")
Je nach dem wie die Passwort-Hashes abgespeichert wurden (md5, SHA256, ...) muss die Zeile md5_hash = hashlib.md5(line.encode()).hexdigest() angepasst werden. Im Internet ist MD5 noch sehr weit verbreitet...
Gute Antwort. Allerdings sind es 36 hoch 6 = 2.176.728.336 Möglichkeiten für ein PW aus 6 Zeichen mit Kleinbuchstaben und Ziffern.