XST 的攻擊手段#
XST 的全稱是 Cross-Site Tracing,中文譯作 “跨站式追蹤攻擊”。具體而言,是客戶端發 TRACE / TRACK 請求至伺服器,如果伺服器按照標準實現了 TRACE / TRACK 回應,則在 response body 裡會返回此次請求的完整頭資訊。通過這種方式,客戶端可以獲取某些敏感的 header 字段,例如 httpOnly 的 Cookie 等。
可見 XST 的攻擊原理非常之簡單,借由 XST 攻擊獲取到 Cookie 資訊或者其他敏感資訊之後,攻擊者可以利用這些資訊再發動 XSS、CSRF、中間人攻擊等,看似無害,但潛在的危險卻很巨大。僅根據 XST 攻擊並不會對伺服器造成實質性的傷害,它真實的影響是暴露了敏感的 header 資料,如擁有 httpOnly 屬性的 Cookie,已經禁止前端 JavaScript 訪問它(如 document.cookie
),防止它被發送給第三方,但即使在這種情況下,TRACE 方法也可用於繞過此保護並訪問 cookie。因此 XST 也被稱作 Trace 泄露攻擊、Trace header 反射、Trace 方法注入(TMI)、Trace Header Cookie 攻擊(THC)。
XST 攻擊的條件:
- 需要目標 Web 伺服器允許接受 Trace、Track 方法的請求。
- 客戶端可以發送 Trace、Track 方法的請求。(如今瀏覽器環境下已經杜絕這種請求)
下面舉個栗子,這裡我用 Express 搭建了一個簡單的 Web 伺服器,接受一個 Trace 方法的請求:
import express from 'express'
import cookieParser from 'cookie-parser'
const app = express()
app.use(cookieParser())
app.use('/', (req, res, next) => {
res.cookie('account', 'airing', { maxAge: 900000, httpOnly: true })
return res.json(req.headers)
})
app.listen(3000)
我們用 TRACE 方法攜帶 Cookie 請求,可以發現 Cookie 是可以被發送過去的(Chrome 24 環境下):
var xhr = new XMLHttpRequest();
xhr.open('TRACE', 'http://127.0.0.1:3000/', false);
xhr.withCredentials = true
xhr.setRequestHeader('Cookie', 'account=airingursb');
xhr.send(null);
if(200 == xhr.status) console.log(xhr.responseText);
XST 的真正結果是它暴露了 JavaScript 通常無法訪問的 HTTP 頭,httpOnly 本應該阻止 JavaScript 讀取與發送 cookie 到伺服器,但 XST 成功繞過了 httpOnly 的限制。另外,用於 HTTP Basic Auth 的 Authentication 頭只是 Base64 編碼的使用者名和密碼,不是 DOM 的一部分,理應也不能直接被 JavaScript 讀取,但若使用 XST 也可以繞過。這些敏感資訊只通過一個 Trace 請求卻全都暴露了出來。
XST 的防禦方法#
杜絕 XST 非常簡單,Web 伺服器限制 Trace、Track 方法的請求即可。另如今, XMLHTTPRequest 已經杜絕了 Trace 與 Track 方法的請求(Chrome 25 版本及 FireFox 19 之後),如果嘗試用 Trace / Track 方法請求,會拋出 SecurityError 異常,這也從根本上杜絕了 XST 攻擊。
var xhr = new XMLHttpRequest();
xhr.open('TRACE', 'http://localhost:3000/', false);
xhr.send(null);
if(200 == xhr.status) console.log(xhr.responseText);
同時,在 FireFox 43 之後,Cookie 等不安全字段也被禁止攜帶在請求的 header 中發送。詳見 Forbidden header name | MSD
雖說目前現代瀏覽器已經越來越安全,XST 也成為了歷史,但其給我們 web 開發者也留下警示 —— 代碼編寫時一定要注意安全性和嚴謹性。