2015-04-07 9 views
5

Ich habe versucht, Informationen darüber zu finden, ob password_verify() Längenkonstante Zeitvergleich verwendet, um Timing-Angriff zu vermeiden.PHP password_verify() und langsam gleich Vergleich

Nun einfaches Beispiel:

$hash = '$2y$10$HH3906lfby7HOy1N3duQh.Kju.84ct6AcMZm2p/SYZsZSXuYWvvT.'; 

$startTime = microtime(TRUE); 
password_verify('rasmuslerdorf', $hash); 
$endTime = microtime(TRUE); 

$time = $endTime - $startTime; 

Dies erzeugt immer etwas andere Ausgabe, die nach this article (Länge Konstante ‚Zeit„Warum wird der Hash-Code auf dieser Seite die Hashes in vergleichen‘? " Absatz", könnte in Timing-Angriff verwendet werden, um einen Hash abzuholen. Ich denke, diese Ergebnisse sehen eher zufällig aus, aber sie sind sicherlich nicht konstant.

Frage ist, verwendet password_verify() verwendet Länge-Konstante-Zeit-Vergleich, Timing-Angriff zu vermeiden? Keine Informationen in den Dokumenten und aufgrund meiner geringen Erfahrung kann ich die Ergebnisse der Funktionsverarbeitung nicht gut interpretieren.

Antwort

8

Die Antwort ist JA, es verwendet Längen-Konstante Zeitvergleich.

Dies ist ein Auszug aus password_verify Funktion des php

/* We're using this method instead of == in order to provide 
* resistance towards timing attacks. This is a constant time 
* equality check that will always check every byte of both 
* values. */ 
for (i = 0; i < hash_len; i++) { 
    status |= (ret->val[i]^hash[i]); 
} 

Sie einen Blick auf die vollständigen Quellcode haben, können bei https://github.com/php/php-src/blob/master/ext/standard/password.c

+0

Vielen Dank! Habe dieses Repo noch nie zuvor gesehen. – Nevertheless

4

Kurze Antwort: Ja, es tut.

Lange Antwort: es ist nicht notwendig.

Um zu verstehen, warum es nicht notwendig ist, müssen wir auf den Saiten suchen verglichen werden:

$2y$10$9JxHB8U1QKsLS/ynplKzm.iIO7f6gtTKYA61ppVuANYxWNCA5DW1S 
$2y$10$ILlWQrYyDJvHHkxcCgjm7OThLRAmMcTzsJOZOwjaSYiRUHq8LVYde 
$2y$10$8JfydDKUNbOeiybwZ9m.j.5TC8CBqkc3RZu2DX42A4dFNpNYPWfzm 
$2y$10$qeG.53lr9PVVGN4Yk.kSZuOMpfone5kINyWVpAf2gUXPseU2WdSzK 
$2y$10$nZUgPUwiXIvCJ9BY1wbtbuV5vH6yff9CNyumFsI/NN2eJmf20iec. 

Die 5 verschiedene Hashes mit dem gleichen Passwort sind. Das Format ist:

$2y$10$saltsaltsaltsaltsaltsahashhashhashhashhashhashhashhas 

nun zu einem entfernten Angreifer (derjenige, der Timing-Angriffe würden laufen), das Salz ein Geheimnis. Und das Salz ist das gleiche, wenn wir ihren Versuch wiederholen. Zum Beispiel:

stored password "test": 
hash = $2y$10$9JxHB8U1QKsLS/ynplKzm.iIO7f6gtTKYA61ppVuANYxWNCA5DW1S 

Wenn der Angreifer das Passwort "abc" versucht, intern password_verify()crypt("abc", hash) nennen. Welche führen zu:

$2y$10$9JxHB8U1QKsLS/ynplKzm.FTYpGS/gNDw4SB6YD0wEtCSPgGvtPim 

Jetzt ist bei diesen beiden Hashes aussehen lassen, nebeneinander:

$2y$10$9JxHB8U1QKsLS/ynplKzm.iIO7f6gtTKYA61ppVuANYxWNCA5DW1S 
$2y$10$9JxHB8U1QKsLS/ynplKzm.FTYpGS/gNDw4SB6YD0wEtCSPgGvtPim 

Hinweis das Salz das gleiche ist? Beachten Sie, dass alles bis zum ersten . gleich ist. Beachten Sie auch, dass der Angreifer keine Ahnung hat, was das Salz ist.

Wenn der Angreifer in der Lage war, den Vergleich zu timpfen, würde das nicht helfen. Weil sie das Salz nicht kennen (und daher ableiten, was das Hash ist, verschwendet es einfach Zeit, denn ohne das Salz können sie das Passwort nicht bestimmen).

So Timing-Sicherheit ist nicht unbedingt erforderlich.

Warum ist es dann enthalten? Weil jeder Fehler macht. Weil Verteidigung in der Tiefe eine gute Idee ist.Weil diese Analyse annimmt, dass nichts über den Hash ohne das Salz nützlich ist (zB: Was ist, wenn ein Fehler in bcrypt die Hashes basierend auf dem Passwort verzerrt, so dass ohne Kenntnis des Salzes der Schlüsselraum von 72^255 reduziert wird).

Kurz gesagt, es ist eine gute Sache zu haben, aber es ist nicht unbedingt notwendig ...