SAML: ¿Por qué el certificado está dentro de la firma?

103

Tengo que implementar SSO con SAML para el sitio web de mi empresa (como parte de confianza). Por supuesto, una parte esencial es la verificación de la firma. Aquí está la parte de la firma de un SAML de muestra de nuestra empresa asociada (parte declarante):

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

Lo que simplemente no entiendo es, ¿por qué está el certificado dentro de la firma?

Quiero decir, normalmente obtengo un certificado de la empresa de forma segura, así que sé que el certificado es de ellos. Y cuando la verificación de la firma se realiza correctamente, sé que nuestra empresa asociada la ha firmado.

Pero cuando el certificado está dentro de la firma de SAML-Response, ¡cualquiera podría haberlo enviado! Lo único que sé es que la respuesta no ha sido falsificada. Pero el caso es que no tengo ni idea de quién envió el SAML.

¿Alguien puede explicarme cómo funciona?

Dante
fuente

Respuestas:

66

Las respuestas SAML vienen con una firma y una clave pública para esa firma.

Puede usar la clave pública para verificar que el contenido de la respuesta SAML coincida con la clave; en otras palabras, esa respuesta definitivamente provino de alguien que tiene la clave privada coincidente con la clave pública en el mensaje, y la respuesta no ha sido manipulado.

No sé con qué tecnología está trabajando, pero en .Net puede verificarlo así:

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

Eso solo verifica que el mensaje sea de quien dice ser. Necesita una verificación adicional de que el mensaje proviene de alguien en quien confía, y esta verificación es más lenta: debe incluir la revocación y es posible que deba verificar una cadena completa de certificados.

Normalmente, esta será una lista de claves públicas de las que aceptaría respuestas SAML.

Luego, puede verificar que este mensaje no haya sido manipulado y que sea de alguien de su confianza, para que pueda autorizar los detalles del usuario proporcionados en los atributos SAML proporcionados.

Ya podría tener la clave pública, lo que significa que la firma no debería necesitar incluir la clave pública nuevamente, pero también podría tener varios posibles remitentes conocidos, o incluso una cadena de remitentes conocidos.

Por ejemplo, puede tener dos proveedores confiables; en cualquier caso, verifica que el mensaje no haya sido manipulado antes de verificar si confía en alguno de los proveedores. Si la clave no está en la firma, las afirmaciones pueden ser un poco más pequeñas, pero ahora tiene que saber de antemano de qué proveedor de identidad procede la afirmación.

Entonces, realmente, hay dos razones principales por las que la clave pública está en la firma:

  1. La verificación de manipulación es más rápida que la verificación de identidad y se puede aislar si se conoce la clave pública.
  2. Las identidades múltiples son mucho más fáciles de soportar si la clave está en la aserción.
Keith
fuente
2
@svlada, la aserción SAML no necesita su propio cifrado, ya que el texto en sí se puede enviar a través de SSL; toda la sesión del usuario debe ser HTTPS. Dada esa verificación de que el remitente conocido y de confianza firmó la afirmación y que no ha sido manipulada es suficiente.
Keith
5
@svlada ninguna autenticación basada en HTTP (de ningún tipo) debe realizarse sin SSL. Cifrar el certificado evitará que un intermediario (MitM) lo lea, pero no evitará que lo reutilicen de manera similar a un ataque MitM basado en cookies.
Keith
8
Las respuestas SAML no requieren incluir la clave pública para esa firma. La sección 5.4.5 de la especificación SAML2 establece "La firma XML define el uso del elemento <ds: KeyInfo>. SAML no requiere el uso de <ds: KeyInfo>, ni impone restricciones sobre su uso. Por lo tanto, <ds : KeyInfo> PUEDE estar ausente. " Puede verificar la firma si la clave pública se le ha proporcionado a través de otros medios, por ejemplo, almacenada en su almacén de certificados local antes de implementar el consumidor SAML.
Sam Rueby
2
@ Sam.Rueby ah, lo corregiré. Cada implementación que he visto ha incluido la clave.
Keith
5
@Jez todo este protocolo es tan confuso como el infierno. Básicamente, la aserción es autónoma: puede verificar que no haya sido manipulada desde que la clave privada la firmó. Puede hacer esto sin tener esa clave pública (así que sé que esta afirmación proviene de Dave, y que nadie la ha alterado desde que Dave la firmó, pero es posible que no tenga idea de quién es Dave o si puedo confiar en él). Luego, después de verificar eso, puedo verificar que la clave pública sea una en la que confío. Creo que esto se debe a que podría haber un retraso en la verificación final (mientras voy a preguntar por la oficina si alguien conoce a Dave)
Keith
41

La razón por la que se especifica la clave es que los metadatos para el proveedor de identidad pueden especificar varias claves de firma, y ​​usted puede especificar la clave a utilizar incluyéndola con la firma. SAML 2.0 requiere que si la clave no se especifica con el Assertion, entonces se puede inferir por contexto (de los metadatos para la parte afirmante).

Por ejemplo, puede tener esto en sus metadatos para la parte afirmante:

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

Cada elemento XML que está firmado puede especificar qué clave se utiliza para la firma. Sin embargo, en el caso de SAML 2.0, esa clave de firma debe (por ejemplo) coincidir con una que esté definida en los Metadatos para la parte que genera la firma. Si la clave suministrada con la firma no es de confianza (no especificada en los Metadatos en este caso), entonces el sistema SAML debe generar un error al validar la firma.

jbindel
fuente
9
Creo que este es un punto importante, que el certificado en la respuesta debe coincidir con el certificado en los metadatos. De lo contrario, podría firmar la respuesta con cualquier certificado que quisiera y enviar su clave pública para su verificación.
dana
5
Creo que esta es la mejor respuesta, me parece que a los otros les falta el punto de que comparar el mensaje con la clave declarada en el mensaje en sí no le da ninguna seguridad ... Aún debe verificar la clave en el mensaje ¡es correcto! (en este caso, debe asegurarse de que esté en metadatos confiables).
rchampourlier
3
Totalmente de acuerdo con los comentarios anteriores: el certificado que se pasa en el mensaje no tiene valor por sí mismo porque el objetivo de la firma es verificar que el mensaje es confiable. Si el mensaje no es confiable, tampoco lo son los certificados incluidos.
Jez
@jbindel - ¡gracias! Tengo una nueva pregunta si es posible: ¿Este certificado SAML tiene que coincidir con el certificado físico actual, o solo se usa para lograr una coincidencia de metadatos? Pregunto esto porque me preocupa el impacto operativo de un IdP que cambia la clave de su certificado, momento en el que presumiblemente se desincroniza con la clave de metadatos. Si los 2 están empatados, entonces me preocupa re. el impacto operativo, es decir. que hasta que tanto el SP como el IdP hayan actualizado manualmente la clave SAML2, todo SSO fallará y el consiguiente impacto en los usuarios de SSO si las comunicaciones técnicas son imperfectas. (disculpas si pregunta estúpida)
Pancho
Los metadatos del SP deben incluir el certificado, pero los metadatos del SP pueden especificar los certificados de IdP nuevos y antiguos. Si el IdP está actualizando su certificado, se puede agregar a los metadatos del SP. Una vez que se supone que el IdP debe usar el certificado anterior, puede eliminarlo de los metadatos del SP. ¿Eso aborda lo que estás preguntando? Sé que esto funciona perfectamente en Shibboleth SP. El archivo de metadatos del SP solo necesita tener <KeyDescriptor use="signing">elementos para los certificados de IdP que serán aceptados por el SP.
jbindel
8

La parte pública del certificado de firma está en el mensaje SAML. Esto se usa para verificar la firma del token en sí y, por supuesto, para permitir a los receptores decir quién emitió el token y tratarlo en consecuencia.

El hecho de que esté ahí es parte de las especificaciones de la firma digital XML, no es nada específico de SAML. Sin el certificado, ¿cómo podría saber de dónde vino el token y cómo podría validarlo?

XmlDSig especifica otros métodos, puede identificar la clave de firma por un asunto, número de serie, hash, etc., pero esto supone que la parte receptora tiene el certificado público. Para SAML, este puede no ser el caso, de ahí la incrustación de la parte pública del certificado X509.

soplar el dardo
fuente
1
"Sin el certificado, ¿cómo podría saber de dónde vino el token y cómo podría validarlo?" - ¿de qué estás hablando? Con el fin de confiar en una firma en un mensaje SAML, debe ya tener una lista de certificados de confianza pública. Puede usar el Issuerelemento y almacenar el certificado de ese emisor con él, y elegir ese certificado con el que verificar la firma de este mensaje.
Jez
2
No es cierto en absoluto Jez. Puede confiar en un emisor de certificados, como una CA, sin tener que confiar en los certificados individuales que emite y sin tener que conservar copias locales de cada certificado.
blowdart
3
blowdart que significa que está confiando en el token saml firmado por cualquier otro certificado válido emitido por CA. ¡No es imposible comprar uno! Para asegurarse de que su token proviene de la fuente correcta, como mencionó @Jez, ya debería tener una lista de certificados públicos confiables.
dom
2
@Sun, incorrecto. Eso es como decir que Wells Fargo puede hacerse pasar por Bank of America si tienen la misma CA. Un certificado X509 tiene un DN de sujeto que se puede validar para la identidad correcta.
Paul Draper
+1 especialmente para identificar que esto es parte de la especificación de firma digital XML, algo que es menos que obvio para un principiante y crucial para comprender cómo se procesan realmente los mensajes, ya que casi todas las implementaciones de SAML se basan en una biblioteca XML para hacer el levantamiento pesado.
BryKKan