2017-12-05 18 views
5

サードパーティのIDP(SP開始)を使用してSAML SSOを実装する必要があるWebアプリケーションで作業しています。それはそれは、手動実装の要求がnetcoreapp2.0ターゲットだAsp.NetコアSAML応答シグネチャの検証

<?xml version="1.0" encoding="UTF-8"?> 
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" InResponseTo="63622fa6-9a00-4d39-9c92-791c3a1efc3f" IssueInstant="2017-12-04T13:47:30Z" ID="mjmobamignjdlgkpmkiijfbknamlbkadhkjcamhp" Version="2.0"> 
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://idp.com</saml:Issuer> 
    <samlp:Status> 
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> 
    </samlp:Status> 
    <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="gkifgihgclegelojncjfgegcddfncgdaefcjgbod" IssueInstant="2017-12-04T13:47:30Z" Version="2.0"> 
    <saml:Issuer>https://idp.com</saml:Issuer> 
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
     <ds:SignedInfo> 
     <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
     <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 
     <ds:Reference URI="#gkifgihgclegelojncjfgegcddfncgdaefcjgbod"> 
      <ds:Transforms> 
      <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> 
      <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
      </ds:Transforms> 
      <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
      <ds:DigestValue>nyU3iydIomlY9+D+YO7E6zNyq1A=</ds:DigestValue> 
     </ds:Reference> 
     </ds:SignedInfo> 
     <ds:SignatureValue>1AVSFcmgaPMFZvPHYyZDz1oFWzgiMCHI6yMfe6yCSK1pw6bkbZd/yZys8DuySi3Q75bnu3FmbrJQ 
L9eEfoXK7kJEut79f9xrBwScNYQ21AZdYh5Rdzm7jRsbugYuQpfUUWasR6U37+bStVPpsCYEo4+C 
Y1arLC/9ujj7aGxF7H+EMk7X0L4059+2v711X7a/3biowx2CyNOgjNRcrri3cyX/0soryyCA6/zH 
fO2wcQi4udMXcZwXtZpAsluah7DjGp9MSTS5NInKm3Is4VIS9fN3KmKKTJYYZI27N0lFAxgHGVXc 
GPWsh4hAd1CqQvuM0P5YlBfgPBD6Mu6tmZ9VLg==</ds:SignatureValue> 
     <ds:KeyInfo> 
     <ds:X509IssuerSerial> 
      <ds:X509IssuerName>CN=Symantec Class 3 Secure Server CA - G4,OU=Symantec Trust Network,O=Symantec Corporation,C=US</ds:X509IssuerName> 
      <ds:X509SerialNumber>142421751065451577073995987482935596892</ds:X509SerialNumber> 
     </ds:X509IssuerSerial> 
     <ds:X509Data> 
      <ds:X509Certificate>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 
TyU0Bbc2VGLlcP8=</ds:X509Certificate> 
     </ds:X509Data> 
     </ds:KeyInfo> 
    </ds:Signature> 
    <saml:Subject> 
     <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified">C229699</saml:NameID> 
     <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> 
     <saml:SubjectConfirmationData InResponseTo="63622fa6-9a00-4d39-9c92-791c3a1efc3f" NotOnOrAfter="2017-12-04T13:57:30Z" Recipient="http://my-app.net/saml"/> 
     </saml:SubjectConfirmation> 
    </saml:Subject> 
    <saml:Conditions NotBefore="2017-12-04T13:42:30Z" NotOnOrAfter="2017-12-04T13:57:30Z"> 
     <saml:AudienceRestriction> 
     <saml:Audience>http://my-app.net</saml:Audience> 
     </saml:AudienceRestriction> 
    </saml:Conditions> 
    <saml:AuthnStatement AuthnInstant="2017-12-04T13:47:30Z" SessionIndex="gkifgihgclegelojncjfgegcddfncgdaefcjgbod"> 
     <saml:AuthnContext> 
     <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef> 
     </saml:AuthnContext> 
    </saml:AuthnStatement> 
    <saml:AttributeStatement> 
     <saml:Attribute Name="UserID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> 
     <saml:AttributeValue>D100000</saml:AttributeValue> 
     </saml:Attribute> 
    </saml:AttributeStatement> 
    </saml:Assertion> 
</samlp:Response> 

ので、私は適切な思い付くしようとしている:私はこのようになります私はIDPからのSAML応答を受け付けております点に達しました提供されている署名値を検証するためのソリューションです。この文書、How to: Verify the Digital Signatures of XML Documentsは、プロセスの一部を説明するのに役立ちましたが、私のSSOの実装にはさらに検証が必要です。 SAMLレスポンスからXML形式を引っ張って

私は、次のチャンクを持っている:

var samlResponse = Request.Form["SAMLResponse"]; 
var toBytes = Convert.FromBase64String(samlResponse); 
string decodedString = 
Encoding.UTF8.GetString(toBytes); 

ただ、このコードは私のサンプル値/変数を使用して、(次のようになります上記のリンクを開かずにすぐに参照できます該当する場合):

CspParameters cspParams = new CspParameters(); 
cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"; 

// Create a new RSA signing key and save it in the container. 
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); 

// Create a new XML document. 
XmlDocument xmlDoc = new XmlDocument(); 

// Load an XML file into the XmlDocument object. 
xmlDoc.PreserveWhitespace = true; 
xmlDoc.LoadXml(decodedString); 

// Verify the signature of the signed XML. 
Console.WriteLine("Verifying signature..."); 
bool result = VerifyXml(xmlDoc, rsaKey); 

// Display the results of the signature verification to 
// the console. 
if (result) 
{ 
    Console.WriteLine("The XML signature is valid."); 
} 
else 
{ 
    Console.WriteLine("The XML signature is not valid."); 
} 

public static Boolean VerifyXml(XmlDocument Doc, RSA Key) 
{ 
    // Check arguments. 
    if (Doc == null) 
     throw new ArgumentException("Doc"); 
    if (Key == null) 
     throw new ArgumentException("Key"); 

    // Create a new SignedXml object and pass it 
    // the XML document class. 
    SignedXml signedXml = new SignedXml(Doc); 

    // Find the "Signature" node and create a new 
    // XmlNodeList object. 
    XmlNodeList nodeList = Doc.GetElementsByTagName("Signature"); 

    // Throw an exception if no signature was found. 
    if (nodeList.Count <= 0) 
    { 
     throw new CryptographicException("Verification failed: No Signature was found in the document."); 
    } 

    // This example only supports one signature for 
    // the entire XML document. Throw an exception 
    // if more than one signature was found. 
    if (nodeList.Count >= 2) 
    { 
     throw new CryptographicException("Verification failed: More that one signature was found for the document."); 
    } 

    // Load the first <signature> node. 
    signedXml.LoadXml((XmlElement)nodeList[0]); 

    // Check the signature and return the result. 
    return signedXml.CheckSignature(Key); 
} 

UPDATE:Asp.NetコアでSAML SSOの私の手動実装のためのワーキング・ソリューション2.0:まず、私は以下の方法があるXML文書の署名を検証するために、「VerifyXml」と命名しています検索SAMLレスポンスフォームのデータから編集します。私はAccountControllerコードのX509証明書を@Evk(ヘルプのおかげでもう一度)として検証していますが、署名を検証するだけでは不十分です。この場合、任意のSAML応答が送信されて受け入れられないようにします。私の場合、これらの2つの値を検証する上で、 "InResponseTo"パラメータが妥当な期間内に私のWebアプリケーション(SP)によって生成された値と一致することを検証する必要もあります。一般的に、ログインには時間がかかるべきではありません。たとえば、一定時間経過後にWebアプリケーションによって生成され、発行されたAuthnRequest IDを忘れるタスクを作成することができます。あなたに該当する分や時間を言う(このコードを答えに含めなかった)。この(あなたは私のために確認しませんが、それはここでそれを掲示しながら、行われた変更が原因である可能性があり)のように署名を検証する

public static bool VerifyXml(XmlDocument Doc) 
{ 
    // Check document isn't null. 
    if (Doc == null) 
     throw new ArgumentException("Doc");  
    SignedXml signedXml = new SignedXml(Doc); 
    var nsManager = new XmlNamespaceManager(Doc.NameTable); 
    nsManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); 
    var node = Doc.SelectSingleNode("//ds:Signature", nsManager); 
    signedXml.LoadXml((XmlElement)node); 
    return signedXml.CheckSignature(); 
} 
/* ******* CONTROLLER CODE ******* */ 
SignedXml signedXml = new SignedXml(xdoc); 
var nsManager = new XmlNamespaceManager(xdoc.NameTable); 
nsManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); 
var certElement = xdoc.SelectSingleNode("//ds:X509Certificate", nsManager); 
/* Convert the received X509 Certificate into a new X509Certificate2 object. */ 
var certReceived = new X509Certificate2(Convert.FromBase64String(certElement.InnerText)); 
/* Load the pre-shared X509 Certificate from the idP metadata file. I have it stored in a secure database (You DO NOT want this stored in an easily accessible place, especially for production, in the project as it contains sensitive information). */ 
var loadSafeCert = _context.StoredMetadata.Where(metadata => idPMetadata.Certificate == "Certificate").FirstOrDefault(); 
/* Create a new X509Certificate2 using the value of the pre-defined certificate. */  
var safeCertificate = new X509Certificate2(Convert.FromBase64String(loadSafeCert.ConfigurationValue));  
/* Compare the received X509 Certificate value vs the pre-defined X509 Certificate value to ensure the validity. */ 
if (certReceived.GetPublicKeyString() == safeCertificate.GetPublicKeyString()) 
{ /* Store/get attributes, authenticate user, etc here */ } 
+0

あなたのレスポンスXMLでそのコードを試しましたか? – Evk

+0

ええ、私はそれを試して、私はまだ真実を返すための検証を得ることができません。また、私はどのように私はそれを使用しようと明確にするためにコードの塊を試みる前に、私は応答フォームのデータを文字列に変換する方法を含めるために私の質問を更新しました。 – Jared

+0

SignedXmlはこの場合に行く方法なので、多く提案するのは難しいです。なぜそれが偽を返すのかは、サンプルのSAMLレスポンス(署名と、あなたがXXXで置き換えられた他のすべてのもの - 私はそれが感覚的なデータだとは思わないので、本当に必要ではない)サイドノート:値がすでにbase64にある場合、なぜUrlDecodeを使用していますか?必要ないと思われる。 – Evk

答えて

2

試してみてください。それでも解決しない場合は

public static bool VerifyXml(XmlDocument Doc) { 
    if (Doc == null) 
     throw new ArgumentException("Doc"); 
    SignedXml signedXml = new SignedXml(Doc); 
    var nsManager = new XmlNamespaceManager(Doc.NameTable); 
    nsManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); 
    var node = Doc.SelectSingleNode("//ds:Signature", nsManager); 
    // find signature node 
    var certElement = Doc.SelectSingleNode("//ds:X509Certificate", nsManager); 
    // find certificate node 
    var cert = new X509Certificate2(Convert.FromBase64String(certElement.InnerText));    
    signedXml.LoadXml((XmlElement)node); 
    return signedXml.CheckSignature(cert); 
} 

、また、同じことをしようとしたが

return signedXml.CheckSignature(); 

代わりの

return signedXml.CheckSignature(cert); 
012を呼び出します

この署名を検証するだけでは、応答が改ざんされていないことを確認するのに十分ではありません。応答自体に含まれる鍵(X509Data)を使用して署名を検証すると、攻撃者が応答を傍受し、情報を抽出して自分の鍵で辞任する可能性があるため、署名は有効になりますが、署名された鍵は、したがって、証明書を抽出した後(または、signedXml.CheckSignatureReturningKeyメソッドを使用して署名に関連する公開鍵を取得することができます)、その証明書が有効であることを確認する必要があります(たとえば、ハッシュと期待される証明書のハッシュを比較します)。

+0

あなたの最初の答えは完全に機能しました(あなたの代替作品も同様)。あなたの助けをありがとう、これは私が必要としていたものです! – Jared

+0

@Jaredが2番目の場合 - それを使用してください。証明ノードを見つけるコードは削除してください。 – Evk

+0

ありがとう!ちょうど説明の目的のために、あなたはなぜ私は2番目の方が良いか説明することができますか? – Jared

関連する問題