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

ディープダイブ

ディープダイブ

公開PoCのあるFortiSIEM gRPCパストラバーサルRCE(CVE-2026-106173)

FortiSIEM 7.5.0のTCP 27918上の未認証gRPCサービスでは、攻撃者がファイルを上書きし、リモートコード実行に至ることができます。7.5.1で修正済みです。公開PoCはありますが、悪用は確認されていません。

要点

  • CVE-2026-106173は、FortiSIEMのgRPCサービスにあるパストラバーサルとヌルバイトインジェクションの組み合わせです。未認証の攻撃者がアプライアンス上の任意のパスに任意の内容を書き込めます。
  • cronが60秒ごとに実行するヘルスチェックスクリプトを上書きすることで、ファイル書き込みがリモートコード実行(RCE)に変わります。
  • 重大度はクリティカル。Fortinetの評価はCVSS v3.1 9.4です。
  • 影響を受けるのはFortiSIEM 7.5.0だけです。FortiSIEM 7.6とFortiSIEM Cloudは影響を受けず、他のリリースも挙げられていません。
  • Fortinetが社内で発見しました(Fortinet Product SecurityチームのGwendal Guégniaud)。2026年10月13日にアドバイザリFG-IR-26-180を公開し、悪用は確認されていないとしています。
  • Horizon3.aiは2026年10月20日に、動作する概念実証(PoC)を含む技術的な詳細分析を公開しました。
  • CISAのレコードは、公開PoCが存在し、悪用は確認されていないとしています。
  • FortiSIEM 7.5.0をすぐに7.5.1以降へアップグレードし、それまではTCPポート27918へのアクセスを制限してください。脆弱なサービスへの未認証アクセスを遮断して悪用を防げますが、欠陥自体は残ります。

影響を受けるか

次の両方に当てはまる場合に影響を受けます。

  • FortiSIEM 7.5.0を使用している。Fortinetのアドバイザリは他の影響リリースを記載しておらず、7.6とFortiSIEM Cloudは影響を受けません。
  • 信頼できないネットワーク上の位置から対象のgRPCサービスに到達できる。phQueryMasterはアプライアンスの全インターフェースでTCP 27918をリッスンするgRPCサービスです。TLS設定はクライアント証明書を要求しないため、そのポートに到達できる場所なら攻撃が可能です。
ソフトウェア 影響を受けるバージョン 修正バージョン
FortiSIEM 7.5.x(自己管理) 7.5.0 7.5.1以降
FortiSIEM 7.6.x 影響なし 該当なし
FortiSIEM Cloud 影響なし 該当なし

攻撃者が使用し得るネットワークから、実際に問題となるポートの公開状態を確認します。

nmap -p 27918 --open <fortisiem-host>       # phQueryMaster's gRPC service; a "27918/tcp open" line means reachable, no output means filtered or closed, which is the safe state

影響を受けるリリースはFortiSIEM 7.5.0だけなので、バージョン確認は単純です。FortiSIEMの管理画面でビルドを確認し、7.5.0なら他の作業より先にアップグレードしてください。セグメンテーションはパッチの代わりになりません。適切に分離された内部SIEMでも脆弱なサービスは稼働しており、同じセグメントのホストが一つ侵害されれば到達できます。修正は欠陥自体を取り除くため、現在の到達性にかかわらずアップグレードしてください。

修正方法

FortinetのFortiSIEMアップグレードガイドに従い、FortiSIEM 7.5.0を7.5.1以降にアップグレードして、アプライアンスのサービスを再起動します。

アップグレードが完了するまでは、TCPポート27918へのアクセスを制限してください。Fortinetのアドバイザリも「TCPポート27918へのアクセス制限により問題を防止できる」として、この回避策を示しています。サービスへの未認証アクセスを遮断して悪用を防ぎますが、欠陥は残ります。

サービスはアプライアンスの全インターフェースにバインドするため、制限はアプライアンス上ではなく、周囲のファイアウォールやネットワークセグメンテーションで適用します。これはネットワーク遮断であり、パッチではありません。同じセグメント上の侵害済みホストを含め、ポート27918に到達する経路が残っていれば、脆弱性にも到達できます。

アップグレード後は、Horizon3が現実的な上書き対象として挙げる/opt/charting/redishb.shと/opt/phoenix/bin/phLicenseToolを調べてください。アップグレード前の上書きは、その後も残るためです。

根本原因

gRPCのSendQueryResultハンドラーは、攻撃者が制御するヘッダーを連結してファイルパスを組み立て、クライアントが宣言した長さでヘッダー値をコピーします。そのため、ヘッダー内のヌルバイトによってパスが切り詰められ、攻撃者が選んだ正確なファイル名になります。

phQueryMasterサービスはTCP 27918でgRPCサーバーを起動します。Horizon3がlibphGrpcServices.soから引用した起動コードです。

// grpcNotificationServer::run()
unsigned short port = mServerPort;                          // command_port = 7918
std::string addr = "[::]:" + phSecureUtils::getGrpcPort(port);  // [::]:27918
grpc::SslServerCredentialsOptions sslOps;
// sslOps.client_certificate_request stays 0 == GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE
auto creds = grpc::SslServerCredentials(sslOps);
builder.AddListeningPort(addr, creds, 0);

phSecureUtils::getGrpcPort()は、アプライアンスの基本コマンドポート(7918)をgRPCサービスの待ち受けポート27918に対応付けます。そのため、引用コードは7918から始まるのに、[::]:27918へバインドします。このアドレスはすべてのインターフェースにバインドし、クライアント証明書のオプションがゼロのままであるため、どのクライアントも証明書や認証なしで接続できます。grpcNotificationService.cppから引用した脆弱なRPCとハンドラーです。

replaceString(srcIp, ".", "_");
std::string fileDir = "/query/result/" + queryId;   // concatenation, no validation
if (!phMiscUtils::DirExists(fileDir.c_str()))
    phMiscUtils::mkdir(fileDir.c_str());

std::stringstream path;
path << fileDir << "/result-" << srcIp << "-"
     << periodStart << "-" << periodEnd << "-"
     << mGetQueryResultUniqId() << ".dat";
std::ofstream output;
output.open(path.str().c_str(), ios::binary|ios::out|ios::trunc);
while (reader->Read(&req))
    output.write(req.file_content().data(), req.file_content().size());

トラバーサル:gRPCメッセージのquery-idヘッダーは検証されずにディレクトリパスへ連結されます。そのため、../../../../../tmp/xによってクエリディレクトリの外へ出られ、攻撃者が任意のディレクトリを制御できます。これだけではファイル名にリクエストの一部がまだ含まれるため、選んだディレクトリの中に、サーバーが付加するresult-...datという名前で書き込まれます。

ヌルバイトによる切り詰め:サーバーはクライアントが宣言した正確な長さでヘッダー値をコピーします。そのため、query-idが../../../../../opt/charting/redishb.sh\0ignoredなら、埋め込まれたヌルバイトがパスに届きます。OSはヌルバイトを文字列の終端と扱い、サーバー側のresult-...datサフィックスを無視し、その直前までの正確なパスに書き込みます。

悪用の仕組み

悪用に必要なのは、未認証のSendQueryResult gRPC呼び出しが一つです。../../のトラバーサルとヌルバイトを含むquery-idによって、ストリーム送信されるfile_contentが/opt/charting/redishb.shを上書きし、cronが60秒以内に実行します。

Horizon3が公開したPoCは、このリクエストを手作業で組み立てています。認証もクライアント証明書もなしでTCP 27918に接続し、query-id: ../../../../../opt/charting/redishb.sh\0ignored、src-ip: 127.0.0.1、period-start: 0、period-end: 0というメタデータでSendQueryResultを呼び出し、ペイロードをfile_contentとしてストリーム送信します。

残りはサーバーが処理します。ハンドラーがトラバーサルからディレクトリを組み立て、/query/resultの外に出ます。ヌルバイトが構築済みパスを切り詰めるため、送信されたバイトが/opt/charting/redishb.shをその場で上書きし、元の所有者と権限を維持します。

redishb.shはRedisサービスのヘルスチェックスクリプトで、cronジョブが60秒ごとに実行します。そのため、上書きから1分以内にアプライアンスが攻撃者のコードを実行します。

既存ファイルの上書きは1リクエストで済みます。正確な名前で新しいファイルを作るには2リクエストが必要です。最初のリクエストで宛先ディレクトリを作り、2つ目でヌルバイトによる切り詰めを使って正確な名前に書き込むためです。curlや標準的なgRPCライブラリはヘッダー値のヌルバイトを制限するため、リクエストは手作業で組み立てます。したがって悪用は可能ですが、単純なスクリプト化はできません。

攻撃フロー

未認証のgRPC呼び出し一つで、cronが毎分実行するスクリプトを上書きします。そのため、ファイル書き込みからコード実行までの遅延は最大60秒です。

flowchart LR A["未認証gRPCクライアントが
tcp/27918に到達"] --> B["SendQueryResultのquery-idに
../../../../../opt/charting/redishb.sh
とヌルバイト"] B --> C["検証なしの連結で
ディレクトリを構築"] C --> D["ヌルバイトがパスを切り詰め
正確なファイル名にする"] D --> E["ストリーム送信したバイトで
/opt/charting/redishb.shを上書き"] E --> F["cronが60秒以内に
スクリプトを実行"]

攻撃者に可能なこと

FortiSIEM 7.5.0アプライアンスのTCP 27918にネットワークからアクセスできる攻撃者は、次を実行できます。

  • アプライアンス上の任意のパスに任意の内容を書き込む。既存ファイルを上書きする場合は1リクエストで可能
  • アプライアンスが定期実行するスクリプトやバイナリを狙い、上書きしたスクリプトの実行コンテキストの権限で60秒以内に内容を実行する。Horizon3はRedisのヘルスチェックスクリプト/opt/charting/redishb.shで実証
  • 同じ基本操作を使って設定を破壊し、SIEM自体のバイナリを改ざんし、永続化の仕掛けを置く。Horizon3は2つ目の注目ファイルとして/opt/phoenix/bin/phLicenseToolを掲載

認証、ユーザー操作、権限は不要で、ポートへのネットワーク到達性だけが必要です。実際の制約は到達性です。Fortinetの回避策がネットワーク制限なのは、同一セグメントの侵害済みホストを含め27918に到達する経路がある限り、悪用が可能だからです。

修正が閉じるべき経路

FortinetはFortiSIEM 7.5.1で欠陥を修正しています。アドバイザリにはパッチの差分が公開されていないため、確実に言える修正情報はバージョンの案内自体です。

修正が対応すべき内容は、Horizon3が分析した不具合の2つの要素からわかります。検証なしにquery-idがディレクトリパスへ到達することを防ぎ、トラバーサルで/query/resultの外へ出られなくする必要があります。また、コピーされたヘッダー値が構築済みパスにヌルバイトを注入できないようにする必要があります。回避策はどちらも修正せず、脆弱なハンドラーへのネットワーク経路を取り除きます。

侵害されたかを確認する方法

Horizon3は、この悪用を明示的に示すアプリケーションログがないとはっきり述べています。そのため、確認はファイルのフォレンジックになります。詳細分析にある指標は次のとおりです。

  • stat /opt/charting/redishb.shを実行し、更新時刻(mtime)と変更時刻(ctime)を周辺のファイルと比較する。周囲と異なるタイムスタンプを持つ上書きが調査の手掛かり
  • Horizon3が2つ目の対象として挙げる/opt/phoenix/bin/phLicenseToolでも同じ確認を行う
  • アプライアンスのcronとプロセスの動きを確認し、予期しない子プロセスを調べる。定期実行スクリプトが起動したシェルやインタープリター、アプライアンスが自ら開始した外向き接続は、否定できるまで関連するものとして扱う

Fortinetのアドバイザリは悪用未確認と記録し、CISAのレコードも公開PoCはあるが悪用は確認されていないとしています。そのため、執筆時点では特定の攻撃キャンペーンを探すための指標はありません。上記のタイムスタンプ比較とプロセスレビューが利用可能な確認方法です。

経緯

  • 2026-10-13:FortinetがCVE-2026-106173のレコードとアドバイザリFG-IR-26-180を公開。クリティカル、CVSS v3.1 9.4、未認証で悪用可能、悪用未確認と評価。
  • 2026-10-20:Horizon3.aiが詳細分析と動作するPoCを公開。gRPCポートから60秒間隔のcron実行までの連鎖全体を説明。
  • 2026-10-26:本記事を公開。FortinetもCISAも実環境の悪用を記録していない。

よくある質問

ポート27918はデフォルトで公開されるか?

FortiSIEM自体の設定による公開という意味では違いますが、デフォルトのバインドは全インターフェースです。phQueryMasterサービスはすべてのインターフェースで待ち受けます。実際の到達性は周囲のネットワークによって決まり、管理ネットワークからしか到達できないアプライアンスなら、攻撃者の経路からポートを外せます。対象ネットワークからnmap -p 27918 --open <fortisiem-host>で確認してください。27918/tcp openなら到達可能で、ポートの行が出なければ意図どおりフィルターされているか閉じています。

TLSの設定が攻撃者を止めるか?

いいえ。サービスはTLS認証情報を提示しますが、クライアント証明書のオプションは「要求しない」のままです。そのため、どのクライアントも証明書なしで接続を完了し、RPCを呼び出せます。ヌルバイトは生のHTTP/2ヘッダー値に含まれ、TLSスタックが検査する層より下にあるため、標準のTLSスタックは拒否しません。

ヌルバイトによってファイル名を完全に制御できる理由は?

サーバーがクライアントの宣言した正確な長さでヘッダー値をコピーするため、ヘッダー内のヌルバイトがパス文字列に残り、OSはその位置でパスの読み取りを停止します。これにより、本来ならファイル名を固定するサーバー側のresult-<src>-<start>-<end>-<id>.datサフィックスが捨てられます。結果は正確なパスへの書き込みです。追加で必要なのは、メッセージを手作業で組み立てることだけです。

FortiSIEM 7.6やFortiSIEM Cloudも影響を受けるか?

いいえ。FortinetのアドバイザリではFortiSIEM 7.6とFortiSIEM Cloudは影響なしで、影響を受けるリリースは7.5.0だけです。7.6の環境はこのCVEに対する対応は不要です。7.5.0の環境は7.5.1へのアップグレードが必要です。

書き込みをコード実行以外に利用できるか?

はい。任意ファイル書き込みは汎用的な基本操作です。設定ファイルの破壊、起動時に実行されるバイナリの置き換え、認証情報の埋め込みも可能です。Horizon3の分析には、ファイルを読み込むアプライアンス上のcron駆動サービスが複数挙げられています。60秒間隔のヘルスチェックスクリプトを使ったコード実行は、実証された最短経路にすぎません。

被害は確認されているか?

Fortinetのアドバイザリは既知の悪用なしとし、CISAのCVEレコードも公開PoCがある一方で悪用は確認されていないとしています。Horizon3のPoCは公開済みであり、公開PoCから実環境の悪用までの間隔は短いため、アップグレードを先延ばしにすべきではありません。

参考資料

  • 2026年10月13日公開のFortinet PSIRTアドバイザリFG-IR-26-180。影響リリース一覧、TCP 27918の回避策、社内発見者への謝辞を含む:https://www.fortiguard.com/psirt/FG-IR-26-180 (2026年10月26日確認)
  • CVE-2026-106173のレコード。Fortinetの評価はCVSS v3.1 9.4、クリティカル、未認証で悪用可能。CISA ADPは公開PoCの存在を記載:https://cveawg.mitre.org/api/cve/CVE-2026-106173 (2026年10月26日確認)
  • Zach Hanleyによる2026年10月20日のHorizon3.ai詳細分析。gRPCの起動とハンドラーのコード、ヌルバイトの仕組み、cron対象のredishb.sh、タイムスタンプに基づく指標を引用:https://horizon3.ai/attack-research/cve-2026-106173-deep-dive-fortisiem-grpc-path-traversal-file-write-rce/ (2026年10月26日確認)
  • Horizon3のPoC:https://github.com/horizon3ai/CVE-2026-106173 (2026年10月26日確認)
  • phMonitorサービスに関するHorizon3の過去のFortiSIEM研究。CVE-2023-34992、CVE-2024-23108、CVE-2025-64155:https://horizon3.ai/attack-research/disclosures/cve-2025-64155-three-years-of-remotely-rooting-the-fortinet-fortisiem/ (2026年10月26日確認)
  • 2026年10月の公開PoCに関するThe Hacker News報道:https://thehackernews.com/2026/10/critical-fortisiem-flaw-gets-public.html (2026年10月26日確認)