SAML: Tại sao chứng chỉ lại nằm trong Chữ ký?


103

Tôi phải triển khai SSO với SAML cho trang web của công ty mình (với tư cách là bên phụ thuộc). Một phần quan trọng không thể thiếu là xác minh chữ ký. Đây là phần chữ ký của SAML mẫu từ công ty đối tác của chúng tôi (bên xác nhận):

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

Điều tôi không hiểu là tại sao chứng chỉ lại có chữ ký?

Ý tôi là thông thường tôi nhận được chứng chỉ từ công ty theo một cách an toàn, vì vậy tôi biết chứng chỉ là của họ. Và khi việc xác minh chữ ký thành công, tôi biết công ty đối tác của chúng tôi đã ký tên đó.

Nhưng khi chứng chỉ nằm trong chữ ký của SAML-Response, bất kỳ ai cũng có thể gửi nó! Điều duy nhất tôi biết là phản hồi không bị làm sai lệch. Nhưng vấn đề là, tôi không biết ai đã gửi SAML.

Bất cứ ai có thể giải thích cho tôi, làm thế nào mà làm việc?

Câu trả lời:


66

Các câu trả lời SAML đi kèm với chữ ký và khóa công khai cho chữ ký đó.

Bạn có thể sử dụng khóa công khai để xác minh rằng nội dung của phản hồi SAML khớp với khóa - nói cách khác - phản hồi đó chắc chắn đến từ người có khóa riêng phù hợp với khóa công khai trong thư và phản hồi không phải can thiệp vào.

Tôi không biết bạn đang làm việc với công nghệ nào, nhưng trong .Net, bạn có thể kiểm tra nó như sau:

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

Điều đó chỉ kiểm tra xem tin nhắn đó là của ai. Bạn cần kiểm tra thêm để đảm bảo rằng thông báo đến từ người mà bạn tin tưởng và quá trình kiểm tra này diễn ra chậm hơn - nó cần bao gồm việc thu hồi và có thể cần xác minh toàn bộ chuỗi chứng chỉ.

Thông thường, đây sẽ là danh sách các khóa công khai mà bạn sẽ chấp nhận phản hồi SAML.

Sau đó, bạn có thể kiểm tra xem tin nhắn này có bị giả mạo hay không và là từ người nào đó mà bạn tin tưởng, vì vậy bạn có thể cho phép thông tin chi tiết người dùng được cung cấp trong các thuộc tính SAML được cung cấp.

Bạn đã có thể có khóa công khai, nghĩa là chữ ký không cần phải bao gồm lại khóa công khai, nhưng bạn cũng có thể có nhiều người gửi đã biết hoặc thậm chí một chuỗi những người gửi đã biết.

Ví dụ: bạn có thể có hai nhà cung cấp đáng tin cậy - trong cả hai trường hợp, bạn kiểm tra xem tin nhắn có bị giả mạo hay không trước khi kiểm tra xem bạn có tin cậy một trong hai nhà cung cấp hay không. Nếu khóa không có trong chữ ký thì xác nhận có thể nhỏ hơn một chút, nhưng bây giờ bạn phải biết trước xác nhận đó đến từ nhà cung cấp danh tính nào.

Vì vậy, thực sự, có hai lý do chính khiến khóa công khai nằm trong chữ ký:

  1. Kiểm tra giả mạo nhanh hơn kiểm tra danh tính và có thể bị cô lập nếu khóa công khai được biết.
  2. Nhiều danh tính sẽ dễ dàng hỗ trợ hơn nhiều nếu chìa khóa nằm trong xác nhận.

2
@svlada khẳng định SAML không cần mã hóa riêng vì bản thân văn bản có thể được gửi qua SSL - toàn bộ phiên người dùng phải là HTTPS. Với việc xác minh rằng người gửi đã biết, đáng tin cậy đã ký xác nhận và xác nhận đó không bị giả mạo là đủ.
Keith

5
@svlada không nên thực hiện xác thực dựa trên HTTP (dưới bất kỳ hình thức nào) mà không có SSL. Mã hóa chứng chỉ sẽ ngăn người ở giữa (MitM) đọc nó, nhưng nó sẽ không ngăn họ sử dụng lại chứng chỉ theo cách tương tự như tấn công MitM dựa trên cookie.
Keith

8
Các phản hồi SAML không yêu cầu bao gồm khóa công khai cho chữ ký đó. Phần 5.4.5 của đặc tả SAML2 nêu rõ "Chữ ký XML xác định việc sử dụng phần tử <ds: KeyInfo>. SAML không yêu cầu sử dụng <ds: KeyInfo>, cũng như không áp đặt bất kỳ hạn chế nào đối với việc sử dụng nó. Do đó, <ds : KeyInfo> CÓ THỂ vắng mặt. " Bạn có thể xác minh chữ ký nếu khóa công khai đã được cung cấp cho bạn thông qua các phương tiện khác, ví dụ: được lưu trữ trong kho lưu trữ chứng chỉ địa phương của bạn trước khi triển khai người dùng SAML.
Sam Rueby

2
@ Sam.Rueby à, tôi sẽ sửa lại. Mọi triển khai tôi đã thấy đều bao gồm chìa khóa.
Keith

5
@Jez toàn bộ giao thức này thật khó hiểu. Về cơ bản, xác nhận là độc lập - bạn có thể kiểm tra xem nó đã không bị giả mạo kể từ khi khóa cá nhân ký vào nó. Bạn có thể làm điều này mà không cần tự mình có khóa công khai đó (vì vậy tôi biết xác nhận này đến từ Dave và không ai can thiệp vào nó kể từ khi Dave ký nó, nhưng tôi có thể không biết Dave là ai hoặc liệu tôi có thể tin tưởng anh ta hay không). Sau đó, sau khi xác minh điều đó, tôi có thể kiểm tra khóa công khai có phải là khóa mà tôi tin tưởng hay không. Tôi nghĩ điều này là do có thể có sự chậm trễ trong lần kiểm tra cuối cùng (trong khi tôi hỏi về văn phòng xem có ai biết Dave không)
Keith

41

Lý do khóa được chỉ định là vì Siêu dữ liệu cho Nhà cung cấp danh tính có thể chỉ định nhiều khóa ký và bạn có thể chỉ định khóa để sử dụng bằng cách bao gồm nó cùng với chữ ký. SAML 2.0 yêu cầu rằng nếu khóa không được chỉ định với Assertion, thì nó có thể được suy ra theo ngữ cảnh (từ Siêu dữ liệu cho bên xác nhận).

Ví dụ: bạn có thể có thông tin này trong Siêu dữ liệu của mình cho bên xác nhận:

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

Mỗi phần tử XML được ký có thể chỉ định khóa nào được sử dụng cho chữ ký. Tuy nhiên, với trường hợp SAML 2.0, khóa ký đó (ví dụ) phải khớp với khóa ký đó được xác định trong Siêu dữ liệu cho bên tạo ra chữ ký. Nếu khóa được cung cấp cùng với chữ ký không đáng tin cậy (không được chỉ định trong Siêu dữ liệu trong trường hợp này), thì hệ thống SAML phải tạo ra lỗi khi xác thực chữ ký.


9
Tôi nghĩ đây là một điểm quan trọng, rằng chứng chỉ trong phản hồi phải khớp với chứng chỉ trong siêu dữ liệu. Nếu không, tôi có thể ký phản hồi bằng bất kỳ chứng chỉ nào tôi muốn và gửi khóa công khai của nó để xác minh.
dana

5
Tôi nghĩ đây là câu trả lời tốt nhất, có vẻ như với tôi những người khác đang thiếu điểm rằng việc kiểm tra tin nhắn so với khóa được khai báo trong tin nhắn không mang lại cho bạn bất kỳ bảo mật nào ... Bạn vẫn phải kiểm tra khóa trong tin nhắn đúng! (trong trường hợp này, bạn phải đảm bảo nó nằm trong siêu dữ liệu đáng tin cậy).
rchampourlier

3
Hoàn toàn đồng ý với các ý kiến ​​trên - bản thân chứng chỉ được thông qua trong tin nhắn là vô giá trị vì toàn bộ điểm ký là để xác minh rằng tin nhắn là đáng tin cậy. Nếu thông báo không đáng tin cậy thì các chứng chỉ đi kèm cũng vậy.
Jez

@jbindel - cảm ơn bạn! Tôi có một câu hỏi mới nếu có thể: Chứng chỉ SAML này phải khớp với chứng chỉ vật lý hiện tại hay nó chỉ được sử dụng để khớp siêu dữ liệu? Tôi hỏi điều này vì tôi lo ngại về tác động hoạt động của việc IdP làm lại chứng chỉ của họ - tại thời điểm đó, có lẽ nó không đồng bộ với khóa siêu dữ liệu. Nếu cả 2 bị ràng buộc, thì tôi lo ngại. tác động hoạt động tức là. rằng cho đến khi cả SP và IdP cập nhật khóa SAML2 theo cách thủ công, tất cả SSO sẽ không thành công và hậu quả là tác động đến người dùng SSO nếu lỗi kỹ thuật không hoàn hảo. (xin lỗi nếu câu hỏi ngu ngốc)
Pancho

Siêu dữ liệu SP phải bao gồm chứng chỉ, nhưng siêu dữ liệu SP có thể chỉ định cả chứng chỉ IdP cũ và mới. Nếu IdP đang cập nhật chứng chỉ của nó, thì chứng chỉ đó có thể được thêm vào siêu dữ liệu SP. Khi IdP được cho là đã được thực hiện bằng chứng chỉ cũ, bạn có thể xóa nó khỏi siêu dữ liệu SP. Đó có phải địa chỉ những gì bạn đang hỏi? Tôi biết điều này hoạt động hoàn toàn tốt trên Shibboleth SP. Tệp siêu dữ liệu SP chỉ cần có <KeyDescriptor use="signing">các phần tử cho chứng chỉ IdP sẽ được SP chấp nhận.
jbindel

8

Phần công khai của chứng chỉ ký nằm trong thông báo SAML. Điều này được sử dụng để kiểm tra chữ ký của chính mã thông báo và tất nhiên để cho phép người nhận biết ai đã phát hành mã thông báo và xử lý nó cho phù hợp.

Thực tế là nó nằm trong đó là một phần của thông số kỹ thuật chữ ký số XML, nó không thực sự là bất kỳ thứ gì cụ thể của SAML. Nếu không có chứng chỉ, làm thế nào bạn có thể biết mã thông báo đến từ đâu và làm thế nào bạn có thể xác thực nó?

XmlDSig không chỉ định các phương pháp khác, bạn có thể xác định khóa ký theo chủ đề, số sê-ri, hàm băm, v.v., nhưng điều này giả định rằng bên nhận có chứng chỉ công khai. Đối với SAML, điều này có thể không đúng, do đó, nhúng phần công khai của CERT X509.


1
"Nếu không có chứng chỉ, làm thế nào bạn có thể biết mã thông báo đến từ đâu và làm thế nào bạn có thể xác thực nó?" - bạn đang nói gì vậy? Để tin tưởng một chữ ký trong một thông báo SAML, bạn phải đã có một danh sách các chứng chỉ nào đáng tin cậy. Bạn có thể sử dụng Issuerphần tử và lưu trữ chứng chỉ của tổ chức phát hành đó dựa vào đó và chọn chứng chỉ đó để kiểm tra chữ ký cho thông báo này.
Jez

2
Không đúng chút nào Jez. Bạn có thể tin tưởng một tổ chức phát hành chứng chỉ, chẳng hạn như CA, mà không cần phải tin tưởng vào từng chứng chỉ mà nó cấp và không cần phải giữ bản sao cục bộ của mọi chứng chỉ.
blowdart

3
Blowdart có nghĩa là bạn đang tin tưởng mã thông báo saml được ký bởi bất kỳ chứng chỉ hợp lệ nào khác do CA. Nó không phải là không thể mua một! Để đảm bảo mã thông báo của bạn đến từ đúng nguồn như @Jez đã đề cập, bạn nên có một danh sách các chứng chỉ công khai đáng tin cậy.
nhật

2
@Sun, không chính xác. Điều đó giống như nói Wells Fargo có thể mạo danh Bank of America nếu họ có cùng CA. Chứng chỉ X509 có Chủ thể DN có thể được xác thực cho danh tính chính xác.
Paul Draper

+1 đặc biệt để xác định rằng đây là một phần của đặc tả chữ ký số XML, một điều gì đó ít rõ ràng hơn đối với người mới làm quen và rất quan trọng để hiểu cách các thư thực sự được xử lý, vì hầu hết mọi triển khai SAML đều dựa vào thư viện XML để thực hiện nâng nặng.
BryKKan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.