Hmac SHA256: Die Alternative zu HTTP Basic-Auth

Das klingt jetzt erstmal kompliziert, aber es ist notwendig. Das Problem ist, dass die HTTP-Basic-Auth immer nur über HTTPS Sinn macht, da ansonsten die HTTP-Header im Klartext zu lesen wären. Mit „Hmac SHA256“ könnte man sogar per HTTP relativ sicher Daten austauschen. Natürlich könnten die Daten selbst dann mitgelesen werden, aber niemand könnte die Daten abändern um sich z.B. selbst einen User anzulegen.

Wie funktioniert das?

Relativ simpel. Hier setzt die PHP-Funktion hash_hmac an. Diesen Methode nutzen zum Beispiel Facebook, Instagram oder Amazon S3 in den REST-Services. Hierzu wird einfach ein Secret-Key erstellt, der von beiden Parteien bekannt ist. Dieser wird dann genutzt, um Nachrichten zu Hashen. Dieser Hash wird dann gemeinsam mit der Nachricht übermittelt.

Die Gegenseite prüft dann mit dem Secret wieder, ob die Hashes übereinstimmen und führt die gewünschte Aktion aus. Der schlaue Leser stellt nun fest, dass man doch einfach eine Nachricht abfangen könnte, und später erneut senden. Das ist soweit auch richtig – vor Replay-Attacken schützt diese Methode nicht! Außerdem sollten die übermittelten Daten nicht sensibel sein – andernfalls muss man doch wieder auf HTTPS zurückgreifen!

Um sich vor Replay-Attacken zu schützen, muss man der Nachricht einfach nur einen Zeitstempel oder eine Message-Id mitgeben. Diese speichert man dann auf der Gegenseite ab, und erlaubt das erneute Ausführen von ein und der selben Message-Id oder älteren Nachrichten nicht mehr.

Kann man aus technischen Gründen nicht auf HTTPS zurückgreifen, könnte man den Body selbst natürlich auch noch verschlüsseln. Hier bietet es sich an, das Ganze über entsprechende RSA-Zertifikate zu lösen. Außerdem hätte man dann sogar die Chance, die Daten zu signieren. So wäre es möglich, alles mögliche zu Übermitteln, ohne dass jemand mit den Daten etwas anfangen kann. Geht man aber so weit, kann man die HMAC-Lösung auch direkt weglassen.

Technik

In PHP ist das Ganze schnell implementiert. Spricht man hier mit bestehenden REST-APIs, muss man sich vorher schlau machen, wie der Hash an die Nachricht gehängt werden soll. Hier gibt es ganz verschiedene Lösungen: Als Zusätzlicher Parameter im JSON, als GET-Parameter, als zusätzlicher HTTP-Header, oder sonst wie.

Ich würde empfehlen, den Hash im Header zu übergeben. So trennt man etwas intelligenter die Daten, und muss sich auf der Gegenseite nicht so viele Gedanken machen, wie man die Nachricht denn nun auseinander nehmen muss, bevor man den Hash kontrolliert.

$secret = '3b97a0faa1fd08df4c52d2993cc4b23389b9568e';
$hash = hash_hmac('sha256', 'Hier stehen ganz viele Informationen', $secret);

echo $hash;

Recht einfach, oder?


Beitrag veröffentlicht

in

, ,

von

Schlagwörter: