Content Security Policy và CMP của bạn: Cho CSP và sự đồng ý cùng hoạt động
Hai lớp bảo mật phải thống nhất với nhau
Content Security Policy (CSP) cho trình duyệt biết trang được phép tải tập lệnh, kiểu dáng, hình ảnh, khung và các yêu cầu mạng từ những nguồn nào. Một nền tảng quản lý sự đồng ý làm công việc ngược lại: quyết định những tập lệnh nào trong số đó được phép chạy dựa trên lựa chọn của người dùng. Khi hai thứ được cấu hình riêng rẽ, chúng va chạm nhau. CMP không tải được vì CSP chặn nó, hoặc CSP bị nới lỏng quá mức để chiều theo CMP và thẻ quảng cáo đến mức không còn bảo vệ được gì.
Hướng dẫn này giải thích CMP thường cần những chỉ thị CSP nào, nonce tương tác với việc chèn tập lệnh ra sao, và cách triển khai thay đổi mà không làm hỏng banner.
CMP thường cần gì từ CSP
Yêu cầu chính xác phụ thuộc vào nhà cung cấp, vì vậy hãy luôn bắt đầu từ tài liệu của chính CMP của bạn. Nói chung, hãy kiểm tra các chỉ thị sau:
script-src— tên miền mà tập lệnh CMP được tải từ đó, cùng mọi tệp tập lệnh bổ sung mà nó tải.connect-src— các điểm cuối mà CMP gọi bằngfetchhoặc XHR, chẳng hạn điểm cuối cấu hình, danh sách nhà cung cấp, định vị địa lý và ghi nhật ký sự đồng ý.style-src— tên miền của bảng định kiểu, và có thể cả kiểu nội tuyến nếu CMP chèn phần tử<style>hoặc đặt thuộc tính style.img-src— logo, biểu tượng và mọi pixel không theo dõi mà CMP sử dụng.font-src— nếu banner tải phông chữ riêng.frame-src— nếu CMP dùng iframe, chẳng hạn để chia sẻ sự đồng ý giữa các tên miền.
Trên các trang dùng TCF, hãy nhớ rằng CMP cũng tạo một khung định vị tên là __tcfapiLocator trên trang. Khung này được tạo ra mà không có nguồn từ xa, nên thường không cần mục frame-src, nhưng đáng để xác nhận trong lúc kiểm thử.
Vấn đề stub nội tuyến
Hầu hết CMP yêu cầu bạn đặt một tập lệnh nội tuyến nhỏ — stub — vào phần head của trang, để các tập lệnh khác có thể xếp hàng các lệnh gọi trước khi CMP chính được tải. Một CSP nghiêm ngặt sẽ chặn tập lệnh nội tuyến trừ khi bạn cho phép rõ ràng. Bạn có ba lựa chọn:
- Nonce. Tạo một giá trị ngẫu nhiên cho mỗi phản hồi, thêm nó vào tiêu đề CSP dưới dạng
'nonce-...'và vào thẻ<script>của stub. Đây là lựa chọn linh hoạt nhất cho các trang động. - Băm (hash). Thêm giá trị băm SHA-256 của nội dung chính xác của stub vào
script-src. Cách này hiệu quả với trang tĩnh, nhưng bất kỳ thay đổi nào với stub, dù chỉ là khoảng trắng, cũng làm nó hỏng. - Tự lưu trữ stub dưới dạng tệp bên ngoài trên tên miền của bạn, được
'self'bao phủ. Cách này cần cẩn thận để đảm bảo nó vẫn tải đủ sớm.
Tránh dùng 'unsafe-inline' như một đường tắt. Nó cho phép mọi tập lệnh nội tuyến, làm mất đi phần lớn sự bảo vệ mà CSP mang lại.
Nonce và các tập lệnh do CMP chèn vào
Một CMP chặn tập lệnh cho đến khi có sự đồng ý thường hoạt động bằng cách giữ chúng lại và chèn vào sau. Với CSP dựa trên nonce, các tập lệnh được chèn đó cũng cần được cho phép. Có hai cách tiếp cận phổ biến:
- Truyền nonce. CMP đọc nonce từ thẻ tập lệnh của chính nó và thêm vào từng tập lệnh nó chèn. Hãy kiểm tra xem CMP của bạn có hỗ trợ không.
'strict-dynamic'. Từ khóa này bảo các trình duyệt hỗ trợ tin cậy các tập lệnh được tải bởi một tập lệnh đã được tin cậy. Nó làm mọi việc dễ hơn với trình quản lý thẻ và các CMP chèn tập lệnh, nhưng cũng có nghĩa là bất kỳ tập lệnh nào bạn tin cậy đều có thể tải các tập lệnh khác, vì vậy hãy tin cậy một cách thận trọng.
Trình quản lý thẻ đặt ra cùng câu hỏi đó. Nếu bạn tải thẻ quảng cáo và phân tích qua trình quản lý thẻ, hãy làm theo tài liệu của nó về nonce và đảm bảo CMP cùng trình quản lý thẻ dùng một cách tiếp cận nhất quán.
Thẻ quảng cáo khiến CSP khó hơn
Quảng cáo lập trình tải tập lệnh và khung từ nhiều tên miền, và danh sách đó thay đổi khi các đối tác nhu cầu thay đổi. Nhà xuất bản thường chọn một trong hai hướng:
- CSP nghiêm ngặt trên các trang không có quảng cáo lập trình, và chính sách rộng hơn ở nơi quảng cáo chạy.
- Một chính sách tập trung vào các chỉ thị vẫn quản lý được, chẳng hạn
frame-ancestors,object-src 'none'vàbase-uri, trong khi nguồn tập lệnh được để rộng hơn.
Dù theo cách nào, CMP cũng nên nằm trong danh sách cho phép tường minh, chứ không chỉ được bao phủ bởi ký tự đại diện, để một thay đổi CSP không bao giờ âm thầm vô hiệu hóa banner.
Triển khai bằng chế độ Report-Only
Hãy dùng tiêu đề Content-Security-Policy-Report-Only trước. Trình duyệt báo cáo các vi phạm mà không chặn bất cứ thứ gì, nhờ đó bạn thấy được chính sách mới sẽ làm hỏng điều gì.
- Triển khai chính sách ở chế độ report-only cùng một điểm cuối báo cáo.
- Tải các trang trong hồ sơ trình duyệt sạch và đi qua toàn bộ luồng đồng ý: lần truy cập đầu tiên, chấp nhận tất cả, từ chối tất cả, lựa chọn tùy chỉnh, rút lại sự đồng ý.
- Xem lại các báo cáo vi phạm và bảng điều khiển trình duyệt để tìm các tài nguyên CMP bị chặn.
- Điều chỉnh chính sách, rồi chuyển sang chế độ thực thi.
- Giữ báo cáo luôn bật sau khi thực thi để phát hiện hồi quy.
Triệu chứng của xung đột CSP
- Banner không bao giờ xuất hiện, và bảng điều khiển hiển thị vi phạm CSP đối với tập lệnh CMP.
- Banner xuất hiện nhưng không có kiểu dáng, vì
style-srcchặn CSS của nó. - Các lựa chọn không được lưu, vì
connect-srcchặn lệnh gọi ghi nhật ký sự đồng ý. - Quảng cáo hoặc phân tích không bao giờ tải sau khi đồng ý, vì các tập lệnh được chèn thiếu nonce.
__tcfapichưa được định nghĩa, vì stub nội tuyến đã bị chặn.
Những điểm chính
- Kiểm tra
script-src,connect-src,style-src,img-srcvàframe-srccho CMP của bạn. - Cho phép stub nội tuyến bằng nonce hoặc hash, không dùng
'unsafe-inline'. - Đảm bảo các tập lệnh được chèn sau khi đồng ý nhận được nonce hoặc được
'strict-dynamic'bao phủ. - Kiểm thử mọi lộ trình đồng ý ở chế độ report-only trước khi thực thi.
- Giữ CMP trong danh sách cho phép tường minh để các thay đổi CSP không thể vô hiệu hóa nó.