株式会社ホコサキ

MVTでiPhoneのスパイウェア痕跡を調べる実務手順

天京祐輔
天京祐輔
MVTでiPhoneのスパイウェア痕跡を調べる実務手順

会社支給のiPhoneに高度なスパイウェアが仕込まれていたとき、MDMの管理コンソールには何も表示されません。
それは、MDMが「そういう目的のツールではない」からです。

このギャップを埋めるのが MVT(Mobile Verification Toolkit) です。
Amnesty InternationalがPegasus Projectの調査の中で開発したOSSで、iOSバックアップやシステムログから侵害の痕跡を掘り起こすフォレンジック補助ツールです。

「スキャンは走らせたのに、大量のJSONファイルが生成されて何を見ればいいかわからない」——その最初のつまずきに重点を置きながら、DockerによるセットアップからIOCsの取得、check-backupの実行、出力の読み解きまでを一気に走ります。

MDMが守れない領域と、MVTが埋める隙間

MDMの役割は、端末への設定配布・ポリシー適用・紛失時のリモートワイプといった 管理と予防 にあります。
EDRやウイルス対策アプリも同様で、リアルタイムの監視と既知の脅威のブロックが主戦場です。

どれも優秀なツールですが、高度なスパイウェアが残した 過去の痕跡 をバックアップから掘り起こす機能は、そもそも設計に含まれていません。
Jamfのフォレンジック製品のページにも「MDMやMTDでは高度な調査に必要なシステム深部へのアクセスができない」と明記されています。
役割が違うので、それ自体は欠陥ではありません。

MVTが埋めるのはその隙間です。
2021年のPegasus Projectで、Amnesty InternationalのSecurity Labがジャーナリストや活動家の端末を調査するために開発し、その後OSSとして公開されました。
「感染を防ぐ」ツールではなく、「すでに起きたかもしれない侵害の痕跡を探す」ための道具です。

OSSとして公開されていることには、実務上の意味があります。
コードが誰でも監査できる状態にあること、そして端末データをどこのクラウドにも送らずローカル環境で完結すること。
この2点は、社内の情報セキュリティポリシー上の稟議を通す際に明確な根拠として使えます。
「社外に端末データが出ない」という事実は、特にデータの機密度が高い組織では説得力を持ちます。

今回のスコープはiOSバックアップの解析に絞っています。
Androidは mvt-android という別コマンドで対応できますが、今回は触れません。

iOSバックアップの準備:暗号化設定とディレクトリ構成

MVTに渡すバックアップは、 暗号化バックアップを強く推奨します
理由はシンプルで、暗号化なしのバックアップにはヘルスデータ・キーチェーン・Wi-Fiパスワードといったデータが含まれません。
スパイウェア調査の観点では、これらは重要な痕跡が残りやすい場所です。
非暗号化バックアップでもMVTは実行できますが、調査の網羅性が落ちることを覚えておいてください。

バックアップはmacOSのFinderから取得します。
iPhoneを接続してFinderのサイドバーから端末を選び、「このMacにバックアップ」を選択して「ローカルのバックアップを暗号化する」にチェックを入れてパスワードを設定します。
バックアップが完了すると、以下のパスに端末のUDIDを名前とするフォルダが生成されます。

~/Library/Application Support/MobileSync/Backup/<UDID>/

このUDIDフォルダが、MVTに渡す バックアップパス になります。

作業に入る前に、ディレクトリ構成を整えておくと後が楽です。

mkdir -p ~/mvt-work/{ioc,backup,decrypted,checked}

iocにはIOCsファイル、backupにはバックアップのコピー、decryptedには復号済みバックアップ、checkedにはMVTの出力結果を格納します。

暗号化バックアップをMVTに渡す前に、復号するステップが必要です。
mvt-ios decrypt-backup を使い、-kオプションで復号鍵をファイルとして保存しておきます。

# 暗号化バックアップを復号(パスワードは対話入力)
mvt-ios decrypt-backup \
  -d ~/mvt-work/decrypted \
  -k ~/mvt-work/backup.key \
  ~/mvt-work/backup/<UDID>/

-kで保存した鍵ファイルは 機密データ です。
MVTの公式ドキュメントも「Keep the file safe.」と明記しています。
また、復号が完了したdecryptedディレクトリ自体が、端末の中身をそのまま展開したものになります。
「調査のためにデータを集めた結果、そのデータ自体がリスクになる」という構造には最初から意識的でいてください。
作業マシンのアクセス制限と、作業後の削除ポリシーは事前に決めておくことを推奨します。

DockerでMVTを動かす:check-backup実行まで一気通貫

MVTのインストール方法はpip(ネイティブ)とDockerの2択です。
情シス環境では Dockerを推奨します
依存ライブラリのバージョン衝突を気にしなくていい、環境を汚さずに済む、誰の環境でも同じ動作が保証される、という理由からです。
ネイティブインストールはPythonのバージョン管理や依存パッケージの解決でつまずきやすく、Dockerで回避できるトラブルを自ら踏みに行く理由はほとんどありません。

スキャンの前に、IOCsファイルを取得します。
IOCsはSTIX2形式のファイルで、 Amnesty TechのGitHubリポジトリ で公開されています。
スキャンを実施するたびに最新版を取得する習慣をつけてください。
古いIOCsで実行しても「新しい痕跡には気づけない」ことになります。

# Amnesty Tech公式リポジトリからIOCsを取得
curl -L \
  https://raw.githubusercontent.com/AmnestyTech/investigations/master/2021-07-18_nso/pegasus.stix2 \
  -o ~/mvt-work/ioc/pegasus.stix2

次にMVTのDockerイメージを取得して、コンテナを起動します。
ホストの作業ディレクトリをボリュームマウントすることで、コンテナ内からバックアップや出力先に直接アクセスできます。

# イメージを取得
docker pull mvt-project/mvt

# ボリュームマウント付きでcheck-backupを実行
docker run --rm -it \
  -v ~/mvt-work:/home/user/mvt-work \
  mvt-project/mvt \
  mvt-ios check-backup \
    --iocs /home/user/mvt-work/ioc/pegasus.stix2 \
    --output /home/user/mvt-work/checked \
    /home/user/mvt-work/decrypted

--iocsを省略するとIOCsとのマッチング処理は一切行われず、データ抽出のみになります。
--outputも省略可能ですが、その場合はディスクに何も残らないので調査用途では必ず指定してください。
最後の引数は、decrypt-backupで復号したディレクトリのパスです。UDIDフォルダではなく復号後のディレクトリを渡す点に注意してください。

実行中はターミナルにモジュール名と処理ログが流れます。
IOCsとのマッチがあった場合は、その場でハイライト表示されます。
処理時間はバックアップのサイズや端末の使用期間によって大きく変わります。

出力JSONを読む:_detectedファイルと「調査の出発点」の作り方

checkedディレクトリを開くと、大量のJSONファイルが生成されています。
最初に見たとき、何を見ればいいかわからなくなるのは自然な反応です。

主要なファイルの役割は以下のとおりです。

  • processes.json:端末で動いていたプロセスの記録。不審なバックグラウンドプロセスの有無を確認します
  • domains.json:端末がアクセスしたドメインの一覧。既知のC2サーバドメインとのマッチングに使われます
  • safari_history.json / safari_favicon.json:Safariの閲覧履歴とファビコンキャッシュ。感染経路となったURLが残ることがあります
  • timeline.json:全イベントを時系列に並べ直したファイル。複数のファイルをまたいで前後関係を追う際に使います
  • net_base.json / datausage.json:ネットワーク通信の記録

このうち、まず確認すべきは _detectedサフィックスが付いたファイルの有無 です。

_detectedファイルは、IOCsファイルに登録された既知の侵害指標とのマッチがあったことを意味します。
たとえばdomains_detected.jsonが存在する場合、端末がアクセスしたドメインの中にPegasusで使われた既知のC2ドメインが含まれていた、ということです。

ただし、 _detectedファイルがある = 感染確定ではありません
IOCsには古い指標も含まれており、正規サービスとのドメイン衝突など誤検知の可能性があります。
逆に、_detectedファイルが一つもなくても「感染していない」の保証にはなりません。
MVTが照合できるのは、あくまで「既知のIOCsに登録された痕跡」だけだからです。

_detectedファイルの構造はこのようなものです(フィールド構成を示す仮の出力例)。

[
  {
    "timestamp": "2023-08-14 09:23:11",
    "module": "Domains",
    "type": "domain",
    "host": "example-suspicious-domain.com",
    "matched_indicator": "example-suspicious-domain.com",
    "ioc": {
      "name": "Pegasus C2",
      "stix_id": "indicator--<uuid>"
    }
  }
]

注目するのはtimestamp、host、そしてiocのnameフィールドです。
いつ、どのホストに、どのIOCがマッチしたかを読みます。

timeline.jsonはこの文脈で威力を発揮します。
_detectedでマッチしたタイムスタンプの前後に何が起きていたかをtimeline.jsonで追うと、「この時間帯に不審なドメインへの通信とプロセス起動が重なっている」という文脈が見えてきます。
MVTの出力は、こうして複数ファイルを突き合わせながら読むものです。

繰り返しになりますが、MVTは 「調査の出発点を作るツール」 です。
_detectedが出た場合の判断は、セキュリティベンダーやCSIRTへのエスカレーションが前提になります。
自組織だけで「シロ/クロ」を断定しようとしないことが、この種のツールを使う上での基本姿勢です。

運用に組み込む前に知っておくべきこと

MVTを定期的に運用しようとすると、まず「どのくらいの頻度で全台スキャンするか」という問いにぶつかります。
正直なところ、全社員のiPhoneを一斉にスキャンするのは現実的ではありません。
一台ずつバックアップを取得して復号してスキャンして、というフローには相応の手間がかかります。

実務的な使い方として考えやすいのは、 リスクの高い端末を優先した定期スキャン と、 インシデント疑いが生じたときのトリガーベース の組み合わせです。
全台を均一に管理するより、リスクに応じた優先順位をつける方が長続きします。

IOCsの鮮度の問題も正直に書いておきます。
現在配布されているIOCsは主に既知のPegasus関連の指標です。
新種のスパイウェアや未公開の侵害指標には、MVTは無力です。
これはMVTの欠陥ではなく、IOCsベースのアプローチ全般が持つ構造的な限界です。
「MVTでシロだったから大丈夫」とはならない、ということを運用ポリシーに組み込んでおく必要があります。

バックアップデータの取り扱いも見落としがちなポイントです。
作業後のdecryptedディレクトリは、端末の中身を丸ごと展開したものです。
スキャンが終わったら速やかに削除するか、暗号化した状態でアクセス制限されたストレージに格納するかを事前に決めておいてください。
「調査のために集めたデータが次のリスクになる」という逆説は、フォレンジック作業に共通する落とし穴です。

最後に、法的・証拠保全の観点についてひとこと。
_detectedが出てインシデントが確定した場合、その後の手順は専門領域に入ります。
証拠としてのデータ保全には適切な手順が必要であり、社内判断だけで進めないことを強く推奨します。
セキュリティベンダーや外部のCSIRTへの早期エスカレーションを基本方針として持っておくと、いざというときに動きやすくなります。


株式会社ホコサキは山口県宇部を拠点に、Web制作・業務システム開発・AI活用支援・DX推進に取り組んでいます。
セキュリティツールの導入調査や社内インフラの整備についても相談を受け付けています。
気になることがあれば お問い合わせページ からどうぞ。

    MVTでiPhoneのスパイウェア痕跡を調べる実務手順 | 株式会社ホコサキ