- Published on
Một số response header giúp trang web của bạn an toàn hơn
- Authors
- Name
- Anh Tuấn
- @datuan
Trong bài viết về Content Security Policy 🔗, nhận thấy bạn đọc vẫn cần một bài viết đầy đủ về các loại header bảo mật giúp đạt điểm cao trên SecurityHeaders 🔗, vì thế mà mình đã xem qua, tổng hợp và sẽ chia sẻ đến các bạn ngay sau đây. Khi mọi người, đặc biệt là các quản trị viên của website quan tâm hơn về vấn đề bảo mật của website và sự riêng tư của người dùng thì đó là niềm vui lớn nhất của mình.
Đáp lại mong muốn đó, dưới đây là bài viết tổng hợp một số response header trả về từ website giúp bảo vệ website của bạn an toàn hơn.
X-Frame-Options
Đã bao giờ bạn gặp vấn đề với một website nào đó, khi họ cố gắng chèn trang của bạn vào website của họ bằng thẻ <iframe>
. Bạn không hề thích điều này, và các trình duyệt cũng vậy. Header X-Frame-Options giúp ngăn chặn website của bạn khỏi bị chèn vào các website khác.
Cách sử dụng rất đơn giản dựa vào giá trị mà bạn có thể đoán được chức năng:
Giá trị | Giải thích |
---|---|
X-Frame-Options: DENY | Không cho phép bất kì trang nào chèn trang bằng thẻ <iframe>, kể cả trang nằm cùng domain. |
X-Frame-Options: SAMEORIGIN | Không cho phép bất kì trang nào chèn trang bằng thẻ <iframe> ngoài trang nằm cùng domain. |
X-Frame-Options: allow-from https://another-domain.com 🔗 | Không cho phép bất kì trang nào chèn trang bằng thẻ <iframe> ngoài trang another |
Từ bây giờ, nếu một website nào đó cố ý chèn website mình vào website của họ bằng thẻ iframe thì sẽ nhận được dòng thông báo:
Refused to display 'https://datuan.dev/iframed.html 🔗' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
Lưu ý, với giá trị allow-from
, bạn chỉ có thể chỉ định duy nhất một và chỉ một tên miền thôi, khác với CSP có thể nhận nhiều tên miền hơn.
X-XSS-Protection
Tấn công XSS trở nên phổ biến hơn bao giờ hết và người dùng nếu không để ý sẽ không thể biết được. Vì vậy, trình duyệt có thêm một lớp bảo vệ khi nhận biết được những pha tấn công XSS và ngăn chặn, đảm bảo an toàn cho người dùng.
Tuy vậy, chức năng này không được bật mặc định trên tất cả các trang mà chúng ta phải tự cấu hình. Ngoài ra, chức năng này hoạt động từ IE 8 trở lên, không hoạt động với Firefox. Dù vậy, theo mình đánh giá đây là tính năng đáng để sử dụng và triển khai.
Các giá trị tham khảo của header X-XSS-Protection:
Giá trị | Giải thích |
---|---|
X-XSS-Protection: 0 | Không bật tính năng bảo vệ tấn công XSS |
X-XSS-Protection: 1 | Bật tính năng bảo vệ tấn công XSS. Trình duyệt tự động lọc bỏ nội dung này và vẫn hiển thị trang. |
X-XSS-Protection: 1; mode=block | Bật tính năng bảo vệ tấn công XSS. Trình duyệt hủy bỏ dựng trang, hiện thông báo lỗi riêng từ trình duyệt. |
X-XSS-Protection: 1; report=<report URL> | Bật tính năng bảo vệ tấn công XSS. Trình duyệt sẽ thông báo vấn đề này đến quản trị trang thông qua địa chỉ <report URL>, tương tự cấu hình theo dõi vi phạm CSP. |
Header X-XSS-Protection được áp dụng ở rất nhiều website lớn và là header nên có trong cấu hình webserver của bạn.
X-XSS-Protection hoạt động ở đời thực.
Strict-Transport-Security
Còn có tên gọi khác là HSTS, đây là một header dành cho những trang đang sử dụng kết nối HTTPS. Header Strict-Transport-Security có nhiệm vụ thông báo đến trình duyệt rằng bạn đang và sẽ sử dụng HTTPS trong một thời gian do bạn quy định, từ đó trình duyệt sẽ bắt buộc các kết nối đến website đều phải thông qua HTTPS bằng cách redirect các kết nối HTTP, chặn truy cập trang nếu chứng chỉ SSL hết hạn hoặc có vấn đề.
Chính vì vậy, hãy vô cùng cẩn thận khi triển khai HSTS vì có thể khiến website bạn không thể truy cập được cho đến khi hết hiệu lực 🔗. Chỉ nên triển khai khi nào HTTPS đã hoạt động ổn định và bạn chắc chắn không quay về kết nối HTTP nữa.
Header HSTS có 3 giá trị chính mà bạn nên tham khảo:
Giá trị | Giải thích |
---|---|
Strict-Transport-Security: max-age=31536000 | Thông báo đến trình duyệt rằng website sẽ đảm bảo sử dụng HTTPS trong 31536000 giây (365 ngày) |
Strict-Transport-Security: max-age=31536000; includeSubDomains | Thông báo đến trình duyệt rằng website sẽ đảm bảo sử dụng HTTPS trong 31536000 giây (365 ngày), áp dụng luôn cho subdomain. |
Strict-Transport-Security: max-age=31536000; preload | Thông báo đến trình duyệt rằng website sẽ đảm bảo sử dụng HTTPS trong 31536000 giây (365 ngày). Ngoài ra, trình duyệt không cần kiểm tra header này cho tới khi hết hiệu lực. |
Mình khuyên các bạn kết hợp cả 3 giá trị này lại để tăng tính bảo mật và tăng tốc độ website. Vì sao có thể tăng tốc độ? Mình sẽ để dành câu trả lời cho bài viết về HSTS preload.
Strict-transport-security: max-age=31536000; includeSubDomains; preload
Fun fact: tên miền đuôi .dev không cần HSTS vì đã được áp dụng ngay từ đầu và không thể thay đổi :D
Content-Security-Policy (CSP)
Đây là một header cực kì quan trọng trong thế giới web hiện nay. Plugin này vừa đảm bảo bảo mật cho website của bạn, vừa đảm bảo trang không bị thay đổi bởi một nhân tố nào khác (mã độc Javascript, extension) mà ta không biết trước.
Mời các bạn đọc bài đầy đủ về Content Security Policy (CSP) 🔗. Đây sẽ là một bài viết tuy dài nhưng rất đáng để đọc.
X-Content-Type-Options
Header X-Content-Type-Options bắt buộc các trình duyệt không "trái lời" của lập trình viên khi xử lý dữ liệu trả về. Nếu không có header này, trình duyệt sẽ cố gắng tự phân tích nội dung và thậm chí dựng trang HTML bằng một đường dẫn là tập tin ảnh thông thường.
Cách tấn công khá đơn giản khi hacker chuẩn bị sẵn một tập tin .JPG
hoặc .PNG
nhưng thực chất nội dụng bên trong là mã HTML. Nếu ứng dụng không được cấu hình tốt, hacker hoàn toàn có thể tải tập tin lên, lưu trong máy chủ của bạn và đường đường chính chính truy cập trực tiếp vào tập tin HTML, hiển thị những gì hacker muốn. Nếu hình ảnh này được chèn vào thẻ <img>
ở trang khác có thể dẫn đến tấn công XSS.
Cách triển khai ngăn chặn rất đơn giản, chúng ta có thể chèn header này vào toàn trang và không cần lo lắng gì nữa:
X-Content-Type-Options: nosniff
Nếu website của bạn cho phép người dùng tải nội dung lên, phải triển khai header này càng sớm càng tốt. Tuy nhiên, tốt nhất hãy triển khai lên mọi website khi có thể để đảm bảo website hiển thị đúng với những gì chúng ta mong muốn.
Feature-policy
Đây là một header khá mới mẻ, chỉ mới được dùng rộng rãi trong năm 2018 trở đi dù nó đã được khai sinh từ năm... 2016. Ý tưởng của header này là yêu cầu trình duyệt không thực thi những chức năng (feature) như camera, microphone, rung,... khi mà người quản trị website không cho phép. Điều này giúp bảo vệ sự riêng tư của người dùng khi truy cập trên các website có gắn quảng cáo, gắn frame từ các nguồn khác mà có thể bị lợi dụng để yêu cầu truy cập vào microphone, webcam,...
Giá trị | Giải thích |
---|---|
accelerometer | Cảm biến gia tốc kế |
ambient-light-sensora | Cảm biến ánh sáng |
autoplay | Tự động phát nhạc, video |
camera | Cảm biến camera, webcam |
fullscreen | Chế độ toàn màn hình |
geolocation | Dịch vụ định vị |
gyroscope | Cảm biến con quay hồi chuyển |
microphone | Cảm biến âm thanh |
Dù xuất hiện đã lâu nhưng Feature Policy vẫn được hỗ trợ rất ít từ các trình duyệt, bạn nên tham khảo qua bảng tương thích của Feature-Policy 🔗 để quyết định có dùng vào Production hay không.
Cách triển khai Feature Policy:
Feature-policy: accelerometer 'none'; camera 'none'; geolocation 'none'; microphone 'none';
Referrer-policy
Đây là một header theo Tuấn đánh giá là khá khó để bắt đầu và quyết định sử dụng. Trước tiên, header này có nhiệm vụ quy định trình duyệt có gửi thông tin Referrer về website khác hay không.
Ví dụ, bạn đang truy cập datuan.dev và mình cấu hình header này với giá trị no-referrer
, khi bạn chuyển sang một trang khác như Google 🔗 từ website của mình thông qua cách nhấp vào liên kết nào đó, Google sẽ không thể xác định được bạn đến Google từ datuan.dev.
Ngược lại, ví dụ mình cấu hình header này với giá trị origin
thì khi chuyển trang, Google sẽ biết bạn đến Google từ datuan.dev, nhưng không biết chính xác bạn đến từ trang nào, ví dụ như bài viết này.
Nếu muốn Google "biết" bạn đến từ bài viết này, chúng ta có thể cấu hình header thành unsafe-url
, Google sẽ biết chính xác chúng ta nhấp vào liên kết Google từ bài viết này.
Website datuan.dev sử dụng strict-origin-when-cross-origin
, sẽ gửi đầy đủ liên kết khi chuyển sang trang cùng tên miền nhưng chỉ gửi mỗi tên miền khi chuyển sang tên miền khác.
Khi nhấp vào một liên kết khác thuộc tên miền datuan.dev, mình vẫn có thể biết được người đọc đến từ bài viết nào hay nói đơn giản hơn là biết người đọc đã truy cập vào trang nào trước đó trước khi chuyển sang trang này.
Đối với Google thì khác, họ chỉ biết người đọc của mình đến từ datuan.dev, không thể biết người đọc chuyển đến từ bài viết nào, trang nào trước đó.
Cách triển khai Content Security Policy
Vì lí do an toàn và bảo mật, mình luôn khuyên các bạn triển khai Content Security Policy ở cấp webserver, có nghĩa là nằm trong cấu hình virtual host và cần phải restart/reload để có thể áp dụng được. Tuy nhiên việc chèn Content Security Policy header vào website WordPress là khá đơn giản và có thể thực hiện được bằng nhiều cách.
Xin lưu ý các plugin hay đoạn code chỉ giúp bạn chèn Content Security Policy header vào website, còn việc nội dung như thế nào, giá trị ra sao phải tự do bạn quyết định. Hiện tại mình chưa thấy có công cụ nào tự động tạo ra giá trị CSP.
Sử dụng plugin
Đầu tiên, cách đơn giản nhất mà không phải động đến code là cài đặt plugin WP Content Security Plugin 🔗. Sau khi cài đặt và kích hoạt plugin xong, bạn có thể chuyển đến Settings > CSP Options để bắt đầu cấu hình CSP.
Vì Content Security Policy thật sự là một tính năng mới, không thể cứ click click rồi hoàn thành cài đặt được nên trông phần cấu hình có vẻ hơi rối. Tuy nhiên nếu bạn đã đọc qua phần đầu bài viết rồi thì sẽ cảm thấy ổn thôi, có thể tự tin chuyển qua tab Content Security Policies để cấu hình cho các directive.
Chèn code trực tiếp
Thường các trang cần thử nhanh một cấu hình cho website nào đó thì mình sẽ dùng cách này, chèn trực tiếp vào tập tin functions.php
của theme đang dùng là được. Tuy xấu và khó nhìn nhưng rất hiệu quả.
function header_csp_generate(){
header("Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' www.googletagmanager.com www.google-analytics.com tagmanager.google.com;
style-src 'self' 'unsafe-inline' tagmanager.google.com;
img-src 'self' data: www.googletagmanager.com www.google-analytics.com www.google.com www.google.com.vn i.ytimg.com https://*.gravatar.com https://images.dmca.com;
frame-src www.googletagmanager.com www.google.com www.youtube.com;
font-src 'self';
connect-src 'self' \*.google.com google.com google.com.vn www.google-analytics.com;
object-src 'none'");
}
add_filter('wp_head', 'header_csp_generate');
Sử dụng webserver để cấu hình
Đây là cách mà mình khuyên dùng để đảm bảo website vẫn được bảo mật nhất có thể kể cả khi có thể truy cập và chỉnh sửa các tập tin mã nguồn của website. Tuy nhiên chúng sẽ gặp khó với việc cấu hình máy chủ dẫn tới CSP header của chúng ta vẫn được bảo vệ một cách tuyệt đối.
Nginx
Chèn vào tập tin /etc/nginx/nginx.conf
, đặt trong block http
, sau đó restart lại Nginx.
http {
# ....
add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' www.googletagmanager.com connect.facebook.net www.googleadservices.com www.google-analytics.com googleads.g.doubleclick.net onesignal.com tpc.googlesyndication.com;";
# ....
}
Apache
Với apache có thể đơn giản hơn, bạn chỉ việc chèn vào tập tin .htaccess
(vẫn khuyên không nên vì hacker có thể can thiệp, nếu không còn cách nào khác, hãy chmod hợp lý trước khi dùng) là được, hoặc chèn vào /etc/httpd/conf/httpd.conf
. Sau đó restart lại Apache.
Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' www.googletagmanager.com connect.facebook.net www.googleadservices.com www.google-analytics.com googleads.g.doubleclick.net onesignal.com tpc.googlesyndication.com;";
Kết luận
Qua bài viết chúng ta thấy không phải response header nào cũng dễ dàng triển khai vào các website. Tuy nhiên chúng ta có thể sắp xếp mức độ ưu tiên để nghiên cứu và triển khai nhanh nhất có thể:
Ưu tiên hàng đầu
Các response header này có thể triển khai ngay, không ảnh hưởng đến trình duyệt, người dùng, bảo vệ website.
- X-Frame-Options
- X-XSS-Protection
- X-Content-Type-Options
- Strict-Transport-Security: có thể triển khai ngay nếu bạn không muốn quay về kết nối HTTP nữa.
Các response header còn lại có thể tham khảo và cần cẩn trọng khi triển khai. Việc triển khai CSP không đúng cách có thể làm hại cho website của bạn.