名詞解釋

CORS 是什麼 — 原理,以及設定錯誤(CORS misconfiguration)會引發什麼

CORS(跨來源資源共用)是瀏覽器控制其他網站的 JavaScript 能否讀取你 API 回應的機制。設定過寬會讓第三方讀到已登入資料。說明原理與安全設定:白名單、不反射 Origin、不把 * 與認證資訊並用。

發布於 2026-06-11 更新於 2026-10-06 閱讀時間 3 分鐘
本頁內容

加上 Access-Control-Allow-Origin 之後能運作的 API,不一定是安全的。CORS 並不是加上一次就不用管的東西,關鍵在於把許可的對象收緊。本文講解它的原理和安全的設定方法(不會寫出攻擊步驟)。

先講原理

瀏覽器有一條同源政策:其他來源的 JS 不能擅自讀取其他網站的回應。CORS 就是用來把這條規則的例外只對伺服器明確許可的對象打開的機制。

來源(origin)是協定(https)、主機名稱與埠的組合。https://example.com 與 https://api.example.com 主機不同,所以是不同來源;http://example.com 與 https://example.com 協定不同,也是不同來源。

回應標頭含義
Access-Control-Allow-Origin允許哪個來源讀取回應
Access-Control-Allow-Credentials是否允許帶 Cookie 等認證資訊的通訊
Access-Control-Allow-Methods / -Headers允許的 HTTP 方法/標頭

關鍵在於,CORS 是屬於「放寬限制」那一側的機制。放寬的方式一旦出錯,本不該被讀取的資料就會被第三方讀到。

還有一點很重要:CORS 阻止的是 JavaScript 讀取回應。簡單請求即使沒有 CORS 許可,也會到達伺服器並被處理。使用自訂標頭等情況時,瀏覽器會先用 OPTIONS 請求(預檢)確認,若不被允許就不送出真正的請求。

與相似機制的區別

CORS 常與名稱相近的機制,以及關係密切的漏洞混淆。

用語決定什麼由誰執行
同源政策其他來源不能讀取回應(瀏覽器的預設)瀏覽器
CORS作為上述規則的例外,允許哪些來源讀取伺服器宣告,瀏覽器執行
CSRF讓使用者已登入的瀏覽器送出非本意請求的攻擊以 CSRF Token 與 SameSite 防止
CSP自己的頁面可以載入哪些指令碼與連線伺服器宣告,瀏覽器執行

CORS 關心的是「回應能不能被讀取」;CSRF 關心的是「能不能代替使用者送出請求」。收緊 CORS 並不能防止 CSRF。

哪些設定是危險的

危險的設定(容易犯)

  • 把請求的 Origin 原樣反射回去並予以許可
  • Access-Control-Allow-Origin: * + 同時允許認證資訊
  • 把不必要的 API 也大範圍地對其他來源開放

安全的設定

  • 白名單(只放可信任的固定來源)
  • 其他一律預設拒絕
  • 帶認證資訊時不用 *,而指定具體的來源
攻擊者網站的 JS 向你的 API 發起請求(使用者處於登入狀態)
↓ 伺服器不加判斷地許可了 Origin(設定錯誤)
瀏覽器允許讀取回應=個人資訊/權杖被交到攻擊者網站手裡
設定太寬時,攻擊者網站的 JS 就能借用使用者的登入狀態讀取到 API 的回應。

設定錯誤通常是怎麼發生的

多數設定錯誤,來自想讓 CORS 錯誤消失。典型的經過如下:

  1. 從前端帶著 Cookie 呼叫 API,出現 CORS 錯誤
  2. 加上 Access-Control-Allow-Origin: *。但對帶認證資訊的請求,瀏覽器不會讓頁面讀取 * 的回應,所以錯誤仍在
  3. 改成把收到的 Origin 原樣回傳,錯誤就消失了。同時,任何網站都能讀取已登入的回應

即使有白名單,比對方式草率也會走到同樣的結果。

  • 以「結尾是 example.com」比對,也會放行 evil-example.com 這類不同的網域
  • 以「開頭是 https://example.com」比對,也會放行 https://example.com.evil.net
  • 為了開發方便而允許 null 來源,也會允許其他網站能製造出的 null 來源讀取

請以完全一致比對整個來源(協定、主機與埠)。

安全設定的基本原則

1

採用白名單方式(最重要)

只許可事先確定的可信任的來源,其他一律拒絕(預設拒絕)。不要「先全部許可了再說」。
2

不要不加判斷地反射 Origin

不要把請求裡的 Origin 原樣 echo 到 Access-Control-Allow-Origin。只有與白名單比對一致時才回傳。由於值會隨請求而變,也要送出 Vary: Origin,避免快取把回應混在一起。
3

帶認證資訊時不要用 *

帶 Cookie 等的通訊中,不要把 Access-Control-Allow-Origin: * 與 Allow-Credentials: true 同時使用。要指定具體的來源。
4

把開放範圍降到最小

只把確實需要對其他來源公開的端點作為對象。不要大範圍開放。* 只用於不需要登入的公開資料。

如何檢查自己的網站

對你的 API 送出一個自稱來自其他來源的請求,看回應標頭。請只對你管理的 API 這樣做。

# 自稱來自未允許的來源,只看回應標頭
curl -s -o /dev/null -D - -H "Origin: https://example.com" https://your-api.example/ | grep -i "^access-control"
  • 如果得到 Access-Control-Allow-Origin: https://example.com,表示 API 會反射 Origin。請加上白名單比對
  • 如果同時出現 Access-Control-Allow-Origin: * 與 Access-Control-Allow-Credentials: true,請重新檢討設定
  • 如果什麼都沒回傳,或只回傳自己前端的來源,就沒問題

用 Origin: null 再做一次同樣的確認。對已確認所有權的網站,網站安全健檢會一併檢查 Origin 反射與認證資訊設定。其他安全標頭可以用安全回應標頭診斷確認。

本站的觀點:CORS 不是「防守」,而是「放寬方式」。要收緊放寬的對象

一個常見的誤解是「加上 CORS 標頭就安全了」。恰恰相反,CORS 是屬於「放寬」瀏覽器限制那一側的機制。所以重要的不是「怎麼加」,而是「把對誰、開放到什麼程度收到最小」。本站建議把可以被外部讀取的資料和不可以的資料區分開,採取預設拒絕、只用白名單打開例外的方針。另外,讓「回應會被讀取」這一前提整個崩塌的 XSS,以及瞄準狀態變更的 CSRF 是另一類漏洞,所以單靠 CORS 並不能守住全部。

出處(一手資料)

  • MDN Web Docs, "Cross-Origin Resource Sharing (CORS)" — developer.mozilla.org(帶認證資訊的請求不可用 *、預檢的條件、Vary: Origin)
  • WHATWG Fetch Standard, "CORS protocol" — fetch.spec.whatwg.org
  • OWASP HTML5 Security Cheat Sheet — cheatsheetseries.owasp.org(只允許可信任的網域;不要未經檢查就回傳 Origin 標頭)
  • PortSwigger Web Security Academy, "Cross-origin resource sharing (CORS)" — portswigger.net(白名單比對的錯誤、null 來源、CORS 不是 CSRF 防護)
  • MITRE CWE-942: Permissive Cross-domain Policy with Untrusted Domains — cwe.mitre.org

延伸閱讀

分類編號

CWE 對造成漏洞的弱點類型進行分類,MITRE ATT&CK 對攻擊者的技術進行分類。兩者皆由 MITRE 維護,廣泛用於標註漏洞資訊與偵測規則。

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

FAQ

QCORS 是做什麼用的機制?
A

瀏覽器有一條「同源政策」:另一個來源(網站)的 JavaScript 不能擅自讀取其他網站的回應。CORS(Cross-Origin Resource Sharing)就是用來把這條規則的例外「只對伺服器明確許可的對象」打開的機制。它透過 Access-Control-Allow-Origin 等回應標頭,宣告允許哪些來源讀取回應。

QCORS 設定錯誤會引發什麼?
A

如果許可放得太寬,攻擊者網站的 JavaScript 就可能讀取到使用者已登入的 API 回應。典型例子是:把請求的 Origin 原樣反射回去並予以許可,或者把 Access-Control-Allow-Origin 設為 * 的同時還允許認證資訊(Cookie 等)。結果就是個人資訊或權杖可能被交到第三方網站手裡。

Q安全設定的基本原則是什麼?
A

就是「白名單方式」。只許可事先確定的、可信任的來源,其他一律拒絕(預設拒絕)。不要不加判斷地反射請求裡的 Origin。在帶認證資訊的通訊中,Access-Control-Allow-Origin 不要用 *,而要指定具體的來源。最根本的是,只把確實需要對其他來源公開的端點作為對象。

Q出現 CORS 錯誤,該把 Access-Control-Allow-Origin 設成 * 嗎?
A

如果是不需要登入、只回傳公開資料的 API,* 沒問題。但對於帶 Cookie 等認證資訊的請求,瀏覽器不會讓頁面讀取 * 的回應,所以錯誤仍會存在。如果接著改成把收到的 Origin 原樣回傳,任何網站都能讀取回應。正確的修正方式是把自己前端的來源列入白名單,只在完全一致時回傳它。

Q設定 CORS 能防止 CSRF 嗎?
A

不能。CORS 控制的是回應能否被讀取,而不是請求會不會被送出。簡單請求(例如表單送出形式的 POST)即使沒有 CORS 許可也會到達伺服器。CSRF 請用 CSRF Token 與 Cookie 的 SameSite 屬性來防止。

Q預檢請求(preflight)是什麼?
A

瀏覽器在送出真正的請求之前,先用 OPTIONS 請求詢問伺服器是否允許該方法與標頭。使用自訂標頭、以 application/json 送出的 POST、PUT、DELETE 等情況會發生。若不被允許,真正的請求就不會送出。只使用允許之標頭與內容類型的 GET、HEAD 或 POST(簡單請求)則不會觸發。