cover

接續上一篇的 XSS、SQLi、CSRF,這篇來看三個容易被忽略但殺傷力不小的東西:SSRF、CORS 的真面目、以及你的 production 網站可能缺少的安全 Headers。

先講結論

SSRF 是你的 server 幫攻擊者存取了內部資源,CORS 不是安全機制而是存取控制(搞混了你會裸奔),security headers 是花 5 分鐘就能設好的免費防禦層。

SSRF——你的 Server 變成攻擊者的跳板

Server-Side Request Forgery 的劇本:攻擊者讓你的 server 去請求他指定的 URL。問題是,你的 server 在內網裡,能碰到很多外面碰不到的東西。

攻擊者: "請幫我抓這個 URL 的內容"
URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/
                              ↑
                    AWS metadata API!
                    可以拿到 IAM credentials

哪些功能最容易中招?「預覽 URL」功能、圖片 URL 下載、Webhook 設定、PDF 生成(如果接受外部 URL)。基本上任何接受使用者提供的 URL 然後你的 server 去 fetch 的功能,都是 SSRF 的溫床。

防禦:

// ✗ 直接拿使用者給的 URL 去 fetch
const response = await fetch(userProvidedUrl)
 
// ✓ 白名單 + URL 驗證
function isAllowedUrl(url) {
  const parsed = new URL(url)
  if (isInternalIP(parsed.hostname)) return false  // 禁止內部 IP
  if (!['http:', 'https:'].includes(parsed.protocol)) return false
  if (!ALLOWED_DOMAINS.includes(parsed.hostname)) return false
  return true
}

你的 API 有接受 URL 作為參數的 endpoint 嗎?那就是潛在的 SSRF。

CORS——它不是你以為的安全機制

最常見的誤解:「設了 CORS 就安全了。」

不,CORS 的本質是:告訴瀏覽器「哪些外部網站可以讀取我的 API 回應」。注意關鍵字——瀏覽器。Server-to-server 的請求完全不受 CORS 影響。CSRF 也不是靠 CORS 防的(preflight 只對某些 request 類型有效)。

最危險的設定:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
# ↑ 同時開這兩個等於沒設

正確的做法:

// 只允許你的前端域名
const allowedOrigins = ['https://yourdomain.com']
 
app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },
  credentials: true
}))

CORS 是存取控制,不是安全機制。搞混這兩件事,你以為自己有防禦,其實在裸奔。

安全 Headers——5 分鐘設好的免費防禦

這些 HTTP headers 應該在你的所有 production 網站上設定,但我敢打賭你的網站少了至少兩個:

  • Content-Security-Policy: default-src 'self'——限制可執行的資源來源,XSS 的最後一道防線
  • Strict-Transport-Security: max-age=31536000; includeSubDomains——強制 HTTPS,不給降級攻擊機會
  • X-Content-Type-Options: nosniff——防止 MIME type sniffing
  • X-Frame-Options: DENY——防止被 iframe 嵌入(clickjacking 防禦)
  • Referrer-Policy: strict-origin-when-cross-origin——控制 Referer header 洩漏多少資訊

不信的話,去 securityheaders.com 掃一下你的網站。看到那個 F 的時候別太驚訝。

設定這些 headers 大概花你 5 分鐘。不設的話,你就是在跟攻擊者說「我這邊防禦很鬆,歡迎光臨」。反正你本來就很歡迎大家來嘛。


Web 安全的本質就一句話:不要信任任何來自外部的東西。聽起來很偏執?在安全領域,偏執才是正確的態度。

延伸閱讀