微軟 17 兆筆資料險遭存取:JWT token 沒驗簽章,一個 16 歲白帽怎麼冒充管理員

恆遠數位編輯團隊約 16 分鐘閱讀
微軟 Titan JWT 漏洞拆解封面:JWT 沒驗簽章導致 17 兆筆資料險失守
複製引文

17,333,335,124,315。這是一個 16 歲的高中生在凌晨兩點盯著螢幕算出來的數字,代表他手上那張偽造的通行證,理論上能碰到的微軟內部資料大約有 17 兆筆。

這幾天這則新聞在 Threads、IG 被轉了很多次,版本越傳越誇張。我們團隊讀完研究員本人寫的原文後,第一件事是回頭確認自家產品的登入驗證,因為整起事件的核心只有一句話:系統有檢查 JWT token 裡寫了什麼,卻沒有檢查那張證件的簽章真不真。這個錯誤很基本,用 AI 快速寫出來的系統也很容易犯。

這篇文章分三塊:事件本身到底發生什麼(包含網路上傳錯的部分)、JWT 驗證與簽章是怎麼一回事、還有你今天就能拿去問工程師的自查清單。事件細節以研究員 Faav 發表的原始技術文章為準,他在文中說明這篇曾經過微軟審閱修改;另外參考 Help Net Security 與 iTnews 的報導交叉比對。

微軟 Titan 漏洞事件整理:三十秒看懂發生什麼事

先講結論:研究員用一張「沒有簽章」的偽造 JWT token 冒充管理員,拿到了對微軟內部分析平台 Titan 下 SQL 查詢的權限。他通報後微軟四天內把端點關掉,並發了 5,000 美元漏洞賞金。整起事件的重點整理如下:

項目

內容

研究員

網名 Faav,16 歲,課餘做漏洞賞金,去年 15 歲時就回報過微軟訪客登記系統的個資問題

被打穿的系統

Titan,微軟內部的資料分析平台,前端要員工連 VPN 才進得去

漏洞本身

後端只檢查 token 內容(租戶、受眾、應用程式、使用者),完全沒驗證簽章

利用方式

偽造一張 alg 設為 none、簽章留空的 token,把使用者欄位填成 admin

理論上碰得到的範圍

17 個分析資料庫、9,863 張資料表,估計約 17.3 兆列(含歷史與重複資料)

實際看了什麼

平台中繼資料(約 2.5 萬筆帳號紀錄)與兩筆 Bing 分析樣本,沒有下載任何客戶資料

時間線

8/25 發現、9/5 打通並當天通報、9/9 端點關閉、9/17 領到 5,000 美元

幫手

研究員自己寫的 AI 漏洞掃描機器人 Antares,底下跑 Codex 與 Claude

網路上流傳的版本有幾個地方講錯了,其中兩個會直接誤導你對事件嚴重性的判斷:

流傳的說法

原文實際寫的

「存取了高達 17 兆筆資料」

17 兆是「技術上碰得到」的估計值,他本人強調從沒碰過任何客戶資料或個資

「取得 2.5 萬名員工個資」

約 2.5 萬筆是帳號與 email 紀錄,其中員工 email 約 1.8 萬筆,只涵蓋跟 Titan 有關的部分員工

「/v2/Query 完全沒有防護」

它有檢查 token、不帶會回 401,只是沒驗簽章;門有關,只是那把鎖是壞的

「跑一行指令就撈到 2.5 萬筆員工資訊」

列出資料庫清單的指令只會看到清單,員工資料是之後查中繼資料表才看到的

把「理論上碰得到」和「實際拿走」分清楚很重要。這起事件真正的教訓在於,一個驗證環節沒做好,就讓一整座資料倉庫的大門形同虛設,這次只是剛好白帽先發現。

JWT token 是什麼:三段文字,簽章才是那張證件照

一句話說明:JWT token 是伺服器發給使用者的一張數位通行證,裡面寫著「你是誰、可以做什麼」,最後附上一段只有伺服器做得出來的簽章,用來證明這張證不是別人偽造的。

很多網站登入後,瀏覽器每次呼叫 API 都會帶著這張通行證。它長得像一串亂碼,用兩個句點切成三段:

段落

裡面裝什麼

別人看得到嗎

Titan 事件中的狀況

Header 標頭

用哪種演算法簽章,例如 RS256

看得到,只是 Base64 編碼

被改成 alg: none

Payload 內容

使用者是誰、屬於哪個租戶、有效期限

看得到,任何人都能解開

使用者欄位被填成 admin

Signature 簽章

用伺服器金鑰對前兩段算出的一段值

看得到,但只有持金鑰的人做得出來

直接留空,系統照樣放行

關鍵在第三段。前兩段只是編碼,誰都可以解開、修改、再重新編碼回去。簽章的作用,是讓伺服器確認「這兩段內容是我發出去的、中途沒被動過手腳」。伺服器如果不驗簽章,JWT token 就等於一張手寫名牌,想寫誰的名字都可以。

Faav 在原文用了一個很貼切的比喻:Titan 像一個夜店保鑣,每張證件上的名字都仔細核對,卻從來不看照片。他還形容整個驗證機制像一間每扇門都有刷卡機的飯店,可是任何一張房卡都能打開任何一間房。

如果你對「API」這個詞還不太熟,可以先看我們寫的API 是什麼:為什麼老闆也該懂這個技術名詞。JWT token 就是 API 用來確認「來敲門的是誰」的那張證件。

我們自己的產品線也是靠 JWT token 串起來的。恆遠會員中樞系統負責所有自家產品的註冊、登入與權限,發給各產品的單一登入 token 用 RS256 私鑰簽章,每個產品驗證時把演算法鎖定在 RS256,收到 alg: none 或其他演算法一律拒絕。驗證邏輯集中在一處,要檢查、要補洞都只改一個地方。如果你的系統每個服務各寫一套登入驗證,很歡迎跟我們聊聊怎麼收攏。這種把身分驗證收攏到單一入口的做法,就是企業單一登入 SSO 在解決的問題。

這個洞是怎麼一步步被走完的:從一張 VPN 提示頁到管理員權限

先講結論:整條路徑沒有用到什麼高深技巧,每一步都是撿系統自己留下的線索。照時間順序拆開來看,你會發現每個環節其實都有機會把它擋下來,這對防守方才是重點。

圖表載入中…

第一關,前端上鎖擋不住後端。Titan 的網頁介面要員工連 VPN 才看得到,但那支 AI 機器人掃描微軟的子網域時,找到一台架在 Azure 雲端上、直接對外的 API 主機。前端上鎖、後端 API 卻裸奔,這種落差在企業系統裡其實很常見。

第二關,說明書公開在外。這台主機有一份公開的 Swagger 文件,也就是 API 的使用說明書,把四支 API 全列了出來,其中一支可以直接接受 SQL 查詢指令。內部 API 的說明書掛在公開網路上,等於把地圖印好送給對方。

第三關,舊設定檔還躺在網路存檔裡。查詢需要填資料表名稱,說明書沒給範例。Faav 到網路時光機(Wayback Machine)翻出 Titan 在 2023 年的登入頁快照,從當時留下的 Apache Superset 設定裡找到 56 個資料表名稱。系統早就改版,舊設定卻沒人清掉。

第四關,系統一路把答案送上門。不帶 token 呼叫會回 401。接下來十天,那支 AI 機器人拿一張從自己測試環境簽出來的 token,每次只改一個欄位,看系統回什麼錯誤:

每次改了哪個欄位

系統回的錯誤

透露了什麼

用研究員自己測試環境的 token

租戶錯誤

系統有檢查租戶

租戶改成微軟的

受眾(audience)錯誤

過了租戶這關

受眾改成 Titan 的

應用程式白名單錯誤

過了受眾這關

應用程式 ID 改成白名單內的

找不到使用者

已經進到使用者查詢,而簽章從頭到尾沒被檢查

這張表是整起事件最值得工程師看的地方。內容一直在改、簽章一直沒動,系統卻一路放行,這就等於自己承認沒在驗簽章。更糟的是每一層都回傳清楚的錯誤訊息,等於一步一步告訴對方下一格要填什麼。錯誤訊息給太細,本身就是一種資訊外洩。

最後一關,一個很不起眼的字。Faav 把整張 token 換成 alg 設為 none、簽章留空的版本,一樣通過,只剩「使用者是誰」卡住。AI 一直試 email 格式的帳號,因為那個欄位照規格應該放 email。9 月 5 日凌晨一點多,Faav 想到後端可能拿這個欄位去對應內部帳號名稱,於是填了 admin。查詢回傳一個「1」,他就以 Titan 管理員的身分執行了查詢。用他自己的話說:有時候答案真的就是 admin。

JWT 驗證最常見的四種寫錯法,Titan 中的是最嚴重那一種

先講結論:JWT 驗證出問題,九成都落在下面這四種寫法。Titan 犯的是第一種,也是最致命的一種,因為它讓任何人都能自己簽發一張管理員通行證。這一節寫給要維護自家系統的開發者,把該檢查的地方一次列清楚。

寫錯法

實際長什麼樣

會被怎麼利用

正確做法

只解碼、不驗簽章

把內容讀出來就直接拿來判斷身分

自己做一張 token,想當誰就當誰

一律用 verify 類函式,簽章不過就拒絕

接受 alg: none

讓 token 自己決定演算法,none 也照收

送一張沒有簽章的 token 就過關

在伺服器端寫死允許的演算法清單

演算法混淆

該用非對稱簽章卻沒鎖死,被換成對稱

拿公開的公鑰當密鑰去偽造簽章

驗證時指定演算法,公鑰與密鑰分開管理

不檢查期限與來源

只驗簽章,不看效期、簽發者、受眾

拿過期或別的系統發的 token 繼續用

效期、簽發者、受眾一起驗,token 效期設短

這些都不是新問題。OWASP 把「身分驗證失效」列在 API 安全風險的第二名,白紙黑字寫出「接受未簽章或弱簽章的 JWT(alg: none)」就是典型案例。IETF 在 2020 年發布的 JWT 最佳實務 RFC 8725 也要求:程式庫必須讓呼叫端指定允許的演算法,不能照單全收 token 自己宣告的那個。

程式庫本身也會出包。2026 年 1 月公開的 CVE-2026-23993 就是一例:一套 JWT 程式庫只要遇到它不認識的演算法名稱,none、None、foo 甚至空字串,都會跳過簽章驗證。就算自己的程式碼寫對了,用到沒更新的套件一樣會中招,所以相依套件的版本也要跟著顧。

用 Node.js 最常見的 jsonwebtoken 套件示範,有洞的寫法和補好的寫法其實只差幾行。這段可以直接拿去對照自家程式碼:

JavaScript
import jwt from 'jsonwebtoken'

// 有洞的寫法:decode 只把內容解出來,完全沒驗簽章
function getUserUnsafe(token) {
  const claims = jwt.decode(token)
  if (claims.tid !== EXPECTED_TENANT) throw new Error('tenant')
  if (claims.aud !== EXPECTED_AUDIENCE) throw new Error('audience')
  return db.user.findByName(claims.upn) // 內容可以隨便填,等於沒鎖
}

// 補好的寫法:先驗簽章,並寫死演算法、受眾、簽發者
function getUser(token) {
  const claims = jwt.verify(token, PUBLIC_KEY, {
    algorithms: ['RS256'],      // 只接受這個演算法,擋掉 none 與混淆
    audience: EXPECTED_AUDIENCE,
    issuer: EXPECTED_ISSUER,
  })
  return db.user.findByExternalId(claims.oid) // 用不可變的 ID 對應使用者
}

有洞的版本看起來也很「嚴謹」,租戶、受眾都檢查了,Titan 甚至還多查了應用程式白名單。問題是這些檢查全部建立在「token 內容可信」這個前提上,而內容可不可信,只有簽章能證明。少了那一行 verify,前面查得再多都是白工。

補好的版本還改了一個細節:用使用者不可變的 ID 去對應帳號,不用那種可以隨便填的名稱欄位。Titan 就是拿一個本該是 email 的欄位去比對內部帳號,才讓 admin 這個字變成管理員。這也提醒一件事:拿來查身分的欄位,要挑使用者改不動的那個。

AI 花十天找不到 admin,卻也很會寫出這種洞

先講結論:這起事件裡 AI 站在兩邊。攻擊端的 AI 很會磨、很有耐心;而防守端的系統如果也是 AI 快速寫出來、沒人審過,這種洞只會越來越多。這是我們最想提醒中小企業老闆的一點。

那支 AI 機器人做了十天研究員不用親自做的苦工:列舉子網域、逐欄解讀錯誤訊息、把一張沒有簽章的 token 一路推過四層檢查。但它卡在最後一步,因為它認定那個欄位照規格是 email,就一直試 email,想不到後端工程師其實拿它當內部帳號名稱用。Faav 的結論是:AI 的耐力加上一次人類直覺,缺了任何一邊都找不到這個洞。

攻擊成本正在快速下降。Imperva 2026 年惡意機器人報告統計,2025 年自動化流量已經佔全網 53%,超過人類,而且超過四分之一的機器人攻擊直接打 API。以前要一個資深資安人員花好幾天做的枚舉和試錯,現在一支機器人就能在背景一直跑,不喊累。

防守端的狀況也不樂觀。Veracode 的 2026 年生成式 AI 程式碼安全報告發現,大約 44% 的 AI 寫程式任務產出了帶有已知漏洞的程式碼,各家模型的平均安全通過率只有 56%,跟前一版報告的 55% 幾乎一樣。模型把程式寫得越來越順,安全性卻原地踏步。

我們的判斷很直接:JWT 驗證這種「功能測試一定會過、只有安全測試才會掛」的程式碼,最不適合全交給 AI 寫完就上線。用正常 token 去測,寫錯的版本一樣能登入、一樣能查資料,開發者完全感覺不到問題。只有刻意拿一張偽造的 token 去打,才會發現門根本沒鎖。

我們公司自己每天就在跑 20+ 個 AI 流程,寫程式也大量用 AI。我們的做法是讓 AI 寫,但登入、權限、金流這幾塊一定有人逐行看過,而且會用偽造 token、換成別人的 ID 這類「故意使壞」的測試去打自己。如果你的系統是用 AI 快速做出來的,可以先看Vibe Coding 做出來的 App 能直接上線嗎,裡面整理了最常見的幾種坑;想從原型走到能賣的正式產品,中間差的 7 件事也值得一起對照。

簽章之外,這起事件還有三個常被忽略的破口

先講結論:JWT 沒驗簽章是致命的那一刀,但另外三個破口只要有任何一個被補上,攻擊者都很難走到最後。資安從來就是好幾層防線疊起來,不是靠單一一道牆。

破口

這次的狀況

為什麼危險

該怎麼補

API 說明書公開在外

Swagger 文件任何人都讀得到,還標明哪支能下 SQL

等於把攻擊地圖印好交給對方

內部 API 文件放內網或加驗證,不對外公開

舊設定檔留在網路存檔

2023 年的設定被網路時光機存下,含資料表結構

改版後的舊資料成了現成情報

敏感頁面設定不快取,定期檢查外部存檔有沒有殘留

錯誤訊息說得太細

每一層驗證失敗都回傳明確原因

一步步引導攻擊者填對下一格

對外一律回統一的模糊錯誤,細節只寫進內部日誌

這三件事單獨看都不算「漏洞」,比較像壞習慣。但疊在一起,就把一個原本要花很久摸索的攻擊,縮短成十天就能走完。防守方要建立的觀念是:不要假設「反正沒人知道這支 API 在哪」,網路上的掃描機器人一天到晚在找這種沒公開連結、卻對外開著的端點。

金鑰與機密外洩也是同一類問題,我們在Zeabur 資安事件白話拆解裡整理過中小企業的止血清單,跟這篇可以搭著看。簽章用的私鑰、資料庫密碼這類機密該怎麼存、怎麼輪替,另外整理在企業機密資料 secrets 管理採購指南。

這裡也順帶破解一個常見迷思:很多人以為「我們公司又不是微軟,沒人會盯上我們」。真相是,掃描機器人不挑對象,它只是無差別地在整個網路上找有沒有對外開著、又沒鎖好的端點。規模小反而更危險,因為小公司通常沒有專職資安人員,一個洞可能開著好幾個月都沒人發現。Titan 這種等級的系統都會犯的錯,資源更少的團隊只會更容易犯。

開發者自查清單:這八項今天就能檢查自家系統

先講結論:不用等資安廠商進場,下面八項大部分工程師半天內就能自己驗完。每一項都寫了怎麼測,測不過的就是優先要補的地方。這份清單適合拿去直接問你的開發團隊或外包廠商。

檢查項目

怎麼測

沒過會怎樣

登入驗證有真的驗簽章

把 token 內容改一個字再送出去,看還過不過

任何人都能偽造身分

拒絕 alg: none

送一張 alg 設為 none、簽章留空的 token

不用金鑰就能簽發任意通行證

演算法寫死在伺服器端

看驗證程式有沒有指定 algorithms 清單

會被演算法混淆攻擊繞過

效期、簽發者、受眾都有驗

拿一張過期或別系統的 token 來打

舊 token、跨系統 token 可以一直用

用不可變 ID 對應帳號

看是用 email/名稱還是內部 ID 查使用者

可竄改的欄位會被填成 admin

內部 API 沒有裸奔在公網

從外部網路直接連 API 主機網址

前端上鎖也擋不住後端

錯誤訊息不外洩細節

故意打錯,看回傳有沒有講出哪一關失敗

等於教攻擊者怎麼過關

JWT 相依套件有更新

列出套件版本,對照近期漏洞公告

自己寫對了,套件的洞照樣中招

圖表載入中…

我們的判斷很直接:買再多的網站防火牆和 CDN,也擋不住這種攻擊。防火牆看的是「這個請求長得像不像攻擊」,但一張偽造 token 送出的請求,格式跟正常請求一模一樣。真正有效的防線寫在程式碼裡,而且要有人一支一支 API 看過。這也是我們不認同「買了資安方案就能安心」的原因。

三種常見的資安檢測各自抓不同的東西,別買錯,可以看弱點掃描、滲透測試、壓力測試的差異。這類「功能正常、驗證有洞」的問題,自動掃描工具往往抓不到,因為掃描器不知道你的商業邏輯該長什麼樣。若公司要把這些檢查變成長期制度、而不是出事才做一次,可以參考CNS 27001 與 ISO 27001 資安管理制度指南。

用 AI 快速做出來的系統特別要留意這一塊。AI 寫的登入功能測起來都會過,但常常就少了驗簽章那幾行。如果你的系統是外包或用 AI 趕出來的、自己看不出有沒有這種洞,我們的 Vibe Coding 上線前健檢會逐項檢查登入與權限、API 金鑰外洩、金流流程,出一份不是工程師也看得懂的報告和修復優先順序。先聊聊你的系統現況,值不值得做、先看哪一塊,我們會直接告訴你。

ℹ️我們怎麼看

接下來兩三年,這種「系統功能全都正常、只是少驗一個環節」的事件會越來越多,因為越來越多程式是 AI 快速生出來、沒人逐行審過就上線的。Veracode 的數據已經顯示 AI 寫的程式有四成帶著已知漏洞,而攻擊端的 AI 只會越來越有耐心。我們在自己做的系統裡的選擇是:簽章一定驗、演算法一定寫死、身分一定用不可變 ID 對應,這幾條寧可開發時多花時間也不省。給老闆一個最簡單的判斷方法:問你的工程師「有人拿一張自己偽造、沒有簽章的登入證來打我們系統,會怎樣?」答得出來、也實際測過,就先放心;答不出來,就該排時間檢查了。

ℹ️我們做過這件事

恆遠目前有 40+ 企業客製案落地,自家產品線的登入與權限也是我們自己做的共用中樞,發出去的單一登入 token 用 RS256 簽章、驗證時把演算法鎖死,這一塊一直是我們交付前花最多時間確認的部分之一。

例如我們做的高雄市幼兒園招生系統,同一套系統要服務家長、園所、教育局三端,每一端能看到、能改的資料都不一樣,權限一步都錯不得。

看到這裡,如果你也在想「我們的系統登入與權限到底做得對不對」,我們很樂意聽你聊聊現在的情況,一起看看哪些地方該先補。

看到這裡,如果你也在想「我們家的登入驗證有沒有這種洞」,很歡迎把系統現況丟過來,我們陪你看從哪一支 API 開始檢查最划算。

Q這次微軟真的外洩 17 兆筆資料嗎?

沒有。17 兆是研究員估算「技術上碰得到」的資料量,他強調自己從沒下載或碰過任何客戶資料與個資,只看了平台中繼資料和兩筆分析樣本就通報微軟。網路上「存取了 17 兆筆」的說法是把「能碰到」誤當成「已拿走」。

QJWT token 沒驗簽章為什麼這麼嚴重?

JWT 的前兩段內容任何人都能解開、修改再重新編碼,簽章是唯一能證明「這張證是伺服器發的、沒被動過」的部分。系統不驗簽章,等於接受任何人手寫的名牌,想冒充誰就冒充誰。這次攻擊者就是把使用者欄位填成 admin,直接變成管理員。

Qalg: none 是什麼?該怎麼防?

alg: none 是 JWT 規格裡「這張 token 不簽章」的宣告,本來只用於受信任的封閉環境。有洞的系統會照著 token 自己宣告的演算法去驗,看到 none 就跳過簽章檢查。正確做法是在伺服器端寫死允許的演算法清單(例如只收 RS256),收到 none 或清單外的演算法一律拒絕。

Q我不是工程師,要怎麼確認公司系統安全?

問你的開發團隊或外包廠商一個問題就好:「有人拿一張自己偽造、沒有簽章的登入 token 來打我們系統,會發生什麼事?」答得出來、也實際測過就相對安心。答不出來,代表沒人驗證過這一塊,建議安排一次上線前的資安健檢。

QAI 寫的程式碼可以直接上線嗎?

功能可以,但登入、權限、金流這幾塊建議一定要有人審過。業界研究顯示約四成 AI 生成的程式碼帶有已知漏洞,而且這種洞用正常操作測不出來,功能完全正常,只有拿偽造請求去打才會現形。上線前做一次針對性的審計,比出事後補救便宜得多。

Q這種漏洞,一般的弱點掃描工具掃得到嗎?

多半掃不到。這類「功能正常、驗證邏輯有洞」的問題屬於商業邏輯層面,掃描器不知道你的系統該怎麼判斷身分與權限,很難自動判定。要靠人工的程式碼審查或滲透測試,用偽造 token、換別人 ID 這類手法去驗證。

分享文章
恆

AUTHOR

恆遠數位編輯團隊

查看作者頁

留言(0)

尚無留言,成為第一個留言的人吧!

需要網站系統架設或軟體開發?

無論是品牌官網、客製化系統還是應用程式,我們的團隊擁有豐富經驗,歡迎聯繫我們,讓專業為您的事業加分。