Defenderがあるのに5日間マイニングされた — 開発機という脆い標的
Defenderがあるのに5日間マイニングされた — 開発機という脆い標的
アンチウイルスが有効であるという事実は、安全の証拠なのか、それとも誰もその警報を読んでいないことを覆い隠すアリバイなのか。ある日本のエンジニアの開発機は、Microsoft Defenderが正常に動作した状態で、5日間にわたり暗号資産のマイニングに使われていた。防御が崩れたのではなく、防御が発した信号を誰も読まなかった — この事件は、開発機(dev machine)という標的がなぜこれほど脆いのかを問い直す。
導入
2026年8月、日本のエンジニアコミュニティQiitaに、あるインシデント報告が投稿された。タイトルは「Defenderが有効なのに、開発機で5日間マイニングされていた」。報告者は自宅のWindows 11開発機 — DTM(音楽制作)とプログラミングを兼ねる20コアのマシン — を使い、DiscordからClaude Codeへ指示を出す形でAI支援開発を行っていると明かしている。発端は些細だった。Discordの音声読み上げボットが不安定になり、報告者は最初「AIがコードを壊した」と考えた。だが本当の原因はコードではなかった。
報告者によれば、8月10日18時21分(感染ファイルの生成タイムスタンプに基づく)に仕込まれたマイナーXMRig 6.21.3が、発覚した8月15日の夜まで5日間、20の論理コアのうち15を100%で焼き続けていた。その間、Defenderは切れていなかった。むしろ感染当日の夕方に、権限昇格に使われるカーネルドライバを一つ検知し、隔離までしていた。問題は、その通知を誰も見ていなかったことである。報告者はこの事件の性質を一文に凝縮する。「Defenderは仕事をしていた。気づかなかったのは人間の側だ」。本稿では、報告者が実際に観測した事実と、エンドポイントセキュリティが開発機の前でなぜ無力になるのかについての筆者の構造的分析とを、分けて整理する。事実には出典を添え、一般化した診断は筆者の論として示す。
何が起きたのか — Defenderは働き、誰も通知を見なかった
まず時間軸を事実どおりに写す。報告者の再構成によれば、侵入は8月10日18時21分に始まった。そしてわずか一時間後の19時46分、DefenderはC:\Windows\SystemTemp配下の一時ファイルから、WinRing0x64.sysという14.5KBのカーネルドライバを検知し隔離した。このドライバはハードウェアレジスタへ直接アクセスして権限を引き上げる、マイナーがしばしば携える部品である。つまり防御の最初のボタンは正しく掛かっていた。検知もされ、遮断もされた。ただその結果がデスクトップの片隅にトースト通知として一度浮かんで消えただけで、誰もそれを読まなかった。
同じ時点で攻撃者は防御の裏口を開けておいた。報告者によれば、マルウェアはDefenderの除外(例外)リストに二つのパスを追加した — C:\Users\[user]\AppData\Local\Microsoft\Edge\SystemとC:\Users\[user]\AppData\Roaming\DriversUpdateである。いずれも正規の構成要素の名を模した場所だ。除外リストを書き換えるには管理者権限が要るため、侵入は配置の時点ですでに管理者権限を握っていたことを意味する。防御エンジンは生きていたが、マイナーが常駐するフォルダだけは、そのエンジンの視野から切り抜かれていたわけである。
5日間、体が発した信号はあった。マシンは普段より熱く、キーボード入力がときおり利かなくなった。だが、それぞれにはもっともらしい日常的な説明が付いていた — 夏だから暑い、負荷が掛かっているから、プログラムが重いから。決定的な信号は8月15日の夜に来た。Discordボットのハートビートが28秒間ブロックされ、DNS解決が繰り返し失敗し、WebSocketが遅延した。報告者は当初これを最近のコード変更のせいにした。CPUが枯渇したときの典型的な症状だったが、開発機でCPUが跳ね上がるのはあまりにありふれた出来事で、誰もそれを侵害の信号として読まなかった。
転換点は名前ではなく測定だった。報告者によれば、調査の過程でClaudeがプロセステレメトリをスナップショットで比較した。5秒の観測窓で、updater.exeというプロセスが75.55 CPU秒を消費していた。5秒のあいだに75秒分を焼いたということは、およそ15コアを同時に完全占有したことを意味する。ウィンドウタイトルにはXMRig 6.21.3がそのまま露出しており、ネットワークを覗くと15.235.234.199:3333へ向かうTCP接続が生きていた。3333はマイニングプールがよく使うポートである。検知時点までにこのプロセスが積み上げた稼働時間は9時間54分だった。ここで核心の原理が現れる。名前はいくらでも偽装できるが、実際に消費したCPU秒は偽装できない。updater.exeという正常な名前と、15コアを持続的に焼くという挙動との矛盾が、正体を暴いたのである。
対応は順序が肝心だった。報告者によれば、措置は次の順で進んだ。第一に、正規のWindows名を模した五つのスケジュールタスク(\Microsoft\Windows\Shell\FamilySafetyRefreshingTask、\Microsoft\Windows\Multimedia\SystemRecordServiceなど、いずれも最高権限)を削除した。第二に、プロセスを名前ではなく実行ファイルのパスで照合して終了させた — 正規のRuntimeBroker.exeを誤って終了させないためである。第三に、ユーザーが自ら登録した除外は残し、マルウェアが追加した二つの除外だけを取り除いた。第四に、XMRigの部品とペイロードDLL、そしてSQLite.Interop.dll(約2MB)が入っていた三つのディレクトリを削除した。第五に、フルスキャンで検証した。プロセスを終了させると、CPU使用率は100%から3%へ即座に落ちた。
ここで報告者が重く扱ったのが、認証情報の流出の可能性である。マイナーのそばにSQLite.Interop.dllがあったという事実は、Cookieやパスワードといったブラウザのデータベースに手を掛けた可能性を示唆する。そこで対応は、パスワード変更よりも先に、全デバイスからの強制サインアウト(セッションハイジャックの遮断)と2要素認証の導入、トークンの再発行を優先した。データが実際に持ち出されたという証拠はなかったが、無いという証拠も無かったため、最悪を仮定して動いたのである。
なぜ開発機は脆い標的なのか — 管理者権限・除外・性能優先
この事件の表面的な教訓は「通知を見逃した」だが、より深い問いは別にある。Defenderのような現代のエンドポイント防御が、5時間でもなく5日間マイナーを放置した構造とは何か。ここからは筆者の分析である。
第一に、名前ベースの信頼の崩壊だ。このマルウェアは自らをupdater.exeと名乗り、スケジュールタスクはFamilySafetyRefreshingTaskのように本物のWindowsタスクの名を被り、常駐フォルダはEdgeとMicrosoftの名を模した。レピュテーションベース・シグネチャベースの判定は「この名前が既知の悪性リストにあるか」を問うが、初見の名前と正常に見える名前の前では、どちらも沈黙する。報告者がまとめた教訓も同じだ — 検知は名前ではなく、実際の実行ファイルのパスをSystem32やProgram Filesの正規の場所と突き合わせて初めて成り立つ。正常な名前を掲げたまま異常な場所で回るプロセスこそ、偽装の本質である。
第二に、開発機では唯一の挙動信号が雑音に埋もれる。マイナーを振る舞いで検知できる最も強い手掛かりは「CPUが長く100%に張り付いている」である。ところが開発機・DTMマシンにおいてCPU 100%は異常ではなく日常だ。コンパイル、ビルド、オーディオレンダリング、学習ジョブ、ローカル推論 — コアを長く焼く作業が常時走っている。アンチウイルスのベンダーが「持続的な高負荷」を脅威として挙げないのはここに理由がある。そうすれば誤検知が爆発するからだ。結局、マイナーを露わにする唯一の挙動信号が、開発機では正常なワークロードと区別できない。脆い標的の第一の定義はこれである — 防御が依拠する信号を、その環境の正常状態がすでに使い尽くしている場所。
第三に、除外と管理者権限の文化だ。マルウェアがDefenderの除外を追加するには管理者権限が必要であり、それをすでに持っていた。開発者にとって管理者権限とアンチウイルスの除外は、例外的な出来事ではなく作業条件である。node_modulesをリアルタイム検査するとビルドが這うため、プロジェクトフォルダを除外に入れ、ツールのインストールのたびに権限プロンプトを反射で通す。報告者自身も「権限プロンプトを反射で通している自覚がある人」という言い回しでこの習慣を認めている。だから除外リストに見知らぬ項目が二つ増えても、それは目立つ異物ではなく背景の雑音になる。
第四に、散らかった環境が隠れ家になる。報告者の観察は鋭い — 「AppData配下に実行ファイルが増えることが『普通』になる」、そして「環境が雑然としているほど、異物は目立たなくなる」。ここに筆者の一般化を重ねると、AI支援開発と現代のパッケージ生態系はこの散らかりを加速する。npm、pip、cargo、言語サーバー、エディタ拡張、各種CLIが、ユーザープロファイルの下に無数のバイナリを撒く。「これは何のプロセスか説明できない」が積み上がった状態それ自体がリスクだという報告者の結論は、まさにこの蓄積を突いている。
この点で、最近のサプライチェーン攻撃の流れと結びつけたい — これは明示的に筆者の分析である。報告者自身は感染経路を特定できなかった(「感染経路は特定できなかった」と明記している)。ログが8月12日以前にローテーションで消え、タスクスケジューラの登録イベントも残らなかったためだ。報告者が状況証拠から疑ったのはDTM生態系だった — 出所の検証が甘く管理者権限を要求する無料の音源・プラグイン・サンプルパックが、インストーラ形式で配布される点を挙げている。ここで筆者が一般化したい論は、その疑いの経路をnpm/pipのような開発依存に置き換えても、話がそのまま成り立つということだ。ここ数年のnpmサプライチェーン侵害 — 人気パッケージが乗っ取られ、インストールスクリプトにマイナーやトークン窃取器が仕込まれた事例 — は、開発機がサードパーティ製バイナリの広大な表面を常時信頼しているという同じ前提を狙う。感染経路がオーディオプラグインであれ、汚染されたnpmパッケージであれ、脆い標的の条件は同一だ。管理者権限、寛容な除外、性能優先の文化、そして正体を説明できないバイナリで満ちたホームディレクトリ。
最後に沈黙の問題である。Defenderはカーネルドライバを捕らえたが、その成功は誰も読まない通知として散った。発報しても誰も聞かない警報は統制ではない。常時忙しい開発機において、トースト通知は妨害として扱われ、真っ先に無視される種類の信号だ。防御の成功が静かに消えるよう設計された場所では、防御の存在そのものが安全の錯覚を提供するにすぎない。
検知の再設計 — 名前ではなく挙動で、沈黙ではなく通知で
では、開発機をより脆くない標的にする実務的な方向とは何か。事件が指し示す軸は三つある。
第一に、静かな成功を騒がしくせよ。報告者の第一の推奨は、Defenderの検知を人が実際に読む場所へ流すことだ — WMIイベントサブスクリプションで脅威検知をチャットやメールへルーティングする自動化である。この事件の5日間は、検知の失敗ではなく通知の失敗だった。無人に近い形で回るマシンほど、警報はそのマシンの前ではなく、人が必ず見るチャネルへ出さねばならない。失敗は静かに飲み込まれず、露わになるべきだ。
第二に、正体を名前ではなくパスと挙動で確かめよ。報告者は管理者PowerShellで回せる六つの点検を残している。Defenderの除外リスト、脅威検知の履歴、ユーザーコンテキストのスケジュールタスク(パスがAppData・Temp・Publicを含むものでフィルタ)、非標準のパスで回るプロセス、WMIイベントコンシューマ(空であるのが正常 — ファイルレス永続化の痕跡)、そしてキーボードフィルタドライバ(kbdclassだけが正常)。共通する原理は一つだ。「名前が正常か」ではなく「正常な名前が正常な場所で、正常な資源で回っているか」を問う。測定が偽装に勝つ。
第三に、認証情報の窃取を既定として仮定せよ。マイニングが目に見える症状だとすれば、そのそばのSQLite.Interop.dllのような部品は、目に見えない損失 — Cookie・トークン・パスワード — を示唆する。報告者がパスワード変更よりもセッション無効化とトークン再発行を先に行った判断は正しい。生きているセッショントークンは新しいパスワードを迂回するからだ。マイナーを見つけたら「CPUを盗まれた」で止まらず、「ほかに何を読み取られた可能性があるか」まで対応範囲を広げねばならない。
もう一つ、この事件で筆者が印象深く見た構造が、調査の役割分担である。報告者によれば、実際に手を動かしたのはClaudeであり、人は管理者の認証情報と最終実行だけを担った。興味深いのは、症状を「夏だから暑い、コードのせいだろう」と説明して片づけていたのは人間の側であり、その日常の物語に何の持ち分もなかったツールが、プロセスを冷静に測定して矛盾を拾い上げたことだ。これは筆者の解釈だが、セキュリティで最も価値あるものは、時に「どうせ大丈夫だろう」というバイアスの不在なのかもしれない。報告者の締めくくりもこの筋へ向かう — 「お前のせいだろう」と言われて、それを鵜呑みにせず現物を確認したことが、発見の入口だった、と。
展望を三つのシナリオに整理する。楽観的には、開発機に関するこうしたインシデント共有が増えるにつれ、「ホームディレクトリのバイナリ一覧を説明できるか」が開発者衛生の基本項目になるだろう。悲観的には、性能優先の文化と除外の乱発がそのままに、サプライチェーン侵害だけが精緻化し、マイニングのような騒がしいペイロードの代わりに、静かにトークンだけを抜く侵入が標準になるだろう。現実的にはその中間のどこかだ — 大半の開発機は依然として寛容な除外と反射的な管理者承認を保ちつつ、今回のように偶然の性能異常が調査につながったときにのみ、遅れて正体が露わになる。
結論
リードの問いへ戻ろう。Defenderが有効であるという事実は、安全の証拠なのか、誰も警報を読んでいないことを覆い隠すアリバイなのか。この事件は後者に近い。防御エンジンは感染から一時間でカーネルドライバを捕らえたが、その成功は読まれない通知として消え、当のマイナーは正常な名前をまとったまま、開発機の日常的な高負荷のなかに5日間隠れた。失敗したのはエンジンではなく、読みだった。
開発機が脆い標的である理由は、怠慢ではなく文化の構造だ。性能のために除外を広げ、ツールのために管理者権限を常時握り、生産性のためにホームディレクトリをバイナリで満たす習慣は、それ自体は合理的である。ただその合理性が、防御の依拠する信号 — 見知らぬ名前、新しい実行ファイル、跳ね上がるCPU — を一つずつ正常状態へ吸収してしまう。脆い標的とは、防御が無い場所ではなく、防御の警報が背景の雑音と区別できなくなった場所である。
だから残すべき問いは、特定のツールの性能ではなく、一つの点検の習慣だ。いまあなたの開発機で回っているプロセスのうち、名前ではなくパスと資源で正体を説明できないものは幾つあるか。Defenderが最後に何かを隔離したとき、その通知はどこへ行ったのか — あなたが必ず見る場所か、それとも誰もいないデスクトップの片隅か。今回はCPUが騒がしく鳴いて発覚した。次の侵入が静かにトークンだけを読み取っていくとき、あなたを起こす信号は何として残っているのか。
出典: