Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

XML签名绕过SAML 2.0 SSO原理分析 XML签名 绕过SAML 单点登录 网络安全

$
0
0

本文讲述的是XML签名绕过SAML 2.0 SSO原理分析,旨在服务社会,供安全研究人员学习使用,请勿用于其他非法用途,违者后果自负。最近,我们注意到一种趋势:许多新西兰的网站计划实现SSO(Single Sign-On,单点登录)以替代密码登录,这其中也包括了许多政府类网络服务。目前最流行的SSO标准是SAML 2.0,它支持多个开发框架,同时也支持多种开发语言。通常情况下,SAML 2.0标准在将验证用户身份的SAML响应数据返回给浏览器的过程中,使用数字签名以防止数据被篡改。但不幸的是,许多开发人员并未恰当地验证SAML响应数据,这就给了攻击者可乘之机,攻击者可以绕过身份认证。


XML签名绕过SAML 2.0 SSO原理分析 XML签名 绕过SAML 单点登录 网络安全

SAML 2.0 SSO简介

安全声明标记语言(Security Assertion Markup Language,SAML)是一个基于XML的标准,用于在不同的安全域(Security domain)之间交换认证和授权数据。当使用SAML 2.0标准登录一个站点时,一共有三方参与进来:服务提供商SP(Service Provider,用户打算登录的站点),当事人(Principal,准备登录的用户)和身份提供商IdP(Identity Provider,提供认证服务的权威机构,如Google等)。我们要实现的目标是:IdP通过一种可信的方式告诉SP当事人的身份是谁。

登录时,SP将用户重定向到IdP,同时提交一个SAML请求。一旦IdP确认了用户的身份,就会向SP返回一个SAML响应。发送SSO消息主要有以下三种方式,在标准中称之为“绑定”:

HTTP重定向绑定:将SAML消息直接包含在URL中。

HTTP POST绑定:将SAML消息包含在POST请求体中。

HTTP Artifact绑定:发送一个随机令牌作为标识,通过反向通道获取文档。

前两种绑定方式在实际使用过程中存在一些比较严重的问题。

识别SAML响应

如前所述,通常情况下,SAML响应消息或者通过URL进行传递,如下图所示:


XML签名绕过SAML 2.0 SSO原理分析 XML签名 绕过SAML 单点登录 网络安全

或者包含在一个POST请求体中,如下图所示:


XML签名绕过SAML 2.0 SSO原理分析 XML签名 绕过SAML 单点登录 网络安全

以上两种方式中的SAML消息都要经过浏览器,因此都能被攻击者操纵。但是,另一方面,当通过如下图所示的SAML Artifact方式时:


XML签名绕过SAML 2.0 SSO原理分析 XML签名 绕过SAML 单点登录 网络安全

攻击者可能就束手无策了。因为这些随机令牌被解析进原始消息中了,然后通过一个反向通道被取回,所以除非攻击者有权限访问目标所在的私有网络(比如存在SSL/TLS漏洞刚好被利用),否则这些令牌对攻击者而言并无利用价值。

保护消息传输过程

这里的问题在于,不管是通过HTTP重定向绑定还是通过HTTP POST绑定,IdP返回的验证用户身份信息的数据都要经过用户的浏览器,所以在传输过程中很可能被篡改。而HTTP Artifact绑定则不存在这种问题。

如果SAML响应消息缺乏相应的保护机制,则攻击者可以通过篡改响应数据冒充他人身份。例如,我以Tim的身份登录IdP然后通过简单地修改SAML响应消息声称自己是Emmanuel。实事上,我可以伪造整个响应消息,然后冒充Emmanuel的身份。

当然,SAML标准的开发者并非不够严谨而让错误消息通过认证。相反,他们非常努力地修复这个问题。标准中所采用的方案是:在每个响应消息体中附加一个XML签名,以防止数据被篡改。

XML签名标准

XML签名标准是一头庞大的、复杂难懂的野兽,它由一个成员包含许多大牛的工作组所设计,设计初衷是作为一个放之四海而皆准的、用于构建可抵抗篡改攻击的XML文档的解决方案。不幸的是,“放之四海而皆准”最终却变成了“什么也不适合”。

在标准的数字签名应用中,我们对需要签名的文档执行密码散列函数计算出HASH,然后对该HASH值应用数字签名算法得到数字签名。如果被接收的文档和原始文档是完全一致的,那么通过同样的算法对接收文档计算得到的数字签名和接收到的数字签名是完全一致的;然而,两个数字签名只要有一位数据不同,那么就认为接收到的数字签名是无效的,文档也就会被接收方所拒绝。

不幸的是,XML有一个致命的弱点——XML签名标准允许我们只对文档的一部分而不是整个文档进行签名,然后将这个签名嵌入同一个需要验证的文档——这就是所谓的内联签名(Inline signatures)。为实现内联签名,需要在被签名文档中包含对文档局部的引用,通常是引用一个XML元素的ID属性,但理论上允许使用任何符合XPath标准的对象作为表达式。例如,理论上,我可以在一个文档内的任意位置写入指向“倒数第三个元素”的签名,或者类似的模糊表达式。

当验证一个XML签名时,仅仅确认“这是一个来自签名者的有效的签名吗?”是不够的。我们也必须确认“签名存在吗?如果存在的话,这是指向文档的正确位置的、遵守了正确的标准的、由期望的签名者所签发的、有效的签名吗?”但是经常出现的情况是,至少有一项未被验证。

SAML Raider入门

本文所描述的所有攻击方法并不需要很多工具就能够实现,不过通常情况下,Burp Suite的SAML Raider插件是一个很有用的辅助测试工具。

检测

如前所述,签名可能出现在SAML消息中的多个位置并且覆盖整个消息的多个部分。通过保留消息内容,向其中增加新的部分,并且修改剩余部分的结构,我们可以手工构造出一个新的消息,这个新消息从技术上讲仍然是被合法签名的,但是可能被SAML库解析为包含了已签名的关键内容,尽管实际上该关键内容并不存在。

无论何时,SP在进行验证时,有一定的机率验证失败或者进行了不正确的验证,这都给了我们绕过签名验证的机会。打开Burp的拦截功能,拦截SAML请求报文,然后尝试这些转换。每次尝试都要针对一个新的、有效的登录动作,因为通常会有一个Nonce(如随机令牌)阻止我们重复发送相同的请求报文。

在反复测试的过程中,按照如下设置Burp的Proxy,每次仅仅拦截SSO登录请求,将会帮你省去不少额外动作:


XML签名绕过SAML 2.0 SSO原理分析 XML签名 绕过SAML 单点登录 网络安全

签名是必需的吗?

SAML标准要求所有经过非安全信道(如用户的浏览器)进行传输的消息都要有数字签名。不过,如果消息通过安全信道(如SSL/TLS反向通道)进行传输的话,签名就不是必需的了。但是正因为这一点,我们发现SAML使用者经常这样做:如果有任何签名存在,就进行验证;如果签名被移除,则跳过验证。软件基本上假定我们已经检查了来自非安全信道的消息已签名,而真实情况并非如此。

Viewing all articles
Browse latest Browse all 12749

Trending Articles