SAML: Warum befindet sich das Zertifikat in der Signatur?

103

Ich muss SSO mit SAML für die Website meines Unternehmens (als vertrauende Partei) implementieren. Ein wesentlicher Bestandteil des Kurses ist die Überprüfung der Unterschrift. Hier ist der Signaturteil einer SAML-Probe unserer Partnerfirma (behauptende Partei):

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
 <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
  <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
  <ds:Reference URI="#_2152811999472b94a0e9644dbc932cc3" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
     <ec:InclusiveNamespaces PrefixList="ds saml samlp xs" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    </ds:Transform>
   </ds:Transforms>
   <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
   <ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">bW1Os7+WykqRt5h0mdv9o3ZF0JI=</ds:DigestValue>
  </ds:Reference>
 </ds:SignedInfo>
 <ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
cgrAN4T/UmobhrkkTi3miiRfbo0Z7aakSZjXuTWlZlu9jDptxPNbOFw8ZbYKZYyuW544wQqgqpnG
gr5GBWILSngURjf2N45/GDv7HMrv/NRMsRMrgVfFsKbcAovQdLAs24O0Q9CH5UdADai1QtDro3jx
nl4x7HaWIo9F8Gp/H1c=
 </ds:SignatureValue>
 <ds:KeyInfo>
  <ds:X509Data>
   <ds:X509Certificate>MIIElzCCA3+gAwIBAgIQNT2i6HKJtCXFUFRB8qYsZjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQG
    EwJGUjEOMAwGA1UEBxMFUGFyaXMxDDAKBgNVBAoTA3BzYTEgMB4GA1UECxMXY2VydGlmaWNhdGUg
    YXV0aG9yaXRpZXMxKDAmBgNVBAMTH0FDIFBTQSBQZXVnZW90IENpdHJvZW4gUHJvZ3JhbXMwHhcN
    MDkwODE5MDcxNTE4WhcNMTEwODE5MDcxNTE5WjCBhjELMAkGA1UEBhMCZnIxHzAdBgkqhkiG9w0B
    CQEWEHBhc3NleHRAbXBzYS5jb20xGDAWBgoJkiaJk/IsZAEBEwhtZGVtb2IwMDEMMAoGA1UEChMD
    cHNhMREwDwYDVQQLEwhwcm9ncmFtczEbMBkGA1UEAxMSVGVzdCAtIFBBU1NFWFQgREVWMIGfMA0G
    CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuY1nrepgACvDSTLWk5A1cFOJSwDbl6CWfYp3cNYR0K3YV
    e07MDZn+Rv4jo3SusHVFds+mzKX2f8AeZjkA3Me/0yiS9UpS9LQZu9mnhFlZRhmUlDDoIZxovLXN
    aOv/YHmPeTQMQmJZu5TjqraUq7La1c187AoJuNfpxt227N1vOQIDAQABo4IBkTCCAY0wDgYDVR0P
    AQH/BAQDAgWgMB8GA1UdIwQYMBaAFLceWtTfVeRuVCTDQWkmwO4U01X/MAwGA1UdEwEB/wQCMAAw
    gbYGA1UdIASBrjCBqzCBqAYKKoF6ARfOEAEBBDCBmTBBBggrBgEFBQcCARY1aHR0cDovL3JldW5p
    cy5pbmV0cHNhLmNvbS9hdXRvcml0ZS9QQy1BQy1Qcm9ncmFtcy5wZGYwVAYIKwYBBQUHAgIwSDAK
    FgNwc2EwAwIBARo6UG9saXRpcXVlIGRlIENlcnRpZmljYXRpb24gQUMgUFNBIFBldWdlb3QgQ2l0
    cm9lbiBQcm9ncmFtczBcBgNVHR8EVTBTMFGgT6BNhktodHRwOi8vaW5mb2NlcnQucHNhLXBldWdl
    b3QtY2l0cm9lbi5jb20vQUMtUFNBLVBldWdlb3QtQ2l0cm9lbi1Qcm9ncmFtcy5jcmwwHQYDVR0l
    BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBYGA1UdDgQPBA1BVVRPX0dFTkVSQVRFMA0GCSqGSIb3
    DQEBBQUAA4IBAQCvRtP6bFkOUEHcqc6yUX0Q1Gk2WaAcx4ziUB0tw2GR9I0276JRJR0EGuJ/N6Fn
    3FhLQrSPmS97Xvc9XmiI66fQUdg64g9YqBecdiQlUkR20VLgI6Nq8pldQlWjU2iYlkP15U7VF4Qr
    0Pb2QiIljZUCKdv3qdED2Ri33za46LfykrlwZB0uhTVUxI/AEtjkKVFaZaqanJg+vJyZI5b30z7g
    Ff8L3ht4Z7SFKdmY3IQSGzElIAAUfduzTJX0cwnGSU9D4BJu1BS8hWnYPwhk+nBJ7OFhXdwYQFWq
    fhpBLq+ciJti9OMhcdCSIi0PbrOqzqtX7hZUQOvfShhCTJnl5TJJ</ds:X509Certificate>
  </ds:X509Data>
 </ds:KeyInfo>
</ds:Signature>

Was ich einfach nicht verstehe ist, warum ist das Zertifikat in der Signatur?

Ich meine, normalerweise bekomme ich auf sichere Weise ein Zertifikat von der Firma, also weiß ich, dass das Zertifikat von ihnen stammt. Und wenn die Überprüfung der Unterschrift erfolgreich ist, weiß ich, dass unsere Partnerfirma sie unterschrieben hat.

Aber wenn das Zertifikat innerhalb der Signatur der SAML-Antwort liegt, hätte es jeder senden können! Ich weiß nur, dass die Antwort nicht gefälscht wurde. Aber der Punkt ist, ich habe keine Ahnung, wer die SAML gesendet hat.

Kann mir jemand erklären, wie das funktioniert?

Dante
quelle

Antworten:

66

SAML-Antworten werden mit einer Signatur und einem öffentlichen Schlüssel für diese Signatur geliefert.

Mit dem öffentlichen Schlüssel können Sie überprüfen, ob der Inhalt der SAML-Antwort mit dem Schlüssel übereinstimmt. Mit anderen Worten, diese Antwort stammt definitiv von jemandem, der den passenden privaten Schlüssel zum öffentlichen Schlüssel in der Nachricht hat, und die Antwort war nicht manipuliert.

Ich weiß nicht, mit welcher Technologie Sie arbeiten, aber in .Net können Sie dies folgendermaßen überprüfen:

// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml("The SAML XML that you were sent");

// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("asrt", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("dsig", @"http://www.w3.org/2000/09/xmldsig#");

// get nodes down to the signature
var responseNode = assertion.SelectSingleNode("/samlp:Response", ns);
var assertionNode = responseNode.SelectSingleNode("asrt:Assertion", ns);
var signNode = assertionNode.SelectSingleNode("dsig:Signature", ns);

// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);

// get the certificate, basically:
//     signedXml.KeyInfo[0].Certificates[0]
// ...but with added casting
var certificate = GetFirstX509Certificate(signedXml);

// check the key and signature match
bool isSigned = signedXml.CheckSignature(certificate, true);

Das überprüft nur, ob die Nachricht von dem stammt, von dem sie sagt, dass sie es ist. Sie benötigen eine zusätzliche Überprüfung, ob die Nachricht von jemandem stammt, dem Sie vertrauen, und diese Überprüfung ist langsamer. Sie muss den Widerruf enthalten und möglicherweise eine ganze Kette von Zertifikaten überprüfen.

Normalerweise ist dies eine Liste öffentlicher Schlüssel, von denen Sie SAML-Antworten akzeptieren würden.

Anschließend können Sie überprüfen, ob diese Nachricht nicht manipuliert wurde und von einer vertrauenswürdigen Person stammt, sodass Sie die in den angegebenen SAML-Attributen angegebenen Benutzerdetails autorisieren können.

Sie könnten bereits den öffentlichen Schlüssel haben, was bedeutet, dass die Signatur den öffentlichen Schlüssel nicht erneut enthalten muss, aber Sie könnten auch mehrere mögliche bekannte Absender oder sogar eine Kette bekannter Absender haben.

Beispielsweise haben Sie möglicherweise zwei vertrauenswürdige Anbieter. In beiden Fällen überprüfen Sie, ob die Nachricht nicht manipuliert wurde, bevor Sie überprüfen, ob Sie einem der beiden Anbieter vertrauen. Wenn der Schlüssel nicht in der Signatur enthalten ist, können die Zusicherungen etwas kleiner sein. Jetzt müssen Sie jedoch im Voraus wissen, von welchem ​​Identitätsanbieter die Zusicherung stammt.

Es gibt also zwei Hauptgründe, warum der öffentliche Schlüssel in der Signatur enthalten ist:

  1. Die Manipulationsprüfung ist schneller als die Identitätsprüfung und kann isoliert werden, wenn der öffentliche Schlüssel bekannt ist.
  2. Mehrere Identitäten sind viel einfacher zu unterstützen, wenn sich der Schlüssel in der Zusicherung befindet.
Keith
quelle
2
@svlada Die SAML-Zusicherung benötigt keine eigene Verschlüsselung, da der Text selbst über SSL gesendet werden kann - die gesamte Benutzersitzung sollte HTTPS sein. Angesichts der Überprüfung, dass der bekannte, vertrauenswürdige Absender die Behauptung unterschrieben hat und nicht manipuliert wurde, reicht dies aus.
Keith
5
@svlada Keine HTTP-basierte Authentifizierung (jeglicher Art) sollte jemals ohne SSL durchgeführt werden. Durch das Verschlüsseln des Zertifikats wird ein Mann in der Mitte (MitM) daran gehindert, es zu lesen, aber es wird nicht daran gehindert, es auf ähnliche Weise wie bei einem Cookie-basierten MitM-Angriff wiederzuverwenden.
Keith
8
SAML - Antworten Sie nicht benötigen , einschließlich der öffentlichen Schlüssel für die Signatur. In Abschnitt 5.4.5 der SAML2-Spezifikation heißt es: "XML-Signatur definiert die Verwendung des Elements <ds: KeyInfo>. SAML erfordert weder die Verwendung von <ds: KeyInfo> noch legt es Einschränkungen für dessen Verwendung fest. Daher <ds : KeyInfo> KANN fehlen. " Sie können die Signatur überprüfen, wenn der öffentliche Schlüssel Ihnen auf andere Weise bereitgestellt wurde, z. B. in Ihrem lokalen Zertifikatspeicher, bevor Sie den SAML-Consumer implementieren.
Sam Rueby
2
@ Sam.Rueby ah, ich werde es korrigieren. Jede Implementierung, die ich gesehen habe, enthält den Schlüssel.
Keith
5
@Jez dieses ganze Protokoll ist so verwirrend wie die Hölle. Grundsätzlich ist die Behauptung in sich geschlossen - Sie können überprüfen, ob sie seit der Unterzeichnung durch den privaten Schlüssel nicht manipuliert wurde. Sie können dies tun, ohne diesen öffentlichen Schlüssel selbst zu haben (daher weiß ich, dass diese Behauptung von Dave stammt und dass niemand daran manipuliert hat, seit Dave sie unterschrieben hat, aber ich habe möglicherweise keine Ahnung, wer Dave ist oder ob ich ihm vertrauen kann). Nachdem ich dies überprüft habe, kann ich überprüfen, ob der öffentliche Schlüssel einer ist, dem ich vertraue. Ich denke, das liegt daran, dass es bei dieser letzten Überprüfung zu einer Verzögerung kommen kann (während ich nach dem Büro frage, ob jemand Dave kennt)
Keith
41

Der Grund, warum der Schlüssel angegeben wird, besteht darin, dass die Metadaten für den Identitätsanbieter mehrere Signaturschlüssel angeben können. Sie können den zu verwendenden Schlüssel angeben, indem Sie ihn der Signatur hinzufügen. SAML 2.0 erfordert, dass, wenn der Schlüssel nicht mit dem angegeben Assertionist, er durch den Kontext abgeleitet werden kann (aus den Metadaten für die behauptende Partei).

Zum Beispiel können Sie dies in Ihren Metadaten für die behauptende Partei haben:

        <KeyDescriptor>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>
BQUAMCMxITAfBgNVBAMTGGlkcDEudGFuZ29oZWFsdGhkZW1vLmNvbTAeFw0xMzA1
...snip...
ttHq2Wi5J7img1M2zo28hH5DK78S+XerfXHK2HEZYZs=
                </ds:X509Certificate>
            </ds:X509Data>
            <ds:X509Data>
                <ds:X509Certificate>
H24a88h7zlq+pnAxQm0CAwEAAaN3MHUwVAYDVR0RBE0wS4IYaWRwMS50YW5nb2hl
...snip...
mg1M2zo28hH5DK78=
                </ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </KeyDescriptor>

Jedes signierte XML-Element kann angeben, welcher Schlüssel für die Signatur verwendet wird. Im Fall von SAML 2.0 muss dieser Signaturschlüssel jedoch (zum Beispiel) mit einem übereinstimmen, der in den Metadaten für die Partei definiert ist, die die Signatur generiert. Wenn der mit der Signatur gelieferte Schlüssel nicht vertrauenswürdig ist (in diesem Fall nicht in den Metadaten angegeben), muss das SAML-System beim Überprüfen der Signatur einen Fehler generieren.

jbindel
quelle
9
Ich denke, dies ist ein wichtiger Punkt, dass das Zertifikat in der Antwort mit dem Zertifikat in den Metadaten übereinstimmen muss. Andernfalls könnte ich die Antwort mit einem beliebigen Zertifikat signieren und den öffentlichen Schlüssel zur Überprüfung senden.
Dana
5
Ich denke, dies ist die beste Antwort. Mir scheint, den anderen fehlt der Punkt, dass das Überprüfen der Nachricht anhand des in der Nachricht selbst deklarierten Schlüssels keine Sicherheit bietet. Sie müssen den Schlüssel in der Nachricht trotzdem überprüfen ist richtig! (In diesem Fall müssen Sie sicherstellen, dass es sich um vertrauenswürdige Metadaten handelt.)
Rchampourlier
3
Stimmen Sie den obigen Kommentaren voll und ganz zu - das in der Nachricht übergebene Zertifikat ist für sich genommen wertlos , da der Sinn der Unterzeichnung darin besteht, zu überprüfen, ob die Nachricht vertrauenswürdig ist. Wenn die Nachricht nicht vertrauenswürdig ist, sind auch die gebündelten Zertifikate nicht vertrauenswürdig.
Jez
@jbindel - danke! Wenn möglich, habe ich eine neue Frage: Muss dieses SAML-Zertifikat mit dem aktuellen physischen Zertifikat übereinstimmen oder wird es nur verwendet, um eine Metadatenübereinstimmung zu erzielen? Ich frage dies, da ich besorgt bin über die betrieblichen Auswirkungen eines IdP, der sein Zertifikat erneut verschlüsselt. Zu diesem Zeitpunkt ist es vermutlich nicht mehr mit dem Metadatenschlüssel synchronisiert. Wenn die 2 gebunden sind, bin ich wieder besorgt. die betrieblichen Auswirkungen dh. Bis sowohl SP als auch IdP den SAML2-Schlüssel manuell aktualisiert haben, schlägt alles SSO fehl und die daraus resultierenden Auswirkungen auf SSO-Benutzer, wenn die technische Kommunikation nicht perfekt ist. (Entschuldigung, wenn dumme Frage)
Pancho
Die SP-Metadaten müssen das Zertifikat enthalten, aber die SP-Metadaten können sowohl das alte als auch das neue IdP-Zertifikat angeben. Wenn der IdP sein Zertifikat aktualisiert, kann dies zu den SP-Metadaten hinzugefügt werden. Sobald der IdP mit dem alten Zertifikat ausgeführt werden soll, können Sie es aus den SP-Metadaten entfernen. Adressiert das, was Sie fragen? Ich weiß, dass dies bei Shibboleth SP sehr gut funktioniert. Die SP-Metadatendatei muss nur <KeyDescriptor use="signing">Elemente für die IdP-Zertifikate enthalten, die vom SP akzeptiert werden.
Jbindel
8

Der öffentliche Teil des Signaturzertifikats befindet sich in der SAML-Nachricht. Dies wird verwendet, um die Signatur für das Token selbst zu überprüfen und den Empfängern natürlich zu ermöglichen, zu erkennen, wer das Token ausgestellt hat, und es entsprechend zu behandeln.

Die Tatsache, dass es dort enthalten ist, ist Teil der Spezifikationen für digitale XML-Signaturen. Es ist eigentlich nichts SAML-spezifisches. Wie können Sie ohne das Zertifikat feststellen, woher das Token stammt, und wie können Sie es validieren?

XmlDSig gibt andere Methoden an. Sie können den Signaturschlüssel anhand eines Betreffs, einer Seriennummer, eines Hashs usw. identifizieren. Dies setzt jedoch voraus, dass die empfangende Partei über das öffentliche Zertifikat verfügt. Für SAML ist dies möglicherweise nicht der Fall, daher die Einbettung des öffentlichen Teils des X509-Zertifikats.

Blasrohrpfeil
quelle
1
"Wie können Sie ohne das Zertifikat feststellen, woher das Token stammt, und wie können Sie es validieren?" - Worüber redest du? Um einer Signatur in einer SAML-Nachricht zu vertrauen, müssen Sie bereits über eine Liste vertrauenswürdiger öffentlicher Zertifikate verfügen. Sie können das IssuerElement verwenden und das Zertifikat des Ausstellers dafür speichern und das Zertifikat auswählen, anhand dessen die Signatur für diese Nachricht überprüft werden soll.
Jez
2
Überhaupt nicht wahr Jez. Sie können einem Zertifikatsaussteller wie einer Zertifizierungsstelle vertrauen, ohne den einzelnen ausgestellten Zertifikaten vertrauen zu müssen und ohne lokale Kopien jedes Zertifikats aufbewahren zu müssen.
Blowdart
3
Blowdart bedeutet, dass Sie dem Saml-Token vertrauen, der von einem anderen gültigen, von CA ausgestellten Zertifikat signiert wurde. Es ist nicht unmöglich, einen zu kaufen! Um sicherzustellen, dass Ihr Token von der richtigen Quelle stammt, wie @Jez erwähnt hat, sollten Sie bereits eine Liste vertrauenswürdiger öffentlicher Zertifikate haben.
So
2
@ Sun, falsch. Das ist so, als würde Wells Fargo sich als Bank of America ausgeben, wenn sie dieselbe Zertifizierungsstelle haben. Ein X509-Zertifikat verfügt über einen Betreff-DN, der auf die richtige Identität überprüft werden kann.
Paul Draper
+1, insbesondere um festzustellen, dass dies Teil der Spezifikation für digitale XML-Signaturen ist. Dies ist für Anfänger weniger offensichtlich und für das Verständnis der tatsächlichen Verarbeitung der Nachrichten von entscheidender Bedeutung, da so ziemlich jede SAML-Implementierung auf eine XML-Bibliothek angewiesen ist schweres Heben.
BryKKan