Đả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ì 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ảnh báo của báo cáo Lighthouse cho biết không tìm thấy CSP nào ở chế độ thực thi.
Cảnh báo báo cáo của Lighthouse cho biết rằng không tìm thấy CSP nào ở chế độ thực thi.

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-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 cả script-srcobject-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 JSONPlư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-inlinehttps: 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-toreport-uri, nhưng trên thực tế thì CSP sẽ không thực thi CSP.