DISPATCH-2026-0917highVite CVE-2026-39364 掃描撿鑰匙活動

你只是開了個開發伺服器, 他們卻拿走了 .env 和 terraform.tfstate

Vite dev server 的一個查詢參數就能繞過檔案封鎖清單,F5 Labs 觀察到 8 月起有人在全網掃這個洞撿雲端金鑰。台灣在來源前五名。這跟我們的 Crusader 案是同一門生意。

為什麼現在很紅:The Hacker News 兩天前報導 F5 Labs 的觀測:攻擊者專挑對外開放的 Vite dev server,用 ?raw 之類的參數把 .env、AWS 憑證、terraform.tfstate 直接讀走,還偽裝成 Googlebot、ClaudeBot、GPTBot。

事件期間 2026-04 揭露 → 2026-08 大規模掃描 → 2026-09-15 報告·整理於 2026-09-17·7 分鐘·4 可證明2 推論2 缺口
ViteCVE-2026-39364金鑰外洩掃密前端開發
tl;dr
  1. Vite 7.1.0 到 7.3.2 之前、8.0.5 之前的 dev server,只要用 --host 對外開放,就能靠 ?raw、?import&raw 等查詢參數繞過 server.fs.deny,把 .env、憑證檔讀出來。已於 4 月修補。
  2. F5 Labs 在 8 月觀察到大規模掃描,來源包含美國、比利時、荷蘭、新加坡、台灣,大量借道 GCP 的 IP 段;目標檔案是 .env、AWS/Azure 設定、terraform.tfstate、serverless.yml、/proc/self/environ。
  3. 攻擊者偽裝成 Googlebot/ClaudeBot/GPTBot,並塞假的 X-Forwarded-For 騙過 IP 白名單。這是撿鑰匙的生意,跟我們 INC-2026-0827 的 Crusader 節點做的是同一件事。
◉ 攻擊者視角他不打你的正式站,打的是你「暫時」開給同事看的開發伺服器。一個 GET 就能拿到 .env,成本比釣魚低一百倍。
◎ 防守者視角今天就做一件事:確認沒有任何 dev server 綁在 0.0.0.0,升級 Vite 到 7.3.2 或 8.0.5 以上,然後把 .env 當已外洩處理過一次。
本篇目錄

發生了什麼

把 Vite 的開發伺服器想成辦公室裡那台「大家都能連」的印表機。它平常只該印你放進佇列的東西,但有人發現:在列印指令後面多加一個奇怪的參數,印表機就會把桌上任何一張紙都印出來,包括寫著密碼的那張。

CVE-2026-39364 就是這樣的東西。Vite 有一個 server.fs.deny 清單,預設擋 .env*.crt*.pem 這類檔案。但在受影響版本裡,對 /@fs/ 路徑的請求只要加上 ?raw?import&raw?import&url&inline,被擋的檔案就會以 HTTP 200 回來。前提有三個:dev server 用 --hostserver.host 對外開放、敏感檔案在允許目錄內、而且原本是靠 deny 清單在擋。

這個洞 4 月就揭露並修補了。真正讓它在 9 月上新聞的,是 F5 Labs 觀察到 8 月起有人在全網掃它,而且掃的人很清楚自己要什麼。

  1. 2026-04
    Vite 發布 GHSA-v2wj-q39q-566r,修補於 7.3.2 與 8.0.5
    GitHub Advisory 與 CVE 紀錄。
  2. 2026-08
    F5 Labs 觀察到針對對外開放 Vite dev server 的大規模掃描
    來源集中在美國、比利時、荷蘭、新加坡、台灣;大量使用 GCP 的 34.x/35.x IP 段。
  3. 2026-08
    請求鎖定 .env、AWS/Azure 設定、terraform.tfstate、serverless.yml、/proc/self/environ
    F5 Labs 報告列出的目標路徑。
  4. 2026-09-15
    The Hacker News 報導,進入主流資安新聞
  5. 未知
    有多少台機器實際被讀走憑證、憑證被拿去做什麼
    報告只描述掃描行為,沒有受害統計。

這次外洩了什麼

F5 Labs 列出的目標路徑,本質上是一張「哪些檔案裡躺著明文憑證」的清單。把它翻譯成服務與用途,你就知道被讀走一個檔案代表交出了什麼。

leaked credentials掃描鎖定的檔案,各自裝著誰的鑰匙
服務憑證類型用途存在形式放在哪權限範圍狀態
應用程式會用到的全部第三方服務.env 裡的每一組 KEY=VALUE資料庫密碼、API token、金流與寄信金鑰,一個檔案全包明文 KEY=VALUE 文字檔,沒有任何加密專案根目錄,也就是 dev server 允許讀取的範圍內等於這個應用程式能做的全部外部事件,沒有受害統計
AWS:IAM 使用者access key ID + secret access key程式與 CLI 存取 AWS 全部服務INI 格式設定檔的 profile 區段開發者家目錄的 .aws 目錄,或專案內的副本依 IAM 政策,最糟是管理員權限外部事件
Azure服務主體憑證與訂閱設定存取 Azure 訂閱內的資源CLI 設定檔(JSON/INI)開發者家目錄的 Azure 設定目錄依服務主體的角色指派外部事件
Terraform 管到的每一個服務state 檔裡的明文屬性值記錄整套基礎設施的實際狀態JSON。資源屬性裡直接躺著資料庫密碼、金鑰、連線字串terraform.tfstate,常被留在專案目錄或 commit 進 repo整個環境的拓撲與憑證,是這批目標裡最值錢的一個外部事件
Serverless 平台(Lambda/Functions)部署設定裡的環境變數區塊函式執行期要用的 token 與連線字串YAML(serverless.yml)的 environment 區段專案根目錄該函式能存取的資源外部事件
執行中的 dev server 行程本身整包環境變數(/proc/self/environ)不必猜檔名與絕對路徑,直接把行程載入的秘密讀走以 NUL 分隔的明文字串Linux 行程檔案系統該行程載入的所有秘密,包含只放在環境變數、沒寫進檔案的那些外部事件
被讀走之後實際發生了什麼不明報告只描述掃描行為;受害者通常要等帳單或停權通知才知道
憑證本身已遮蔽或失效;這裡只說明它是哪個服務、拿來做什麼、以什麼形式存放,讓你能對照自己的環境。

證據等級

跟我們的防暴筆記對照

這件事跟 INC-2026-0827 的 Crusader 殭屍網路同一門生意的兩個環節

| | Crusader(我們的案子) | Vite 掃描活動(本篇) | |---|---|---| | 工具找什麼 | 542 條路徑:.env、.git/config、service-account.json、JS bundle 內金鑰 | .env、AWS/Azure 設定、terraform.tfstate、/proc/self/environ | | 從哪裡拿 | 任何對外網站的可預測路徑 | 對外開放的 Vite dev server,用查詢參數繞過封鎖 | | 掃描節點 | 用盜來的 GCP 金鑰在受害專案開的 3 台 VM | 大量 GCP IP 段(推論:同樣是別人的專案) | | 撿到之後 | 回傳 C2,變現:開 VM、AI token、寄信 | 未知,但 terraform.tfstate 通常含整套基礎設施的憑證 |

第一課還是那一句:只要 .env 曾經放在任何對外可讀的位置,就當作已外洩處理。Vite 的洞只是又多了一條「對外可讀」的路。

另一個對照是 INC-2026-0915:那台礦機的入口是一個「開發用」Flask 端點,整條對公網開放。Vite dev server 的 --host 是同一種東西:為了方便同事或手機預覽而開的門,忘了關。

攻擊者 vs 防守者

他不打你的正式站,打的是你隨手開給同事看的東西。
  • 正式站有 WAF、有 CDN、有人在看;dev server 三者皆無,而且 .env 就在專案根目錄。
  • terraform.tfstate 是大獎:裡面常有資料庫密碼、雲端金鑰、整套基礎設施的拓撲。拿到一份等於拿到整個環境的地圖。
  • 偽裝成 Googlebot 或 GPTBot,因為很多人的存取規則對爬蟲特別寬鬆。
  • 用別人的雲端專案當掃描節點。被封 IP、被報 abuse 的都不是他。
一句話

開發伺服器不是「不重要所以沒關係」,是「沒人看所以最危險」。這是我們三起防暴筆記的共同點,也是這則新聞的重點。

這篇提到的項目要花多少錢

這是外部事件,我們拿不到任何一方的帳單,所以下表沒有一列是可證明的。列出來是為了說明量級:他掃你的成本有多低、你被撿走一把金鑰的代價有多高。

cost一個 GET 請求的兩端:他花多少、你可能賠多少
項目用量單價期間US$NT$舉證
他掃你一台主機的成本
估:就算自己租機器,掃 100 萬台的頻寬成本也不到 US$1
1 個 GET 請求,約 1 KB借道別人的雲端專案(推論)每台0.000F5 Labs 報告描述的請求形態;「那些專案是被盜用的」是我們的推論
他的掃描節點:1 台小型 VM
估:若用盜來的金鑰開,這筆記在受害專案的帳上,不是他的
24 小時 × 9 天US$0.134/機器小時(e2-standard-4 牌價)9 天28.94926GCP 官方牌價;F5 Labs 沒有公布節點規格與數量
被讀走的 .env 裡一把管理員 AWS 金鑰
估:量級示意,不是本案的實際損失。他只要撿到一把,一天就把整趟成本賺回來
拿去開 1 台 GPU 機 24 小時US$32.77/小時(p4d.24xlarge,us-east-1 牌價)1 天786.5425,169AWS 官方牌價 2026-09;本案沒有受害統計
被讀走的寄信憑證
估:這一百塊買的是你網域的寄信信譽,信譽掉了不是錢能買回來的
冒用你的網域寄 100 萬封釣魚信US$0.10/千封(SES 牌價)一次100.003,200Amazon SES 官方牌價 2026-09
今天花 3 小時做完盤點
估:這是本文唯一一列「你可以選擇要不要付」的成本
查所有子專案 vite 版本、關掉 --host、列出 .env 裡的金鑰清單顧問日費 NT$27,500(估)/8 小時一次性322.2710,313本站估算的工時;日費為假設值
事後才補的同一件事
估:數字取自本站防暴筆記〈金鑰已經換了,真的每一把都換到了嗎?〉的人力拆解。同一件事,事前 3 小時,事後 26 小時
盤點 4 小時+撤銷切換 6 小時+改建無金鑰架構 2 人日同上一次性2793.0089,376本站 INC-2026-0827 的處置工時;日費為假設值
terraform.tfstate 被讀走之後
它的價值,是讓上面每一列都不必用猜的
一份檔案等於整套基礎設施的拓撲與密碼沒有任何日誌會告訴你檔案被讀走之後對方做了什麼
實際被讀走多少憑證、被拿去做什麼
跟大多數掃描活動一樣,受害者通常要等帳單或停權通知才知道
2026-08 至今F5 Labs 報告只描述掃描行為,沒有受害統計
合計(僅可證明列)0.000
匯率假設 1 USD ≈ NT$32。單價為公開牌價或帳單實付,來源:GCP Compute Engine、AWS EC2、Amazon SES 官方牌價,查價 2026-09(us-central1/us-east-1);掃描規模依 F5 Labs 報告描述推估。「舉證」欄標明每筆損失的證據來源與等級( 可證明 推論 缺口)。

重點學習

keywords重點學習:最需要學習的 10 個關鍵字10
  1. 01
    --host / server.host
    一行設定決定你的開發伺服器只在自己電腦上,還是在全網。這是本篇唯一真正要改的東西。
  2. 02
    .env 視為已外洩
    只要它曾經落在對外可讀的範圍內,就不要爭論有沒有真的被讀;直接輪替,比事後鑑識便宜。
  3. 03
    server.fs.deny
    這次被繞過的就是它。它是清單式封鎖,本質上永遠在跟繞過方式賽跑,不能當唯一防線。
  4. 04
    CVE-2026-39364
    受影響區間是 7.1.0 ≤ v < 7.3.2 與 8.x < 8.0.5。對照 lockfile 只要一分鐘,是今天最划算的一分鐘。
  5. 05
    npm ls vite / pnpm why vite
    真正在跑的版本藏在傳遞相依裡,package.json 寫什麼不算數。子專案越多越要用它。
  6. 06
    /@fs/
    Vite 用來讀專案外檔案的路徑前綴,也是你在 access log 裡最該 grep 的字串。
  7. 07
    terraform.tfstate
    比 .env 更值錢的目標:一份檔案給出整個環境的地圖與密碼。它不該進 repo,也不該在網站根目錄。
  8. 08
    /proc/self/environ 與 /proc/self/cwd
    攻擊者用它們就不必猜你的專案絕對路徑。請求裡出現這兩個字串,代表對方懂你的部署堆疊。
  9. 09
    X-Forwarded-For
    這是使用者可以自己填的字串。拿它做 IP 白名單,等於把門鎖交給敲門的人。
  10. 10
    偽造 User-Agent(Googlebot/ClaudeBot/GPTBot)
    你為爬蟲放寬的規則,會原封不動變成攻擊者的通行證。UA 不是身分。

今天就可以來試試

try today今天就可以來試試15 分鐘

全部唯讀,不改任何設定;做完你會知道自己有沒有同樣的破口。

  1. 看本機與開發主機上,哪些開發埠綁在 0.0.0.0 或 ::。
    ss -tlnp | grep -E ':(5173|5174|3000|4173|8080)\b'
    看到什麼代表什麼:位址是 0.0.0.0 或 :: 代表同網段、甚至整個網際網路都連得到;只有 127.0.0.1 才算安全。
  2. 查每個專案實際在跑的 vite 版本。
    npm ls vite 2>/dev/null | grep vite
    # pnpm 專案改用:pnpm why vite
    看到什麼代表什麼:落在 7.1.0 ≤ v < 7.3.2 或 8.x < 8.0.5 就是受影響版本,今天就排升級。
  3. 找出設定檔裡把 host 打開的專案。
    grep -rn --include='vite.config.*' -E "host:\s*(true|'0\.0\.0\.0')" .
    grep -rn 'vite.*--host' package.json */package.json 2>/dev/null
    看到什麼代表什麼:命中代表這個專案每次啟動都對外開門,而不是偶爾;這種比忘了關的更危險。
  4. 若主機有 access log,看有沒有人已經來過。
    grep -E '/@fs/.*\?(raw|import&raw|import&url&inline)' /var/log/nginx/*access.log* 2>/dev/null | head
    看到什麼代表什麼:命中任何一條,就把該專案 .env 裡的每一把金鑰當已外洩,今天輪替,不要先查「有沒有真的被讀到」。
  5. 列出該專案 .env 的鍵名(只看名字,不看值),當成輪替清單。
    cut -d= -f1 /path/to/project/.env | grep -v '^#' | grep -v '^$'
    看到什麼代表什麼:這個清單的長度,就是「萬一外洩」你今天要處理的工作量。超過十行還沒有人負責,就是本篇講的問題。
  6. 在 log 裡找自稱爬蟲、來源卻不對的請求。
    grep -Ei 'googlebot|gptbot|claudebot' /var/log/nginx/*access.log* 2>/dev/null | awk '{print $1}' | sort | uniq -c | sort -rn | head
    看到什麼代表什麼:這些 IP 如果不在 Google/OpenAI/Anthropic 公布的爬蟲網段內,那就是偽裝;同一批 IP 通常也打了別的路徑。

來源

本文為公開報導與官方公告的整理與拆解,非第一手鑑識;證據等級依來源可信度標註。

§
對應課程模組

M2 身分與金鑰 · M7 殭屍網路解剖(掃密工具與 IOC) · 想在自己的環境做一次同樣的盤點,從 自我盤點 開始。

newsletter
下一篇拆解直接寄到信箱

每篇新文章一封:三點摘要、攻擊者/防守者視角、今天能做的一件事。或先 加入會員 記錄你完成的任務。