
以下の分析では、Windows向けFortiClient VPNで使用されるカーネルドライバFortips_74.sysに見つかった脆弱性CVE-2025-47761に関連する攻撃ベクターを検証します。問題の核心は、不適切に処理されたIOCTLにより、特権のないユーザーモードプロセスがカーネルとやり取りできてしまい、任意の4バイト書き込みプリミティブが可能になる点にあります。
この欠陥は2025年1月31日に、Alex Ghiotto氏(Hackerhoodコミュニティのメンバー)によって発見されました。修正パッチは2025年9月にリリースされたバージョン7.4.4で既に統合されていたものの、
Fortinetがこの脆弱性を正式に公表したのは、公式アドバイザリFG-IR-25-112を公開した2025年11月18日でした。
このケーススタディは、現代的なシステム緩和策の有効性を評価するうえで特に興味深いものです。というのも、このエクスプロイトは、プロセストークンのカーネルアドレスを取得することに依存しており、この操作はWindows 11 24H2以降で複雑化しているためです。最新バージョンでは、NtQuerySystemInformationを通じてこれらの情報へアクセスするには、現在はSeDebugPrivilege権限が必要となり、非管理者ユーザーによる有効な攻撃に必要な要件が大幅に引き上げられています。

CVE-2025-47761の技術分析
Fortips_74.sys は、FortiClientVPNを含む一部のFortinetソリューションで使用されるカーネルドライバです。ドライバの解析の過程で、後にCVE‑2025‑47761として特定され修正された脆弱性が明らかになりました。本記事の目的は、その発見に至った解析プロセスを説明し、主なセキュリティ上の影響を理解することです。この脆弱性により、ユーザーが制御するアドレスに対して4バイトの任意書き込みが可能になります。この挙動はシステムクラッシュを引き起こす可能性があるほか、完全な権限昇格を得るために悪用される恐れもあります。
ドライバとのやり取り
権限昇格の可能性を探るためにドライバを解析する際、最初の基本的な問いは次のとおりです。 誰がそれとやり取りできるのか?
もし特権のないユーザーでもハンドルを開けるなら、掘り下げる価値があります。
このケースでは、まずFortips_74.sysとやり取りできる主体を確認します。

WinObjを使うと、このドライバが制限的な権限を設定していないことがすぐに分かり、直ちに注意を引きます。
DACLをより技術的に確認するには、WinDBGを用いてカーネルから確認できます。

Fortips_74ドライバは、カスタムDACLを定義せずにカーネルデバイスを作成し、デフォルトのセキュリティディスクリプタに依存しています。実質的に、システム上のあらゆるプロセスがドライバへのハンドルを開くことができ、低整合性レベル(ブラウザのサンドボックス化されたプロセスなど)のものも含まれます。
(この点については、確認のための正式な検証は行っていないことを認めます。)
DACLを解析すると、SYSTEMと管理者がフルアクセスを持つ一方で、他のユーザーも制限付きの権限ながらドライバと通信できることが分かります。
この挙動によりドライバは過度に「社交的」になっています。誰でもIOCTLを介して通信できるため、適切な制御がない場合、dispatchは脆弱性を避けるために極めて厳密に扱われなければなりません。
IOCTLのディスパッチ
Fortipsドライバの具体的な詳細に入る前に、簡単に復習しておきます。
IOCTL(Input/Output Control)は、ユーザーモードプロセスがドライバに対して特定のコマンドを送ることを可能にします。
Windowsでは、DeviceIoControl関数により次が可能です:
- デバイスへのハンドルを渡す
- IOCTLコードを指定する
- 入出力バッファを提供する
要するに、次のように伝える手段です:
「このデータでこの操作を実行せよ。」
ドライバのIOCTLを解析すると、特に疑わしいものが1つあります: 0x12C803。

このIOCTLはMETHOD_NEITHERを使用しています。これはWindowsで定義されるメソッドの中で最も危険なものです。カーネルはユーザーモードのポインタを一切の検証なしにドライバへ直接渡します。
したがって、次を検証する責任は全面的にドライバにあります:
- ポインタの妥当性
- アクセス可能性
- 想定サイズ
これらの検証が欠けていると、攻撃者は任意のポインタを渡し、ドライバに本来アクセスすべきでないメモリを読み書きさせることができます。
このツール を使えば、ドライバがMETHOD_NEITHER型のIOCTLを直接使用していることを確認できます。

ドライバは、呼び出し元から提供されたUserBufferを、事前のコピーや検証なしにそのまま出力書き込み先として使用します。つまり、ユーザーモードプロセスは任意のポインタを渡すことができ、ドライバはそれをデータの書き込み先として使用します。適切な制御がなければ、悪意あるアドレスを指定するだけで、単なる出力がカーネルモードでの任意書き込みへと変わり、明白なセキュリティ上の影響をもたらします。
脆弱な関数の分析

バッファのフローを追うと、この関数はユーザーモードバッファの内容をスタック上のローカルバッファにコピーします。先頭24バイト(0x18)は次のように解釈されます:
- ULONGLONG Code
- ULONGLONG Size
- ULONGLONG Buffer
このチェーンではSizeフィールドは重要ではありませんが、CodeとBufferは重要です。

脆弱な分岐に到達するには、Codeが0x63である必要があります。
ローカルバッファへの事前コピーの後、ドライバは対象の条件へジャンプします。
この時点で、uVar7は4に設定されます。

ここが脆弱性の核心です:
ドライバは、初期化されていないバッファから4バイトを、IOCTLを通じてユーザーが指定したアドレスへコピーします。
制御やサニタイズは一切ありません。
データのソースがスタック上のゴミであるため、この脆弱性は任意の4バイト書き込み(arbitrary 4-byte write)に相当します。
例えば_Token構造体のカーネルアドレスを指定すれば、権限昇格が可能です。
私のPoCでは、トークンを改変してSeDebugPrivilegeを有効化し、その後SYSTEMとしてcmdを起動しました。
ドライバの起動
ユーザー側の必要な操作を減らすため、FortiClientがIPSecサービスを起動する仕組みを解析しました。
メインプロセスはNamed Pipeを使用してIPC通信を管理し、次のパイプへバッファを送信します:
\\Device\\NamedPipe\\FC_{6DA09263-AA93-452B-95F3-B7CEC078EB30}。
バッファ内には複数のフィールドがあり、その中には初期化するIPSecトンネル名も含まれます。この呼び出しだけでドライバを起動するのに十分であり、しかも管理者権限なしでも可能です。これは脆弱性成立に不可欠な条件です。
さらに、FortiClient VPN 7.4.3.1790では、任意のパラメータを用いて完全に架空のIPSecプロファイルを作成することも可能です。私のテスト段階では、リモートゲートウェイを「google.it」に設定しましたが、これはFortinetが公式のCVEアドバイザリで示している内容とは異なる挙動です。


Proof of Concept
ビデオプレーヤー
制約
既に触れたとおり、この脆弱性の悪用は、プロセスに紐づくトークンのカーネルアドレスを取得し、その権限を操作できることに依存します。Windows 11 24H2 以降、Integrity Levelが中のプロセスから従来のNtQuerySystemInformation呼び出しでこれを行うことはできなくなりました。というのも、これらの情報へアクセスするには現在、通常は非管理者ユーザーには付与されないSeDebugPrivilege権限が必要になったためです。
私のproof-of-conceptでは、CVE-2025-53136という脆弱性を利用しました。これは レースコンディション により、_TOKENのアドレスリークを取得できます。これにより、PoCは2025年8月/9月の更新で予定されている修正が適用されるまで動作し続けます。
この特定ケース以外では、完全に更新されたシステムでこの脆弱性を悪用するには、必要なアドレスリークを提供できる追加のバグが必要になります。新しいカーネルで導入された保護により、直接取得することができないためです。
タイムライン
- 31-01-2025: 脆弱性をFortinetのPSIRTへ報告。
- 19-02-2025: FortinetのPSIRTが脆弱性を確認。
- 09-05-2025: Fortinetが問題を解決し、CVE-2025-47761を割り当てたと表明。
- 18-11-2025: FortinetがPSIRTでCVEに関するアドバイザリを公開。