Tìm hiểu cách thức hoạt động của CORS ??

CORS(Cross-Origin Resource Sharing) là một cơ chế bảo mật cho phép một web page từ một domain hoặc Origin truy cập vào resource của một domain khác. Nếu không có các tính năng như CORS...


7 min read
Tìm hiểu cách thức hoạt động của CORS ??

Khi thực hiện các API requests, đôi khi, bạn sẽ thấy những lỗi như thế này xuất hiện, để hiểu rõ hơn thì trong bài viết này chúng ta sẽ đi tìm hiểu nguyên nhân phát sinh và cơ chế hoạt động của nó.

Cross-Origin Resource Sharing

Về CORS ??

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own.(source: mozilla)

CORS(Cross-Origin Resource Sharing) hiểu đơn giản: Là một cơ chế bảo mật cho phép một web page từ một domain truy cập vào resource của một domain khác.

CORS sinh ra để giải quyết tính cứng nhắc của cơ chế same-origin policy.

The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps isolate potentially malicious documents, reducing possible attack vectors.(source: mozilla)

Nếu không có các tính năng như CORS, các websites sẽ không có quyền truy cập tới các resources từ origin khác.

Origin là gì ?

Origin refers to the content who initiated the request which is usually the open browser tab, but could also be the origin of an iFrame window.

Origin kết hợp của bộ ba: scheme (protocol), host (domain) và port, để hiểu rõ hơn về các thành phần bạn có thể tham khảo thêm tại đây.

Same-origin là gì ?

Hai đối tượng có cùng same-origin khi chúng có cùng scheme, hostport.
Ví dụ: https://examplebank.comhttps://examplebank.com/api được được xem là cùng origin, nhưng https://examplebank.com http://examplebank.com là 2 origin khác nhau (vì khác protocol).

Để hiểu rõ hơn, chúng ta sẽ xem xét ví dụ sau đây:

So sánh origin với URL: http://store.company.com/dir/page.html

URL KẾT QUẢ NGUYÊN NHÂN
http://store.company.com/dir2/other.html Same origin Only the path differs
http://store.company.com/dir/inner/another.html Same origin Only the path differs
https://store.company.com/page.html Failure Different protocol
http://store.company.com:81/dir/page.html Failure Different port (http:// is port 80 by default)
http://news.company.com/dir/page.html Failure Different host

Đối với các path hay query parameters thì không bị tác động bởi cơ chế same-origin policy.

Nguy cơ về cross-domain

Tìm hiểu thêm phương thức tấn công cross-domain ở đây

Giả sử chúng ta đã đăng nhập vào một tài khoản bank tại: https://examplebank.com, trong khi đó, ở 1 tab khác của browser bạn vô tình click vào 1 trang web chứa mã độc: https://evilunicorns.com.

Nếu không có cơ chế same-origin, Nó có thể đã thực hiện các đoạn scripts và thực hiện request(được xác thực) tới https://examplebank.com/api và thực hiện các hành vi nguy hiểm, mặc dù web đó không có quyền truy cập trực tiếp vào cookie của domain.

Để đảm bảo an toàn, chỉ có https://examplebank.com mới có quyền thực hiện các requests tới https://examplebank.com/api

Bằng cách hạn chế các HTTP requests đến cùng một origin,  same-origin policy sẽ hạn chế một số kịch bản như trên và một số lỗ hổng liên quan đến Cross-Site Request Forgery (CSRF).

Cách CORS hoạt động?


Có hai kiểu CORS requests: Simple requestsPreflighted requests

I. Simple requests

Simple request(source mozilla)

Ví dụ:

1. Ở một tab của browser, chúng ra truy cập: https://www.mydomain.com và nó thực hiện request đến: GET https://api.mydomain.com/widgets

2. Browser sẽ tự động thêm Origin Request Header cho cross-origin requests:

GET /widgets/ HTTP/1.1
Host: api.mydomain.com
Origin: https://www.mydomain.com
[Rest of request...]

3. Server sẽ kiểm tra Origin request header. Nếu giá trị của Origin được cho phép, Server trả về header Access-Control-Allow-Origin với giá trị của request header Origin.

HTTP/1.1 200 OK  
Access-Control-Allow-Origin: https://www.mydomain.com  
Content-Type: application/json
[Rest of response...]  

4. Khi browser nhận được phản hồi, nó sẽ kiểm tra liệu  Access-Control-Allow-Origin có khớp với origin của chính tab đó không. Nếu không, phản hồi sẽ bị chặn. Nếu hợp lệ, giá trị Access-Control-Allow-Origin khớp chính xác với origin hoặc là ký hiệu  * .

Access-Control-Allow-Origin: <origin> | *

Việc sử dụng * thường ẩn chứa rủi ro bảo mật, trừ khi API được public ra ngoài.

Note:

Như bạn có thể thấy, Server có quyền kiểm soát xem có cho phép request hay không tùy thuộc vào origin của request. Browser đảm bảo việc đặt Origin request header chính xác trước khi gửi.

II. Preflighted requests

Preflighted request là một kiểu CORS request khác, với những request có tác động tới data như POST, PUT, DELETE,... Browser sẽ gửi một request với OPTIONS method tới resource của domain trước khi gửi request chính, nhằm để xác định xem request chính có được server cho phép hay ko ?. Lúc này chúng ta sẽ thấy có 2 request tới cùng một Domain.

preflight request(source mozilla)

Nếu hợp lệ Server sẽ trả về response kèm một số header như: Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Max-Age,...

Trong đó:
* Access-Control-Allow-Methods: Mô tả những method nào client có thể gửi đi.
* Access-Control-Max-Age: Mô tả thời gian hợp lệ của preflight request

Preflighted request được thực hiện khi:

  • Sử dụng các method khác: GET, HEAD hoặc POST. Ngoài ra, nếu dùng POST để gửi request data với Content-Type khác với: application/x-www-form-urlencoded, multipart/form-data, text/plain.
    Ví dụ: nếu POST request gửi một XML payload đến server  bằng cách sử dụng application/xml or text/xml, thì sẽ thực hiện preflighted request.
  • Đặt các custom headers trong request  (ví dụ: request sử dụng một header , chẳng hạn như X-PINGOTHER)

Ví dụ:

  1. Ở một tab của browser, chúng ta truy cập https://www.mydomain.com , đồng thời nó sẽ gửi một request đến: POST https://api.mydomain.com/widgets.
    Browser đầu tiên sẽ gửi OPTIONS request (preflight request) đến Server với Requested Method và Requested Headers giả định của request chính.
    Trong đó, các headers: Access-Control-Request-MethodAccess-Control-Request-Headers sẽ được browser thêm tự động.
OPTIONS /widgets/ HTTP/1.1
Host: api.mydomain.com
Origin: https://www.mydomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization, Content-Type
[Rest of request...]

2. Server phản hồi lại các HTTP methods và headers được cho phép.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.mydomain.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type
Content-Type: application/json
[Rest of response...]  

3. Nếu request chính được cho phép, browser sẽ gửi CORS request(simple request), các bước tiếp theo sẽ được hiện giống như simple request.

POST /widgets/ HTTP/1.1
Host: api.mydomain.com
Authorization: 1234567
Content-Type: application/json
Origin: https://www.mydomain.com
[Rest of request...]

4. Phản hồi chứa giá trị origin trong Access-Control-Allow-Origin , browser lúc này sẽ thực hiện xử lý và gửi các request tiếp theo.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.mydomain.com
Content-Type: application/json
[Rest of response...]  

Browser compatibility

Khả năng tương tính của các trình duyệt

Cấu hình CORS dùng Nginx

#
# Wide-open CORS config for nginx
#
location / {
     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
}

Source: Michiel Kalkman


Còn tiếp...


Tham khảo:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://www.moesif.com/blog/technical/cors/Authoritative-Guide-to-CORS-Cross-Origin-Resource-Sharing-for-REST-APIs/
http://www.securityandit.com/security/understanding-cross-domain-attack/
https://techblog.vn/cors-la-giProgrammingcorsRestfulAPIHacking


RESTful: Phần 2 - Một số nguyên tắc thiết kế API
Previous article

RESTful: Phần 2 - Một số nguyên tắc thiết kế API

Security là một trong những yếu tố quan trọng nhất để xây dựng API, cần yêu cầu xác thực(authentication) và ủy quyền(authorization) mỗi khi truy cập API...

YAML 101
Next article

YAML 101

YAML được sử dụng để viết ra các files cấu hình, sử dụng phổ biến trong nhiều dự án vì tính dễ đọc, đơn giản, linh hoạt, ví dụ như: Docker-compose, Kubernetes, Ansible, ...


GO TOP

🎉 You've successfully subscribed to itplusX!
OK
]