写在前面的话

在最近的Web应用程序测试中,我发现了Security Assertion Markup Language(SAML)实现中的一个漏洞。这个漏洞涉及SAML功能以及客户根据支持其客户的需求开发的自定义身份验证机制。通过一些技巧,我们演示了如何将这些不安全的配置组合成一个复杂的钓鱼攻击,使攻击者能够访问精心设计钓鱼页面。

 

应用概述

客户的Web应用程序允许客户创建简单的Web页面和Web表单。客户使用该应用程序从用户收集信息,并将其作为包含人力资源文档和其他潜在敏感材料的门户。客户以各种方式保护这些页面。例如,他们只允许访问授权用户的密码保护页面。该应用程序还支持使用SAML进行单点登录(SSO)。所以测试这些身份验证机制很重要。

 

验证功能

我使用管理员帐户创建了一个简单的页面。然后我添加了一些基本的文本内容,上面写着“If you can see this, good for you”最后,我改变了配置,要求进行SSO认证。我将页面命名为“samlpage”并保存设置,这会生成一个新的URL:

https://clientwebsite.com/samlpage

在使用未经身份验证会话加载页面时,我收到以下消息。

几秒钟后,页面重定向到我们的单点登录页面。Anitian安装的SimpleSAMLphp提供SAML身份程序(IDP),专门用于测试SAML实现。该网页将我重定向到以下登录。

密码不正确无法通过身份验证,我仍然卡在登录页面上。如果我输入了有效的凭据,我会被重定向回我们客户的应用程序。经过几次重定向后,我通过了应用程序验证,现在可以访问受SAML保护的页面了。

基本功能按预期工作。我使用Burpsuite的SAMLRaider插件,用它做一些标准测试,比如签名修改。在我的分析过程中,大多数基本的SAMLRaider测试都失败了。我确实发现了从IDP向客户端应用程序或服务提供商(SP)重放SAML响应的能力。SAML响应仅对单次使用有效。在此测试期间,重复接受响应,从而在同一用户帐户下生成多个有效会话。如果攻击者拦截SAML响应,他们可以打开自己的会话并绕过身份验证。此攻击类似于获取用户密码,但更糟糕的是黑客可以绕过IDP可能使用的多因素身份验证机制。

我深入研究了在SP和IDP之间来回传递的SAML流量。当SP将用户重定向到IDP进行身份验证时,GET参数包括SAML断言的单个参数和名为RelayState的第二个参数。

RelayState参数包含指向客户端应用程序中的页面的URL。从URL解码转换后,是这样的:

https://clientwebsite.com/samlpage?sp_id=73

这是我创建的受保护页面的URL,但它包含一个名为“sp_id”的额外参数.SP在其自己的参数中将此URL发送到IDP。登录到IDP后,用户将被重定向回SP(我们的客户端)。IDP再次将SAML响应与RelayState参数一起发送回SP,该参数未改变并有效地回送给SP。

SAML响应已发布到sso/saml/acs/73页面,用户被重定向到/samlpage上的受保护页面。

如果您查看Burp日志,您将看到SAML响应(紫色线)。下一个请求是针对受保护资源的,这与RelayState参数中的URL类似,但不是这样:

https://clientwebsite.com/samlpage?sp_id=73

而是这样的:

https://clientwebsite.com/samlpage?saml_token=<really long string>

我无法解码saml_token参数,但根据名称,它看起来很重要。我想也许它被用来允许访问受保护的samlpage页面。作为测试,我使用long saml_token参数复制了URL,并尝试在未经身份验证的浏览器会话中打开它。令人惊讶的是,它允许我访问受保护页面。我没有被重定向到IDP,也不必要登录。如果我有一个有效的saml_token值,我就可以访问这个页面。

我们来推理一下RelayState值。乍一看,该值似乎指示SP在哪里重定向用户。但是,此交互最初并未清除,因为sp_id参数未通过。测试很重要,因为如果我修改了参数并将用户重定向到任何网站,那么我手上就会有一个开放的重定向漏洞。

我退出了应用程序并再次启动了SSO流程以进行进一步测试。我拦截了原始SAML请求到IDP并将RelayState值修改为不同的URL。我使用一个我的网络服务器,不是以下url:

https://clientwebsite.com/samlpage?sp_id=73

我改成了这个:

https://anitianwebsite.com/owned
然后我将请求转发给IDP。已加载登录页面,我使用已知有效帐户登录。IDP然后将我重定向回SP。我检查了包含SAML响应的请求,并注意到RelayState参数仍然包含我修改过的值。客户端应用程序对SAML响应进行了身份验证,并将我重定向到受保护的页面。相反,我被重定向到这个URL,这意味着存在一个重定向漏洞:

https://anitianwebsite.com/owned?saml_token=<long value here>

接下来,我使用客户端的应用程序为另一个用户帐户生成SAML。我修改了RelayState参数并复制了整个URL。我从未访问过IDP URL,但可以将其发送给受害用户。该链接将受害者引导至IDP。对IDP的受害者身份验证会将其重定向回客户端的应用程序以及任何域。我可以执行多种攻击,包括用BEEF之类的东西连接浏览器,或设置钓鱼页面来窃取他们的凭据。再看一下我最终的URL,我注意到saml_token被传输到我的攻击者web服务器。我检查了访问日志,发现了以下信息:

我有saml_tokensaml_token参数充当访问受保护页面的密钥。我不再需要用户的密码甚至是SAML响应。我只需要令牌来获取对受保护页面的访问权限。

 

攻击大纲

为了验证这一点,我执行了以下步骤:

作为攻击者

1.我试图访问受保护的页面。
2.我被重定向到IDP,但我拦截了请求并且不允许它完成。
3.相反,我复制了URL并编辑了RelayState来包含我自己的Web服务器URL。
4.然后复制生成的URL并通过电子邮件发送给了受害者。

作为受害者

1.受害者点击了他们电子邮件中的链接,该链接将他们带到了他们的合法IDP登录页面。
2.该网页是合法的,因此受害者输入了用户名和密码进行身份验证。
3.受害者被重定向到SP,后者将其重定向到攻击者的网页。

作为攻击者

1.我检查了我的Web服务器访问日志并复制了saml_token值。
2.然后我获取了原始的RelayState URL并将saml_token值添加到结尾。
3.我在浏览器中输入了该URL并访问了受保护的页面。

此漏洞具有潜在的影响,因为我们的某些客户的客户可能会在这些受保护的页面上存储敏感信息。我在Google上研究了saml_token参数,但在我检查的资源中都找不到任何信息,甚至在SAML规范中也没有。在与客户进行对话后,他们的客户需要开发自定义参数,以授权用户访问受保护的页面而无需使用cookie。使用当前的任何一款自动扫描工具都无法检测到此类漏洞。这个发现展示了我们作为手动渗透测试的一部分可以找到的独特漏洞。

 

修复bug

验证RelayState参数是真正的问题。我们的客户可以修改他们的应用程序,以确保参数始终指向他们自己的域。另一种方法是在该参数中放置一次性令牌。然后可以将令牌放入具有关联URL的查找表中。这样,当应用程序收到RelayState令牌时,他们只需查找该令牌响应的URL并重定向到该页面即可。这样可以防止攻击者将用户重定向到外部域,并避免使用复杂的匹配规则来确保URL是有效的。我在电话交谈中了解到,saml_token仅在30秒的窗口内有效。这有助于减轻风险,因为攻击者必须实时行动或以其他方式使用自动化在收到令牌后立即滥用令牌。更好的是确保saml_token只能使用一次。这样,如果攻击者从某人的浏览器历史记录或代理日志或类似内容中获取令牌,是然并卵的。

审核人:yiwang   编辑:边边