JavaScript: Zufallsgenerator für Diffie-Hellman rückrechnen
Verfasst: Mi Sep 26, 2012 11:49 pm
Hallo 
Mal ein Web-Problem der etwas anderen Art ^^ Vorweg, hier geht es um eine Situation in einer Test-Umgebung. Ich mache hier nichts Illegales ^^
Die Lage sieht folgendermaßen aus:
Ich habe ein Kontakt-Formular, über das eine Nachricht abgeschickt wird. Diese Nachricht wird lokal über JavaScript mit AES (OFB) verschlüsselt. Nun habe ich einen HTTP-Trace (http://pastebin.com/HpGMNn9w), dessen Text ich entschlüsseln soll. Verschlüsselt wird über folgenden Script: http://pastebin.com/7r3mtTAv
Beim Abschicken des Formulars wird die "send()"-Methode ausgeführt.
Weiters habe ich den Hinweis, dass der Bug etwas mit dem Zufallsgenerator zu tun hat.
Ich hab Zugang zum Formular und kann selbst Daten eingeben, die danach verschickt werden. Ich kann den Ablauf also komplett nachvollziehen.
Soweit zur Angabe, jetzt mal meine Erkenntnisse:
Der Script implementiert einen Diffie-Hellman-Schlüsselaustausch (http://de.wikipedia.org/wiki/Diffie-Hel ... laustausch), mit dem dann der AES-Schlüssel erstellt wird. Was mir nun fehlt um den Text im Trace wieder herzustellen, ist die Zufallszahl des Clients ("randomValue" im Script). Diese über Bruteforce auszurechnen ist unpraktisch. Der Schlüssel hat 16 Byte, also hab ich 256^16 Möglichkeiten, was laut Python 340282366920938463463374607431768211456 sind... etwas zu viel für meinen Laptop ^^
Was nun? Sehen wir uns folgenden Code an:
"iv" (Initialization Vector des AES-Hashs: http://de.wikipedia.org/wiki/Initialisierungsvektor) wird unverschlüsselt übertragen und ist dadurch auch im HTTP-Trace vorhanden. Ich kenne also jedes Byte, das zwischen den Bytes der Zufallszahlen erzeugt wird. Da alle üblichen Browser Predictable Random Number Generators (PRNG, http://en.wikipedia.org/wiki/Random_num ... tor_attack) verwenden, könnte man den Status des Zufallsgenerators rekonstruieren und dadurch auf vorherige bwz. nachfolgende Zahlen schließen (http://landing2.trusteer.com/sites/defa ... -3.6.8.pdf). Was ist das Problem dabei? Dass ich die Zufallszahlen nicht vollständig kenne:
Ich multipliziere sie mit 256 und verwende anschließend den Integer-Anteil. Dadurch verliere ich die Informationen über die Nachkommastellen.
Blöde Frage... Welchen Typ hat Math.random() überhaupt? Entspricht das einem double in C/++? long double? Hängt das vom Browser/Betriebssystem ab? Da ich das Problem (spätestens beim Rekonstruieren) auf Bit-Ebene vermute, wäre das sehr wichtig zu wissen.
Ich hab schon einen Ansatz gehabt ein Ergebnis-Byte durch 256 zu dividieren und das Ergebnis so lange zu erhöhen, bis der Status auch für alle nachfolgenden stimmte (Wobei zwischendurch natürlich immer eine Stelle übersprungen wird, die für "iv" verwendet wird). Das ist einerseits schlecht, weil ich dabei eine Fließkommazahl erhöhe, andererseits habe ich noch keinen Code gefunden, der mir nachfolgende/vorhergehende Zahlen berechnet, da muss ich schlimmstenfalls selbst ran.
So... ich bin inzwischen recht ratlos, hat irgendjemand auch nur den Ansatz einer Idee? ^^
Besten Dank im Voraus

Mal ein Web-Problem der etwas anderen Art ^^ Vorweg, hier geht es um eine Situation in einer Test-Umgebung. Ich mache hier nichts Illegales ^^
Die Lage sieht folgendermaßen aus:
Ich habe ein Kontakt-Formular, über das eine Nachricht abgeschickt wird. Diese Nachricht wird lokal über JavaScript mit AES (OFB) verschlüsselt. Nun habe ich einen HTTP-Trace (http://pastebin.com/HpGMNn9w), dessen Text ich entschlüsseln soll. Verschlüsselt wird über folgenden Script: http://pastebin.com/7r3mtTAv
Beim Abschicken des Formulars wird die "send()"-Methode ausgeführt.
Weiters habe ich den Hinweis, dass der Bug etwas mit dem Zufallsgenerator zu tun hat.
Ich hab Zugang zum Formular und kann selbst Daten eingeben, die danach verschickt werden. Ich kann den Ablauf also komplett nachvollziehen.
Soweit zur Angabe, jetzt mal meine Erkenntnisse:
Der Script implementiert einen Diffie-Hellman-Schlüsselaustausch (http://de.wikipedia.org/wiki/Diffie-Hel ... laustausch), mit dem dann der AES-Schlüssel erstellt wird. Was mir nun fehlt um den Text im Trace wieder herzustellen, ist die Zufallszahl des Clients ("randomValue" im Script). Diese über Bruteforce auszurechnen ist unpraktisch. Der Schlüssel hat 16 Byte, also hab ich 256^16 Möglichkeiten, was laut Python 340282366920938463463374607431768211456 sind... etwas zu viel für meinen Laptop ^^
Was nun? Sehen wir uns folgenden Code an:
Code: Alles auswählen
for (i=0; i<c ; i++) {
randomValue.appendByte(getRandom(0, 255));
iv.appendByte(getRandom(0, 255));
}
Code: Alles auswählen
function getRandom( min, max ) {
if( min > max ) {
return( -1 );
}
if( min == max ) {
return( min );
}
return( min + parseInt( Math.random() * ( max-min+1 ) ) );
}
Blöde Frage... Welchen Typ hat Math.random() überhaupt? Entspricht das einem double in C/++? long double? Hängt das vom Browser/Betriebssystem ab? Da ich das Problem (spätestens beim Rekonstruieren) auf Bit-Ebene vermute, wäre das sehr wichtig zu wissen.
Ich hab schon einen Ansatz gehabt ein Ergebnis-Byte durch 256 zu dividieren und das Ergebnis so lange zu erhöhen, bis der Status auch für alle nachfolgenden stimmte (Wobei zwischendurch natürlich immer eine Stelle übersprungen wird, die für "iv" verwendet wird). Das ist einerseits schlecht, weil ich dabei eine Fließkommazahl erhöhe, andererseits habe ich noch keinen Code gefunden, der mir nachfolgende/vorhergehende Zahlen berechnet, da muss ich schlimmstenfalls selbst ran.
So... ich bin inzwischen recht ratlos, hat irgendjemand auch nur den Ansatz einer Idee? ^^
Besten Dank im Voraus
