Thẻ Content-Security-Policy
meta cho phép bạn giảm nguy cơ bị tấn công XSS bằng cách cho phép bạn xác định nơi tài nguyên có thể được tải từ đó, ngăn trình duyệt tải dữ liệu từ bất kỳ vị trí nào khác. Điều này khiến kẻ tấn công tiêm mã độc vào trang web của bạn khó hơn.
Tôi đập đầu vào một bức tường gạch cố gắng tìm ra lý do tại sao tôi lại gặp lỗi CSP lần này và dường như không có bất kỳ hướng dẫn rõ ràng, ngắn gọn nào về cách thức hoạt động của nó. Vì vậy, đây là nỗ lực của tôi trong việc giải thích ngắn gọn một số điểm về CSP, chủ yếu tập trung vào những điều tôi thấy khó giải quyết.
Để đơn giản, tôi sẽ không viết thẻ đầy đủ trong mỗi mẫu. Thay vào đó, tôi sẽ chỉ hiển thị thuộc content
tính, vì vậy một mẫu content="default-src 'self'"
có nghĩa là:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
1. Làm thế nào để cho phép nhiều nguồn?
Bạn chỉ có thể liệt kê các nguồn của mình sau một lệnh dưới dạng danh sách được phân tách bằng dấu cách:
content="default-src 'self' https://example.com/js/"
Lưu ý rằng không có dấu ngoặc kép xung quanh các tham số khác ngoài các tham số đặc biệt , như 'self'
. Ngoài ra, không có dấu hai chấm ( :
) sau chỉ thị. Chỉ cần lệnh, sau đó một danh sách các tham số được phân tách bằng dấu cách.
Tất cả mọi thứ bên dưới các tham số đã chỉ định đều được cho phép. Điều đó có nghĩa là trong ví dụ trên đây sẽ là các nguồn hợp lệ:
https://example.com/js/file.js
https://example.com/js/subdir/anotherfile.js
Những điều này, tuy nhiên, sẽ không hợp lệ:
http://example.com/js/file.js
^^^^ wrong protocol
https://example.com/file.js
^^ above the specified path
2. Làm thế nào để sử dụng các chỉ thị khác nhau, mỗi người làm gì?
Các chỉ thị phổ biến nhất là:
default-src
chính sách mặc định để tải javascript, hình ảnh, CSS, phông chữ, yêu cầu AJAX, v.v.
script-src
xác định nguồn hợp lệ cho các tệp javascript
style-src
xác định nguồn hợp lệ cho các tệp css
img-src
xác định nguồn hợp lệ cho hình ảnh
connect-src
định nghĩa các mục tiêu hợp lệ cho XMLHttpRequest (AJAX), WebSockets hoặc EventSource. Nếu một nỗ lực kết nối được thực hiện với một máy chủ không được phép ở đây, trình duyệt sẽ giả lập 400
lỗi
Có những cái khác, nhưng đây là những thứ bạn cần nhất.
3. Làm thế nào để sử dụng nhiều chỉ thị?
Bạn xác định tất cả các chỉ thị của mình bên trong một thẻ meta bằng cách chấm dứt chúng bằng dấu chấm phẩy ( ;
):
content="default-src 'self' https://example.com/js/; style-src 'self'"
4. Làm thế nào để xử lý các cổng?
Mọi thứ trừ các cổng mặc định cần phải được cho phép rõ ràng bằng cách thêm số cổng hoặc dấu hoa thị sau tên miền được phép:
content="default-src 'self' https://ajax.googleapis.com http://example.com:123/free/stuff/"
Những điều trên sẽ dẫn đến:
https://ajax.googleapis.com:123
^^^^ Not ok, wrong port
https://ajax.googleapis.com - OK
http://example.com/free/stuff/file.js
^^ Not ok, only the port 123 is allowed
http://example.com:123/free/stuff/file.js - OK
Như tôi đã đề cập, bạn cũng có thể sử dụng dấu hoa thị để cho phép rõ ràng tất cả các cổng:
content="default-src example.com:*"
5. Làm thế nào để xử lý các giao thức khác nhau?
Theo mặc định, chỉ cho phép các giao thức tiêu chuẩn. Ví dụ: để cho phép WebSockets, ws://
bạn sẽ phải cho phép nó rõ ràng:
content="default-src 'self'; connect-src ws:; style-src 'self'"
^^^ web sockets are now allowed on all domains and ports
6. Làm thế nào để cho phép giao thức tập tin file://
?
Nếu bạn cố gắng định nghĩa nó như vậy thì nó sẽ không hoạt động. Thay vào đó, bạn sẽ cho phép nó với filesystem
tham số:
content="default-src filesystem"
7. Làm thế nào để sử dụng tập lệnh nội tuyến và định nghĩa kiểu?
Trừ khi được cho phép rõ ràng, bạn không thể sử dụng định nghĩa kiểu nội tuyến, mã bên trong <script>
thẻ hoặc trong thuộc tính thẻ như onclick
. Bạn cho phép họ như vậy:
content="script-src 'unsafe-inline'; style-src 'unsafe-inline'"
Bạn cũng sẽ phải cho phép rõ ràng cho phép hình ảnh được mã hóa nội tuyến, base64:
content="img-src data:"
8. Làm thế nào để cho phép eval()
?
Tôi chắc chắn nhiều người sẽ nói rằng bạn không, vì 'eval là ác quỷ' và là nguyên nhân rất có thể cho sự kết thúc sắp xảy ra của thế giới. Những người đó sẽ sai. Chắc chắn, bạn chắc chắn có thể đục lỗ lớn vào bảo mật trang web của mình bằng eval, nhưng nó có các trường hợp sử dụng hoàn toàn hợp lệ. Bạn chỉ cần thông minh về việc sử dụng nó. Bạn cho phép nó như vậy:
content="script-src 'unsafe-eval'"
9. Chính xác 'self'
nghĩa là gì?
Bạn có thể 'self'
hiểu là localhost, hệ thống tập tin cục bộ hoặc bất cứ thứ gì trên cùng một máy chủ. Nó không có nghĩa là bất kỳ trong số đó. Nó có nghĩa là các nguồn có cùng sơ đồ (giao thức), cùng một máy chủ và cùng một cổng với tệp mà chính sách nội dung được xác định. Phục vụ trang web của bạn qua HTTP? Không có https cho bạn sau đó, trừ khi bạn xác định rõ ràng.
Tôi đã sử dụng 'self'
trong hầu hết các ví dụ vì thường bao gồm nó có ý nghĩa, nhưng không có nghĩa là bắt buộc. Bỏ nó ra nếu bạn không cần nó.
Nhưng chờ một chút! Tôi không thể sử dụng content="default-src *"
và được thực hiện với nó?
Không. Ngoài các lỗ hổng bảo mật rõ ràng, điều này cũng sẽ không hoạt động như bạn mong đợi. Mặc dù một số tài liệu cho rằng nó cho phép mọi thứ, nhưng điều đó không đúng. Nó không cho phép nội tuyến hoặc evals, vì vậy để thực sự, thực sự làm cho trang web của bạn dễ bị tổn thương hơn, bạn sẽ sử dụng điều này:
content="default-src * 'unsafe-inline' 'unsafe-eval'"
... nhưng tôi tin bạn sẽ không.
Đọc thêm:
http://content-security-policy.com
http://en.wikipedia.org/wiki/Content_Security_Policy