当社のAIエンジンNeutronが、UCバークレーのCyberGymベンチマークで97.1%のスコアを記録しました。 詳細を見る

ディープダイブ

ディープダイブ

OpenAMのセッショントークン窃取とSAMLバイパス(CVE-2026-123551)

OpenAM 16.1.4より前は有効なセッショントークンを漏えいし、署名のないSAMLアサーションを受け入れるため、未認証の攻撃者がセッションを乗っ取れます。16.1.4で修正済みです。

要点

  • OpenAM 16.1.4より前は、有効なセッショントークンをポリシーエージェントのトピックへ平文で配信し、ECPとHTTP-Artifactの各バインディングで署名のないSAMLアサーションを受け入れます。未認証の攻撃者はどちらの欠陥でも利用して、ユーザーと管理者のセッションを乗っ取れます。
  • 同じリリースは、匿名ユーザーが管理グループへ参加できる自己登録の欠陥も修正します。OpenIdentityPlatformは2026年10月22日にアドバイザリとOpenAM 16.1.4を公開しました。
  • CVEレコードはトークン漏えいをCVSS v4.0 10.0、残る2件を9.3と評価しています。ベンダーアドバイザリはトークンの欠陥をCVSS v3.1 10.0、残る2件を9.8と評価しています。
  • 公開された実証コードも、実際の悪用も報告されていません。2026年11月8日時点でCISAのKEVカタログには載っていません。OpenAM 16.1.4へ更新してください。

影響を受けますか?

次のすべてを満たす場合に該当します。

  • OpenIdentityPlatform OpenAMの16.1.4より前のバージョンを実行している。
  • セッショントークンの欠陥については、14.0.0から16.1.3を実行し、通知WebSocketへ到達できる。エージェント通知は既定で有効で、これがセッション識別子をエージェントのトピックへ載せます。
  • SAMLの欠陥については、OpenAMがホスト型SAML v2.0サービスプロバイダーとして動作している。メタデータがECP(PAOS)アサーションコンシューマーサービスを通知し、生成されるメタデータは既定でそうなります。サービスプロバイダーのWantAssertionsSignedがfalseで、生成されるメタデータも既定でfalseにします。さらに、アイデンティティプロバイダーがアサーションを暗号化できるよう暗号化キーが設定されている。
  • 自己登録の欠陥については、レルムで自己登録が有効になっている。既定では無効です。
ブランチ 影響を受けるバージョン 修正バージョン
OpenAM 14.0.0から16.1.3 3件すべての欠陥 16.1.4(2026年10月22日)
OpenAM 14.0.0より前 SAMLアサーションのバイパスと自己登録による権限昇格。通知WebSocketは存在しない 16.1.4(2026年10月22日)

バージョンのエンドポイントはセッションなしで応答します。サーバーへ直接問い合わせてください。

curl -s https://openam.example.com:8443/openam/json/serverinfo/version

応答にはversion、revision、dateが含まれます。コンテナイメージでは同じリクエストをローカルポートへ送ります。

docker exec openam curl -s http://localhost:8080/openam/json/serverinfo/version

修正方法

OpenAM 16.1.4以降へ更新してください。ベンダーはアドバイザリと同じ2026年10月22日に公開しました。

修正コミットからCVEレコードまでの年表:2026年10月21日に修正、2026年10月22日にOpenAM 16.1.4とアドバイザリ、2026年11月8日にCVEレコード
図 1: OpenAMはCVEレコードより前に3件すべての欠陥を修正した。出典: OpenAMのコミット、16.1.4リリース、CVEレコード、2026年11月8日確認。

  1. コンテナイメージでは、Composeファイルでサービスをopenidentityplatform/openam:16.1.4に設定します。設定したイメージを取得し、コンテナを再作成します。
docker compose pull openam
docker compose up -d openam
  1. WARデプロイでは、Maven Centralからopenam-server-only 16.1.4をダウンロードし、新しいopenam.warを既存のWebアプリケーションへ上書きデプロイします。デプロイ後にコンテナを再起動します。

  2. OpenAMのアーティファクトに依存するMavenビルドでは、org.openidentityplatform.openam:openam-server-onlyと他のOpenAMモジュールを16.1.4に固定します。

すぐに更新できない場合、次の緩和策は露出を減らしますが、コードは修正しません。

  • ホスト型SAML v2.0サービスプロバイダーごとにWantAssertionsSignedをtrueにし、レスポンス署名を有効にします。これはアサーションの欠陥を覆います。通知WebSocketと自己登録は覆いません。
  • /openam/notificationsのWebSocketとレガシーLiberty ID-FFのエンドポイントを、リバースプロキシまたはネットワーク層でポリシーエージェントのホストだけに制限します。これはトークン漏えいの経路を狭めます。別の経路でこれらのエンドポイントへ到達できる攻撃者は止められません。
  • 各レルムで自己登録を無効にします。これは匿名登録の経路だけを閉じます。
  • 更新前にインターネットへ露出していたOpenAMインスタンスはすべて露出したものとして扱い、更新後にセッションと管理者を確認します。

根本原因は何ですか?

OpenAMはSAMLの署名継承をHTTP-POSTバインディングだけで適用し、他のすべてのバインディングは、生成されるサービスプロバイダーメタデータがfalseに設定するメタデータフラグに任せていました。 検査はフェデレーションライブラリのSAML2Utils.verifyResponseにあり、OpenAM 16.1.3では次のとおりです。

if (wantAssertionsSigned && !(responseIsSigned || allAssertionsSigned)) {
    throw new SAML2Exception(bundle.getString("assertionNotSigned"));
}

if (profileBinding.equals(SAML2Constants.HTTP_POST)) {
    boolean wantPostResponseSigned = SAML2Utils
            .wantPOSTResponseSigned(orgName, hostEntityId, SAML2Constants.SP_ROLE);
    if (wantPostResponseSigned && !responseIsSigned) {
        throw new SAML2Exception(bundle.getString("responseNotSigned"));
    }
    if (!responseIsSigned && !allAssertionsSigned) {
        throw new SAML2Exception(bundle.getString("assertionNotSigned"));
    }
}

最初のブロックは、サービスプロバイダーのWantAssertionsSignedメタデータがtrueの場合にだけ、署名のないレスポンスを拒否します。2番目のブロックは、そのフラグに関係なく署名のないレスポンスまたはアサーションを拒否しますが、HTTP_POSTの場合にだけ実行されます。ECP(PAOS)とHTTP-Artifactの各バインディングでは、メタデータフラグが無効ならどちらのブロックも署名を要求しません。

通知WebSocketは、コンテナがフィルターを実行することを前提にしていました。しかしフィルターはリクエストディスパッチにだけマッピングされていました。 WebSocketハンドラーは、クライアントが指定した任意のトピックへサブスクライブさせていました。

String topic = json.get("topic").asString();
subscription.bindTo(Topic.of(topic));

セキュリティフィルターはエージェントCookieを読み、トークンがJ2EEまたはWebポリシーエージェントのものかを検査します。OpenAM 16.1.3のweb.xmlのマッピングはディスパッチャーを指定していなかったため、コンテナはREQUESTディスパッチでだけ実行しました。

/notificationsへの内部フォワードはFORWARDディスパッチとして届きます。フィルターは飛ばされ、エージェント検査なしでWebSocketのアップグレードが進みました。OpenAMのレガシーLiberty ID-FFエンドポイントはそのようなフォワードを行います。アドバイザリは、検証されていない内部フォワードを、認証情報なしでソケットへ到達する方法として挙げています。

匿名の自己登録アクションは、システム管理者トークンでアカウントを作成し、属性の許可リストをまったく適用していませんでした。 16.1.3のIdentityResourceV2.anonymousCreateでは、リクエスト本文がそのままアイデンティティサービスへ渡りました。

SSOToken admin = RestUtils.getToken();
return createInstance(admin, jVal, realm, context, null)

許可リストはIdentityRestUtilsにあり、SelfServiceContextを持つリクエストにだけ適用されました。レガシーアクションはそれを持たないため、呼び出し側は任意の属性を設定できました。memberofの値は属性として残らず、アイデンティティ層がグループメンバーシップへ変換します。そのため自己登録したユーザーは管理グループへ参加できました。

どのように悪用されますか?

SAMLの経路には認証情報もユーザー操作も不要です。

  1. 攻撃者は影響を受けるOpenAMインスタンス上のホスト型SAML v2.0サービスプロバイダーを見つけます。それはECP(PAOS)を通知し、WantAssertionsSignedが無効で、暗号化キーが設定されています。
  2. 攻撃者は、管理者を含む標的アカウントを名指すアサーションを含むSAMLレスポンスを作り、署名なしでECPまたはHTTP-Artifactのエンドポイントへ送ります。
  3. OpenAMは発行者を信頼の輪に対して検査しますが、そのバインディングの署名は検査しません。アサーションをローカルアカウントへ対応付け、セッションを発行します。
  4. 攻撃者はそのセッションをOpenAMと、シングルサインオンのためにOpenAMを信頼するすべてのアプリケーションに対して使います。

通知の経路にはWebSocketへの経路が必要です。

  1. 攻撃者は内部で/notificationsへフォワードするレガシーLiberty ID-FFエンドポイントへリクエストを送ります。フォワードはポリシーエージェントのトークンを検査するフィルターを飛ばします。
  2. 攻撃者は内部トピックへサブスクライブします。修正前のハンドラーは任意のトピック名を受け入れました。
  3. OpenAMはセッションの作成、ログアウト、タイムアウト、プロパティ変更のたびにiPlanetDirectoryProの値を配信します。エージェント通知が既定で有効だからです。
  4. 攻撃者は取得した値をベアラー資格情報として、OpenAMのRESTエンドポイントと、同じセッションを信頼するアプリケーションに対して再利用します。

自己登録の経路には自己登録が有効であることが必要です。

  1. 攻撃者は自分が管理するアドレスでメール確認を完了します。
  2. 攻撃者は管理グループを名指すmemberof値を付けてanonymousCreateアクションを送ります。
  3. OpenAMはシステム管理者トークンでアカウントを作成し、グループメンバーシップを書き込みます。新しいアカウントはレルムを管理できます。

3件の欠陥のいずれにも公開された実証コードはありません。アドバイザリは、運用者が更新する時間を確保するため、技術的詳細と実証コードを伏せていると述べています。

攻撃の流れは?

署名のないSAMLアサーションが、別のバインディングでだけ署名を検査するサービスプロバイダーへ届き、ローカルアカウントへ対応付けられて、OpenAM背後のすべてのアプリケーションで使えるセッションになります。

flowchart LR A["攻撃者が署名のない
SAMLアサーションを作成"] --> B["ECPまたはHTTP-Artifactの
エンドポイントへ送信"] B --> C["SPはHTTP-POSTでだけ
署名を検査"] C --> D["このバインディングでは
署名検査なし"] D --> E["アサーションがローカルユーザーへ対応付け、
管理者も含む"] E --> F["OpenAMがセッションを発行"] F --> G["攻撃者がOpenAMを信頼する
すべてのアプリケーションへ到達"]

攻撃者に何ができますか?

SAMLの欠陥により、未認証の攻撃者は、サービスプロバイダーが対応付けできる任意のアカウントのセッションを取得できます。管理者アカウントも含みます。到達できるアカウントは対応付けの方法によります。

自動フェデレーション、またはユーザー識別子として使われるNameIDは、任意のアカウントへ到達します。メールアドレスやユーザー名をフェデレーション識別子にしている場合、攻撃者が識別子を知っているか推測できる任意のアカウントへ到達します。攻撃者は乗っ取ったセッションを信頼するすべてのアプリケーションを引き継ぎます。

通知の欠陥により、未認証の攻撃者は、WebSocket接続が開いている間にセッションが作成、変更、終了したすべてのユーザーの有効なセッショントークンを読めます。管理者も含みます。トークンはOpenAMのREST APIと、同じセッション背後のすべてのアプリケーションに対するベアラー資格情報です。攻撃者は内部トピックへもサブスクライブできます。

自己登録の欠陥により、匿名の攻撃者は既存の任意のグループのメンバーになるアカウントを作成できます。管理グループも含みます。そのようなグループがある場合、結果はレルムの完全な管理制御です。攻撃者には自己登録が有効である必要があり、それは既定の設定ではありません。

3件のCVEレコードはどの欠陥もCriticalと評価しています。トークン漏えいがCVSS v4.0 10.0、残る2件が9.3です。

3件のCVSS v4.0スコアの棒グラフ:セッショントークン漏えいが10.0、SAMLアサーションバイパスが9.3、自己登録による権限昇格が9.3
図 2: 3件のCVEレコードはどの欠陥もCriticalと評価している。出典: 3件のCVEレコード、2026年11月8日確認。

3件の欠陥はいずれもローカル位置を必要としません。SAMLと通知の欠陥はネットワークから到達できます。自己登録の欠陥は、機能が有効なときにネットワークから到達できます。

修正が機能する理由

SAMLの修正は、署名の判定を他のすべての検査より前に置き、すべてのバインディングへ適用します。コミットはisMissingRequiredSignatureを追加します。レスポンスとそのすべてのアサーションのどちらも署名されていない場合にレスポンスを拒否します。ただし、バインディングがバックチャネルのHTTP-Artifactで、その設定が許可する場合は除きます。抜粋はその検査と例外に絞っています。

+boolean allAssertionsSigned = true;
+List<String> unsignedAssertionIDs = new ArrayList<>();
+for (Assertion assertion : assertions) {
+    if (!assertion.isSigned()) {
+        allAssertionsSigned = false;
+        unsignedAssertionIDs.add(assertion.getID());
+    }
+}
+if (isMissingRequiredSignature(responseIsSigned, allAssertionsSigned,
+        () -> isAssertionSignatureRequired(wantAssertionsSigned, profileBinding, spConfig, orgName,
+                hostEntityId))) {
+    throw new SAML2Exception(bundle.getString("assertionNotSigned"));
+}

同じコミットはHTTP-Artifactのレスポンスを、アーティファクトを解決したアイデンティティプロバイダーへ結び付けます。これにより、ある信頼済みパートナーが別のパートナーの名前で発行したレスポンスで応答できなくなります。修正はアドバイザリが説明するサービスプロバイダーのレスポンス経路に対して完全です。

WebSocketの修正はトピックの許可リストを追加し、フィルターをすべてのディスパッチ種別で実行させます。

+private static final String ALLOWED_TOPIC_PREFIX = "/agent/";
+if (!topic.startsWith(ALLOWED_TOPIC_PREFIX)) {
+    sendError(session, id, "topic not permitted");
+    return;
+}
 <filter-mapping>
     <filter-name>NotificationsWebSocketFilter</filter-name>
     <url-pattern>/notifications</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>FORWARD</dispatcher>
+    <dispatcher>INCLUDE</dispatcher>
+    <dispatcher>ASYNC</dispatcher>
+    <dispatcher>ERROR</dispatcher>
 </filter-mapping>

フェデレーションのコードは、リクエスト専用フィルターを持つルートへのフォワードも拒否します。修正は、アドバイザリが説明するソケットへの2つの到達方法を覆います。

自己登録の修正は、SelfServiceContextの外で許可リストを明示的に適用します。

+if (!USER_TYPE.equals(objectType)) {
+    throw new BadRequestException("Self-registration is only supported for users");
+}
+removeIgnoringCase(jVal, EMAIL);
+removeIgnoringCase(jVal, FIELD_MAIL);
+jVal.put(FIELD_MAIL, email);
+enforceSelfRegistrationWhiteList(configHandler, realm, jVal, objectType);

許可リストの検査は、許可されていないグループメンバーシップも拒否し、属性名を大文字と小文字を区別せずに比較し、変換できない本文を拒否します。アイデンティティは引き続き管理者トークンで作成されますが、許可リストが認める属性だけで作成されます。

侵害されたかどうかを確認するには?

侵害の指標は公開されておらず、アドバイザリは悪用が報告されていないと述べています。これらは手がかりであり証拠ではないと扱い、失敗した試行は痕跡を残さない場合があることに注意してください。

最初にバージョンを確認してください。他のすべての確認がそれに依存します。次に、アイデンティティプロバイダーの対応するログインなしでフェデレーションのエンドポイントから作成されたセッションを探します。自己登録で作成され、管理グループのメンバーになっているアカウントと、ポリシーエージェントではないホストからの/openam/notificationsへのWebSocket接続も探します。

リバースプロキシのアクセスログにはWebSocketのパスが記録されます。

grep -iE "GET /openam/notifications|anonymousCreate" /var/log/nginx/access.log

OpenAMの監査ログはアイデンティティとセッションのイベントをJSONで記録します。調査対象期間のアイデンティティ作成とセッションイベントを検索します。

grep -hE '"eventName": ?"AM-(IDENTITY|SESSION)"' /path/to/openam/audit/*.json | tail -n 200

監査ログが有効でない場合は、更新前に有効にし、既存のログを保管してください。ログアウト前に取得されたセッショントークンは、期限が切れるまで有効です。露出を疑う理由がある場合は、更新後に有効なセッションを取り消してください。

年表

  • 2026年10月21日:OpenAMがSAML、通知WebSocket、自己登録の各欠陥の修正をコミット。
  • 2026年10月22日:OpenAM 16.1.4がリリースされ、3件のアドバイザリが公開。
  • 2026年11月8日:VulnCheckがCVEレコードを公開し、GitHubアドバイザリデータベースがそれらを掲載。

よくある質問

ForgeRock AMや他のOpenAMフォークも影響を受けますか?

アドバイザリはOpenIdentityPlatform OpenAMを対象にしています。ForgeRock AMや他のフォークは名指していません。別のフォークを実行している場合は、このアドバイザリに頼る前に、同じ修正が含まれているかベンダーへ確認してください。

16.1.4で十分ですか?

はい。OpenAM 16.1.4には3件すべての欠陥の修正が含まれ、ベンダーはアドバイザリと同じ日に公開しました。16.1.4以降を使用してください。

SAMLを使っていなければ影響を受けませんか?

影響を受ける可能性があります。通知WebSocketの欠陥はSAMLの使用にかかわらずOpenAM 14.0.0から16.1.3に影響し、自己登録の欠陥は自己登録が有効なすべての環境に適用されます。バージョンと機能設定を確認してください。

公開されたエクスプロイトはありますか?

3件の欠陥のいずれにも公開された実証コードはありません。アドバイザリは、運用者が更新する時間を確保するため、技術的詳細とエクスプロイトコードを伏せています。2026年11月8日時点でCISAのKEVカタログには載っていません。

更新せずに緩和できますか?

一部だけです。WantAssertionsSignedの設定、自己登録の無効化、/openam/notificationsの制限は、それぞれ1つの経路を閉じますが、コードは修正しません。できるだけ早く16.1.4へ更新してください。

修正版のリリース後にCVEレコードが現れたのはなぜですか?

ベンダーは2026年10月22日に16.1.4とともにアドバイザリを公開しました。VulnCheckがCVEレコードを割り当てて公開したのは2026年11月8日で、CVEフィードだけを読むスキャナーが初めてバージョンを指摘できるようになった日です。

Ostorlabで露出したOpenAMサーバーを特定する

Ostorlabのアタックサーフェスディスカバリーは、インターネットに露出したホストを棚卸しします。どのOpenAMデプロイが露出しているかを把握し、優先して更新するものを判断できます。表示されるのは露出したサービスであり、特定のインスタンスが脆弱かどうかではありません。

参考資料

  • OpenIdentityPlatformアドバイザリGHSA-5c3q-hp86-xjr8「OpenAM: unauthenticated disclosure of live session tokens via the notification WebSocket」、CVSS v3.1 10.0、影響14.0.0から16.1.3、16.1.4で修正:https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-5c3q-hp86-xjr8(2026年11月8日確認)
  • OpenIdentityPlatformアドバイザリGHSA-3j2f-qhrc-rjfj「OpenAM: SAML v2.0 service provider accepts unsigned assertions on some bindings」、CVSS v3.1 9.8、16.1.4で修正:https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-3j2f-qhrc-rjfj(2026年11月8日確認)
  • OpenIdentityPlatformアドバイザリGHSA-jv8f-m88g-h6mm「OpenAM: self-registration does not enforce the allowed attribute list」、CVSS v3.1 9.8、16.1.4で修正:https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-jv8f-m88g-h6mm(2026年11月8日確認)
  • CVE-2026-123551レコード、セッショントークン漏えい、CVSS v4.0 10.0とv3.1 10.0:https://www.cve.org/CVERecord?id=CVE-2026-123551(2026年11月8日確認)
  • CVE-2026-123550レコード、SAMLアサーションバイパス、CVSS v4.0 9.3とv3.1 9.8:https://www.cve.org/CVERecord?id=CVE-2026-123550(2026年11月8日確認)
  • CVE-2026-123549レコード、自己登録による権限昇格、CVSS v4.0 9.3とv3.1 9.8:https://www.cve.org/CVERecord?id=CVE-2026-123549(2026年11月8日確認)
  • SAMLの欠陥の修正コミット、3bf8e61a7e、2026年10月21日:https://github.com/OpenIdentityPlatform/OpenAM/commit/3bf8e61a7e(2026年11月8日確認)
  • 通知WebSocketの修正コミット、7d6a031c8e、2026年10月21日:https://github.com/OpenIdentityPlatform/OpenAM/commit/7d6a031c8e(2026年11月8日確認)
  • 自己登録の修正コミット、4c8a33822a、2026年10月21日:https://github.com/OpenIdentityPlatform/OpenAM/commit/4c8a33822a(2026年11月8日確認)
  • OpenAM 16.1.4リリース、2026年10月22日:https://github.com/OpenIdentityPlatform/OpenAM/releases/tag/16.1.4(2026年11月8日確認)
  • OpenAM 16.1.3のSAML2Utils.java、脆弱な署名ロジック:https://github.com/OpenIdentityPlatform/OpenAM/blob/16.1.3/openam-federation/openam-federation-library/src/main/java/com/sun/identity/saml2/common/SAML2Utils.java(2026年11月8日確認)
  • OpenAM 16.1.3のweb.xml、ディスパッチャーなしのフィルターマッピング:https://github.com/OpenIdentityPlatform/OpenAM/blob/16.1.3/openam-server-only/src/main/webapp/WEB-INF/web.xml(2026年11月8日確認)
  • OpenAMのServerVersionResource、未認証のバージョンエンドポイント:https://github.com/OpenIdentityPlatform/OpenAM/blob/16.1.4/openam-core-rest/src/main/java/org/forgerock/openam/core/rest/server/ServerVersionResource.java(2026年11月8日確認)
  • CISAの悪用済み脆弱性カタログ、バージョン2026.11.06、OpenAMの項目なし:https://www.cisa.gov/known-exploited-vulnerabilities-catalog(2026年11月8日確認)
  • OpenAMリポジトリの規模、902個のスターとDocker Hub 474,791回の取得:https://github.com/OpenIdentityPlatform/OpenAM と https://hub.docker.com/r/openidentityplatform/openam(2026年11月8日確認)
  • 図1の出典、3件の修正コミットと16.1.4リリース:https://github.com/OpenIdentityPlatform/OpenAM/compare/16.1.3...16.1.4(2026年11月8日確認)