Chính sách bảo mật nội dung (CSP) giúp đảm bảo mọi nội dung tải trên trang đều được chủ sở hữu trang web tin cậy. CSP giảm thiểu các cuộc tấn công tập lệnh trên nhiều trang web (XSS) vì các CSP này có thể chặn các tập lệnh không an toàn do những kẻ tấn công chèn vào. Tuy nhiên, CSP này có thể dễ dàng bị bỏ qua nếu không đủ nghiêm ngặt. Hãy xem nội dung Giảm thiểu tập lệnh trên nhiều trang web (XSS) bằng Chính sách bảo mật nội dung (CSP) nghiêm ngặt để biết thêm thông tin. Lighthouse thu thập các CSP được thực thi trên tài liệu chính và báo cáo vấn đề từ Trình đánh giá CSP nếu có thể bỏ qua các nội dung này.
Các phương pháp bắt buộc dành cho CSP không thể bỏ qua
Hãy triển khai các phương pháp sau để đảm bảo rằng CSP của bạn không thể bỏ qua. Nếu có thể bỏ qua CSP, Lighthouse sẽ phát ra cảnh báo có mức độ nghiêm trọng cao.
CSP nhắm mục tiêu XSS
Để nhắm mục tiêu XSS, CSP phải bao gồm lệnh script-src
, object-src
và base-uri
. CSP cũng không được có lỗi cú pháp.
script-src
và object-src
lần lượt bảo mật một trang khỏi các tập lệnh không an toàn và trình bổ trợ không an toàn. Ngoài ra, bạn có thể sử dụng default-src
để định cấu hình một chính sách rộng thay cho nhiều lệnh, bao gồm script-src
và object-src
.
base-uri
ngăn chặn hành vi chèn các thẻ <base>
trái phép có thể dùng để chuyển hướng tất cả URL tương đối (chẳng hạn như tập lệnh) đến miền do kẻ tấn công kiểm soát.
CSP sử dụng nonces hoặc hashes để tránh việc bỏ qua danh sách cho phép
CSP định cấu hình danh sách cho phép cho script-src
dựa trên giả định rằng tất cả phản hồi đến từ một miền đáng tin cậy đều an toàn và có thể được thực thi dưới dạng tập lệnh. Tuy nhiên, giả định này không áp dụng cho các ứng dụng hiện đại. Một số mẫu hình vô hại phổ biến như hiển thị giao diện JSONP và lưu trữ bản sao của thư viện AngularJS cho phép kẻ tấn công thoát khỏi giới hạn của CSP.
Trong thực tế, mặc dù tác giả ứng dụng có thể không rõ ràng, nhưng phần lớn danh sách cho phép của script-src
có thể bị kẻ tấn công tránh né bằng lỗi XSS và cung cấp ít biện pháp bảo vệ khỏi việc chèn tập lệnh. Ngược lại, các phương pháp dựa trên số chỉ dùng một lần và dựa trên hàm băm không gặp phải những vấn đề này, đồng thời giúp bạn dễ dàng áp dụng cũng như duy trì chính sách an toàn hơn.
Ví dụ: mã này sử dụng điểm cuối JSONP được lưu trữ trên một miền đáng tin cậy để chèn tập lệnh do kẻ tấn công kiểm soát:
Chính sách bảo mật nội dung (CSP):
script-src https://trusted.example.com
HTML:
<script src="https://trusted.example.com/path/jsonp?callback=alert(document.domain)//"></script>
Để tránh bị bỏ qua, CSP nên cho phép từng tập lệnh sử dụng nonces hoặc hashes, đồng thời dùng thuộc tính "strict-dynamic" thay vì danh sách cho phép.
Những đề xuất khác để đảm bảo CSP bảo mật
Hãy triển khai các phương pháp sau để tăng cường tính bảo mật và khả năng tương thích. Nếu CSP không tuân theo một trong các đề xuất, Lighthouse sẽ phát ra cảnh báo có mức độ nghiêm trọng trung bình.
Định cấu hình tính năng báo cáo CSP
Định cấu hình đích báo cáo sẽ giúp theo dõi mọi sự cố. Bạn có thể thiết lập đích báo cáo bằng cách sử dụng lệnh report-uri
hoặc report-to
. report-to
hiện không được một số trình duyệt hiện đại hỗ trợ. Vì vậy, bạn nên sử dụng cả hai hoặc chỉ report-uri
.
Nếu có nội dung vi phạm CSP, trình duyệt sẽ gửi báo cáo đến đích đến đã thiết lập. Hãy đảm bảo rằng bạn đã định cấu hình một ứng dụng tại đích đến này để xử lý các báo cáo này.
Xác định CSP trong tiêu đề HTTP
Bạn có thể xác định CSP trong thẻ meta như sau:
<meta http-equiv="Content-Security-Policy" content="script-src 'none'">
Tuy nhiên, bạn nên xác định CSP trong tiêu đề phản hồi HTTP nếu có thể. Việc chèn trước thẻ meta sẽ bỏ qua CSP. Ngoài ra, frame-ancestors
, sandbox
và báo cáo không được hỗ trợ trong CSP thẻ meta.
Đảm bảo CSP có khả năng tương thích ngược
Không phải trình duyệt nào cũng hỗ trợ nonces/hashes của CSP. Do đó, bạn nên thêm unsafe-inline
làm phương án dự phòng cho các trình duyệt không tuân thủ. Nếu trình duyệt không hỗ trợ nonces/hashes, thì unsafe-inline
sẽ bị bỏ qua.
Tương tự, một số trình duyệt không hỗ trợ strict-dynamic
. Bạn nên đặt danh sách cho phép làm phương án dự phòng cho mọi trình duyệt không tuân thủ. Danh sách cho phép sẽ bị bỏ qua trong các trình duyệt hỗ trợ strict-dynamic
.
Cách xây dựng một CSP nghiêm ngặt
Dưới đây là ví dụ về cách sử dụng một CSP nghiêm ngặt với chính sách dựa trên số chỉ dùng một lần.
Chính sách bảo mật nội dung (CSP):
script-src 'nonce-random123' 'strict-dynamic' 'unsafe-inline' https:;
object-src 'none';
base-uri 'none';
report-uri https://reporting.example.com;
HTML:
<script nonce="random123" src="https://trusted.example.com/trusted_script.js"></script>
random123
sẽ là bất kỳ chuỗi base64 nào được tạo ở phía máy chủ mỗi khi tải trang. unsafe-inline
và https:
bị bỏ qua trong các trình duyệt hiện đại do các số chỉ dùng một lần và strict-dynamic
. Để biết thêm thông tin về cách sử dụng một CSP nghiêm ngặt, hãy xem Hướng dẫn về CSP nghiêm ngặt.
Bạn có thể kiểm tra CSP về khả năng bỏ qua bằng Lighthouse và Công cụ đánh giá CSP. Nếu bạn muốn thử nghiệm một CSP mới mà không có nguy cơ làm hỏng các trang hiện có, hãy xác định CSP đó ở chế độ chỉ báo cáo bằng cách sử dụng Content-Security-Policy-Report-Only
làm tên tiêu đề. Thao tác này sẽ gửi các lỗi vi phạm Chính sách bảo mật nội dung (CSP) tới mọi đích báo cáo mà bạn đã thiết lập với report-to
và report-uri
, nhưng thực tế sẽ không thực thi Chính sách bảo mật nội dung (CSP) đó.