
2026/09/12 6:16
Android の NAT-T キープアライブオフロード回避が VPN ロックアウトをバイパスする
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Android 12 以降のシステムにおいて、悪意のあるアプリが物理ネットワークインターフェースを通じてユーザーの実 IP アドレスを漏洩させることで、「VPN Lockdown」保護を回避できる重大な脆弱性が存在します。この問題の根源は、2019 年に導入された「破綻した信頼モデル(collapsed trust model)」にあります。同モデルでは、トラフィックをハードウェアに転送する前にアプリのトラフィックを VPN を経由させるべきか検証が行われておらず、その結果トラフィックが安全なトンネル内に留まらず漏洩します。具体的には、
IpSecManager.UdpEncapsulationSocket や ConnectivityManager.createSocketKeepalive(...) といった公的な API を、標準的な権限のみ(root アクセスを必要としない)で利用し、NAT-T キープアライブパケットを送信することが可能です。Pixel 8 Pro、Samsung SM-F966B、Nothing A059 のようなデバイスにおいて、「VPN Lockdown」が有効になっているにもかかわらず、定期的な間隔で物理ゲートウェイが UDP/4500 パケットを受信しているという事実は確認されています。この問題は、2021 年末から 2026 年までの Android 系出荷台数の約 91.24% に影響を及ぼしており、強制停止やアンインストールといった様々なシステム状態においても漏洩が続いています。独立型アプリストアの利用者は広く被害を受けていますが、研究では Google Play のアプリや F-Droid リポジトリでこれらの API がほぼ使用されていないことが判明しており、現在の暴露度は利用者の約 0.01% に限られています。研究者らは、プラットフォームに対してハードウェアへのトラフィック転送前に、ファイル記述子および呼出元固有の資源に対する厳格な検証を義務付けるよう提言しています。本文
Android 常時接続 VPN のセキュリティ脆弱性:NAT-T キープアライブによるロックダウンバイパス
要約と発見の概要
- 問題の本質
- Android の「常時接続 VPN」および「VPN がない場合の接続をブロック」という設定は、非暗号化ネットワーク(物理経路)へのトラフィック流出を防ぐことを目的としています。
- しかし、公開された
ソケットキープアライブ API を悪用することで、このセキュリティ境界を侵害でき、VPN 以外のパスへ固定形式の UDP/4500 パケットが漏洩する問題が確認されました。NAT-T
- 影響を受けたデバイスの例(Android 16)
- Pixel 8 Pro: 「常時接続 VPN」と「ロックダウン」を有効にした状態で、制御されたアクセスポイントから 10 秒以上の間隔で UDP/4500 パケットの記録が確認されました。
- Samsung SM-F966B: 「VPN Leak Guard」設定下でも、物理 IPv4 デフォルトゲートウェイを選択し、24 時間 32 分間にわたってルーター向けのリースを維持しました。
- Nothing A059 (Asteroids): 第三者の OEM でも同様の公開パス(物理ゲートウェイ選択とアクティブコールバック)が確認されました。
- 脆弱性の根本原因
API における信頼モデルの縮小と、リソース検証および VPN ポリシー強制の不備です。startNattKeepaliveWithFd(...)- 特権的な raw-fd API から公開 API へ移行する過程で、リソース所有性の認証やVPN ロックダウンポリシーの強制が停止してしまいました。
序論:なぜこれが問題なのか
- VPN ロックダウンの期待
- ユーザーは「VPN が利用できない際」にアプリが閉じる(Fail Closed)ことを期待しており、自身の実際のネットワークアイデンティティを隠す機能を求められています。
- 過去の研究では、ルーティング例外や DNS リークなどが問題視されていましたが、今回の件はフレームワークレベルの共有パスによるものです。
- 技術的な抜け道
- 通常のアプリが
を通じて NAT-T マッピング維持を依頼できます。ConnectivityManager.createSocketKeepalive(...) - フレームワーク側はこれを処理する際、呼び出し元の UID やリソース所有性を厳格に検証せずに、VPN ロックダウンポリシーを無視して物理 Wi-Fi への発射許可を行ってしまいます。
- 通常のアプリが
- 攻撃の手口
- プラットフォームがパケット形状を修正しますが、宛先アドレスはアプリ側で制御可能です。
- ユーザーが再送要求进行すると、物理ネットワークのソースアドレスとタイミングが宛先に露出します。これはアイデンティティ隔離の原則に反しています。
背景:Android VPN ロックダウンと NAT-T オフロード
Android VPN ロックダウンモデル
- 仕組み: アプリのトラフィックを
インターフェースへ強制ルータリングします。TUN- カバーされた UID
- ソケット接続/書き込み
- Fwmark/netd ポリシーチェック
- ロックダウン判定(閉じる失敗)
- VPN TUN インターフェース
- 暗号化されたトンネル
- 例外ケース: プラットフォーム機能や特権操作は別ポリシーに従いますが、通常のアプリからのトラフィックは完全に遮断される必要があります。
NAT-T キープアライブ オフロードパス(脆弱な経路)
このパスは通常アプリソケットの下位レイヤーに位置し、VPN ロックダウンをバイパスします。
- アプリ UID が
を開くIpSecManager.UdpEncapsulationSocket
を呼び出すConnectivityManager.createSocketKeepalive(...)
を実行NattSocketKeepalive.startImpl()
に渡されるIConnectivityManager.startNattKeepaliveWithFd(...)- ハードウェアオフロード(Wi-Fi HAL/ファームウェア)へ到達
脆弱性:NAT-T キープアライブ ロックダウンバイパスの仕組み
攻撃に必要なコードシーケンス
攻撃者は以下の標準的な公開 API のみを呼び出すだけで、ルート権限や特殊な Binder コールは不要です。
// 1. NAT-T エンカプソレーションソケットを開く IpSecManager.UdpEncapsulationSocket socket = ipSecManager.openUdpEncapsulationSocket(); // 2. キープアライブを生成(宛先・ソースアドレスを指定可能) SocketKeepalive keepalive = connectivityManager.createSocketKeepalive( network, // ネットワーク選択 socket, // エンカプソレーションソケット sourceAddress, // ソース IP destinationAddress,// 宛先 IP(攻撃者が制御可能) executor, // 実行スレッド callback); // コールバック // 3. キープアライブを起動 keepalive.start(10); // 約 10 秒周期で送信
パケットパス上の決定的な欠落
- 認証不足:
は、渡された fd やリソース ID が「生きている呼び出し元に所有されている」かを厳密に検証しません。IConnectivityManager.startNattKeepaliveWithFd(...)- 偽の値(0, -2, MAX_VALUE など)や、非 null な fd もすべて受け入れてしまいます。
- ポリシーチェックの欠落: ハードウェアオフロードを開始する前に、呼び出し元 UID の VPN/ロックダウンポリシーを物理下位レイヤーへブロックしているか確認しません。
- 結果: Wi-Fi HAL への渡された後、UID ベースのルートリングやファイアウォールルールの外側でパケットが繰り返し発射され続けます。
根本原因:撤回された信頼モデル
以前は特権的な raw-fd API と公開 API の間で厳格な検証が行われていましたが、2019 年のコミット変更により以下のセキュリティチェックが削除されました。
| 削除されたチェック | 元の実装 | 現在の状態(脆弱性) |
|---|---|---|
| リソース所有性の証明 | がリソースを検証し、UID 固有のロックを保持 | resourceId を利用せず、複製された fd を無条件に受け入れる |
| ライフタイムロック | 重複アクティブ使用を拒絶し、リソースをピン留め | スロットクォータのみで制限され、認証は行わない |
| VPN ポリシー強制 | オフロード前にポリシー違反を検知 | ハードウェアオフロード時に検証なしに進行 |
評価:ランタイムでの確認結果
制御された Pixel パケットキャプチャ
- 環境: Pixel 8 Pro, Android 16, 「常時接続 VPN」有効化
- 観察事項: OpenWrt ルーターの tcpdump で UDP/4500 トラフィックが記録されました。
2026-05-28 18:36:31.709917 ... IP 192.168.1.182:38904 > 1.2.3.4:4500 UDP (length 1) 2026-05-28 18:36:41.710042 ... IP 192.168.1.182:38904 > 1.2.3.4:4500 UDP (length 1) - 結論: 公開 API を使用しただけで、物理ネットワーク上の非暗号化パケット送信が可能でした。
独立した Samsung ランタイム確認
- 環境: Samsung SM-F966B, Android 16, 「VPN Leak Guard」有効
- 観察事項:
- VPN 論理ネットワークを除外し、物理 IPv4 デフォルトゲートウェイを選択。
- 24 時間 32 分にわたってアクティブなスロットが維持されました(リース切れなし)。
- 結論: Qualcomm ハードウェアでも同様の脆弱な公開パスが動作しています。
Nothing A059 (Asteroids) の確認
- 環境: Nothing, Android 16, Qualcomm チップセット
- 観察事項:
- 第三者 OEM でも「物理ゲートウェイ許可」と「アクティブコールバック」を確認。
- ただし、外部キャプチャや持続時間測定は行われていませんでした。
ライフサイクル動作の安定性
- 維持される動作: バックグラウンド化、ロック画面表示、バッテリーセーバー起動時、Binder フリージング時など、様々な状態でもキープアライブは継続されました。
- 停止する動作: 手動強制停止、アンインストール、再起動、ネットワーク切断のみで停止しました。
デバイスクラスへの影響範囲
- 対象デバイス: Android 12 以降の大多数(推定出荷量の 91.24%)。
- Qualcomm, Broadcom, MediaTek, Unisoc, Huawei, Samsung, HiSilicon の主要 WLAN ストック。
- 非対象/未確認: 残りの 8.76% は未解決の混合/ロングテール SKU です。
影響とリスク
- 直接の影響
- 攻撃者が制御する宛先に、デバイスの実際の非暗号化ソース IP アドレスが露出します。
- デバイスがオンラインであることを示すシグナルが周期的に送信され続けます(測定例では 1 日以上)。
- リスクの具体性
- IP アドレッシング: ISP、組織、または VPN サブスクリプション情報が漏洩する可能性があります。
- タイミング相関: ペイロードの内容は固定ですが、送信間隔(カデンス)からデバイスが存在し続けることを証明できます。
- ユーザーの期待との乖離
- ユーザーは「VPN なし時に閉じる」ことを期待していますが、この脆弱性によりその約束が守られていません。
修復とリグレステストの提案
修復責任(どこを直すか)
の許可ロジック:startNattKeepaliveWithFd(...)- 公開された
を使用しているかを確認し、そのソケットリソースが「生きている呼び出し元に所有されている」かを厳密に検証する。UdpEncapsulationSocket - オフロード前に、UID ごとの VPN/ロックダウンポリシーで発射をブロックするか再確認する。
- 公開された
- KeepaliveTracker とトランスポートバックエンド:
- 拒否やシステム停止時にリソースを正しく解放する。
- ネットワーク設定の変更(VPN のアンインストールなど)に対して、アクティブな記録を即座に無効化する。
リグレステストの条件
修復されたコードが以下のシナリオで正常に動作することを確認する必要があります。
- ロックダウン有効時: 通常アプリが NAT-T キープアライブをリクエストしても、物理発射は禁止される(スロット割り当て失敗)。
- ポリシー変更時: VPN を削除または所有者を変更すると直ちにキープアライブが停止する。
- リソース不正時: 無効な fd や重複したアクティブリソースの使用は拒絶され、エラーが返される。
- 正当な場合の確保: オフロードパスを持つ正当なアプリ(VPN 所有者など)は正常に機能し続ける。
開示と倫理
- 報告の流れ
- 2026-05-15 に Android Vulnerability Reward Program (VRP) へ報告。
- Google は協調公開を求め、検証資料を受け付けた。
- 2026-07-29 に一般公開開始(CVE 割り当て済み)。
- 倫理的配慮
- 発見当初は第三者への共有を避け、脆弱性を悪用しない範囲で検証を行いました。
- パケットキャプチャやコード分析の詳細なデータは保護されたままの状態で報告されています。