Ngăn chặn kẻ trung gian độc hại bằng HTTPS và cơ chế bảo mật truyền tải nghiêm ngặt HTTP

Do lượng dữ liệu cá nhân lưu chuyển qua mạng Internet là rất lớn, nên chúng ta không thể hoặc không nên xem nhẹ việc mã hoá. 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ật và Bảo mật truyền tải nghiêm ngặt là hai trong số những cơ chế quan trọng nhất. Các chính sách 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ưới dạng văn bản 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á ít nhiều cũng giống như việc đưa một phong bì chưa dán kín cho người đầu tiên bạn nhìn thấy trên đường, người có vẻ như đang đi về hướng bưu điện. Nếu bạn may mắn, cô ấy có thể tự mình mang bức thư đến tận nơi, hoặc có thể đưa bức thư cho người tiếp theo mà cô ấy thấy đang đi đúng hướng. Người đó có thể làm điều tương tự, và cứ thế.

Hầu hết những người lạ trong chuỗi ngẫu hứng này đều đáng tin cậy và sẽ không bao giờ xem trộm bức thư ngỏ của bạn hoặc thay đổi nội dung trong đó. Tuy nhiên, thư càng qua tay nhiều người 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 thứ gì đó trong thư, nhưng liệu thứ đó có giống với thứ mà bạn đã gửi ngay từ đầu hay không vẫn là một câu hỏi chưa có lời đáp. Có lẽ bạn nên dán kín phong bì đó…

Người trung gian

Dù tốt hay xấu, phần lớn Internet đều dựa vào mức độ tin cậy của người lạ. Các máy chủ không được kết nối trực tiếp với nhau, nhưng 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 hoạt động bằng lệnh traceroute. Tuyến đường từ máy tính của tôi đến HTML5Rocks 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 tệ, thực sự. Tuy nhiên, nếu tôi gửi yêu cầu qua HTTP, thì mỗi bộ định tuyến trung gian đó đều có toàn quyền truy cập vào yêu cầu của tôi và phản hồi của máy chủ. Tất cả dữ liệu đều được chuyển dưới dạng văn bản thuần tuý không mã hoá, và bất kỳ bên trung gian nào cũng có thể đóng vai trò là Kẻ tấn công xen giữa, đọc qua dữ liệu của tôi hoặc thậm chí là thao túng dữ liệu đó trong quá trình truyền.

Tệ hơn nữa, loại hình can thiệp 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 ai đó quyết định phá hoại Internet của tôi để mua vui, thì tôi gần như không thể làm gì được.

Đường dây này có an toàn không?

Chuyển từ HTTP văn bản thuần tuý sang kết nối HTTPS bảo mật là cách tốt nhất để bạn phòng vệ trước kẻ trung gian. Kết nối HTTPS mã hoá toàn bộ kênh từ đầu đến cuối trước khi gửi bất kỳ dữ liệu nào, 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 đang 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.
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.

Tính bảo mật mà HTTPS cung cấp bắt nguồn từ khái niệm khoá mã hoá công khai và riêng tư. Một cuộc thảo luận sâu về các chi tiết (vui vẻ) 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 trình duyệt bắt đầu quá trình 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ỉ chứa tất cả thông tin cần thiết để trình duyệt xác minh danh tính của máy chủ bằng cách kiểm tra xem máy chủ có sở hữu khoá riêng tư thích hợp hay không. Tất cả thông tin liên lạc từ thời điểm đó trở đi đều đượ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 nhận được từ máy chủ đã xác thực.

Do đó, HTTPS đảm bảo rằng bạn đang giao tiếp với máy chủ mà bạn nghĩ là bạn đang giao tiếp, và không có ai khác đang nghe lén hoặc can thiệp vào dữ liệu trên đường truyền. Loại mã hoá này là điều kiện tiên quyết tuyệt đối để đảm bảo an toàn 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à tôi khuyên bạn nên xem để biết thông tin chi tiết về kỹ thuật. Cấu hình sẽ khác nhau tuỳ theo nhà cung cấp và máy chủ, nhưng quy trình yêu cầu chứng chỉ là như 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 người dùng của bạn được hưởng lợi từ nỗ lự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 an toàn.

Mời đi lối 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 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 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 mà máy chủ đang phản hồi tại thời điểm đó. Sau khi đảm bảo rằng người dùng truy cập vào trang web của chúng ta qua HTTPS, chúng ta cũng nên đảm bảo rằng dữ liệu nhạy cảm được lưu trữ trong cookie chỉ được chuyển qua một kết nối an toàn và không bao giờ được gửi dưới dạng văn bản 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 phiên bằng cách thêm 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 sẽ không bao giờ được gửi qua HTTP.

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

Việc chuyển hướng minh bạch đến HTTPS có nghĩa là 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, việc này vẫn để lại một lỗ hổng nhỏ cho các cuộc tấn công: kết nối HTTP ban đầu hoàn toàn không được bảo vệ, dễ bị tấn công tước bỏ SSL và các cuộc tấn công liên quan. Do kẻ tấn công xen giữa có toàn quyền truy cập vào yêu cầu HTTP ban đầu, nên kẻ đó có thể đóng vai trò là proxy giữa bạn và máy chủ, giữ bạn ở 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 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 lệnh chuyển hướng từ 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ẽ ghi chú 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 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 kết nối HTTP. Tốt hơn nữa, nếu trình duyệt phát hiện thấy chứng chỉ không hợp lệ (có khả năng đang cố gắng giả mạo danh tính của máy chủ), thì người dùng sẽ không được phép tiếp tục thông qua HTTP; tất cả hoặc không có gì, điều này thậ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 ở mức 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

Tiếp tục, một cách an toàn

HTTPS là cách duy nhất để đảm bảo rằng dữ liệu bạn gửi đến người nhận dự kiến còn nguyên vẹn. Bạn nên thiết lập kết nối bảo mật cho các trang web và ứng dụng của mình 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 kênh mã hoá, bạn nên chuyển hướng người dùng đến kết nối an toàn này một cách minh bạch, 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 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 khi đặt cookie. Sau khi hoàn tất, hãy đảm bảo rằng người dùng không bao giờ vô tình bị rớt khỏi xe buýt: bảo vệ họ bằng cách đảm bảo rằng trình duyệt của họ thực hiện đúng việc bằng cách gửi tiêu đề Strict-Transport-Security.

Việc thiết lập HTTPS không tốn nhiều công sức nhưng mang lại lợi ích rất lớn cho trang web và người dùng của bạn. Việc này rất đáng để bạn bỏ công sức.

Tài nguyên

  • StartSSL cung cấp chứng chỉ miễn phí cho miền đã xác minh. Không gì bằng 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ý.
  • SSL Server Test (Kiểm tra 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 kiểm tra máy chủ của SSL Labs. Bạn sẽ nhận được một báo cáo chi tiết cho biết liệu bạn có thực sự đang hoạt động hay không.
  • Bài viết gần đây của Ars Technica "Bảo mật máy chủ web của bạn bằng SSL/TLS" là một bài viết đáng đọc để biết thêm một số thông tin cơ bản về các bước thiết lập máy chủ.
  • Bạn nên đọc lướt qua quy cách Bảo mật truyền tải nghiêm ngặt 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 biết.
  • Khi bạn thực sự biết mình đang làm gì, bước tiếp theo có thể là quảng cáo rằng trang web của bạn chỉ có thể truy cập được thông qua một nhóm 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 sớm nhưng thú vị và đáng theo dõi.