Chính sách bảo mật nội dung hoạt động như thế nào?


248

Tôi đang gặp một loạt lỗi trong bảng điều khiển dành cho nhà phát triển:

Từ chối đánh giá một chuỗi

Từ chối thực thi tập lệnh nội tuyến vì nó vi phạm chỉ thị Chính sách bảo mật nội dung sau đây

Từ chối tải tập lệnh

Từ chối tải biểu định kiểu

Chuyện này là sao? Chính sách bảo mật nội dung hoạt động như thế nào? Làm cách nào để sử dụng Content-Security-Policytiêu đề HTTP?

Cụ thể, làm thế nào để ...

  1. ... Cho phép nhiều nguồn?
  2. ... sử dụng các chỉ thị khác nhau?
  3. ... sử dụng nhiều chỉ thị?
  4. ... xử lý cổng?
  5. ... xử lý các giao thức khác nhau?
  6. ... Cho phép file://giao thức?
  7. ... sử dụng kiểu nội tuyến, tập lệnh và thẻ <style><script>?
  8. ... cho phép eval()?

Và cuối cùng:

  1. Chính xác thì 'self'có nghĩa là gì?

Câu trả lời:


557

Thẻ Content-Security-Policymeta 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 contenttí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 400lỗ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 filesystemtham 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


6
Bài đăng tuyệt vời. Một điều: không rõ ràng những gì xảy ra khi nhiều chỉ thị được chỉ định; các cài đặt style-src trong ví dụ 3 có được ưu tiên hơn default-src không? v.v ...
track0

29
Vì vậy, để cho phép mọi thứ mọi thứ mọi thứ nội dung sẽ códefault-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;
Arnold Roa

8
Điều quan trọng cần biết content="default-src * 'unsafe-inline' 'unsafe-eval'"là cần thiết để làm cho một số ứng dụng Angular hoạt động.
flanger001

2
@Mahesh "Blog" đó có đầy đủ các bài đăng được sao chép từ SO. Có vẻ như rất nhiều người dùng SO sẽ sao chép nội dung từ một blogger không xác định - tôi biết tôi đã không làm thế.
Schlaus

2
Lưu ý ngắn về connect-srcđường dẫn và đường dẫn: dấu gạch chéo là bắt buộc nếu bạn muốn bao gồm toàn bộ đường dẫn phụ. Ví dụ: tệp http://foo.com/files/bar.txtsẽ bị chặn nếu nguồn là http://foo.com/files, nhưng được phục vụ khi nóhttp://foo.com/files/
Griddo

15

APACHE2 MOD_HEADERS

Bạn cũng có thể kích hoạt mod_headers của Apache2, trên Fedora, nó đã được bật theo mặc định, nếu bạn sử dụng Ubuntu / Debian cho phép nó như thế này:

# First enable headers module for Apache2, 
# then restart the Apache2 service   
a2enmod headers
apache2 -k graceful

Trên Ubuntu / Debian bạn có thể định cấu hình các tiêu đề trong tệp /etc/apache2/conf-enabled/security.conf

#
# Setting this header will prevent MSIE from interpreting files as something
# else than declared by the content type in the HTTP headers.
# Requires mod_headers to be enabled.
# 
#Header set X-Content-Type-Options: "nosniff"

#
# Setting this header will prevent other sites from embedding pages from this
# site as frames. This defends against clickjacking attacks.
# Requires mod_headers to be enabled.
#
Header always set X-Frame-Options: "sameorigin"
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Permitted-Cross-Domain-Policies "master-only"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Pragma "no-cache"
Header always set Expires "-1"
Header always set Content-Security-Policy: "default-src 'none';"
Header always set Content-Security-Policy: "script-src 'self' www.google-analytics.com adserver.example.com www.example.com;"
Header always set Content-Security-Policy: "style-src 'self' www.example.com;"

Lưu ý: Đây là phần dưới cùng của tệp, chỉ có 3 mục cuối là cài đặt CSP.

Tham số đầu tiên là chỉ thị, thứ 2 là các nguồn được liệt kê trắng. Tôi đã thêm Google Analytics và máy chủ quảng cáo mà bạn có thể có. Hơn nữa, tôi thấy rằng nếu bạn có bí danh, ví dụ: www.example.com và example.com được định cấu hình trong Apache2, bạn cũng nên thêm chúng vào danh sách trắng.

Mã nội tuyến được coi là có hại, bạn nên tránh nó. Sao chép tất cả các javascripts và css vào các tệp riêng biệt và thêm chúng vào danh sách trắng.

Trong khi bạn đang ở đó, bạn có thể xem các cài đặt tiêu đề khác và cài đặt mod_security

Đọc thêm:

https://developers.google.com/web/fundamentals/security/csp/

https://www.w3.org/TR/CSP/


2
Tôi đã có thể thêm các lệnh tương tự đó vào tệp .htaccess của mình, vì tôi không có khả năng chỉnh sửa cấu hình Apache trên máy chủ được chia sẻ của mình. Tôi đã tìm thấy các công cụ tuyệt vời để điều chỉnh các cài đặt này tại report-uri.io/home/tools .
Michael McGinnis

Có cách nào để giải quyết vấn đề này với tomcat 7. Tôi đã thử thêm bộ lọc và không hoạt động.
El Sơn

0

Đừng quên về font-src, nó hoạt động giống như mọi phông chữ khác, nhưng nếu bạn sử dụng các phông chữ được tải từ các nguồn gốc khác - hãy đảm bảo bạn thêm nó vào thẻ meta

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.