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ì chúng có thể chặn các tập lệnh không an toàn do kẻ tấn công đưa vào. Tuy nhiên, CSP có thể dễ dàng bị bỏ qua nếu CSP không đủ nghiêm ngặt. Hãy tham khảo bài viết 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 các vấn đề qua Công cụ đánh giá CSP nếu có thể bỏ qua.

Các phương pháp bắt buộc đối với CSP không thể bỏ qua
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 CSP có thể bị bỏ qua, Lighthouse sẽ phát ra cảnh báo có mức độ nghiêm trọng cao.
CSP nhắm đến XSS
Để nhắm đến 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 cả script-src
và object-src
.
base-uri
ngăn chặn hành vi chèn thẻ <base>
trái phép có thể dùng để chuyển hướng tất cả URL tương đối (như tập lệnh) đến miền do kẻ tấn công kiểm soát.
CSP dùng nonces hoặc hashes để tránh bỏ qua danh sách cho phép
Một 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ả cá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 lành tính phổ biến như để lộ 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 phạm vi giới hạn của CSP.
Trên 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 trên 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 hành vi chèn tập lệnh. Ngược lại, phương pháp tiếp cận dựa trên số lượng một lần và phương pháp 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 người dùng dễ dàng áp dụng và duy trì một chính sách an toàn hơn.
Ví dụ: mã này sử dụng một đ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:
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 phải cho phép các tập lệnh riêng lẻ dùng nonces hoặc hashes, đồng thời dùng "strict-dynamic" thay vì danh sách cho phép.
Các đề xuất khác cho một CSP bảo mật
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ẽ đưa ra cảnh báo có mức độ nghiêm trọng trung bình.
Thiết lập báo cáo CSP
Định cấu hình đích báo cáo sẽ giúp giám sát mọi sự cố. Bạn có thể thiết lập đích đến báo cáo bằng cách 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ỉ dùng report-uri
.
Nếu có nội dung vi phạm CSP, trình duyệt sẽ gửi một báo cáo đến đích đến đã định cấu hình. Hãy đảm bảo rằng bạn đã định cấu hình ứng dụng tại đích này để xử lý các báo cáo này.
Xác định CSP trong tiêu đề HTTP
CSP có thể được xác định 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 một CSP trong tiêu đề phản hồi HTTP nếu có thể. Việc chèn nội dung trước thẻ meta sẽ bỏ qua CSP. Ngoài ra, frame-ancestors
, sandbox
và tính năng báo cáo cũng 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 cho CSP. Do đó, bạn nên thêm unsafe-inline
làm phương án dự phòng cho những trình duyệt không tuân thủ. Nếu trình duyệt không hỗ trợ số chỉ dùng một lần/hàm băm, unsafe-inline
sẽ bị bỏ qua.
Tương tự, strict-dynamic
không được tất cả trình duyệt hỗ trợ. 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.
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 số chỉ dùng một lần và strict-dynamic
. Để biết thêm thông tin về cách áp 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 một CSP để tìm những trường hợp có thể bỏ qua bằng Lighthouse và Trình đá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 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 CSP đến mọi đích báo cáo mà bạn đã thiết lập bằng report-to
và report-uri
, nhưng trên thực tế thì CSP sẽ không thực thi CSP.