SAML: Por que o certificado está dentro da Assinatura?

103

Tenho que implementar o SSO com SAML para o site da minha empresa (como a parte confiável). Uma parte essencial do curso é a verificação da assinatura. Aqui está a parte da assinatura de um exemplo de SAML de nossa empresa parceira (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>

O que eu simplesmente não entendo é, por que o certificado está dentro da assinatura?

Quer dizer, normalmente eu obtenho um certificado da empresa de uma forma segura, então eu sei que o certificado é deles. E quando a verificação da assinatura for bem-sucedida, sei que nossa empresa parceira a assinou.

Mas quando o certificado está dentro da assinatura da Resposta SAML, qualquer pessoa pode tê-lo enviado! A única coisa que sei é que a resposta não foi falsificada. Mas a questão é que não tenho ideia de quem enviou o SAML.

Alguém pode me explicar como isso funciona?

Dante
fonte

Respostas:

66

As respostas SAML vêm com uma assinatura e uma chave pública para essa assinatura.

Você pode usar a chave pública para verificar se o conteúdo da resposta SAML corresponde à chave - em outras palavras - essa resposta definitivamente veio de alguém que tem a chave privada correspondente à chave pública na mensagem, e a resposta não foi adulterado.

Não sei com que tecnologia você está trabalhando, mas em .Net você pode verificar assim:

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

Isso apenas verifica se a mensagem é de quem diz ser. Você precisa de uma verificação adicional de que a mensagem veio de alguém em quem você confia, e essa verificação é mais lenta - ela precisa incluir a revogação e pode precisar verificar uma cadeia inteira de certificados.

Normalmente, esta será uma lista de chaves públicas das quais você aceitaria respostas SAML.

Em seguida, você pode verificar se esta mensagem não foi adulterada e é de alguém em quem você confia, para que possa autorizar os detalhes do usuário fornecidos nos atributos SAML fornecidos.

Você já pode ter a chave pública, o que significa que a assinatura não precisa incluir a chave pública novamente, mas você também pode ter vários remetentes conhecidos possíveis, ou até mesmo uma cadeia de remetentes conhecidos.

Por exemplo, você pode ter dois provedores confiáveis ​​- em ambos os casos, você verifica se a mensagem não foi adulterada antes de verificar se confia em um deles. Se a chave não estiver na assinatura, as asserções podem ser um pouco menores, mas agora você deve saber com antecedência de qual provedor de identidade a asserção veio.

Então, realmente, há dois motivos principais pelos quais a chave pública está na assinatura:

  1. A verificação de violação é mais rápida do que a verificação de identidade e pode ser isolada se a chave pública for conhecida.
  2. Múltiplas identidades são muito mais fáceis de suportar se a chave estiver na declaração.
Keith
fonte
2
@svlada a asserção SAML não precisa de sua própria criptografia, pois o próprio texto pode ser enviado por SSL - toda a sessão do usuário deve ser HTTPS. Considerando que a verificação de que o remetente conhecido e confiável assinou a declaração e que não foi adulterada é suficiente.
Keith
5
@svlada nenhuma autenticação baseada em HTTP (de qualquer tipo) deve ser feita sem SSL. Criptografar o certificado impedirá que um homem no meio (MitM) o leia, mas não os impedirá de reutilizá-lo de maneira semelhante a um ataque MitM baseado em cookies.
Keith
8
As respostas SAML não exigem a inclusão da chave pública para essa assinatura. A seção 5.4.5 da especificação SAML2 declara "Assinatura XML define o uso do elemento <ds: KeyInfo>. SAML não exige o uso de <ds: KeyInfo>, nem impõe nenhuma restrição ao seu uso. Portanto, <ds : KeyInfo> PODE estar ausente. " Você pode verificar a assinatura se a chave pública foi fornecida a você por outros meios, por exemplo, armazenada em seu armazenamento de certificado local antes de implementar o consumidor SAML.
Sam Rueby
2
@ Sam.Rueby ah, vou corrigi-lo. Cada implementação que vi incluiu a chave.
Keith de
5
@Jez todo este protocolo é tão confuso como o inferno. Basicamente, a declaração é independente - você pode verificar se ela não foi adulterada desde que a chave privada a assinou. Você pode fazer isso sem ter essa chave pública (então eu sei que esta afirmação veio de Dave e que ninguém a alterou desde que Dave a assinou, mas posso não ter ideia de quem é Dave ou se posso confiar nele). Então, depois de verificar isso, posso verificar se a chave pública é aquela em que confio. Acho que isso ocorre porque pode haver um atraso na verificação final (enquanto eu vou perguntar sobre o escritório se alguém conhece Dave)
Keith
41

O motivo da chave ser especificada é que os metadados para o provedor de identidade podem especificar várias chaves de assinatura e você pode especificar a chave a ser usada incluindo-a com a assinatura. O SAML 2.0 exige que, se a chave não for especificada com o Assertion, ela pode ser inferida pelo contexto (a partir dos Metadados da parte de confirmação).

Por exemplo, você pode ter isso em seus Metadados para a parte declarante:

        <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 assinado pode especificar qual chave é usada para a assinatura. No entanto, no caso do SAML 2.0, essa chave de assinatura deve (por exemplo) corresponder àquela definida nos metadados para a parte que gerou a assinatura. Se a chave fornecida com a assinatura não for confiável (não especificada nos Metadados, neste caso), o sistema SAML deve gerar um erro ao validar a assinatura.

jbindel
fonte
9
Eu acho que este é um ponto importante, que o certificado na resposta deve corresponder ao certificado nos metadados. Caso contrário, poderia assinar a resposta com qualquer certificado que quisesse e enviar sua chave pública para verificação.
dana
5
Acho que esta é a melhor resposta, parece-me que os outros estão perdendo o ponto de que verificar a mensagem com a chave declarada na própria mensagem não está lhe dando nenhuma segurança ... Você ainda deve verificar a chave na mensagem está certo! (neste caso, você deve garantir que está em metadados confiáveis).
rchampourlier
3
Concordo totalmente com os comentários acima - o certificado passado na mensagem não vale por si só porque o objetivo da assinatura é verificar se a mensagem é confiável. Se a mensagem não for confiável, os certificados agrupados também não serão.
Jez
@jbindel - obrigado! Eu tenho uma nova pergunta, se possível: este certificado SAML precisa corresponder ao certificado físico atual ou ele é usado apenas para obter uma correspondência de metadados? Eu pergunto isso porque estou preocupado com o impacto operacional de um IdP recodificando seu certificado - ponto em que, presumivelmente, ele fica fora de sincronia com a chave de metadados. Se os 2 estiverem empatados, estou preocupado com relação a isso. o impacto operacional, isto é. até que o SP e o IdP tenham atualizado manualmente a chave SAML2, todo o SSO falhará e o consequente impacto nos usuários do SSO se houver comunicações técnicas imperfeitas. (desculpas se pergunta estúpida)
Pancho
Os metadados do SP devem incluir o certificado, mas os metadados do SP podem especificar os certificados IdP antigos e novos. Se o IdP estiver atualizando seu certificado, ele pode ser adicionado aos metadados do SP. Uma vez que o IdP deve ser feito usando o certificado antigo, você pode removê-lo dos metadados do SP. Isso responde ao que você está perguntando? Eu sei que isso funciona perfeitamente bem no Shibboleth SP. O arquivo de metadados do SP só precisa ter <KeyDescriptor use="signing">elementos para os certificados IdP que serão aceitos pelo SP.
jbindel de
8

A parte pública do certificado de assinatura está na mensagem SAML. Isso é usado para verificar a assinatura do próprio token e, é claro, para permitir que os destinatários digam quem emitiu o token e o tratem de acordo.

O fato de estar lá faz parte das especificações da assinatura digital XML, não é nada específico do SAML. Sem o certificado, como saber de onde veio o token e como validá-lo?

O XmlDSig especifica outros métodos, você pode identificar a chave de assinatura por assunto, número de série, hash etc., mas isso pressupõe que a parte receptora tenha o certificado público. Para SAML, esse pode não ser o caso, daí a incorporação da parte pública do certificado X509.

dardo
fonte
1
"Sem o certificado, como saber de onde veio o token e como validá-lo?" - do que você está falando? Para confiar em uma assinatura em uma mensagem SAML, você deve ter uma lista de certificados públicos confiáveis. Você poderia usar o Issuerelemento e armazenar o certificado do emissor em relação a ele, e escolher aquele certificado para verificar a assinatura desta mensagem.
Jez de
2
Não é verdade, Jez. Você pode confiar em um emissor de certificado, como uma CA, sem ter que confiar nos certificados individuais que ele emite e sem ter que manter cópias locais de cada certificado.
blowdart
3
blowdart significa que você está confiando no token saml assinado por qualquer outro certificado válido emitido pela CA. Não é impossível comprar um! Para garantir que seu token está vindo da fonte correta, como @Jez mencionou, você já deve ter uma lista de certificados públicos confiáveis.
Dom
2
@Sun, incorreto. É como dizer que o Wells Fargo pode se passar pelo Bank of America se eles tiverem o mesmo CA. Um certificado X509 possui um DN de assunto que pode ser validado para a identidade correta.
Paul Draper
+1 especialmente para identificar que isso é parte da especificação de assinatura digital XML, algo que é menos óbvio para um novato e crucial para entender como as mensagens são realmente processadas, já que quase toda implementação de SAML depende de uma biblioteca XML para fazer o levantamento pesado.
BryKKan