一個更新器把要下載的執行檔網址用明文寫在 app.config 裡、用 HTTP 抓回來、下載完不驗任何簽章就執行——任何坐在你和 AMD 之間的網路攻擊者,理論上都能把那個檔案換成自己的。諷刺的是,真正擋住這條攻擊鏈的,不是 AMD 的任何防線,而是一個把更新器自己弄壞的次要 bug。
AMD 不肯修的那個更新器 RCE——一場 124 天的揭露
這條漏洞的起點不是什麼專案,而是一場惱怒。研究者 MrBruh 換了新的遊戲主機後,被一個週期性彈出的 console window 反覆打斷——那是一個「會週期性彈出在我新遊戲 PC 上的惱人 console window」,他循線把那個惹事的執行檔追到 AMD 的 AutoUpdate 軟體上。他形容自己是出於懊惱「決定懲罰這個軟體」,把它反編譯來搞清楚運作方式,結果在過程中「意外發現一個 trivial 的 remote code execution 漏洞」。值得留意的是這個「trivial」用得很重:在資安語境裡,它意味著這不是要鏈起好幾個小缺陷、繞過好幾層緩解才湊得出的精巧利用,而是把更新流程拆開看一眼就能指認的設計缺失。一個本來只想讓彈窗閉嘴的下午,挖出了一條從 MITM 直通 RCE 的更新路徑。
這種起點本身是這類漏洞的常態,也是它最值得警惕的地方。沒有人是為了找 AMD 麻煩才去翻 AutoUpdate 的;觸發整件事的只是一個惱人的彈窗。換句話說,把這個軟體反編譯、攤開來讀的門檻低到「一個被打擾的下午」就夠了——而它暴露出的東西,卻是一條能讓攻擊者在受害者機器上跑任意程式碼的路徑。攻擊面不是藏在某個冷僻角落,是擺在任何願意花一個下午反編譯的人面前。
從 2026 年 2 月 6 日首次回報,到 6 月 9 日 embargo 結束,整整 124 天。技術核心不複雜,複雜的是過程:一個按業界慣例三句話就能定性的更新器 RCE,被 AMD 先以「affects optional tools and relies on a MITM attack scenario」判為 out of scope、拒付約一萬美元等值(作者估「~10k USD if it was considered in scope」)的賞金,轉頭卻又要求把已經公開的 blog 下架。最終修補只用了 CRC-32 校驗,而不是密碼學簽章。這幾個動作放在一起,比漏洞本身更刺眼:一份不被當成漏洞的報告,為什麼值得廠商要求作者噤聲,又值得發一個 CVE?
值得記下的不是「又一個 RCE」,而是這條攻擊鏈的每一道防線都不存在、卻長期沒被利用的理由,以及一個廠商在「這不算漏洞」與「請你別公開」之間的自相矛盾。這篇揭露的價值,一半在它把一條教科書式的攻擊鏈攤得乾淨,另一半在它把廠商處理一個自己不想承認的漏洞時的全部小動作——拒絕、反轉、要求下架、發 CVE 卻不付錢——按日期記了下來。先把攻擊鏈本身攤開——下面這個 widget 讓你逐一打開三道本該存在的防線,看哪一道缺席時 MITM 攻擊者就能達成 RCE。
toggle the three defences to see when RCE lands · 3 switches
兩道防線皆缺:攻擊者替換的執行檔會被直接執行——這就是 RCE。
逆向 app.config——一條全程沒上鎖的更新路徑
MrBruh 在 2026 年 1 月 27 日反編譯 AMD AutoUpdate 時注意到的第一件事,是更新檢查要去抓的網址並不藏在哪個編譯進去的常數裡,而是明文擺在程式的 app.config 檔案中。換句話說,這個更新器去哪裡問「有沒有新版」這件事,是攤開來看得到的,沒有任何混淆。一個小細節讓這一段更耐人尋味:那個 URL 用的還是 AMD 自己的「Development」網址——研究者形容「a little odd that they use their 'Develpment' URL in production」,連 AMD 內部的拼字錯誤都原封不動帶進了正式版。
弔詭的是,這第一步本身並沒有問題。那個寫在 app.config 裡的 manifest URL 走的是 HTTPS——研究者的判斷是「it uses HTTPS, so it's perfectly safe」。取「有沒有新版」這份清單的這一段,傳輸是加密的、不會被中途竄改。換句話說,AMD 並非不知道 HTTPS 該怎麼用、也不是整個更新流程都裸奔——他們在「問清單」這一步把事情做對了。如果整條鏈都維持這個標準,這篇揭露就不會存在。問題是它沒有,而最諷刺的恰恰在於:被保護的是最不需要保護的那一步。
真正的破口在下一步。研究者的原話是「the real problem starts when you open up this .xml URL in your web browser, and realise that all the executable download URLs are using HTTP」——那份用 HTTPS 安全取回的 XML manifest,裡面列出的、指向實際更新執行檔的每一個下載網址,全部退回了明文 HTTP。於是出現一個荒謬的落差:問「有沒有新版」是加密的,真正把那個「新版」執行檔抓下來卻是明文的。HTTPS 保護的是那份目錄,被它指向、真正會被下載並執行的東西,反而走在沒上鎖的路上。這種「外層加密、內層裸奔」的組合,比整條鏈都用 HTTP 更容易騙過審查——一份快速的安全檢視看到 manifest 走 HTTPS,很可能就此打勾放行,沒有人去追問它裡面列的下載連結用的是什麼協定。
而最後一道、也是最致命的一步是執行前的驗證——它根本不存在。研究者寫得很直接:「the AutoUpdate software does no such validation and immediately executes the downloaded file.」下載完成,不檢查憑證、不檢查簽章、不檢查這個檔案到底是不是 AMD 發的,直接執行。下載什麼,就跑什麼。這一步的缺席之所以致命,是因為它本來是 HTTP 那個問題的最後一道保險:就算傳輸途中真被人換了檔案,只要執行前驗一次「這是不是 AMD 用私鑰簽的」,被換的檔案就過不了關。把這道保險也拿掉,等於宣告整條鏈對「被換掉的檔案」毫無察覺能力——它分不出 AMD 發的執行檔和攻擊者塞進來的執行檔有什麼不同。
三件事疊在一起,攻擊路徑就成形了,而且研究者把它講得毫不含糊:「a malicious attacker on your network, or a nation-state that has access to your ISP, can easily perform a MITM attack and replace the network response with any malicious executable of their choosing.」一個能在受害者與 AMD 之間做 MITM 的人——同一個咖啡店 Wi-Fi、被攻陷的家用路由器、企業內網裡的旁路者,或更上游、能碰你 ISP 的國家級對手——可以攔下那個明文 HTTP 回應,把更新執行檔換成自己的惡意程式。更新器抓到後不驗證、直接執行,攻擊者的程式碼就在受害者機器上跑起來了。這是教科書式的 remote code execution,唯一的門檻只在於「能不能做 MITM」。
這條鏈不只屬於 AutoUpdate 這一個程式。MrBruh 指出受影響的是一整批共用同一套更新機制的工具——AMD AutoUpdate、Ryzen Master,以及他所說的「multiple optional tools」。AMD 自己在後續溝通裡也用「optional tools」這個複數來指稱,等於從廠商口中印證了範圍不止一支程式。這一點放大了問題的份量:當缺陷不在某個獨立工具裡、而在被很多工具共用的更新元件裡,blast radius 就是所有依賴它的工具。補一個地方等於補很多個地方,這是好消息;但反過來,當初漏掉一個地方,也等於同時讓很多個地方裸奔——而 Ryzen Master 這類超頻調校工具,本來就常以高權限執行,落到它身上的 RCE 份量並不輕。下面這張圖把信任鏈在哪一步斷掉、修補後又補了哪一步標出來。
救了 AMD 一命的,是另一個 bug
最反諷的部分在這裡:這條攻擊鏈在現實裡其實沒辦法被直接利用,而擋住它的不是 AMD 的任何安全設計,是一個無關的功能 bug。
事情是這樣的:AMD 在某個時間點把套件清單從 ati.com 搬到了 drivers.amd.com,用瀏覽器打開那個 XML 網址,會自動被轉址到新網域。問題是 AutoUpdater 這支程式處理不了這個轉址——研究者的描述是它會因此「crash or lock up」,直接崩潰或卡死。它在拿到更新內容、走到那段有漏洞的程式碼之前,就先倒在了轉址這一關。結果是一個荒謬的狀態:更新器壞到連自己的漏洞都觸發不了。
這個 bug 的諷刺層次值得拆開看。它和 RCE 漏洞出自同一份不及格的工程——一支連標準 HTTP 轉址都處理不好的更新器,本來就不該被信任去下載並執行任意程式碼。也就是說,救了 AMD 的,和害了 AMD 的,是同一種粗糙。AMD 把套件搬家是日常維運,沒有人是為了堵漏洞才去動那個網域;更新器恰好在搬家後因為不會跟著轉址而失效,純屬巧合。一個本該是「壞掉的功能」的 bug,意外地兼任了唯一在運作的「安全機制」。
這件事在攻防的意義上很微妙。漏洞客觀存在——程式碼路徑就在那裡,明文 HTTP、零驗證一個不少;但要實際走到那段路徑,更新器得先成功完成一次正常的更新檢查,而它連這個前置條件都做不到。對防守方而言這是純粹的運氣,不是設計。更要命的是這份運氣相當脆弱:任何一次讓轉址重新能用的維護、AMD 哪天把 AutoUpdater 升級到會跟隨轉址、或者攻擊者自己在做 MITM 時順手把轉址那一段補正、直接餵給更新器一個不需要轉址的回應,理論上都會讓這條鏈重新活過來。換句話說,擋住攻擊的條件,攻擊者自己就有能力解除。把這個 bug 當成防線,等於把安全寄託在「我們的更新器剛好壞了、而且最好別修好」上面——這顯然不是任何人會願意寫進設計文件的句子。
這也解釋了 AMD 後續判定裡「需要 MITM」這個理由為什麼站不住:一個漏洞利用前提是不是合理門檻,跟它有沒有被一個不相干的 bug 暫時擋住,是兩回事。前者談的是攻擊者要付出的代價,後者只是當下的巧合。把攻擊鏈逐步攤開來看(回到上面那個 widget,關掉「轉址 bug」這一格),就能看清:真正讓系統安全的從來不是那個 bug,而是任何一道本該存在卻缺席的防線。
124 天,從 out of scope 到「請把文章下架」
披露的時間線本身比技術更值得讀。下面這個 scrubber 把 124 天的關鍵節點排開,拖動把手看每一步發生了什麼。
drag the handle along 124 days · 6 milestones
互動圖表
回報當天判 out of scope、隔天反悔又要求下架,到 embargo 結束共 124 天。
回報發生在 2026 年 2 月 6 日。AMD 當天就把這份報告關掉,標記為 out of scope,理由是它「is not eligible for a bounty under our current program guidelines, as it affects optional tools and relies on a MITM attack scenario」——不符賞金資格,因為它只影響 optional tools 又依賴 MITM 攻擊情境。這個拒絕來得很快:同一天回報、同一天關閉,幾乎沒有給審查留下時間。研究者也在同一天公開了原始 blog——這個時間點很關鍵,因為它意味著文章是在 AMD 判定「不在範圍內」之後才公開的,而不是搶在廠商之前搶發。對一個被告知「這不算數」的研究者來說,公開自己的發現是再合理不過的選擇。
隔天,2 月 7 日,AMD 反轉。態度從「不在範圍內」變成願意看一看:「We are still happy to review the details to determine whether there may be any potential validity.」一份前一天還被判定「不符賞金資格」的報告,二十四小時內變成了「我們很樂意審查、看看是否有任何潛在的有效性」。緊接著是那句和前一天判定自相矛盾的要求——「Could you please take the post down and wait for us to complete our review and provide an official response?」既然這份報告不算漏洞、不在範圍內,為什麼需要研究者把已經公開的文章撤下、等官方回應?這裡藏著一個說不通的邏輯:一個東西不可能同時「不值得我們付錢」又「重要到請你別講」。out of scope 是用來把報告擋在賞金之外的說法,take-down 卻是只有在你認真看待一份報告時才會提出的要求——AMD 同時做了這兩件事。
審查的結論把這層矛盾推到了最明處:AMD 願意為此漏洞發一個 CVE、實作修補、並在致謝裡給研究者署名——但不付賞金。發 CVE 不是隨手的動作,它等於在公開的漏洞編號體系裡正式承認「這是一個需要被追蹤、需要被修的安全漏洞」;修補與署名也都是只有在你承認問題存在時才會做的事。三件事每一件都和最初那句「out of scope」對著幹,唯一被守住的,只有「不付那筆約一萬美元的賞金」。整條時間線從首次回報到 6 月 9 日 embargo 結束跑了 124 天,遠超業界對這類「機制清楚、利用條件明確」漏洞的慣常處理時程——這不是一個技術上難修的洞,拖長的是定性與賠付的拉鋸,不是工程。
修補補上了傳輸,沒補上信任
AMD 對修補的官方說法是:所有更新通訊都用 HTTPS 加密,更新會經過 signature verification——原文「all update communications are secured using HTTPS, and updates undergo signature verification」。第一句解決了傳輸層:HTTP 換 HTTPS,中間人不能再隨意竄改傳輸中的內容,這道補上了確實有效。
第二句才是問題。研究者實際驗證後寫得很清楚——「Although it is true that they now fully use HTTPS, the claim about signature verification is untrue; they only perform a CRC-32 check on the downloaded executable, which is not cryptographically secure.」HTTPS 那句屬實,但 signature verification 那句不實:執行前做的只是 CRC-32 校驗,並非密碼學上安全的簽章。這兩者的差別不是程度問題,是本質問題。CRC-32 是設計來偵測傳輸過程中的位元翻轉、檔案損毀這類隨機錯誤的——它有固定的多項式、沒有任何密鑰,任何人都能對任意內容算出對應的 CRC-32 值。一個刻意偽造檔案的攻擊者,可以把惡意執行檔連同它正確的 CRC-32 一起送出去,校驗照樣通過、毫無異狀。CRC-32 從來不是為了對付「有人故意換檔案」而生的,硬把它擺在這個位置上,它擋不住任何稍有準備的攻擊者。
密碼學簽章要解決的恰恰是 CRC-32 解決不了的那個問題——「這個檔案真的是 AMD 簽發的嗎」。簽章用私鑰產生、用公鑰驗證:AMD 用只有自己握有的私鑰對發布的執行檔簽名,更新器用公開的公鑰驗證那個簽名對不對得上。攻擊者手裡沒有 AMD 的私鑰,就算他換掉了檔案,也產不出一個能通過驗證的合法簽名。這正是 CRC-32 缺的那一塊:密鑰。有密鑰,偽造才有代價;沒密鑰,校驗就只是一道任何人都能重算的算術題。把這道防線換成 CRC-32,等於對外宣稱「我驗了」,但驗的是完全不同、也完全擋不住攻擊者的東西。下面這張表把 AMD 宣稱的與研究者實測的並排,點欄位標題可排序。
click a column header to sort · 3 columns × 4 rows
| 環節 | AMD 宣稱的修補 | 研究者實測 |
|---|---|---|
| 傳輸協定 | all communications secured using HTTPS | 確實改用 HTTPS,傳輸竄改被擋下 |
| 執行前完整性 | updates undergo signature verification | 實際只做 CRC-32 校驗 |
| 防隨機損毀 | (簽章隱含涵蓋) | CRC-32 可以——這是它的本職 |
| 防蓄意偽造 | (宣稱由 signature verification 提供) | CRC-32 無密鑰,攻擊者可連校驗一起偽造 |
對一個正在挑 patch 版本的工程師,這個結尾的實際意義很具體:當廠商在 advisory 裡寫「now uses signature verification」時,這份揭露提醒你那行字可能名實不符。HTTPS 與完整性校驗解決的是不同的威脅——前者管傳輸途中的竄改、後者管「拿到的東西是不是發布者本人簽的」——一個 CRC-32 同時冒充後者,是這次最該被記住的細節。MITM 是不是高門檻另說,但「我驗了簽章」與「我算了 CRC-32」之間的距離,跟攻擊者好不好做到 MITM 無關。
The lesson:當 advisory 說「已加 signature verification」,去確認它驗的是密碼學簽章還是 CRC-32——前者擋偽造,後者只擋手滑,而這次補的是後者。