SAML: Pourquoi le certificat est-il dans la signature?

103

Je dois implémenter SSO avec SAML pour le site Web de mon entreprise (en tant que partie de confiance). Une partie essentielle est bien sûr la vérification de la signature. Voici la partie signature d'un échantillon SAML de notre société partenaire (partie revendicatrice):

<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>

Ce que je ne comprends tout simplement pas, c'est pourquoi le certificat figure-t-il dans la signature?

Je veux dire que généralement, j'obtiens un certificat de la société de manière sécurisée, donc je sais que le certificat vient d'eux. Et lorsque la vérification de la signature réussit, je sais que notre entreprise partenaire l'a signée.

Mais lorsque le certificat est dans la signature de la réponse SAML, n'importe qui aurait pu l'envoyer! La seule chose que je sais, c'est que la réponse n'a pas été falsifiée. Mais le fait est que je n'ai aucune idée de qui a envoyé le SAML.

Quelqu'un peut-il m'expliquer comment cela fonctionne?

Dante
la source

Réponses:

66

Les réponses SAML sont accompagnées d'une signature et d'une clé publique pour cette signature.

Vous pouvez utiliser la clé publique pour vérifier que le contenu de la réponse SAML correspond à la clé - en d'autres termes - cette réponse provient définitivement de quelqu'un qui a la clé privée correspondante à la clé publique dans le message, et la réponse n'a pas été altéré.

Je ne sais pas avec quelle technologie vous travaillez, mais dans .Net, vous pouvez le vérifier comme ceci:

// 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);

Cela vérifie simplement que le message provient de qui il dit être. Vous avez besoin d'une vérification supplémentaire que le message provient d'une personne en qui vous avez confiance, et cette vérification est plus lente - elle doit inclure la révocation et peut avoir besoin de vérifier toute une chaîne de certificats.

Normalement, ce sera une liste de clés publiques à partir desquelles vous accepteriez les réponses SAML.

Ensuite, vous pouvez vérifier que ce message n'a pas été falsifié et provient d'une personne de confiance, afin que vous puissiez autoriser les détails utilisateur fournis dans les attributs SAML fournis.

Vous pourriez déjà avoir la clé publique, ce qui signifie que la signature ne devrait pas avoir besoin d'inclure à nouveau la clé publique, mais vous pourriez également avoir plusieurs expéditeurs connus possibles, ou même une chaîne d'expéditeurs connus.

Par exemple, vous pouvez avoir deux fournisseurs de confiance - dans les deux cas, vous vérifiez que le message n'a pas été falsifié avant de vérifier si vous faites confiance à l'un ou l'autre fournisseur. Si la clé n'est pas dans la signature, les assertions peuvent être un peu plus petites, mais vous devez maintenant savoir à l'avance de quel fournisseur d'identité provient l'assertion.

Donc, vraiment, il y a deux raisons principales pour lesquelles la clé publique est dans la signature:

  1. Le contrôle de sabotage est plus rapide que le contrôle d'identité et peut être isolé si la clé publique est connue.
  2. Les identités multiples sont beaucoup plus faciles à prendre en charge si la clé se trouve dans l'assertion.
Keith
la source
2
@svlada l'assertion SAML n'a pas besoin de son propre cryptage, car le texte lui-même peut être envoyé via SSL - toute la session utilisateur doit être HTTPS. Étant donné que la vérification que l'expéditeur connu et de confiance a signé l'assertion et qu'elle n'a pas été falsifiée est suffisante.
Keith
5
@svlada aucune authentification basée sur HTTP (de quelque nature que ce soit) ne devrait jamais être effectuée sans SSL. Le chiffrement du certificat empêchera un homme du milieu (MitM) de le lire, mais cela ne les empêchera pas de le réutiliser de la même manière qu'une attaque MitM basée sur des cookies.
Keith
8
Les réponses SAML ne nécessitent pas d'inclure la clé publique pour cette signature. La section 5.4.5 de la spécification SAML2 indique que «la signature XML définit l'utilisation de l'élément <ds: KeyInfo>. SAML ne requiert pas l'utilisation de <ds: KeyInfo>, ni n'impose aucune restriction à son utilisation. Par conséquent, <ds : KeyInfo> PEUT être absent. " Vous pouvez vérifier la signature si la clé publique vous a été fournie par d'autres moyens, par exemple stockée dans votre magasin de certificats local avant la mise en œuvre du consommateur SAML.
Sam Rueby
2
@ Sam.Rueby ah, je vais le corriger. Chaque implémentation que j'ai vue a inclus la clé.
Keith
5
@Jez, tout ce protocole est aussi déroutant que l'enfer. Fondamentalement, l'assertion est autonome - vous pouvez vérifier qu'elle n'a pas été falsifiée depuis que la clé privée l'a signée. Vous pouvez le faire sans avoir vous-même cette clé publique (donc je sais que cette affirmation vient de Dave, et que personne ne l'a falsifiée depuis que Dave l'a signée, mais je n'ai peut-être aucune idée de qui est Dave ou si je peux lui faire confiance). Ensuite, après avoir vérifié cela, je peux vérifier que la clé publique est celle en laquelle j'ai confiance. Je pense que c'est parce qu'il pourrait y avoir un retard sur ce dernier contrôle (pendant que je demande au bureau si quelqu'un connaît Dave)
Keith
41

La raison pour laquelle la clé est spécifiée est que les métadonnées du fournisseur d'identité peuvent spécifier plusieurs clés de signature, et vous pouvez spécifier la clé à utiliser en l'incluant avec la signature. SAML 2.0 exige que si la clé n'est pas spécifiée avec le Assertion, alors elle peut être déduite par contexte (à partir des métadonnées de la partie qui affirme).

Par exemple, vous pouvez avoir ceci dans vos métadonnées pour la partie déclarante:

        <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>

Chaque élément XML signé peut spécifier la clé utilisée pour la signature. Cependant, dans le cas de SAML 2.0, cette clé de signature doit (par exemple) correspondre à celle définie dans les métadonnées pour la partie générant la signature. Si la clé fournie avec la signature n'est pas approuvée (non spécifiée dans les métadonnées dans ce cas), le système SAML doit générer une erreur lors de la validation de la signature.

jbindel
la source
9
Je pense que c'est un point important, que le certificat dans la réponse doit correspondre au certificat dans les métadonnées. Sinon, je pourrais signer la réponse avec le certificat de mon choix et envoyer sa clé publique pour vérification.
dana le
5
Je pense que c'est la meilleure réponse, il me semble que les autres manquent le point que la vérification du message par rapport à la clé déclarée dans le message lui-même ne vous donne aucune sécurité ... Vous devez toujours vérifier la clé dans le message est correct! (dans ce cas, vous devez vous assurer qu'il s'agit de métadonnées approuvées).
rchampourlier
3
Tout à fait d'accord avec les commentaires ci-dessus - le certificat transmis dans le message est sans valeur en soi car le but de la signature est de vérifier que le message est digne de confiance. Si le message n'est pas digne de confiance, les certificats fournis ne le sont pas non plus.
Jez
@jbindel - merci! J'ai une nouvelle question si possible: ce certificat SAML doit-il correspondre au certificat physique actuel ou est-il uniquement utilisé pour obtenir une correspondance de métadonnées? Je pose cette question car je suis préoccupé par l'impact opérationnel d'un IdP qui recrée son certificat - à quel point il est vraisemblablement désynchronisé avec la clé de métadonnées. Si les 2 sont à égalité, alors je suis inquiet re. l'impact opérationnel ie. que jusqu'à ce que le SP et l'IdP aient mis à jour manuellement la clé SAML2, tout SSO échouera, et l'impact qui en résulte sur les utilisateurs SSO si les communications techniques sont imparfaites. (excuses si question stupide)
Pancho
Les métadonnées du SP doivent inclure le certificat, mais les métadonnées du SP peuvent spécifier à la fois l'ancien et le nouveau certificat IdP. Si l'IdP met à jour son certificat, cela peut être ajouté aux métadonnées du SP. Une fois que l'IdP est censé être effectué à l'aide de l'ancien certificat, vous pouvez le supprimer des métadonnées du SP. Est-ce que cela répond à ce que vous demandez? Je sais que cela fonctionne parfaitement sur Shibboleth SP. Le fichier de métadonnées du SP doit simplement contenir des <KeyDescriptor use="signing">éléments pour les certificats IdP qui seront acceptés par le SP.
jbindel
8

La partie publique du certificat de signature se trouve dans le message SAML. Ceci est utilisé pour vérifier la signature du jeton lui-même, et bien sûr pour permettre aux destinataires de dire qui a émis le jeton et de le traiter en conséquence.

Le fait que ce soit là fait partie des spécifications de signature numérique XML, ce n'est pas vraiment quelque chose de spécifique à SAML. Sans le certificat, comment pouvez-vous savoir d'où vient le jeton et comment le valider?

XmlDSig spécifie d'autres méthodes, vous pouvez identifier la clé de signature par un sujet, un numéro de série, un hachage, etc., mais cela suppose que la partie destinataire possède le certificat public. Pour SAML, cela peut ne pas être le cas, d'où l'intégration de la partie publique du cert X509.

blowdart
la source
1
"Sans le certificat, comment pourriez-vous savoir d'où vient le jeton et comment pouvez-vous le valider?" - Qu'est-ce que tu racontes? Pour faire confiance à une signature dans un message SAML, vous devez déjà disposer d'une liste de certificats publics approuvés. Vous pouvez utiliser l' Issuerélément et stocker le certificat de cet émetteur par rapport à celui-ci et choisir ce certificat par rapport auquel vérifier la signature de ce message.
Jez
2
Pas vrai du tout Jez. Vous pouvez faire confiance à un émetteur de certificats, comme une autorité de certification, sans avoir à approuver les certificats individuels qu'il émet et sans avoir à conserver des copies locales de chaque certificat.
blowdart
3
blowdart qui signifie que vous faites confiance au jeton saml signé par tout autre certificat valide émis par CA. Il n'est pas impossible d'en acheter un! Pour vous assurer que votre jeton provient de la bonne source, comme @Jez l'a mentionné, vous devriez déjà avoir une liste de certificats publics de confiance.
dim
2
@Sun, incorrect. C'est comme dire que Wells Fargo peut se faire passer pour la Bank of America s'ils ont le même CA. Un certificat X509 a un nom distinctif de sujet qui peut être validé pour l'identité correcte.
Paul Draper
+1 en particulier pour identifier que cela fait partie de la spécification de signature numérique XML, ce qui est moins qu'évident pour un novice et crucial pour comprendre comment les messages sont réellement traités, car pratiquement chaque implémentation SAML repose sur une bibliothèque XML pour faire le levage de charges lourdes.
BryKKan