SAML (Security Assertion Markup Language)
XML-basiertes Protokoll für Single Sign-On (SSO) zwischen Identity Provider (IdP) und Service Provider (SP). SAML ermöglicht, dass Benutzer sich einmal beim IdP anmelden und ohne erneute Passwort-Eingabe auf mehrere Dienste zugreifen können.
SAML 2.0 ist der De-facto-Standard für Enterprise-SSO. Wenn Sie sich bei Slack, Salesforce, GitHub Enterprise oder SAP mit Ihren Unternehmens-Credentials anmelden, läuft im Hintergrund meistens SAML. Das Protokoll ist mächtig, aber auch komplex - und damit Angriffsfläche für Schwachstellen wie XML-Signatur-Wrapping.
SAML-Grundkonzepte
Die drei Rollen
1. Principal (Benutzer):
- Möchte auf einen Dienst zugreifen
2. Identity Provider (IdP):
- Kennt und authentifiziert den Benutzer
- Stellt SAML-Assertion aus (Zertifikat dass User XY existiert)
- Beispiele: Microsoft Entra ID (Azure AD), Okta, JumpCloud, Active Directory Federation Services (ADFS)
3. Service Provider (SP):
- Dienst auf den der Benutzer zugreifen möchte
- Vertraut dem IdP (via vorherigem Metadaten-Austausch)
- Beispiele: Salesforce, Jira, GitHub Enterprise, AWS
Das Vertrauen zwischen IdP und SP
- Vorab: Metadaten-Austausch (EntityID, Zertifikate, Endpoints)
- IdP-Zertifikat: SP vertraut nur Assertions die mit diesem Key signiert sind
- EntityID: eindeutiger Identifier (oft URL)
SAML SSO-Flow (SP-initiated)
Ablauf wenn User auf Service Provider zugreift:
1. User navigiert zu: https://app.salesforce.com/login
2. SP erkennt: User nicht eingeloggt → SAML erforderlich
3. SP generiert AuthnRequest (XML):
<samlp:AuthnRequest
ID="_abc123"
AssertionConsumerServiceURL="https://salesforce.com/saml/callback"
Destination="https://idp.firma.de/sso/saml"
/>
4. SP redirectet User zu IdP (GET/POST mit AuthnRequest)
5. IdP zeigt Login-Seite (oder nutzt existierende Session)
6. User loggt sich beim IdP ein (Passwort + MFA)
7. IdP erstellt SAML-Response (XML) mit Assertion:
<Assertion>
<Subject>user@firma.de</Subject>
<AttributeStatement>
<Attribute Name="email">user@firma.de</Attribute>
<Attribute Name="role">admin</Attribute>
</AttributeStatement>
<Conditions NotBefore="..." NotOnOrAfter="..."/>
</Assertion>
8. IdP signiert Assertion mit privatem Schlüssel (XML Signature)
9. IdP sendet Response via Browser (HTTP POST) an SP
10. SP prüft Signatur mit IdP-Zertifikat
11. SP erstellt Session für User → Zugang gewährt
Wichtig: Browser ist Vermittler! IdP und SP kommunizieren nie direkt.
SAML vs. OAuth 2.0 / OpenID Connect
| Aspekt | SAML 2.0 | OAuth 2.0 + OIDC |
|---|---|---|
| Format | XML | JSON (JWT) |
| Zweck (primär) | Authentifizierung | Autorisierung |
| OIDC ergänzt | - | Authentifizierung |
| Verbreitung | Enterprise (Legacy) | Web/Mobile/APIs |
| Komplexität | Hoch (XML, Zerts) | Mittel (JSON) |
| Mobile Apps | Schlecht | Sehr gut |
| Browser-only? | Ja (Redirect-Flow) | Nein (API-Flows) |
| Beispiel-IdPs | ADFS, Okta, Entra | Entra, Google, Auth0 |
Wann SAML verwenden:
- Enterprise-Anwendungen (SAP, Salesforce, ServiceNow)
- Bestehendes SAML-Ökosystem
- Wenn SP nur SAML unterstützt
Wann OAuth 2.0/OIDC verwenden:
- Neue Entwicklung
- Mobile Apps
- APIs und Microservices
- Moderne IdPs (Auth0, Cognito)
Hybridfall: Viele Enterprises nutzen beide - SAML für Legacy-Enterprise-Apps, OIDC für neue Apps und APIs. Entra ID / Okta unterstützt beide.
SAML-Konfiguration - Wichtige Parameter
Service Provider Konfiguration (Beispiel: Jira):
entityID: https://jira.firma.de # Eindeutige SP-ID
ACS URL: https://jira.firma.de/plugins/servlet/saml/sso
# Callback nach SSO
SLO URL: https://jira.firma.de/plugins/servlet/saml/slo
# Single Logout
NameID Format: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
# Wer ist der User?
Signing Certificate: <Zertifikat des IdP> # Für Signaturprüfung
Identity Provider Konfiguration (Beispiel: Entra ID / Azure AD):
Identifier (EntityID): https://jira.firma.de
Reply URL (ACS): https://jira.firma.de/plugins/servlet/saml/sso
Sign-on URL: https://idp.firma.de/saml2/sso/request
Claims Mapping (Attribute):
email: user.mail
username: user.userprincipalname
firstName: user.givenname
lastName: user.surname
role: user.assignedroles
Signing Certificate: <Privates Zertifikat des IdP>
Sicherheitsparameter:
- Assertion gültig für: max. 5 Minuten (NotOnOrAfter!)
- Assertion Encryption: ja (wenn SP unterstützt)
- Request Signing: ja (SP signiert AuthnRequest)
- Response Signing: Pflicht (IdP signiert Assertion)
SAML-Sicherheitslücken
1. XML Signature Wrapping (XSW)
SAML-Response enthält signierten und unsignierten Teil. Angreifer fügt gefälschte Assertion ein; die signierte originale Assertion wird “eingewickelt”. Manche SP-Implementierungen prüfen das falsche Element.
Beispiel CVE-2017-11427 (SimpleSAMLphp): Authentifizierung als beliebiger User möglich. Root Cause: falsche XPath-Abfrage für signiertes Element.
Schutz: Aktuelle, gepatchte SAML-Bibliotheken verwenden.
2. XML External Entity (XXE) in SAML
SAML-Parser liest externe XML-Entities.
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
Schutz: XXE in XML-Parser deaktivieren.
3. Comment Injection / Parser Differentials
IdP und SP parsen XML unterschiedlich:
user@firma.de<!-- comment -->fake@attacker.de
→ IdP sieht: user@firma.de
→ SP sieht: user@firma.defake@attacker.de (oder umgekehrt!)
4. Replay-Angriff
Alte SAML-Assertion wird erneut verwendet. Schutz: InResponseTo + AssertionID cachen, Zeitfenster (5min)
5. Open Redirect beim IdP
RelayState-Parameter nicht validiert → nach Login Redirect zu Phishing-Seite.
SAML Security Checklist
- XML-Signaturen korrekt prüfen (gesamtes Element, nicht nur Inhalt)
- Zeitfenster prüfen (NotBefore, NotOnOrAfter)
- Assertion ID cachen (Replay-Schutz)
- InResponseTo validieren (AuthnRequest → Response mapping)
- IdP-Zertifikat rotieren (jährlich)
- Aktuelle SAML-Bibliothek (CVEs prüfen!)
- SAML Tracer (Firefox Extension) für Debug
SAML-Troubleshooting
Häufige Fehler und Lösungen
“Audience Restriction” Fehler:
- SP-EntityID stimmt nicht mit Assertion überein
- Lösung: EntityID in IdP und SP identisch konfigurieren
“Assertion is expired”:
- Server-Zeitdifferenz zwischen IdP und SP
- Lösung: NTP auf beiden Systemen synchronisieren; Assertion-Gültigkeitsfenster ggf. erweitern (5→10min)
“Signature validation failed”:
- IdP-Zertifikat abgelaufen oder nicht importiert
- Lösung: neues Zertifikat in SP importieren
“NameID mismatch”:
- E-Mail im IdP: Groß/Kleinschreibung
- Lösung: Case-insensitive Vergleich im SP
Debug-Tools
- SAML Tracer (Firefox/Chrome Extension): zeigt Base64-decoded XML
- https://www.samltool.com/decode.php: SAML-Response dekodieren
- SP-Logs: meist unter
/var/log/apache2/oder App-Logs