セキュリティブログ

Cisco ISEで発見したゼロデイのRCE攻撃チェーンを解説:CVE-2025-20286の静的認証情報の脆弱性からroot権限を奪取

Cisco ISEで発見したゼロデイのRCE攻撃チェーンを解説:CVE-2025-20286の静的認証情報の脆弱性からroot権限を奪取

公開日:2025.09.24 更新日:2025.09.24

こんにちは。アセスメントサービス部の川根です。

昨年、Cisco Identity Services Engine (Cisco ISE)というアプライアンスを調査していました。Cisco ISEとは、ネットワークアクセスを管理し、セキュリティを強化するためのプラットフォームです。ネットワークに接続するすべてのデバイスとユーザーを識別し、それぞれに適切なアクセス権限を与えることで、ゼロトラストのセキュリティモデルの観点からネットワークを安全に保つことができます。

調査の結果、複数の脆弱性を発見し、最終的に3つの脆弱性を連鎖させることでroot権限でのリモートコード実行が可能でした。Cisco ISEがネットワークのアクセス制御を担っていることを考えると、攻撃者に脆弱性を悪用された場合、ネットワークの侵害につながった可能性があります。本記事では、Cisco ISEでリモートコード実行を達成するために使用した3つの脆弱性について解説します。

本記事はCiscoの承認を得た上で公開しています。記載されている脆弱性は既に修正済み、または修正されないことが正式に決定されたものです。

内部ユーザーの資格情報を使った認証バイパス

Cisco ISEのAPIの認証ロジックを調査している際に、内部で使用されていると思われる資格情報のようなものを発見しました。Cisco ISEは、管理用のWeb UIだけでなく、運用の自動化などに利用できるAPIを提供しています。

APIにリクエストが送信されると、ユーザーが認証されているかを検証するためにauthenticate()が呼び出されます。このメソッドはAuthorizationヘッダから、ユーザー名とパスワードを取り出し、realm.authenticate()に渡します。認証に成功するとプリンシパルが返され、そのユーザーの権限に応じてAPIの操作が許可されます。

realm.authenticate()の処理を追っていくと、authenticateAdminAccess()にたどり着きます。このメソッドは、ユーザー名とパスワードを引数として受け取り、getInternalPrincipal()とauthenticateAdminUser()を呼び出します。それぞれのメソッドで資格情報の検証が行われ、成功した場合はプリンシパルが返されるため認証されたユーザーであるとみなされます。

authenticateAdminUser()は、引数として受け取った資格情報がISEの管理UIのユーザーの資格情報と一致するかを検証します。コードを読み進めるとこのメソッドだけで認証機能は完結していることがわかったため、getInternalPrincipal()は不要なように思えました。

不思議に思って読んでみたところ、getInternalPrincipal()は引数のユーザー名が「_!_internal_!_」から始まっている場合に、verifyCredentialForInternalPrincipal()を呼び出して何らかの認証を行っているようです。

CiscoはSecurity Vulnerability Policyで、製品内に文書化されていないアカウントの作成・利用や資格情報のハードコードを禁止しています。「_!_internal_!_」アカウントに関しての情報がどこにも見つからなかったため、Ciscoのポリシー上これは脆弱性であると言えます。もし仮に、このアカウントのパスワードもハードコードされていれば、そのパスワードを使い外部から認証を行うことで認証バイパスの脆弱性につながります。

ユーザー名が「_!_internal_!_」から始まっている場合にどのような検証が行われるか調べてみます。 「_!_internal_!_」ユーザーの認証を行うverifyCredentialForInternalPrincipal()はCredentialVeriferクラスのverify()を呼び出します。このメソッドはユーザー名によって認証方法を分岐させているようで、「”_!_internal_!_-” + ClusterInfoHelper.getClusterInfo().getDeploymentName()」である場合はcheckInternalCommToken()を呼び出し、「_!_internal_!_-upgrade」の場合はcheckInternalCommTokenDuringUpgrade()を呼び出します。「_!_internal_!_」はデプロイメントとアップグレードに関係したユーザーのようです。

ユーザー名が「_!_internal_!_-upgrade」の場合に呼び出されるcheckInternalCommTokenDuringUpgrade()を見てみると、引数のパスワードがCredentialProviderクラスのgetCredsPreUpgraded()の戻り値と一致するかを検証しています。getCredsPreUpgraded()はユーザー名とパスワードの配列を返すメソッドで、パスワードはprivateGetPreUpgradedCreds()を呼び出すことで取得されます。パスワードが一致し、このメソッドの戻り値がtrueになった場合は認証に成功したとみなされ、APIを管理者権限で操作できるようになります。

privateGetPreUpgradedCreds()を見てみると、iResourceDAO.getResource()を呼び出して、引数のリソース名を元に動的なSQLクエリを生成して実行しているようです。引数のリソース名は「NAC Group:NAC:__internalAESKey__」となっており、AESの鍵のように見えますが、実際に取得されるのは「_!_internal_!_-upgrade」ユーザーの暗号化されたパスワードとivです。その後、暗号化されたパスワードは_fetchPreUpgradedCreds()によって復号されます。

iResourceDAO.getResource()によって生成されるSQLクエリを実際に実行してみると、Base64エンコードされた文字列を取得していることを確認できます。興味深いのはこのパスワードが登録されたのが、2023年の7月4日であるということです。筆者はCisco ISEのバージョン3.3で検証しており、3.3のリリース日が2023年の7月10日であることから、このパスワードはリリース直前に登録された可能性があることを示しています。

暗号化されたパスワードを取得できたので、_fetchPreUpgradedCreds()でどのように復号しているかを調べてみると、IEncryptorクラスのdecrypt()に暗号化されたパスワードを渡して復号していることがわかりました。

decrypt()はデータベースから取得した文字列の%より前を暗号文とし、%より後をivとして扱い、AES暗号化されたパスワードを復号します。

パスワードがAES暗号化されていることがわかったので復号してみましょう。

AESの暗号鍵はdbKeyPathNameの値の「/opt/CSCOcpm/appsrv/apache-tomcat/config/db_key.txt」です。復号する際に暗号鍵として扱えるように16進数に変換します。

データベースから取得した文字列の%より後をivとして扱うために16進数に変換します。

必要な情報が全て揃ったので「_!_internal_!_-upgrade」ユーザーのパスワードをopensslコマンドで復号します。

「_!_internal_!_-upgrade」ユーザーのパスワードがわかったので、APIの認証で使えるよう「ユーザー名:パスワード」の形式でBase64エンコードします。

作成した認証情報をAuthorizationヘッダに設定しAPIにアクセスすると、認証に成功してCisco ISEのバージョン情報を取得できていることがわかります。

何度かCisco ISEを構築して検証を行いましたが、データベースに保存されている暗号化されたパスワードや復号に使われる鍵は変更されませんでした。このことから、筆者以外の環境でも同じ固定パスワードが使われていると考えられました。

その後のCiscoの調査により、クラウドプラットフォームで同一のバージョンを使用している場合には、別の環境であっても内部ユーザーのパスワードが全く同じになることが判明しました。

これは、「_!_internal_!_-upgrade」ユーザーの資格情報を使って、公開されている世界中のISEのAPIで管理アクセスを取得できた可能性があることを意味します。

この脆弱性はCVE-2025-20286として公開されており、記事の執筆時点ではホットフィックスを適用することで修正が可能です。

ドキュメント化されていないAPIでのOSコマンドインジェクション

認証バイパスの脆弱性を発見した時点で、他の脆弱性と組み合わせることで、リモートコード実行などの深刻な脆弱性にエスカレーションできないかを考え始めました。

実は、この時点で既にWeb UIで任意のコード実行ができる別の脆弱性を発見してはいたのですが、「_!_internal_!_-upgrade」ユーザーについて調査すると、このユーザーの資格情報はAPIでしか利用できず、Web UIでは利用できないことが分かりました。したがって、そのWeb UIの脆弱性は役に立ちません。APIはユーザーを作成する機能を提供していないため、より重大度の高い脆弱性にエスカレーションするためには、APIで脆弱性を見つける必要があるようです。

APIのソースコードを調査していると、内部から呼び出すことを目的とした、ドキュメント化されていないAPIが存在することがわかりました。tcpdumpに関連すると思われるExecuteTcpDumpCmdもその一つです。

APIの引数のTcpDumpRequestはtcpdumpコマンドに渡される引数を定義しているようでした。このAPIはリクエストボディのXMLを受け取るのですが、気になるのはXMLのroot要素がtcpDumpReqestになっていることです。これはtcpDumpRequestの誤字であるため、このAPIが直接呼び出されることを想定していない、もしくは現在使われていないAPIだと推測できます。これまでの経験から、このようなコードは監査が行われていない可能性が高く、脆弱性が見つかりやすいので詳しく見てみることにします。

APIの処理を追っていくと、リクエスト時にXMLで渡したパラメータを引数としてvalidateAndSetTcpDumpCommand()を呼び出しています。このメソッドは引数のパラメータを元にtcpdumpコマンドを構築します。メソッド名にvalidateとついていますが、ポート番号やファイルサイズが数値になっているかなど、最低限のバリデーションしか行われていませんでした。その後、構築したコマンドをexecuteCmd()に渡しています。

executeCmd()を見てみると、構築したtcpdumpコマンドをProcessBuilder()で実行しているようです。ProcessBuilder()は第一引数をコマンドとして実行し、第二引数以降をコマンド引数として扱うため、第二引数以降に別のコマンドを挿入しても実行されません。しかし、executeCmd()では第一引数にsh、第二引数に-cを渡しているため、その後の文字列がシェルによって解釈されます。そのため、構築されるコマンド内に別のコマンドを挿入することでOSコマンドインジェクションが発生します。

OSコマンドインジェクションが見つかったので、実際にAPIにリクエストを送信してCisco ISEのシェルにアクセスしてみます。リバースシェルをキャッチできるように、あらかじめ別のサーバーでポートを開けておきます。

Authorizationヘッダには「_!_internal_!_-upgrade」ユーザーの資格情報を設定します。フィルター式として扱われるfilter要素にリバースシェルを行うコマンドを挿入し、APIにリクエストを送信します。

リクエストを送信すると挿入したコマンドが実行され、Webのサービスを実行しているiseadminportalユーザーとしてシェルにアクセスできていることがわかります。

このAPIは過去にWebUIでTcpDump機能を利用していないと使えないことがわかっており、悪用の難しさからかCVEはアサインされていません。この脆弱性はCSCwj61421としてCiscoにより既に修正されています。

脆弱なsudo設定を悪用した権限昇格

iseadminportalユーザーとしてシェルにアクセスすることができたので、次はroot権限に昇格させる方法を考えます。

sudo -lで別のユーザーとして実行可能なコマンドを確認すると、さまざまなコマンドをパスワード無しでroot権限として実行できることがわかります。特に気になるのはcurlコマンドです。

NOEXECで/etcにあるファイルを送信することを禁止しているようですが、ファイルの保存は禁止されていないため、/etc/passwdを書き換えてroot権限のユーザーを追加してみます。

新しいユーザーのパスワードを作成しておきます。

/etc/passwdを/tmp/passwdにコピーし、uidを0に設定したr00tユーザーを書き込みます。

sudoコマンドを使いroot権限でcurlを実行し、r00tユーザーを書き込んだ/tmp/passwdで/etc/passwdを上書きします。その後r00tユーザーにログインすることで、root権限へ昇格できていることがわかります。

さいごに

本記事では、Cisco ISEを調査した際に発見した3つの脆弱性を組み合わせて、root権限でリモートコード実行を行った方法について解説しました。

注目すべきは、ドキュメント化されていないアカウントやAPIの存在であり、このアカウントの資格情報が固定されていることが起点となって、root権限まで取得できてしまったことです。攻撃者はこうした隠れたアカウントやAPIを悪用し、Cisco ISEを利用している組織のネットワークを侵害できた可能性があります。

クラウド環境でCisco ISEを利用している場合は、Ciscoが公開しているアドバイザリを確認した上で、ホットフィックスを速やかに適用することをお勧めします。

弊社では、豊富な診断実績と技術的知見に基づき、お客様のシステムやご予算、運用状況に応じた最適な診断プランをご提案しています。Webアプリケーション脆弱性診断をご検討の際は、ぜひお気軽にお問い合わせください。

Webアプリケーション脆弱性診断

シェア
X FaceBook
セキュリティ診断のことなら
お気軽にご相談ください
セキュリティ診断で発見された脆弱性と、具体的な内容・再現方法・リスク・対策方法を報告したレポートのサンプルをご覧いただけます。

関連記事

経験豊富なエンジニアが
セキュリティの不安を解消します

Webサービスやアプリにおけるセキュリティ上の問題点を解消し、
収益の最大化を実現する相談役としてぜひお気軽にご連絡ください。

疑問点やお見積もり依頼はこちらから

お見積もり・お問い合わせ

セキュリティ診断サービスについてのご紹介

資料ダウンロード