在我的asp.net MVC网站中,我实施了SSO,其中IDP / ADFS发送SAML响应,我验证SAML令牌以允许用户访问该网站。我使用自定义代码(使用System.IdentityModel.dll和System.IdentityModel.Services.dll库来验证SAML响应和令牌,而不是让.NET框架使用web.config设置进行检查)。
到目前为止,代码似乎工作正常,但由于我是这个领域的新手,因此担心黑客能够通过正确构造的SAML响应绕过验证。最近我尝试了SAML令牌生成部分,我意识到如果智能生成令牌,我的令牌验证码可以被绕过。
在高级别,我正在做的是验证令牌:
我担心的是,如果黑客创建SAML令牌(比如我自己的令牌生成器代码)并在响应中添加公钥并将其发布到我的网站,我的网站将成功验证响应,因为响应本身已经很好地形成并签字。这是一个有效的问题吗?我缺少一些基本的验证来处理这种情况? 我可以考虑采用以下方案来降低风险:
检查URLReferrer并确保从预期的实体发布SAML响应。我不确定是否有办法操纵URLReferrer。
避免使用响应中的公钥来验证摘要值。我可以将X509证书存储在我的终端并使用它来验证响应。黑客将无法使用相同的证书签署响应,因为他没有私钥。如果这是正确的方法,有人可以建议我如何指示“tokenhandler”忽略响应中存在的公钥并使用显式公钥吗?
我是否有办法对IDP进行后端呼叫,可以进行网络服务呼叫,并检查我的网站收到的令牌是否确实是由IDP生成的?
由于我是新手,我可能会错过基本的SAML验证概念。如果我的担忧是合法的,请告诉我。 以下是我用于验证响应的示例代码。
public ActionResult SAMLAssert()
{
var fam = new WSFederationAuthenticationModule();
var request = this.HttpContext.Request;
// Get the security token from the SAML response
var securityToken = fam.GetSecurityToken(request);
var config = new SecurityTokenHandlerConfiguration
{
CertificateValidator = X509CertificateValidator.None,
IssuerNameRegistry = new CustomIssuerNameRegistry(),
};
config.AudienceRestriction.AudienceMode = AudienceUriMode.Never;
var tokenHandler = new Saml2SecurityTokenHandler
{
CertificateValidator = X509CertificateValidator.None,
Configuration = config,
};
//// validate the token and get the ClaimsIdentity out of it
var identity = tokenHandler.ValidateToken(securityToken);
bool isSuccess = identity[0].IsAuthenticated;
// Code to retrieve the claims/user information from the token
//....
return View();
}
这是自定义" IssuerNameRegistry"。
public class CustomIssuerNameRegistry : IssuerNameRegistry
{
public override string GetIssuerName(SecurityToken securityToken)
{
X509SecurityToken x509Token = securityToken as X509SecurityToken;
return x509Token.Certificate.Subject;
}
}
我怀疑自定义类是有问题的部分,因为它没有进行任何验证。
答案 0 :(得分:2)
我认为您不应该检查引荐来源值。它很容易被欺骗。
IdP使用其私钥对发送给您的回复进行签名。攻击者无法访问此私钥。因此,如果攻击者想要欺骗签名,他将需要使用自己的证书并将其公钥放入令牌。虽然您认为验证码使用嵌入式公钥来验证签名是正确的,但AFAICT还可以做一件事:检查我们的机器是否信任公钥。可以通过将公钥添加到Windows证书存储区来建立此处的信任 - > TrustedPeople。我没有所有代码来验证这一点,但它应该以这种方式工作,或者它应该为您提供一种方法。 如果您完全控制IdP,替代嵌入式公钥(也称为X509Data),则只能使用键名,主题名称和指纹。但是他们提供的安全性和实施方式超出了这个问题的范围。
不,SAML协议并未设计为以这种方式工作。最接近这一点的是使用Artifact流,其中IdP仅向您的应用程序返回Artifact,并且它需要向IdP发出ArtifactResolve请求以获取实际响应。见What is the purpose of a SAML Artifact?。但是,您仍然需要验证收到的响应的签名。