Ich habe in zahlreichen Quellen gelesen, dass die Ausgabe von rand () von PHP als PRNG vorhersehbar ist, und ich akzeptiere das meistens als Tatsache, einfach weil ich es an so vielen Orten gesehen habe.
Ich bin an einem Proof-of-Concept interessiert: Wie würde ich die Ausgabe von rand () vorhersagen? Beim Lesen dieses Artikels habe ich verstanden, dass die Zufallszahl eine Zahl ist, die von einer Liste zurückgegeben wird, die mit einem Zeiger (dem Startwert) beginnt - aber ich kann mir nicht vorstellen, wie dies vorhersehbar ist.
Könnte jemand vernünftigerweise herausfinden, welche zufällige # zu einem bestimmten Zeitpunkt innerhalb weniger tausend Vermutungen über rand () generiert wurde? oder sogar 10.000 Vermutungen? Wie?
Dies ist darauf zurückzuführen, dass ich eine Authentifizierungsbibliothek gesehen habe, die rand () verwendet, um ein Token für Benutzer zu erstellen, die Kennwörter verloren haben, und ich nahm an, dass dies eine potenzielle Sicherheitslücke darstellt. Ich habe seitdem die Methode durch eine Mischung aus Hashing openssl_random_pseudo_bytes()
, dem ursprünglichen Hashing- Passwort und Microtime ersetzt. Nachdem ich dies getan hatte, stellte ich fest, dass ich keine Ahnung hätte, wie ich das Token erraten könnte, selbst wenn ich wüsste, dass es ein md5 von rand () ist.
Antworten:
Die Fähigkeit, den nächsten Wert zu erraten,
rand
hängt davon ab, zu bestimmen, womitsrand
aufgerufen wurde. Insbesondere das Säensrand
mit einer vorbestimmten Anzahl führt zu einer vorhersehbaren Ausgabe ! Über die interaktive PHP-Eingabeaufforderung:Dies ist nicht nur ein Zufall. Die meisten PHP-Versionen * auf den meisten Plattformen ** erzeugen
srand
bei 1024 die Sequenz 97, 97, 39, 77, 93 .Um es klar auszudrücken, dies ist kein Problem mit PHP, dies ist ein Problem mit der Implementierung von sich
rand
selbst. Dasselbe Problem tritt in anderen Sprachen auf, die dieselbe (oder eine ähnliche) Implementierung verwenden, einschließlich Perl.Der Trick ist, dass jede vernünftige Version von PHP
srand
einen "unbekannten" Wert hat. Oh, aber es ist nicht wirklich unbekannt. Vonext/standard/php_rand.h
:Also ist es ein bisschen Mathe mit
time()
, der PID und dem Ergebnis vonphp_combined_lcg
, das in definiert istext/standard/lcg.c
. Ich werde nicht hierher kommen, da meine Augen glasig wurden und ich beschloss, die Jagd einzustellen.Ein bisschen googeln zeigt, dass andere Bereiche von PHP nicht die besten Eigenschaften für die Zufallsgenerierung haben , und fordert dazu auf
php_combined_lcg
, hier hervorzuheben , insbesondere diese Art der Analyse:Ja das
uniqid
. Es scheint, dass der Wert von dasphp_combined_lcg
ist, was wir sehen, wenn wir die resultierenden hexadezimalen Ziffern betrachten, nachdem wiruniqid
das zweite Argument auf einen wahren Wert gesetzt haben.Wo waren wir jetzt?
Oh ja.
srand
.Wenn der Code, aus dem Sie zufällige Werte vorhersagen möchten, nicht aufgerufen wird
srand
, müssen Sie den von bereitgestellten Wert ermittelnphp_combined_lcg
, den Sie (indirekt?) Durch einen Aufruf von abrufen könnenuniqid
. Mit diesem Wert in der Hand ist es möglich , den Rest des Werts -time()
, die PID und etwas Mathematik - brachial zu erzwingen . Bei dem verknüpften Sicherheitsproblem geht es um das Unterbrechen von Sitzungen, aber die gleiche Technik würde hier funktionieren. Wieder aus dem Artikel:Ersetzen Sie einfach den letzten Schritt nach Bedarf.
(Dieses Sicherheitsproblem wurde in einer früheren PHP-Version (5.3.2) gemeldet als derzeit (5.3.6). Daher ist es möglich, dass sich das Verhalten von
uniqid
und / oderphp_combined_lcg
geändert hat, sodass diese spezielle Technik möglicherweise nicht mehr funktioniert. YMMV.)Auf der anderen Seite, wenn der Code , den Sie Produkt sind versuchen Anrufe
srand
manuell , dann , wenn sie nicht verwenden etwas oft besser als das Ergebnisphp_combined_lcg
, sind Sie wahrscheinlich eine viel haben , gehen leichte Zeit zu raten , den Wert und Säen Sie Ihre lokalen Generator mit der richtigen Nummer. Die meisten Leute, die manuell anrufensrand
würden , würden auch nicht erkennen, wie schrecklich eine Idee ist, und werden daher wahrscheinlich keine besseren Werte verwenden.Es ist erwähnenswert, dass
mt_rand
das gleiche Problem auch betroffen ist. Das Säenmt_srand
mit einem bekannten Wert führt auch zu vorhersehbaren Ergebnissen. Esopenssl_random_pseudo_bytes
ist wahrscheinlich sicherer, Ihre Entropie zu begründen .tl; dr: Um die besten Ergebnisse zu erzielen , sollten Sie den PHP-Zufallszahlengenerator nicht verwenden. Um Himmels willen, sollten Sie ihn nicht
uniqid
den Benutzern aussetzen . Wenn Sie eine oder beide dieser Methoden anwenden, sind Ihre Zufallszahlen möglicherweise besser zu erraten.Update für PHP 7:
PHP 7.0 führt
random_bytes
undrandom_int
als Kernfunktionen ein. Sie verwenden die CSPRNG-Implementierung des zugrunde liegenden Systems, wodurch sie frei von den Problemen sind, die ein Start-Zufallszahlengenerator hat. Sie sind praktisch ähnlichopenssl_random_pseudo_bytes
, nur ohne dass eine Erweiterung installiert werden muss. Für PHP5 ist eine Polyfill verfügbar .*: Der Suhosin-Sicherheitspatch ändert das Verhalten von
rand
undmt_rand
so, dass sie bei jedem Anruf neu generiert werden . Suhosin wird von Dritten bereitgestellt. Einige Linux-Distributionen enthalten es standardmäßig in ihren offiziellen PHP-Paketen, während andere es als Option festlegen und andere es vollständig ignorieren.**: Abhängig von der Plattform und den verwendeten zugrunde liegenden Bibliotheksaufrufen werden andere Sequenzen generiert als hier dokumentiert. Die Ergebnisse sollten jedoch weiterhin wiederholbar sein, es sei denn, der Suhosin-Patch wird verwendet.
quelle
Um visuell zu veranschaulichen, wie nicht zufällig die
rand()
Funktion ist, ist hier ein Bild, in dem alle Pixel aus "zufälligen" roten, grünen und blauen Werten bestehen:Normalerweise sollten die Bilder kein Muster enthalten.
Ich habe versucht,
srand()
mit verschiedenen Werten aufzurufen . Es ändert nichts daran, wie vorhersehbar diese Funktion ist.Beachten Sie, dass beide nicht kryptografisch sicher sind und vorhersehbare Ergebnisse liefern.
quelle
Es ist ein linearer Kongruenzgenerator . Das bedeutet Sie haben eine Funktion , die effektiv ist:
NEW_NUMBER = (A * OLD_NUMBER + B) MOD C
. Wenn Sie NEW_NUMBER gegen OLD_NUMBER ein Diagramm erstellen, werden diagonale Linien angezeigt. Einige der Hinweise in der RAND-Dokumentation von PHP enthalten Beispiele dafür.Auf einem Windows-Computer beträgt der Maximalwert von RAND 2 ^ 15. Dies gibt dem Angreifer nur 32.768 Überprüfungsmöglichkeiten.
Obwohl dieser Artikel nicht genau der ist, den Sie suchen, zeigt er, wie einige Forscher eine vorhandene Implementierung eines Zufallszahlengenerators nutzten, um mit Texas Holdem Geld zu verdienen. Es gibt 52! Mögliche gemischte Decks, aber die Implementierung verwendete einen 32-Bit-Zufallszahlengenerator (das ist die maximale Anzahl von mt_getrandmax auf einem Windows-Computer) und setzte die Zeit in Millisekunden seit Mitternacht fest. Dies reduzierte die Anzahl möglicher gemischter Decks von ungefähr 2 ^ 226 auf ungefähr 2 ^ 27, was es möglich machte, in Echtzeit zu suchen und zu wissen, welches Deck behandelt wurde.
Ich würde empfehlen, etwas aus der SHA-2- Familie zu verwenden, da die Regierung md5 als defekt ansieht. Einige Leute verwenden Google, um MD5-Hashes zu entschlüsseln, weil sie so häufig sind. Hasch einfach etwas und wirf dann den Hash in eine Google-Suche - im Grunde ist Google zu einem riesigen Regenbogentisch geworden .
quelle
Es ist wirklich genauer zu sagen, dass bei einer zufällig generierten Zahl die nächste relativ vorhersehbar ist. Es gibt nur so viele Zahlen, wie es sein kann. Das heißt aber nicht, dass Sie es erraten könnten, sondern eher, dass Sie ein Programm schreiben könnten, das es ziemlich schnell tut.
quelle