OpenID-Sicherheit:RPs stellen nicht sicher, dass die Authentifizierung vom tatsächlichen Anbieter genehmigt wurde
-
11-12-2019 - |
Frage
Allgemeine Beschreibung
Ich habe einen OP (OpenID Provider) implementiert mit DotNetOpenAuth.Ich teste es gegen Beispiel-RPs (vertrauende Parteien), wie z. B. Drupals OpenID-Login und das OpenIdRelyingPartyWebForms
projekt in den DotNetOpenAuth's Samples
Lösung.
Das Problem ist, dass, soweit ich das beurteilen kann, wenn ein Browser gegen mein OP prallt und eine "erfolgreiche Authentifizierungs" -Anfrage sendet (mode: id_res
, claimed_id: smth
, usw.) zurück zum RP versucht der RP nicht, eine serverseitige Anforderung an das OP auszuführen und zu fragen, ob der Benutzer tatsächlich authentifiziert wurde.Ich kann sehen, dass es eine gibt openid.sig
die Signatur wurde vom OP zurückgegeben, aber ich sehe auch hier nicht, wie der RP sie möglicherweise überprüfen könnte, da er keine Schlüssel mit dem OP ausgetauscht hat.
Die Frage ist also: Gibt es auf der OP-Seite eine Einstellung, die ich aktivieren kann, um den Workflow sicher zu machen?
Technische Details
Ich benutze Wireshark, um HTTP-Verkehr auf der RP-Seite zu schnüffeln.Es gibt kein HTTPS, also kann ich alle Nachrichten sehen und lesen.Unten sehen Sie, was genau passiert. B = Browser, AUF = OpenID-Anbieter, RP = Vertrauende Partei.Die Domainnamen werden durch * ersetzt.example.com .
(B –> RP) Der Benutzer versucht, eine Ressource nur für Mitglieder auf der vertrauenden Partei zu besuchen.Er gibt den OP-Endpunkt ein, den der Browser an den RP sendet.
openid_identifizierer: http://OP.example.com/OpenId/Provider.aspx?xrds
(RP -> OP -> RP) RP gibt eine serverseitige Anforderung an mein OP aus, die ein XRDS-Dokument zurückgibt.Ich kann hier nichts Ähnliches wie den Austausch geheimer Schlüssel sehen.
<?xml version="1.0" encoding="UTF-8"?> <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns:openid="http://openid.net/xmlns/1.0" xmlns="xri://$xrd*($v*2.0)"> <XRD> <Service priority="10"> <Type>http://specs.openid.net/auth/2.0/server</Type> <Type>http://openid.net/extensions/sreg/1.1</Type> <URI>http://OP.example.com/OpenId/Provider.aspx</URI> </Service> </XRD> </xrds:XRDS>
(RP –> B -> OP) Vertrauende Partei 302 - leitet den Benutzer zu OPS weiter
/OpenId/Provider.aspx?[params]
URL, wobei die Parameter die folgenden sind:openid.claimed_id: http://specs.openid.net/auth/2.0/identifier_select openid.identity: http://specs.openid.net/auth/2.0/identifier_select openid.assoc_handle: {634730422000625000}{jkQC1Q==}{32} openid.return_to: http://RP.example.com/login.aspx?ReturnUrl=%2FMembersOnly%2FDefault.aspx&dnoa.receiver=ctl00_Main_OpenIdLogin1&dnoa.UsePersistentCookie=Session&dnoa.userSuppliedIdentifier=http%3A%2F%2FOP.example.com%2FOpenId%2FProvider.aspx%3Fxrds openid.realm: http://RP.example.com/ openid.mode: checkid_setup openid.ns: http://specs.openid.net/auth/2.0 openid.ns.sreg: http://openid.net/extensions/sreg/1.1 openid.sreg.policy_url: http://RP.example.com/PrivacyPolicy.aspx openid.sreg.required: email,gender,postcode,timezone
(OP –> B -> RP) Der Provider authentifiziert den Benutzer und leitet ihn mit den folgenden URL-Parametern 302-mäßig zum RP zurück:
ReturnUrl: /MembersOnly/Default.aspx dnoa.receiver: ctl00_Main_OpenIdLogin1 dnoa.UsePersistentCookie: Session dnoa.userSuppliedIdentifier: http://OP.example.com/OpenId/Provider.aspx?xrds openid.claimed_id: http://OP.example.com/OpenId/User.aspx/2925 openid.identity: http://OP.example.com/OpenId/User.aspx/2925 openid.sig: pWJ0ugjQATKGgRSW740bml9LDsSxFiJ+a9OLO6NlsvY= openid.signed: claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.sreg,sreg.nickname,sreg.email openid.assoc_handle: {634730422000625000}{jkQC1Q==}{32} openid.op_endpoint: http://OP.example.com/OpenId/Provider.aspx openid.return_to: http://RP.example.com/login.aspx?ReturnUrl=%2FMembersOnly%2FDefault.aspx&dnoa.receiver=ctl00_Main_OpenIdLogin1&dnoa.UsePersistentCookie=Session&dnoa.userSuppliedIdentifier=http%3A%2F%2FOP.example.com%2FOpenId%2FProvider.aspx%3Fxrds openid.response_nonce: 2012-05-19T16:40:11ZSfsL4BK1 openid.mode: id_res openid.ns: http://specs.openid.net/auth/2.0 openid.ns.sreg: http://openid.net/extensions/sreg/1.1 openid.sreg.nickname: user@OP.example.com openid.sreg.email: user@OP.example.com
(RP -> OP) Der RP führt eine serverseitige HTTP-Anforderung an das OP aus.Es werden keine Daten übertragen, nur eine GET-Anfrage an die zuvor erfasste Benutzeridentitäts-URL.Warum stellt sie diese Bitte übrigens überhaupt?
GET /OpenId/User.aspx/2925 HTTP/1.1
(OP -> RP) Das OP antwortet mit einem anderen XRDS-Dokument:
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns:openid="http://openid.net/xmlns/1.0" xmlns="xri://$xrd*($v*2.0)"> <XRD> <Service priority="10"> <Type>http://specs.openid.net/auth/2.0/signon</Type> <Type>http://openid.net/extensions/sreg/1.1</Type> <URI>http://OP.example.com/OpenId/Provider.aspx</URI> </Service> <Service priority="20"> <Type>http://openid.net/signon/1.0</Type> <Type>http://openid.net/extensions/sreg/1.1</Type> <URI>http://OP.example.com/OpenId/Provider.aspx</URI> </Service> </XRD> </xrds:XRDS>
(RP –> B) Das war's.Der Benutzer ist autorisiert und RP zeigt ihm die Ressource nur für Mitglieder an.
Lösung
RPs kann in betrieben werden statusbehaftete oder Staatenlose modi (auch als intelligenter bzw. dummer Modus bezeichnet).Auschecken Netzwerkflussdiagramme für jeden.
Es findet ein einmaliger Schlüsselaustausch zwischen RP und OP statt, sofern der RP im statusbehafteten Modus arbeitet.Im zustandslosen Modus wird nach jeder Authentifizierung eine Nachricht vom RP an das OP angezeigt, um die Signatur der Assertion zu überprüfen.
In Bezug auf Ihre Frage zu # 5 (die HTTP-HEAD-Anfrage an die beanspruchte Kennung) ist dies der DotNetOpenAuth-RP, der überprüft, ob das OP für die Identität, die es behauptet, autoritativ ist.Da diese URL zuvor abgerufen wurde, wird der Cache aktiviert und die Inhaltsübertragung vermieden.
Andere Tipps
Ich fühle mich jetzt dumm, ich habe etwas Grundlegendes verpasst - da is ein Schlüsselaustausch zwischen RP und OP, aber es passiert nur einmal, und dann wird der Schlüssel für einige Zeit auf beiden Seiten zwischengespeichert.
Meine Implementierung des OpenID-Providers erweist sich also als sicher :)