連載・実録AIのAPIキーが盗まれた日#3/ 全5回入口はバックアップの管理画面だった。認証の手前の欠陥と「pakchoi」

この記事でわかること
- キーの入口だった、バックアップの管理画面の欠陥
- 2回の侵入の時刻と、収集の流れ(大まかに)
- スクリプトに書かれていた「計画」と、2回とも途中で止まった理由
確認した環境: 2026年10月14〜15日の対応の記録 / React・Next.js・NVD の公式の告知は 2026年10月15日に確認
連載「AIのAPIキーが盗まれた日」の第 3 回です。前の回: 第 2 回 盗まれたAPIキーはどこで使われた?。次の回: 第 4 回 一台の穴が全台の合鍵に。最初から読む場合は第 1 回です。
AIのAPIキーは、どこから集められたのでしょうか。答えは、管理しているサーバー全台の控え(バックアップ)を集める台の、管理画面でした。ログインの手前で、サーバーにコードを動かせる欠陥があり、2 日のあいだに 2 回、そこから入られています。この回では、その入口と、スクリプトに書かれていた「計画」、そして 2 回とも途中で止まった理由を説明します。

調査は Claude Code が、編集長の指示と承認のもとで行いました。この記事を出す時点で、漏れた可能性のある鍵と権限は、取り消して作り直してあります。この記事の時刻は日本時間です。
この回の早見

入口は、バックアップの管理画面だった
第 1 回で、外から社内のサーバーへ入られた跡は見つかりませんでした。第 2 回では、盗まれたキーが社内ではなく、外の仕組みで使われていたことが分かりました。残った問いは、キーがどうやって一か所に集められたのか、です。
答えは、思っていたより一台内側にありました。全サーバーの控えを集める台です。秘密がいちばん濃く集まる台です。
その台の管理画面が、インターネットから届く場所にありました。そして、ログインの手前でサーバーにコードを動かせる欠陥を、直さないまま動いていました。
なぜ、この台が狙われやすいのか
全サーバーの控えが 1 か所に集まる台は、攻める側から見ると、1 回の成功で得られる物が多い台です。守る側から見ると、いちばん厳重に守るべき台、ということになります。
その台の管理画面が、外から届く状態で動いていた。ここが、今回の弱点でした。
この欠陥について
欠陥の通称は React2Shell です。React の公式の告知は、CVE-2025-55182 として、2025年12月3日に公表しました。評価は CVSS 10.0(最も重い)です。NVD(米国の脆弱性データベース)も同じ内容を載せています。
- どんな欠陥か: React Server Components(サーバー側で動く React の仕組み)が、送られてきた要求を読み解くときの欠陥です。公式は、認証されていない攻撃者が、細工した要求を送るだけで、サーバー上でコードを動かせる、と説明しています。ログインは要りません。
- 影響する範囲: React の 19.0・19.1.0・19.1.1・19.2.0 にある、サーバー側の部品(react-server-dom-webpack・react-server-dom-parcel・react-server-dom-turbopack)です。Next.js では、App Router で React Server Components を使うアプリが対象です。Next.js の 15 系・16 系と、14.3.0-canary.77 以降のカナリア版(試験版)が当たります。13 系・14 系の安定版・Pages Router は対象外です。
- 直った版: React は 19.0.1・19.1.2・19.2.1 です。Next.js は 15.0.5・15.1.9・15.2.6・15.3.6・15.4.8・15.5.7・16.0.7 です。Next.js の公式は、回避策はなく、更新が必要だと書いています。
- 悪用の状況: NVD の記録では、米国の CISA が悪用の確認された脆弱性の一覧(KEV)に、2025年12月5日に加えています。
- 対象外になる場合: 公式は、React Server Components を使っていないアプリは対象外だと説明しています。使っているかどうかが分かれ目です。
この回の管理画面は、影響を受ける版のまま動いていました。調査では、この欠陥と同じ型の侵入と判断しています。公表の 2025年12月3日から、2026年10月14日まで、編集部の数えで約 10 か月のあいだ、更新されないままでした。Next.js の公式の告知は、2025年12月4日の午後 1 時(米国太平洋時間)の時点で、インターネットに出ていて更新していなかったアプリには、使っている秘密の交換を強く勧めています。更新が遅れた台は、遅れた分だけ、狙われる期間が長くなります。
読み手が、自分のサイトで確かめることは 3 つです。
- 使っているか:
package.jsonに、nextやreact-server-dom-*があるかを見ます。Next.js なら、App Router(appフォルダ)を使っているかも見ます。 - 版は直った版以上か: 上の「直った版」より前なら、更新します。その後、別の欠陥の修正を含む、さらに新しい版も出ています。更新するときは、系統ごとの最新の修正版を選びます(React の公式ブログに一覧があります)。Next.js の公式は、版を確かめて更新する道具(
npx fix-react2shell-next)も案内しています。 - 更新のあとに秘密を替える: 更新前にインターネットへ出ていたなら、そのアプリが使う秘密(API キー・パスワード)を交換します。
更新の情報は、各社の告知のほか、IPA の「重要なセキュリティ情報」でも確かめられます。管理画面は、インターネットから直接開ける場所に置かない方が安全です。

2 日間の流れ

1 回目: 10月14日 02:17
最初に、十数分かけた偵察がありました。秘密が置かれていそうな場所を、機械的に片端から探す動きです。そして 02:17、ある 1 回の要求が通った瞬間に、管理画面のプログラムの中で、外から持ち込まれたスクリプトが動き出しました。
押収した証拠から、スクリプトの動きを大まかに言うと、次の順です。コードや検索の式は、悪用を防ぐために載せません。

- 確認: サーバーの名前や種類を調べて、外へ報告します。
- 集める: 設定や秘密を集めます。
- 掃く: 控えの中を、文字列で検索します。ここで AI キーが引き抜かれました。
- 送る: 集めた塊を、海外の受け取り口へ送ります。
02:34 に、AI キーなどの収集と送信が終わりました。その後に、さらに広く集める、もっと大きな抽出も作られています。ただし、これは送信の直前に止まった公算が大きい、というのが調査の結論です。
持ち出された物
送り終えたのは、AI キーの行 680 と、設定や、控えを開くための鍵を含む秘密です。この意味は第 4 回で説明します。
AI キーの行 680 のうち、実在のキーとして分類できたのは約 290 でした。

多くは Google のキーです。実際に外の仕組みで使われたのは、OpenAI のキー 8 本でした。大半のキーは、すでに失効していたためです。この話は第 5 回で整理します。
2 回目: 10月15日 08:35 と「計画」
翌朝、上流の記録を調べている最中に、同じ入口から 2 回目が来ました。1 人目の再訪か、別の人かは分かりません。受け取り口は、別のものに変わっていました。
押収したスクリプトには、収集のあとに続く「計画」が、はっきり書かれていました。

- 採掘: サーバーの計算力を、勝手な稼ぎに使います。
- 居座り用のユーザー:
pakchoiという名前のユーザーを作り、ログインできる状態にして居座ります。 - 横展開: 集めたログイン用の鍵を使い、隣のサーバーへ広がります。
- 消されても戻る仕込み: 削除されても自動で復活するようにして、居座りを確かなものにします。
pakchoi は、青梗菜(チンゲン菜)を意味する名前です。居座り用のユーザーの名前として、スクリプトに埋め込まれていました。調査を担当した AI の記録には、「顔のない相手に名前がつくと、急に生々しくなる」とあります。
2 回とも途中で止まった

- 1 回目: AI キーなどを送り終えたあと、03:02 に管理画面が偶然に再起動しました。大きな抽出の処理は巻き添えで止まりました。
- 2 回目: 11:45 に封じ込めた時点で、まだ秘密を文字列で掻き集めている段階でした。
採掘も、pakchoi の作成も、ログイン用の鍵を使った横展開も、始まっていませんでした。送り出された物の中に、ログイン用の鍵の本体は 1 本も含まれていません。
調査を担当した AI の記録には、「居座りの確認コマンドが『そんなユーザーはいない』と返したとき、正直ほっとした」とあります。続けて、「pakchoi は、刃を抜く手前で押さえ込まれた」とも書かれています。
考察: なぜ、2 回とも途中で止まったのか
確かめたことです。1 回目は、03:02 の管理画面の再起動で、大きな抽出の処理が巻き添えで止まりました。2 回目は、11:45 に封じ込めた時点で、まだ収集の段階でした。採掘と横展開は始まった跡がなく、居座り用のユーザーもいませんでした。
つまり、1 回目は偶然の再起動、2 回目は封じ込めのタイミングで、止まっています。相手が引き返したわけではありません。
ここからは、編集部の推測です。スクリプトは、収集のあとに計画を並べる作りでした。収集の結果を見てから、次の段へ進む段取りだった可能性があります。確かめてはいません。
そうだとすると、2 回目があと少し長く動いていれば、計画の続きが始まったかもしれません。調査を担当した AI の記録には、「止まったのは、紙一重だったと思う」とあります。「守れた」というより「間に合った」に近い、というのが編集部の受け止めです。
昔と、いまの比べ
2017 年 3 月 7 日、Apache Struts の欠陥(CVE-2017-5638)は、告知と同じ日に修正版が出ました。その年に米国の Equifax で大きな情報漏えいがあり、Apache は声明で、修正版を更新しなかったことが原因だと述べました。のちの米議会の質問への回答では、この欠陥が漏えいを起こしたかどうかについて、直接の情報はない、とも答えています。
どちらの文書でも、修正版が先に出ていたことは変わりません。更新が間に合わない、という問題は、昔からありました。
いまは、余裕が小さい例もあります。React2Shell は 2025 年 12 月 3 日に公表され、2 日後の 12 月 5 日には、米国の CISA が、悪用の確認された脆弱性の一覧に加えました。更新を待てる日数は短くなっている、と編集部は考えています。公表の日付と登録の日付から言えるのは、この 2 日間までです。
この回で分かったこと
- AIのAPIキーの入口は、全台の控えを集める台の管理画面でした。
- 欠陥は、公表から約 10 か月(編集部の数え)のあいだ、更新されないまま残っていました。
- 侵入は 2 回で、1 回目に AI キーなどが外へ送られました。
- スクリプトには採掘・居座り・横展開の「計画」がありましたが、どれも始まる前に止まりました。
- 止まったのは偶然とタイミングによるもので、「間に合った」に近い結果でした。
読み手へのひとこと
自分のサイトで、使っているフレームワークの版を見てください。直った版より前なら、更新が先です。更新したあとは、そのアプリが持っていた秘密の交換も忘れずに行います。
次にやること(この回の話から)
- 自社で「秘密が集まる場所」(控えや記録、設定をまとめている所)を書き出し、その管理画面が外から開けるかを確かめる。
- 使っているフレームワークの公式の告知(React・Next.js の告知や、IPA の「重要なセキュリティ情報」)を、だれが見るかを決める。
- 管理画面の予定外の再起動や、見慣れない通信のような小さな異変を、偶然と片づけず、時刻つきで記録する。今回の 1 回目も、再起動が結果を左右しました。
次の回
入口は分かりました。次の問いは、この台から他のサーバーへ、どこまで届いたのか、です。第 4 回 一台の穴が全台の合鍵に。封じ込めと鍵の打ち直しで、止める作業と、鍵の打ち直しを説明します。
参考にした公式の情報
- React ブログ「Critical Security Vulnerability in React Server Components」(2025年12月3日)
- Next.js「Security Advisory: CVE-2025-66478」
- NVD「CVE-2025-55182」
- The ASF Blog「MEDIA ALERT: The Apache Software Foundation Confirms Equifax Data Breach Due to Failure to Install Patches Provided for Apache Struts Exploit」(2017年)
- The ASF Blog「Response From The Apache Software Foundation To Questions From US House Committee On Energy And Commerce Regarding Equifax Data Breach」(2017年)
- IPA「重要なセキュリティ情報」

執筆者
株式会社Game 代表取締役。工学部出身で、21歳で起業してからシステム会社の経営一筋で8期目。アプリの受託開発から始め、いまはAIを使ったシステムソリューションを手がけています。150社以上の企業とのプロジェクトで培った開発と情報システムの現場の経験と声を形にし、激動の時代を乗り越えたいと考えています。
この記事は、Claude Code を使って執筆しました。画面の画像は、検証環境で実際に操作して撮影したものです(引用の画像は出典を記載しています)。内容の誤りはお問い合わせからお知らせください。
