Trong quá trình phát triển và kiểm thử các ứng dụng web hiện đại, CORS là một trong những khái niệm bắt buộc phải hiểu rõ, đặc biệt với những ai làm Web Security, Pentest, Bug Bounty hoặc Backend API.
Rất nhiều lỗi “khó chịu” trên trình duyệt – và không ít lỗ hổng bảo mật nghiêm trọng – đều bắt nguồn từ việc hiểu sai hoặc cấu hình sai CORS.
🌐 Same-Origin Policy (SOP) – Nền tảng của CORS
Trước khi nói về CORS, cần hiểu Same-Origin Policy (SOP).
SOP là cơ chế bảo mật mặc định của trình duyệt, quy định rằng: Một website chỉ được phép truy cập tài nguyên nếu chúng có cùng origin.
Một origin được xác định bởi 3 thành phần:
- Scheme (http / https)
- Domain
- Port
- https://example.com ❌ không được gọi https://api.example.com (khác subdomain)
- https://example.com ❌ không được gọi http://example.com (khác scheme)
- https://example.com:443 ❌ không được gọi https://example.com:8443
- Đánh cắp dữ liệu giữa các website
- Đọc response nhạy cảm của người dùng
- Lạm dụng phiên đăng nhập
- Frontend thường đặt ở domain khác
- Backend API dùng chung cho mobile / web
- Microservices giao tiếp chéo domain
➡️ SOP trở thành rào cản, và đó là lúc CORS xuất hiện.
🔄 CORS là gì?
Cross-Origin Resource Sharing (CORS) là một cơ chế do trình duyệt triển khai, cho phép server chỉ định rõ domain nào được phép truy cập tài nguyên của mình.
Nói ngắn gọn: CORS là cách để server “nới lỏng SOP” một cách có kiểm soát.
CORS không thay thế SOP, mà mở rộng SOP, giúp các request cross-origin hợp lệ vẫn hoạt động.
🧠 CORS hoạt động như thế nào?
CORS dựa hoàn toàn trên HTTP Response Headers.
Khi trình duyệt gửi một request cross-origin, nó sẽ kiểm tra các header trả về từ server để quyết định:
- Có cho phép JavaScript truy cập response hay không
- Có cho gửi cookie / token hay không
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Allow-Credentials
Access-Control-Allow-Origin: https://frontend.example Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Credentials: true
👉 Nghĩa là:
- Chỉ frontend.example được phép truy cập
- Chỉ cho GET, POST
- Cho phép gửi cookie / session
🚦 Preflight Request – Bước kiểm tra trước khi gửi
Với các request “nhạy cảm” (PUT, DELETE, custom header…), trình duyệt sẽ gửi preflight request bằng phương thức OPTIONS trước.
Mục đích:
- Hỏi server: “Tao có được gửi request này không?”
- Nếu server trả lời không hợp lệ → request chính bị chặn
⚠️ CORS Misconfiguration – Lỗi cấu hình cực kỳ phổ biến
CORS không nguy hiểm nếu cấu hình đúng, nhưng lại trở thành lỗ hổng nghiêm trọng nếu cấu hình ẩu. ❌ Các cấu hình CORS nguy hiểm thường gặp:
- Access-Control-Allow-Origin: *
- Cho phép mọi origin + Allow-Credentials: true
- Phản chiếu Origin từ request (Origin: attacker.com)
- Whitelist origin quá rộng (regex lỏng lẻo)
- Attacker có thể đọc dữ liệu nhạy cảm
- Bypass authentication
- Đánh cắp thông tin người dùng
- Khai thác tài khoản người khác chỉ bằng trình duyệt
- Bug Bounty
- Pentest report
- OWASP Top 10 (liên quan Access Control)
🚫 Hiểu lầm phổ biến về CORS
❌ CORS KHÔNG phải là cơ chế chống CSRF
CORS không ngăn attacker gửi request, nó chỉ ngăn trình duyệt đọc response. ❌ CORS chỉ áp dụng cho trình duyệt
- curl
- Postman
- server-side script
👉 Vì vậy, CORS không phải security control toàn diện, mà chỉ là browser security mechanism.
🛡️ Best Practices khi triển khai CORS
✔ Chỉ cho phép origin cần thiết
✔ Không dùng * cho API có dữ liệu nhạy cảm
✔ Không bật Allow-Credentials nếu không cần
✔ Validate Origin nghiêm ngặt phía server
✔ Kết hợp với:
- Authentication
- Authorization
- CSRF protection
- Proper access control
📌 Kết luận
CORS là con dao hai lưỡi:
- ✔ Cấu hình đúng → ứng dụng linh hoạt, an toàn
- ❌ Cấu hình sai → tự mở cửa cho attacker
- Web Developer
- Pentester
- Bug Hunter
- Security Engineer