Gây nhầm lẫn cho bên trung gian độc hại bằng HTTPS và Bảo mật truyền tải nghiêm ngặt HTTP

Do lượng dữ liệu cá nhân lưu thông qua hàng loạt các ống dẫn khổng lồ là Internet, nên việc mã hoá không phải là điều mà chúng ta có thể hoặc nên bỏ qua một cách dễ dàng. Các trình duyệt hiện đại cung cấp một số cơ chế mà bạn có thể sử dụng để đảm bảo rằng dữ liệu của người dùng được bảo mật trong khi truyền: cookie bảo mậtBảo mật nghiêm ngặt trong quá trình truyền là hai trong số những cơ chế quan trọng nhất. Các API này cho phép bạn bảo vệ người dùng một cách liền mạch, nâng cấp kết nối của họ lên HTTPS và đảm bảo rằng dữ liệu người dùng không bao giờ được gửi ở dạng thô.

Tại sao bạn nên quan tâm? Hãy cân nhắc điều này:

Việc phân phối một trang web qua kết nối HTTP không mã hoá cũng giống như việc đưa một phong bì chưa niêm phong cho người đầu tiên bạn gặp trên đường và có vẻ như đang đi theo hướng của bưu điện. Nếu bạn may mắn, cô ấy có thể tự mang thư đến nơi hoặc chuyển thư cho người tiếp theo mà cô ấy thấy đang đi đúng hướng. Người đó cũng có thể làm tương tự, v.v.

Hầu hết người lạ trong chuỗi thư ngẫu hứng này đều đáng tin cậy và sẽ không bao giờ xem trộm hoặc thay đổi thư ngỏ của bạn. Tuy nhiên, càng nhiều lần thư thay đổi chủ sở hữu, thì càng có nhiều người có toàn quyền truy cập vào thư bạn đang gửi. Cuối cùng, rất có thể người nhận thư của bạn sẽ nhận được một thứ gì đó trong thư, nhưng liệu thứ đó có phải là chính thứ mà bạn đã gửi ban đầu hay không thì vẫn còn là một câu hỏi mở. Có lẽ bạn nên đóng phong bì đó lại…

Người trung gian

Dù tốt hay xấu, Internet phụ thuộc rất nhiều vào độ tin cậy của người lạ. Các máy chủ không kết nối trực tiếp với nhau, mà chuyển các yêu cầu và phản hồi từ bộ định tuyến này sang bộ định tuyến khác trong một trò chơi Điện thoại khổng lồ.

Bạn có thể xem các bước nhảy này trong thực tế bằng traceroute. Tuyến đường từ máy tính của tôi đến HTML5Rocks sẽ có dạng như sau:

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 bước nhảy không phải là quá tệ. Tuy nhiên, nếu tôi gửi yêu cầu qua HTTP, thì mỗi bộ định tuyến trung gian đó sẽ có toàn quyền truy cập vào các yêu cầu của tôi và phản hồi của máy chủ. Tất cả dữ liệu đang được chuyển dưới dạng văn bản thuần tuý chưa mã hoá, và bất kỳ bên trung gian nào trong số đó đều có thể đóng vai trò là Người ở giữa, đọc dữ liệu của tôi hoặc thậm chí thao túng dữ liệu trong quá trình truyền.

Tệ hơn nữa, loại hành vi chặn này gần như không thể phát hiện được. Phản hồi HTTP bị sửa đổi một cách độc hại trông giống hệt như phản hồi hợp lệ, vì không có cơ chế nào cho phép bạn đảm bảo rằng dữ liệu nhận được chính xác là dữ liệu đã gửi. Nếu có người quyết định đảo lộn Internet của tôi để mua vui, thì tôi sẽ gặp phải một số rắc rối.

Đây có phải là đường dây bảo mật không?

Việc chuyển từ HTTP văn bản thuần tuý sang kết nối HTTPS bảo mật là biện pháp bảo vệ tốt nhất của bạn trước những kẻ trung gian. Các kết nối HTTPS mã hoá toàn bộ kênh từ đầu đến cuối trước khi gửi dữ liệu, khiến các máy giữa bạn và đích đến không thể đọc hoặc sửa đổi dữ liệu trong quá trình truyền.

Thanh địa chỉ của Chrome cung cấp khá nhiều thông tin chi tiết về trạng thái của một kết nối.
Hộp tìm kiếm của Chrome cung cấp khá nhiều thông tin chi tiết về trạng thái của một kết nối.

Tính bảo mật mà HTTPS cung cấp bắt nguồn từ khái niệm về khoá mật mã công khai và riêng tư. (Rất may) việc thảo luận sâu về các chi tiết nằm ngoài phạm vi của bài viết này, nhưng tiền đề cốt lõi khá đơn giản: dữ liệu được mã hoá bằng một khoá công khai nhất định chỉ có thể được giải mã bằng khoá riêng tư tương ứng. Khi một trình duyệt bắt đầu bắt tay HTTPS để tạo một kênh bảo mật, máy chủ sẽ cung cấp một chứng chỉ cung cấp cho trình duyệt tất cả thông tin cần thiết để xác minh danh tính của trình duyệt bằng cách kiểm tra xem máy chủ có sở hữu khoá riêng thích hợp hay không. Tất cả thông tin liên lạc từ thời điểm đó trở đi sẽ được mã hoá theo cách chứng minh rằng các yêu cầu được gửi đến và phản hồi được nhận từ máy chủ đã xác thực.

Do đó, HTTPS giúp bạn đảm bảo rằng bạn đang nói chuyện với máy chủ mà bạn nghĩ rằng mình đang nói chuyện, đồng thời không ai khác đang nghe lén hoặc can thiệp vào luồng dữ liệu. Loại mã hoá này là điều kiện tiên quyết tuyệt đối để bảo mật trên web; nếu ứng dụng của bạn hiện không được phân phối qua HTTPS, thì ứng dụng đó dễ bị tấn công. Khắc phục. Ars Technica có một hướng dẫn tuyệt vời về cách lấy và cài đặt chứng chỉ (miễn phí) mà bạn nên tham khảo để biết thông tin kỹ thuật. Cấu hình sẽ khác nhau giữa các nhà cung cấp và máy chủ, nhưng quy trình yêu cầu chứng chỉ thì giống nhau ở mọi nơi.

Bảo mật theo mặc định

Sau khi bạn yêu cầu và cài đặt chứng chỉ, hãy đảm bảo rằng người dùng của bạn được hưởng lợi từ công sức của bạn: di chuyển người dùng hiện tại sang kết nối HTTPS một cách minh bạch thông qua tính năng chuyển hướng HTTP và đảm bảo rằng cookie chỉ được phân phối qua các kết nối bảo mật.

Vui lòng đi theo hướng này

Khi người dùng truy cập vào http://example.com/, hãy chuyển hướng họ đến https://example.com/ bằng cách gửi phản hồi 301 Moved Permanently có tiêu đề Location thích hợp:

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

Bạn có thể dễ dàng thiết lập loại lệnh chuyển hướng này trong các máy chủ như Apache hoặc Nginx. Ví dụ: cấu hình Nginx chuyển hướng từ http://example.com/ sang https://example.com/ có dạng như sau:

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

Cookie giúp chúng tôi có thể mang đến cho người dùng trải nghiệm đăng nhập liền mạch qua giao thức HTTP không có trạng thái. Dữ liệu được lưu trữ trong cookie, bao gồm cả thông tin nhạy cảm như mã phiên, được gửi cùng với mọi yêu cầu, cho phép máy chủ hiểu được người dùng nào đang được phản hồi tại thời điểm này. Sau khi đảm bảo rằng người dùng truy cập vào trang web của chúng tôi qua HTTPS, chúng ta cũng phải đảm bảo rằng dữ liệu nhạy cảm được lưu trữ trong cookie chỉ được chuyển qua kết nối an toàn và không bao giờ được gửi ở dạng thô.

Việc đặt cookie thường liên quan đến một tiêu đề HTTP có dạng như sau:

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

Bạn có thể hướng dẫn trình duyệt hạn chế việc sử dụng cookie để bảo mật các phiên bằng cách theo dõi một từ khoá duy nhất:

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

Cookie được đặt bằng từ khoá secure (an toàn) sẽ không bao giờ được gửi qua HTTP.

Đóng cửa sổ đang mở

Tính năng chuyển hướng minh bạch sang HTTPS có nghĩa là trong phần lớn thời gian người dùng truy cập vào trang web của bạn, họ sẽ sử dụng kết nối an toàn. Tuy nhiên, điều này cũng tạo ra một cơ hội nhỏ để tấn công: kết nối HTTP ban đầu được mở rộng, dễ bị loại bỏ SSL và các cuộc tấn công liên quan. Do kẻ tấn công có toàn quyền truy cập vào yêu cầu HTTP ban đầu, nên kẻ này có thể đóng vai trò là proxy giữa bạn và máy chủ, khiến bạn phải sử dụng kết nối HTTP không an toàn bất kể ý định của máy chủ.

Bạn có thể giảm thiểu rủi ro của loại hình tấn công này bằng cách yêu cầu trình duyệt thực thi Bảo mật truyền tải nghiêm ngặt HTTP (HSTS). Việc gửi tiêu đề HTTP Strict-Transport-Security sẽ hướng dẫn trình duyệt thực hiện việc chuyển hướng HTTP sang HTTPS ở phía máy khách mà không cần chạm vào mạng (điều này cũng rất tốt cho hiệu suất; yêu cầu tốt nhất là yêu cầu bạn không cần thực hiện):

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Các trình duyệt hỗ trợ tiêu đề này (hiện tại là Firefox, Chrome và Opera: caniuse có thông tin chi tiết) sẽ lưu ý rằng trang web cụ thể này đã yêu cầu quyền truy cập chỉ qua HTTPS, nghĩa là bất kể người dùng truy cập vào trang web này bằng cách nào, họ sẽ truy cập qua HTTPS. Ngay cả khi nhập http://example.com/ vào trình duyệt, cô ấy vẫn sẽ truy cập vào HTTPS mà không cần tạo kết nối HTTP. Tốt hơn nữa, nếu trình duyệt phát hiện một chứng chỉ không hợp lệ (có thể đang cố gắng giả mạo danh tính của máy chủ), người dùng sẽ không được phép tiếp tục qua HTTP; tất cả hoặc không có gì, điều này rất tuyệt vời.

Trình duyệt sẽ hết hạn trạng thái HSTS của máy chủ sau max-age giây (khoảng một tháng trong ví dụ này); hãy đặt giá trị này thành một giá trị cao hợp lý.

Bạn cũng có thể đảm bảo rằng tất cả miền con của một nguồn gốc đều được bảo vệ bằng cách thêm lệnh includeSubDomains vào tiêu đề:

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Hãy tiến lên một cách an toàn

HTTPS là cách duy nhất để bạn có thể chắc chắn rằng dữ liệu bạn gửi đến người nhận dự kiến sẽ được giữ nguyên. Bạn nên thiết lập các kết nối bảo mật cho trang web và ứng dụng ngay hôm nay. Đây là một quy trình khá đơn giản và sẽ giúp bảo vệ dữ liệu của khách hàng. Sau khi thiết lập xong kênh đã mã hoá, bạn nên chuyển hướng người dùng một cách minh bạch đến kết nối bảo mật này bất kể họ truy cập vào trang web của bạn bằng cách nào bằng cách gửi phản hồi HTTP 301. Sau đó, hãy đảm bảo rằng tất cả thông tin nhạy cảm về phiên hoạt động của người dùng chỉ sử dụng kết nối bảo mật đó bằng cách thêm từ khoá secure (an toàn) khi đặt cookie. Sau khi bạn thực hiện tất cả những việc đó, hãy đảm bảo rằng người dùng không bao giờ vô tình bị rơi khỏi xe buýt: bảo vệ họ bằng cách đảm bảo trình duyệt của họ làm đúng việc bằng cách gửi tiêu đề Strict-Transport-Security.

Việc thiết lập HTTPS không mất nhiều công sức và mang lại lợi ích to lớn cho trang web cũng như người dùng. Bạn sẽ thấy công sức bỏ ra là xứng đáng.

Tài nguyên

  • StartSSL cung cấp chứng chỉ miễn phí được xác minh theo miền. Bạn không thể đánh bại miễn phí. Tất nhiên, bạn có thể nâng cấp lên các cấp độ xác minh cao hơn với mức giá hợp lý.
  • Kiểm thử máy chủ SSL: Sau khi thiết lập HTTPS cho máy chủ, hãy xác minh rằng bạn đã thiết lập đúng cách bằng cách chạy qua quy trình kiểm thử máy chủ của SSL Labs. Bạn sẽ nhận được một báo cáo chi tiết và rõ ràng cho biết liệu bạn có thực sự đang hoạt động hay không.
  • Bạn nên đọc bài viết gần đây của Ars Technica có tiêu đề "Bảo mật máy chủ web bằng SSL/TLS" để biết thêm một số thông tin chi tiết về cơ sở của việc thiết lập máy chủ.
  • Bạn nên đọc lướt quy cách Bảo mật nghiêm ngặt trong quá trình truyền tải HTTP (RFC6797) để biết tất cả thông tin kỹ thuật về tiêu đề Strict-Transport-Security mà bạn có thể muốn.
  • Sau khi bạn thực sự biết mình đang làm gì, bước tiếp theo có thể là thông báo rằng trang web của bạn chỉ có thể truy cập được thông qua một bộ chứng chỉ cụ thể. IETF đang tiến hành một số công việc cho phép bạn làm điều đó thông qua tiêu đề Public-Key-Pins; vẫn còn ở giai đoạn đầu nhưng rất thú vị và đáng theo dõi.