「AIのせい」という誤診と潜伏の正体
開発者の日常において、PCの動作が重くなることは日常茶飯事だ。特に我々のようなエンジニアは、バックグラウンドでコンテナを回し、複数のIDEを立ち上げ、時にはLLMのローカル推論を走らせる。そんな環境で「キーボード入力が引っかかる」「DiscordのBotが落ちる」といった事象が発生したとき、真っ先に疑うのは「自分が書いたコードのバグ」や「最近入れたライブラリの非効率な処理」である。今回のインシデント報告は、まさにその「エンジニア特有の思い込み」が、いかにしてマルウェアの潜伏を許してしまったかという、極めて生々しい教訓を突きつけている。
被害に遭ったのは、20論理コアを搭載したWindows 11の開発機だ。5日間もの間、CPUの15コアがXMRig 6.21.3によって占有され、累計10時間近いCPU時間が無断で採掘に費やされていた。特筆すべきは、攻撃者が「Windowsの正規タスク名」を巧妙に模倣し、タスクスケジューラというOSの心臓部を乗っ取っていた点だ。例えば、MicrosoftWindowsShellFamilySafetyRefreshingTaskといった、一見するとシステムの一部に見える名称を悪用し、実行パスをAppData配下に偽装する。これは、タスクスケジューラのGUIを眺める程度の管理では、まず見抜けない。我々が普段、いかに「名前」という表面的な情報に依存し、実行パスという「実体」の確認を怠っているかを浮き彫りにしている。
さらに恐ろしいのは、このマルウェアがDefenderの除外リストを改ざんしていた事実だ。Defenderが有効であっても、管理者権限を奪取された時点で、セキュリティ製品は「信頼された設定」としてマルウェアのフォルダをスキャン対象から外してしまう。これは、鍵をかけたはずの玄関のドアを、泥棒が内側から「ここは安全な場所だ」と書き換えてしまったようなものだ。ログのローテーションによって侵入経路が消失している点も、標的型攻撃の常套手段であり、我々が「ログさえあれば追跡できる」と信じている前提がいかに脆いかを物語っている。
AIによる調査と「名前」という罠
今回のインシデントにおいて、発見と駆除の主役となったのはClaude Codeであった。人間が「AIがコードを壊した」と誤認する中、AIは感情や先入観を排し、純粋なプロセス統計とCPU時間の増分という「事実」のみを計測した。ここで重要なのは、AIがGet-CimInstanceを用いて、瞬間的な負荷ではなく、一定時間のCPU増分を測定した点だ。タスクマネージャのGUIで確認できるCPU使用率は、あくまで瞬間的なスナップショットに過ぎず、高速に切り替わるプロセスを見逃す可能性が高い。AIは、5秒間で75秒分ものCPU時間を消費するプロセスを特定し、それがupdater.exeという、いかにも「ありそうな」名前のプロセスであることを突き止めた。
この調査プロセスで明らかになったのは、人間もAIも「名前」を見た瞬間に思考を停止してしまうという共通の脆弱性だ。RuntimeBroker.exeが10個並んでいれば、人間は「正規のプロセスだ」と判断し、それ以上の調査を打ち切る。しかし、そのうちの1つがC:WindowsSystem32ではなく、AppDataRoamingから起動されていたらどうなるか。AIは、この「パスの不一致」を執拗に追跡することで、偽装されたプロセスを特定した。これは、我々エンジニアが日々のデバッグで陥りがちな「既知のパターンへの当てはめ」がいかに危険であるかを示唆している。
駆除の手順においても、AIは「順番」の重要性を理解していた。単にファイルを削除するのではなく、まずタスクスケジューラを無効化し、次にプロセスを停止し、その後にDefenderの除外設定を解除し、最後にファイルを削除するという、依存関係を考慮した論理的なアプローチをとった。特に、除外設定を解除する前にファイルを消すと、Defenderが監視していない領域にマルウェアが再生成されるリスクを考慮した点は、セキュリティエンジニアとしての洞察に満ちている。以下に、今回のインシデントで確認された主な偽装タスクの構造を整理する。
| タスク名 | 実行パス(偽装先) |
|---|---|
| FamilySafetyRefreshingTask | AppDataLocalMicrosoftEdgeSystemupdate.exe |
| SystemRecordService | AppDataRoamingDriversUpdateCoreUpdateCoreDrivers.exe |
| Usb-Notification | AppDataRoamingDriversUpdateRuntime_Broker.exe |
| RPRemove | AppDataRoamingMicrosoftCryptoCRCRuntime.exe |
この表から分かる通り、攻撃者はEdgeやCryptoといった、Windowsの正規フォルダ構造を模倣することで、管理者の目視によるチェックを回避しようと試みている。我々は、こうした「OSの正規構造を悪用する」手口に対して、GUIツールに頼らない、PowerShellによる自動化された検証を日常的に行う必要がある。
エンジニアが明日から取るべき防衛策
今回のインシデントは、単なるマイニング被害の報告ではない。「Defenderが入っているから大丈夫」という、我々エンジニアが抱きがちな慢心に対する強烈な警鐘である。管理者権限を奪取された時点で、OS上のセキュリティ製品は「管理者の意図」を優先せざるを得ない。つまり、我々が管理者権限で作業を行うこと自体が、最大の脆弱性になり得るというパラドックスを突きつけられているのだ。では、我々エンジニアは明日から何をすべきか。まず、自身の環境において「管理者権限で実行されているタスク」と「Defenderの除外リスト」を定期的に監査するスクリプトを走らせるべきだ。これは、障害対応のチェックリストと同様に、ルーチン化しなければならない。
また、今回のケースでは、WMIイベント購読やAppInit_DLLsといった、より高度な永続化手法は使われていなかった。しかし、攻撃者は常に進化している。我々が「CPU使用率が低いから安全だ」と判断している間に、より巧妙な情報窃取系マルウェアが潜伏している可能性を否定できない。真のセキュリティとは、ツールを信じることではなく、常に「自分の環境は既に侵害されているかもしれない」というゼロトラストの精神で、OSの挙動を疑い続けることにある。AIをデバッグのパートナーとして活用するのは素晴らしいが、そのAIが提示する結果を鵜呑みにせず、最終的な「パスの正当性」や「通信先の妥当性」を判断するのは、依然として人間のエンジニアの責務である。
最後に、読者諸君に問いたい。あなたのPCで、今この瞬間、AppData配下から起動されているプロセスはいくつあるだろうか? それらはすべて、あなたが意図してインストールしたアプリケーションのものだと断言できるだろうか? ログがローテーションで消える前に、あなたは自分の環境の「正常な状態」を定義し、それを監視できているだろうか? ツールに依存した安全神話から脱却し、OSの深層を自らの手で検証するスキルこそが、これからの時代を生き抜くエンジニアの必須要件となるだろう。明日、出社したらまず、自身の開発環境のタスクスケジューラと除外リストを、PowerShellでダンプすることから始めてほしい。それが、このインシデントから我々が持ち帰るべき唯一の、そして最大の処方箋である。


コメント