Đảm bảo CSP có khả năng chống lại các cuộc tấn công XSS

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.

Báo cáo Lighthouse cảnh báo rằng không tìm thấy CSP nào ở chế độ thực thi.
Báo cáo của Lighthouse cảnh báo về việc không tìm thấy CSP nào ở chế độ thực thi.

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-srcbase-uri. CSP cũng không được có lỗi cú pháp.

script-srcobject-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-srcobject-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 JSONPlư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-inlinehttps: 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-toreport-uri, nhưng thực tế sẽ không thực thi Chính sách bảo mật nội dung (CSP) đó.