mcpField
A
attacking-saml

attacking-saml

github.com/trilwuセキュリティ17749 回インストール12 週間前に更新
リポジトリ

attacking-saml について

許可を得た SAML セキュリティ評価向けのスキルです。SSO メッセージとサービスプロバイダーの挙動を調べるテスターを対象に、アサーション検証の弱点、リプレイ、XML 解析の問題、関連する ID 偽造経路を扱います。

主な機能

  1. 01SAML メッセージのデコードと検査
  2. 02XML 署名ラッピングのテスト
  3. 03未署名アサーション処理の確認
  4. 04アサーションとリプレイ検証の評価
  5. 05SAML パーサーの XXE 検査
  6. 06証明書の信頼動作のテスト

活用シーン

  1. 01SAML ACS エンドポイントの評価
  2. 02署名検証とアサーション選択ロジックのテスト
  3. 03サービス間のアサーション再利用の確認
  4. 04XML 解析と証明書信頼の評価

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/trilwu/secskills --skill attacking-saml

インストール後、Claude Code で/attacking-samlを入力して読み込まれたか確認します。

詳細

SAML への攻撃

SAML のセキュリティは XML 署名の検証にかかっていますが、XML 署名を正しく検証するのは非常に困難です。アサーションには署名されていますが、署名対象の要素、XML パーサーが読み取る内容、アプリケーションが最終的に信頼する内容は、まったく異なる場合があります。この隔たりが XML Signature Wrapping であり、暗号技術の印象以上に SAML で問題が頻発する理由です。

許可を得ているシステムに対してのみ実施してください。

使用する場合

  • リクエストまたはリダイレクトに SAMLRequest または SAMLResponse パラメーターが含まれている
  • Base64(リダイレクトバインディングの場合は DEFLATE も適用)をデコードすると、<saml:Assertion>、<samlp:Response>、または <saml:Subject> を含む XML になる
  • 対象が /saml/acs、/sso、/saml2/acs、または /Shibboleth.sso のアサーションコンシューマーサービスエンドポイントを公開している
  • IdP 起点のログインで、事前の AuthnRequest なしにアサーションが SP へ直接 POST される
  • フェデレーションで Okta、ADFS、PingFederate、Azure/Entra、Shibboleth、SimpleSAMLphp、または Keycloak が使われている
  • 低権限のフェデレーションアカウントを管理しており、別の ID またはロールへのアクセスを目指している

使用しない場合

  • SSO フローが OAuth 2.0 または OpenID Connect である(code、id_token、access_token、/authorize、/.well-known/openid-configuration)— attacking-oauth-oidc を使用してください
  • トークンが署名済み XML ではなく JWT である(ドット区切りの eyJ...)— attacking-jwt を使用してください
  • 対象範囲に SAML アーティファクトがない一般的な Web テスト — testing-web-applications を使用してください
  • 侵害済みの AD FS サーバーまたはクラウドテナントを対象とする Golden SAMLで、すでにトークン署名鍵を保有している場合 — これは attacking-entra-id で扱うテナント乗っ取りです
  • 署名プリミティブ自体の評価(SHA-1 と SHA-256 の比較、RSA 鍵長、正規化アルゴリズムの選択)— reviewing-cryptography を使用してください

デコードと検査

すべてはメッセージを読み取ることから始まります。ワイヤ形式はバインディングによって異なります。

# HTTP-Redirect binding: base64 then raw DEFLATE (no zlib header)
echo 'fVLLbtsw...' | base64 -d | python3 -c \
  "import sys,zlib; sys.stdout.write(zlib.decompress(sys.stdin.buffer.read(),-15).decode())"

# HTTP-POST binding: plain base64, no deflate
echo 'PHNhbWxwOl...' | base64 -d | xmllint --format -

リダイレクトバインディングでは、ヘッダーなしの raw DEFLATE を使い、ウィンドウビットは -15 です。POST バインディングではデフレートは行いません。誤った方法を選ぶと意味不明なデータになります。両方試してください。

SAML Raider(Burp 拡張機能)は作業環境として最適です。ACS への POST をインターセプトし、XML を整形して表示し、IdP 証明書をインポートし、以下の署名ラッピング攻撃をワンクリックで実行できます。手作業を始める前にインストールしてください。

samltool.com(OneLogin の SAMLtool)はメッセージのデコードと再エンコードに使え、構造の理解に役立ちます。ただし、オフラインの参考用途に限ってください。稼働中の本番アサーションをサードパーティの Web サイトに貼り付けてはいけません。代わりに、上記のコマンドでデコードしてください。

まず次のフィールドを確認してください。これらが以降のすべての攻撃の基盤となります。

  • <ds:Signature> — どこに配置され、<ds:Reference URI="#..."> が何を指しているか。これが攻撃の要です。
  • <saml:Subject><saml:NameID> — アサートされている ID
  • <saml:AttributeStatement> — ロール、グループ、メールアドレス、エンタイトルメント
  • <saml:Conditions> — NotBefore、NotOnOrAfter、AudienceRestriction
  • <saml:SubjectConfirmationData> — Recipient、NotOnOrAfter、InResponseTo
  • レスポンスエンベロープ上の Destination と Issuer

XML Signature Wrapping(XSW)

SAML の中核的な攻撃です。署名は暗号学的に有効ですが、署名チェッカーが引き続き受け入れる場所へ署名済み要素を移動させる一方で、アプリケーションのロジックには、攻撃者が制御する別の未署名アサーションを読み取らせます。検証側と利用側で、どの要素が信頼できるのかについて認識が食い違います。

代表的な 8 種類の亜種(Somorovsky ら)は、元の署名済みアサーションを移動する場所と、偽造したアサーションを挿入する場所によって異なります。

  • XSW1 / XSW2 — <Response> 全体をラップします。署名は元のレスポンスを参照しつつ、偽造したレスポンスが処理されます。XSW2 では、署名の配置位置がエンベロープ形式ではありません。
  • XSW3 / XSW4 — アサーションレベルの攻撃です。XSW3 では偽造したアサーションを署名済みアサーションの兄弟要素にし、XSW4 では署名済みアサーションを偽造したアサーションの内側にネストします。同一または重複する ID を使います。
  • XSW5 / XSW6 — コピーしたアサーションで署名を囲み、参照が引き続き解決されるよう ID 属性を操作します。
  • XSW7 / XSW8 — スキーマ検証が緩いラッパーに隠します。XSW7 では偽造したアサーションを <Extensions> 要素に配置し、XSW8 では元の署名済みアサーションを <Object> の中に埋め込み、検証は通るものの利用されないようにします。
# Attack in SAML Raider:
#   1. Intercept the ACS POST, select the signed assertion
#   2. Edit NameID / attributes in the assertion the app will read
#   3. Click XSW1..XSW8 in turn — each rebuilds the document layout
#   4. Forward; watch for a successful login as the forged identity

8 種類すべてを試してください。どれが機能するかは SP の XML ライブラリと、信頼するアサーションの選択方法に完全に依存します。予測する方法はないため、SP が安全だと結論づける前にすべての亜種を試してください。正当に取得したことのない NameID でログインに成功すれば、それが発見事項です。

未署名のアサーションと署名の削除

ラップ攻撃を試す前に、最も単純な不具合をテストしてください。SP は署名を検証しているでしょうか?

  • 署名を削除する。 <ds:Signature> を完全に削除して転送します。署名が存在する場合にのみ検証する SP もあります。
  • 署名を空にする。 SignatureValue または DigestValue を空にします。
  • 誤った対象に署名する。 SP が一方しか確認しない場合、アサーションには署名せずレスポンスに署名する、またはその逆を試します。
  • アルゴリズムをダウングレードする。 SP が想定されたアルゴリズムを固定していない場合、SHA-1 の SignatureMethod や、さらには md5/何もしない方式を試します。
# xmlsec1 can tell you what a document's signature actually covers
xmlsec1 --verify --pubkey-cert-pem idp.crt --id-attr:ID Assertion response.xml

SP が署名を削除したアサーションや未署名のアサーションを受け入れる場合、暗号処理なしで ID を偽造できます。これは SAML で最も深刻な結果です。

アサーションの改ざん

アサーションを受け入れさせることができたら(署名の削除、未署名、または機能する XSW 亜種を介して)、アサーションの内容を書き換えます。

  • NameID — 対象ユーザー(admin@corp、別テナントのユーザーなど)に差し替えます。
  • 属性 — Role/Group/memberOf を admin に変更し、IdP が発行していないエンタイトルメント属性を追加し、SP でアカウント連携を発生させるために email を変更します。
  • AudienceRestriction — SP が <Audience> を確認しない場合、同じフェデレーション内の別の SP 向けに発行されたアサーションをここで再利用できます。
  • NotOnOrAfter / NotBefore — 有効期間が広い、または確認されない場合、取得したアサーションを本来の有効期限が過ぎた後も再利用できます。
  • InResponseTo — SP 起点フローでは、SP がレスポンスを自身の AuthnRequest ID に紐づけているかを確認します。紐づけていなければ、注入または再利用されたレスポンスが受け入れられます。

それぞれを個別にテストしてください。署名を検証していても、AudienceRestriction やリプレイ防止期間を無視する SP は、依然として完全に悪用可能です。

NameID へのコメント挿入

複数の SAML ライブラリで発生した正規化の不具合です(2018 年の Duo/python-saml/OneLogin 系の CVE)。XML のテキストノード処理と署名の正規化処理で、XML コメントがテキストノードを分割する方法が異なります。

<saml:NameID>[email protected]</saml:NameID>

署名は正規化された値(コメントを削除したり、ノードを連結したりする場合があります)に対して計算されますが、アプリケーションによるテキスト抽出ではコメントより前のノードだけが読み取られ、admin になります。そのため、[email protected](攻撃者が正当に所有するアカウント)宛てに有効な署名が付いたアサーションで、admin として認証されます。NameID や、アカウントのマッピングに使われる email/username 属性など、ID に関わるフィールドの中にコメントを挿入して試してください。

SAML パーサーを介した XXE

SP は、攻撃者が用意した XML をパーサーに渡します。外部エンティティが無効化されていない場合、ACS エンドポイントは XXE の攻撃対象になります。

<?xml version="1.0"?>
<!DOCTYPE samlp:Response [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<samlp:Response ...>...&xxe;...</samlp:Response>

帯域外 DTD(http://attacker/evil.dtd)を使って、ブラインドファイル読み取りや SP の内部ネットワークへの SSRF を実行します。パラメーターエンティティ、OOB によるデータ窃取、エラーベースの情報漏えいを含む手法全体については、exploiting-xxe を参照してください。SAML 固有のポイントは、アサーションがインジェクションポイントであり、ACS が認証なしでアクセスできることです。

証明書の偽造と自己署名証明書による再署名

SP が IdP の証明書をピン留めせず、代わりに <ds:KeyInfo> に埋め込まれた証明書をそのまま信頼したり、広範な CA バンドルに含まれる任意の証明書を受け入れたりする場合、実際の署名を削除し、自分の鍵で再署名して、その証明書をメッセージに含めることができます。

# Generate a key/cert and re-sign a tampered assertion
openssl req -x509 -newkey rsa:2048 -keyout evil.key -out evil.crt -days 30 -nodes -subj "/CN=idp"
xmlsec1 --sign --privkey-pem evil.key,evil.crt \
        --id-attr:ID Assertion tampered.xml > forged.xml

SAML Raider を使えば、この操作を自動化できます。「Send Certificate」で証明書をインポートまたは生成し、編集したメッセージにその場で再署名します。偽造した自己署名アサーションが受け入れられた場合、SP はピン留めされた IdP 証明書ではなく、メッセージ自身に埋め込まれた鍵を信頼しているため、認証を完全に回避できます。

Recipient/Destination の混同と IdP 起点のリプレイ

  • Recipient/Destination が検証されない。 SP が SubjectConfirmationData 内の Recipient やレスポンスの Destination を無視する場合、ある SP で取得したアサーションを、同じ IdP を共有する別の SP で再利用できます。
  • IdP 起点のリプレイ。 IdP 起点の SSO には紐付け対象となる AuthnRequest がないため、InResponseTo がなく、リプレイ防止の状態管理も行われないことがよくあります。有効な IdP 起点の POST を取得して再送すると、有効期間内であればそのまま再ログインできる可能性があります。ログ、リファラー、履歴に漏えいしたアサーションは、使用可能な認証情報になります。
  • テナント間でのトークン再利用。 マルチテナントの SaaS では、テナント A 向けに発行されたアサーションが、テナント B の ACS でも受け入れられるか確認してください。

Golden SAML

これは侵入の糸口ではなく、最終段階です。IdP の秘密のトークン署名鍵(AD FS サーバーの証明書ストア、Azure/Entra のフェデレーション信頼、またはエクスポートされた IdP キーストアから窃取したもの)をすでに入手していれば、任意のユーザー、任意のロールに対する、完全に署名されたアサーションを無期限に偽造できます。認証情報も MFA も IdP とのやり取りも不要で、パスワードリセット後も有効です。

# With the stolen signing key, mint an assertion for any identity
xmlsec1 --sign --privkey-pem tokensigning.key,tokensigning.crt \
        --id-attr:ID Assertion golden.xml > any-user.xml

鍵の入手はホストやテナントの侵害に関する作業であり、SAML メッセージに関する作業ではありません。この経路(AD FS のトークン署名証明書、DKM 鍵、またはクラウドフェデレーションシークレットの抽出)については、attacking-entra-id を参照してください。ここに戻るのは、偽造するアサーションを組み立てるときだけです。

退けるべき合理化

  • 「アサーションには署名があるので、改ざんできません。」 署名ラッピングでは、アプリが別の要素を読み取る一方で、署名は有効なままです。署名されていることは、その署名対象が信頼されていることを意味しません。
  • 「XSW1 が機能しなかったので、SP は安全です。」 8 種類のバリアントがあるのには理由があります。何らかの結論を出す前に、XSW1~XSW8 をすべて実行してください。
  • 「署名は検証しています。確認しました。」 ある署名を検証することと、実際に使用するアサーションを検証することは同じではありません。また、署名がある場合にしか検証しない可能性があります。署名を削除してテストしてください。
  • 「Audience/Recipient は単なるメタデータです。」 SP が AudienceRestriction、Recipient、Destination を強制しない場合、アサーションは SP やテナントをまたいでリプレイされます。
  • 「コメントの件は見た目だけの問題です。」 [email protected] は admin として認証されます。正規化の不一致は、アカウントの完全な乗っ取りにつながります。
  • 「信頼できる IdP からの XML なので、XXE は問題になりません。」 ACS は信頼する前にバイト列を解析し、そのバイト列はあなたのブラウザーから送られます。つまり、信頼できないデータです。
  • 「Golden SAML には秘密鍵が必要なので、対象外です。」 アサーションの偽造はここで扱う範囲です。鍵の漏えいを記録し、鍵の抽出は attacking-entra-id に引き継いでください。影響を軽視しないでください。

ATT&CK の対象範囲

secskills-core/ttp-index.json から生成されます。このファイルを編集してから、 python3 scripts/sync_attack.py --write を実行してください。レポートで引用する前に、 現在の ATT&CK リリースに照らして ID を再確認してください。

認証情報アクセス(TA0006)

  • T1606.002 SAML トークン — attacking-entra-id も参照してください

これらに関する検出コンテンツ:engineering-detections。プロアクティブな検索:hunting-threats。侵害後の対応:responding-to-incidents。

参考資料

  • attacking-oauth-oidc — SSO フローが OAuth 2.0 / OpenID Connect の場合
  • attacking-jwt — トークンが XML ではなく署名付き JWT の場合
  • exploiting-xxe — ACS パーサーがシンクとなる場合の XXE 手法全般
  • attacking-entra-id — AD FS サーバーまたはテナントの侵害を介した Golden SAML
  • testing-web-applications — 関連する Web 手法
  • reporting-security-findings — 署名回避およびリプレイの重大度
  • SAML Raider(Burp 拡張機能)、Burp Suite、xmlsec1、SAMLtool(samltool.com)

コメント