Mô hình bảo mật của trang web này bắt nguồn từ
chính sách cùng nguồn gốc. Mã
từ https://mybank.com
chỉ có quyền truy cập vàohttps://mybank.com
và https://evil.example.com
chắc chắn không bao giờ được phép truy cập.
Mỗi nguồn gốc đều được tách biệt với phần còn lại của web, nhằm cung cấp cho nhà phát triển
trong hộp cát để xây dựng và chơi. Trên lý thuyết, đây là một con đường hoàn hảo. Trong
kẻ tấn công đã tìm ra những cách thức khéo léo để phá vỡ hệ thống.
Tập lệnh trên nhiều trang web (XSS) các cuộc tấn công khác. Ví dụ: bỏ qua cùng một chính sách nguồn gốc bằng cách lừa một trang web phân phối mã độc hại cùng với nội dung mong muốn. Đây là một vì các trình duyệt tin tưởng tất cả mã hiển thị trên một trang là một phần chính đáng của nguồn gốc bảo mật của trang đó. Chiến lược phát hành đĩa đơn Bản tóm tắt về XSS là một mặt cắt cũ nhưng mang tính đại diện cho những phương pháp mà kẻ tấn công có thể sử dụng xâm phạm sự tin tưởng này bằng cách chèn mã độc hại. Nếu kẻ tấn công thành công chèn bất kỳ mã nào, nhưng mọi việc gần như không kết thúc: dữ liệu phiên của người dùng được bị xâm phạm và thông tin cần được giữ bí mật được trích xuất cho The Bad Các bạn ơi. Hiển nhiên là chúng tôi sẽ ngăn chặn điều đó nếu có thể.
Nội dung tổng quan này nêu bật một biện pháp phòng ngừa có thể làm giảm đáng kể rủi ro và tác động của các cuộc tấn công XSS trong các trình duyệt hiện đại: Chính sách bảo mật nội dung (CSP).
TL;DR
- Sử dụng danh sách cho phép để cho khách hàng biết những nội dung được phép và không được phép.
- Tìm hiểu xem có những lệnh nào.
- Tìm hiểu các từ khoá họ sử dụng.
- Mã cùng dòng và
eval()
được coi là gây hại. - Hãy báo cáo lỗi vi phạm chính sách cho máy chủ của bạn trước khi thực thi.
Danh sách nguồn đã cho phép
Vấn đề bị các cuộc tấn công XSS khai thác là trình duyệt không thể phân biệt
giữa tập lệnh là một phần của ứng dụng và tập lệnh đã được
do một bên thứ ba chèn vào một cách ác ý. Ví dụ: nút Google +1 ở
cuối trang này tải và thực thi mã từ
https://apis.google.com/js/plusone.js
theo ngữ cảnh nguồn gốc của trang này. T4
tin tưởng mã đó, nhưng chúng ta không thể kỳ vọng trình duyệt tự tìm ra mã đó
từ apis.google.com
thì tuyệt vời, trong khi mã từ apis.evil.example.com
có thể không. Trình duyệt thoải mái tải xuống và thực thi bất kỳ mã nào trên một trang
các yêu cầu, bất kể nguồn.
Thay vì tin tưởng một cách mù quáng mọi thứ mà máy chủ phân phối, CSP sẽ xác định
Tiêu đề HTTP Content-Security-Policy
, cho phép bạn tạo danh sách cho phép cho
nguồn nội dung đáng tin cậy và hướng dẫn trình duyệt chỉ thực thi hoặc hiển thị
từ các nguồn đó. Ngay cả khi kẻ tấn công có thể tìm thấy lỗ hổng
chèn tập lệnh, tập lệnh sẽ không khớp với danh sách cho phép và do đó sẽ không được
thực thi.
Vì chúng tôi tin tưởng apis.google.com
cung cấp mã hợp lệ và chúng tôi tin tưởng chính mình
để làm tương tự, hãy xác định một chính sách chỉ cho phép tập lệnh thực thi khi tập lệnh đó
bắt nguồn từ một trong hai nguồn đó:
Content-Security-Policy: script-src 'self' https://apis.google.com
Thật đơn giản, đúng không? Như bạn có thể đoán, script-src
là một lệnh
kiểm soát một nhóm đặc quyền liên quan đến tập lệnh cho một trang cụ thể. Chúng tôi đã chỉ định
'self'
là một nguồn tập lệnh hợp lệ và https://apis.google.com
là
khác. Trình duyệt tải xuống và thực thi JavaScript hợp lệ từ
apis.google.com
qua HTTPS, cũng như từ nguồn gốc của trang hiện tại.
Khi chính sách này được xác định, trình duyệt chỉ gửi lỗi thay vì đang tải tập lệnh từ bất kỳ nguồn nào khác. Khi một kẻ tấn công thông minh tìm được chèn mã vào trang web của bạn, chúng sẽ chạy đầy đủ trong một thông báo lỗi thay vì so với thành công họ mong đợi.
Chính sách áp dụng cho nhiều loại tài nguyên
Mặc dù tài nguyên tập lệnh là những rủi ro bảo mật rõ ràng nhất, nhưng CSP cung cấp
một tập hợp chỉ thị chính sách cho phép kiểm soát khá chi tiết các tài nguyên
mà một trang được phép tải. Bạn đã xem script-src
, vì vậy, khái niệm này
phải rõ ràng.
Hãy cùng tìm hiểu nhanh phần còn lại của các lệnh tài nguyên. Danh sách bên dưới biểu thị trạng thái của lệnh kể từ cấp 2. Thông số kỹ thuật cấp 3 đã được xuất bản, nhưng phần lớn chưa được triển khai trong trình duyệt.
base-uri
hạn chế các URL có thể xuất hiện trong phần tử<base>
của trang.child-src
liệt kê URL của worker và nội dung khung được nhúng. Cho ví dụ:child-src https://youtube.com
sẽ bật nhúng video từ YouTube chứ không phải từ các nguồn khác.connect-src
giới hạn các nguồn gốc mà bạn có thể kết nối (thông qua XHR, WebSockets và EventSource).font-src
chỉ định những nguồn gốc có thể phân phát phông chữ trên web. Web của Google phông chữ có thể được bật quafont-src https://themes.googleusercontent.com
.form-action
liệt kê các điểm cuối hợp lệ để gửi bằng các thẻ<form>
.frame-ancestors
chỉ định các nguồn có thể nhúng trang hiện tại. Lệnh này áp dụng cho các thẻ<frame>
,<iframe>
,<embed>
và<applet>
. Lệnh này không được dùng trong các thẻ<meta>
và chỉ áp dụng cho các mục không phải HTML của chúng tôi.frame-src
đã ngừng hoạt động trong cấp độ 2, nhưng sẽ được khôi phục trong cấp độ 3. Nếu không trình bày thì lớp này vẫn quay vềchild-src
như trước đây.img-src
xác định các nguồn gốc có thể tải hình ảnh.media-src
hạn chế các nguồn gốc được phép phân phối video và âm thanh.object-src
cho phép kiểm soát Flash và các trình bổ trợ khác.plugin-types
giới hạn các loại trình bổ trợ mà một trang có thể gọi.report-uri
chỉ định một URL mà trình duyệt sẽ gửi báo cáo khi một chính sách bảo mật nội dung là vi phạm. Không được dùng lệnh này trong<meta>
các thẻ.style-src
là phiên bản tương đương củascript-src
cho biểu định kiểu.upgrade-insecure-requests
hướng dẫn các tác nhân người dùng ghi lại giao thức URL, thay đổi HTTP thành HTTPS. Lệnh này dành cho các trang web có số lượng lớn URL cũ cần được viết lại.worker-src
là một lệnh CSP cấp 3 có tác dụng hạn chế các URL mà có thể được tải dưới dạng trình thực thi, trình thực thi dùng chung hoặc trình chạy dịch vụ. Tính đến tháng 7 năm 2017, có có giới hạn số lượng triển khai.
Theo mặc định, các lệnh sẽ mở rộng. Nếu bạn không đặt chính sách cụ thể cho
giả sử là font-src
, thì lệnh đó sẽ hoạt động theo mặc định như sau:
mặc dù bạn đã chỉ định *
làm nguồn hợp lệ (ví dụ: bạn có thể tải phông chữ từ
mọi nơi, mà không bị hạn chế).
Bạn có thể ghi đè hành vi mặc định này bằng cách chỉ định default-src
. Lệnh này xác định các chế độ mặc định cho hầu hết
mà bạn không chỉ định. Nói chung, chính sách này áp dụng cho mọi chỉ thị
kết thúc bằng -src
. Nếu default-src
được đặt thành https://example.com
và bạn không thành công
để chỉ định một lệnh font-src
, sau đó bạn có thể tải phông chữ từ
https://example.com
và không nơi nào khác. Chúng ta chỉ xác định script-src
trong
các ví dụ trước đó, có nghĩa là hình ảnh, phông chữ, v.v. có thể được tải từ
nguồn gốc bất kỳ.
Các lệnh sau đây không dùng default-src
làm phương án dự phòng. Hãy nhớ rằng
không đặt chúng cũng giống như cho phép bất kỳ thứ gì.
base-uri
form-action
frame-ancestors
plugin-types
report-uri
sandbox
Bạn có thể sử dụng số lượng lệnh trong số này tuỳ ý
ứng dụng cụ thể, chỉ cần liệt kê từng thông báo trong tiêu đề HTTP,
bằng dấu chấm phẩy. Đảm bảo rằng bạn liệt kê tất cả
tài nguyên cần thiết thuộc một loại cụ thể trong một lệnh duy nhất. Nếu bạn đã viết
điều gì đó tương tự như script-src https://host1.com; script-src https://host2.com
lệnh thứ hai sẽ bị bỏ qua. Ví dụ:
chỉ định chính xác cả hai nguồn gốc là hợp lệ:
script-src https://host1.com https://host2.com
Ví dụ: nếu bạn có một ứng dụng tải tất cả tài nguyên của nó từ một
mạng phân phối nội dung (giả sử https://cdn.example.net
) và biết rằng bạn
không cần bất kỳ trình bổ trợ hoặc nội dung có khung nào, thì chính sách của bạn có thể trông giống
như sau:
Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'
Chi tiết triển khai
Bạn sẽ thấy tiêu đề X-WebKit-CSP
và X-Content-Security-Policy
trong nhiều hình thức
trên web. Từ giờ trở đi, bạn nên bỏ qua những tiền tố này
. Các trình duyệt hiện đại (ngoại trừ IE) hỗ trợ mã không có tiền tố
Tiêu đề Content-Security-Policy
. Đó là tiêu đề mà bạn nên sử dụng.
Bất kể tiêu đề bạn sử dụng là gì, chính sách đều được xác định trên cơ sở từng trang: bạn sẽ cần gửi tiêu đề HTTP cùng với mọi phản hồi mà mình muốn đảm bảo được bảo vệ. Điều này mang lại tính linh hoạt cao, vì bạn có thể tinh chỉnh chính sách cho các trang cụ thể dựa trên nhu cầu cụ thể của các trang đó. Có thể một nhóm các trang trong trang web của bạn có nút +1, trong khi các trang khác thì không: bạn có thể cho phép mã nút chỉ được tải khi cần.
Danh sách nguồn trong mỗi lệnh rất linh hoạt. Bạn có thể chỉ định nguồn theo
lược đồ (data:
, https:
) hoặc có đặc điểm khác nhau từ chỉ tên máy chủ
(example.com
, khớp với mọi nguồn gốc trên máy chủ đó: mọi lược đồ, cổng bất kỳ) để
URI đủ điều kiện (https://example.com:443
, chỉ khớp với HTTPS
example.com
và chỉ cổng 443). Chấp nhận ký tự đại diện, nhưng chỉ dưới dạng lược đồ,
một cổng hoặc ở vị trí ngoài cùng bên trái của tên máy chủ: *://*.example.com:*
sẽ
khớp với tất cả các miền con của example.com
(nhưng không phải example.com
), sử dụng
mọi lược đồ, trên bất kỳ cổng nào.
Danh sách nguồn cũng chấp nhận 4 từ khoá:
'none'
, như bạn dự kiến, không khớp với giá trị nào.'self'
khớp với nguồn gốc hiện tại, nhưng không khớp với miền con của nguồn này.'unsafe-inline'
cho phép CSS và JavaScript cùng dòng. (Chúng tôi sẽ trình bày về vấn đề này trong chi tiết hơn.)'unsafe-eval'
cho phép các cơ chế chuyển văn bản sang JavaScript nhưeval
. (Chúng tôi sẽ lấy tính năng này.)
Những từ khoá này cần có dấu ngoặc đơn. Ví dụ: script-src 'self'
(có dấu ngoặc kép)
cho phép thực thi JavaScript từ máy chủ hiện tại; script-src self
(không có dấu ngoặc kép) cho phép JavaScript từ máy chủ có tên "self
" (và không từ
máy chủ hiện tại) và có thể không phải là ý của bạn.
Cơ chế hộp cát
Còn một lệnh nữa đáng nói: sandbox
. Hơi quan tâm
khác với các hành động khác mà chúng tôi xem xét vì hệ thống này đặt ra các quy định hạn chế đối với những hành động
trang có thể sử dụng thay vì tài nguyên mà trang có thể tải. Nếu
Đã có lệnh sandbox
, trang được xử lý như thể trang này đã được tải
bên trong <iframe>
có thuộc tính sandbox
. Chiến dịch này có thể có nhiều
tác động lên trang: buộc trang thành một nguồn gốc duy nhất và ngăn biểu mẫu
nội dung gửi, v.v. Mặc dù nội dung nằm ngoài phạm vi của bài viết này một chút, nhưng bạn
Bạn có thể xem toàn bộ thông tin chi tiết về các thuộc tính hộp cát hợp lệ trong
"Cơ chế hộp cát" của thông số HTML5.
Thẻ meta
Cơ chế phân phối ưu tiên của CSP là tiêu đề HTTP. Tuy nhiên, cách này có thể hữu ích
để đặt chính sách trên một trang ngay trong mã đánh dấu. Bạn có thể làm việc đó bằng cách sử dụng thẻ <meta>
với
thuộc tính http-equiv
:
<meta
http-equiv="Content-Security-Policy"
content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>
Bạn không thể sử dụng tính năng này cho frame-ancestors
, report-uri
hoặc sandbox
.
Mã cùng dòng được coi là gây hại
Cần phải làm rõ rằng CSP dựa trên nguồn gốc trong danh sách cho phép, vì đó là
phương pháp rõ ràng hướng dẫn trình duyệt xử lý các nhóm tài nguyên cụ thể
chấp nhận được và từ chối các thông tin còn lại. Danh sách cho phép dựa trên nguồn gốc sẽ không hoạt động
tuy nhiên, giải quyết mối đe doạ lớn nhất do tấn công XSS gây ra: chèn tập lệnh nội tuyến.
Nếu kẻ tấn công có thể chèn thẻ tập lệnh trực tiếp chứa một số phần mềm độc hại
tải trọng (<script>sendMyDataToEvilDotCom();</script>
),
trình duyệt không có cơ chế nào để phân biệt với trình duyệt
thẻ tập lệnh nội tuyến. CSP giải quyết vấn đề này bằng cách cấm hoàn toàn tập lệnh cùng dòng:
đó là cách duy nhất để chắc chắn.
Lệnh cấm này không chỉ bao gồm các tập lệnh được nhúng trực tiếp trong thẻ script
mà còn bao gồm cả các tập lệnh
Trình xử lý sự kiện cùng dòng và javascript:
URL. Bạn cần chuyển nội dung của
Các thẻ script
vào một tệp bên ngoài rồi thay thế URL javascript:
và <a ... onclick="[JAVASCRIPT]">
bằng các lệnh gọi addEventListener()
thích hợp. Ví dụ:
bạn có thể viết lại những nội dung sau từ:
<script>
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>
thành một số thứ khác như:
<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>
<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('amazing').addEventListener('click', doAmazingThings);
});
Mã viết lại có một số ưu điểm vượt trội hơn khi hoạt động hiệu quả với CSP; đây đã là phương pháp hay nhất, cho dù bạn có sử dụng CSP hay không. Cùng dòng JavaScript kết hợp cấu trúc và hành vi chính xác theo cách không cần thiết. Các tài nguyên bên ngoài dễ dàng được lưu vào bộ nhớ đệm hơn cho trình duyệt, cũng dễ hiểu hơn đối với phát triển, hỗ trợ việc biên dịch và giảm kích thước. Bạn sẽ viết tốt hơn nếu bạn muốn di chuyển mã vào các tài nguyên bên ngoài.
Kiểu cùng dòng được xử lý theo cùng một cách: cả thuộc tính style
và style
thẻ phải được hợp nhất vào biểu định kiểu bên ngoài để bảo vệ chống lại
nhiều loại thông minh đáng ngạc nhiên
phương thức đánh cắp dữ liệu mà CSS cho phép.
Nếu phải có kiểu và tập lệnh cùng dòng, bạn có thể bật chế độ đó
bằng cách thêm 'unsafe-inline'
làm nguồn được phép trong script-src
hoặc style-src
. Bạn cũng có thể sử dụng số chỉ dùng một lần hoặc hàm băm (xem bên dưới), nhưng thực sự không nên làm vậy.
Cấm tập lệnh cùng dòng là biện pháp bảo mật lớn nhất mà CSP mang lại, và
việc cấm kiểu cùng dòng cũng sẽ làm cứng ứng dụng của bạn. Hơi quan tâm
nỗ lực trước để đảm bảo rằng mọi thứ hoạt động chính xác sau khi di chuyển tất cả mã
ngoài luồng, nhưng đó cũng là một sự đánh đổi đáng để thực hiện.
Nếu bạn chắc chắn phải sử dụng
CSP cấp 2 cung cấp khả năng tương thích ngược cho các tập lệnh cùng dòng bằng cách cho phép bạn thêm các tập lệnh cùng dòng cụ thể vào danh sách cho phép bằng cách sử dụng một số chỉ dùng một lần bằng mật mã (số sử dụng một lần) hoặc một hàm băm. Mặc dù có thể rườm rà nhưng sẽ hữu ích trong tích tắc.
Để sử dụng số chỉ dùng một lần, hãy cung cấp cho thẻ tập lệnh của bạn thuộc tính số chỉ dùng một lần. Giá trị của trường này phải khớp với một trong danh sách các nguồn đáng tin cậy. Ví dụ:
<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
// Some inline code I can't remove yet, but need to asap.
</script>
Bây giờ, hãy thêm số chỉ dùng một lần vào lệnh script-src
được thêm vào từ khoá nonce-
.
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
Hãy nhớ rằng số chỉ dùng một lần phải được tạo lại cho mọi yêu cầu trang và chúng phải được không thể đoán được.
Hàm băm cũng hoạt động tương tự như vậy. Thay vì thêm mã vào thẻ tập lệnh,
tạo hàm băm SHA của chính tập lệnh rồi thêm hàm này vào lệnh script-src
.
Ví dụ: giả sử trang của bạn có chứa:
<script>
alert('Hello, world.');
</script>
Chính sách của bạn sẽ chứa nội dung sau:
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
Có một vài điều cần lưu ý ở đây. Tiền tố sha*-
chỉ định thuật toán
để tạo hàm băm. Trong ví dụ trên, sha256-
được sử dụng. CSP cũng
hỗ trợ sha384-
và sha512-
. Khi tạo hàm băm, đừng thêm
Thẻ <script>
. Ngoài ra, cách viết hoa và khoảng trắng cũng quan trọng, bao gồm cả dấu đầu dòng hoặc
khoảng trắng ở cuối.
Khi tìm kiếm trên Google về cách tạo hàm băm SHA sẽ đưa bạn đến các giải pháp cho mọi số lượng ngôn ngữ. Khi sử dụng Chrome 40 trở lên, bạn có thể mở Công cụ cho nhà phát triển, sau đó tải lại trang của bạn. Thẻ Bảng điều khiển sẽ chứa các thông báo lỗi với thông tin chính xác hàm băm sha256 cho từng tập lệnh cùng dòng của bạn.
Cả Eval
Ngay cả khi kẻ tấn công không thể chèn tập lệnh trực tiếp, chúng vẫn có thể đánh lừa
ứng dụng của bạn thành chuyển đổi văn bản trơ thành JavaScript có thể thực thi
và thực hiện thay mặt cho họ. eval()
, mới
Function() , setTimeout([string], ...)
và
setInterval([string], ...)
là tất cả các vectơ mà thông qua đó được chèn
có thể thực thi nội dung nào đó độc hại không mong muốn. Giá trị mặc định của CSP
ứng phó với rủi ro này là chặn hoàn toàn tất cả các vectơ này.
Điều này có một vài tác động đến cách bạn xây dựng ứng dụng:
- Bạn phải phân tích cú pháp JSON qua
JSON.parse
tích hợp sẵn thay vì dựa vàoeval
Hoạt động JSON gốc có trong mọi trình duyệt kể từ IE8 và chúng được hoàn toàn an toàn. - Viết lại mọi cuộc gọi
setTimeout
hoặcsetInterval
mà bạn đang thực hiện bằng các hàm cùng dòng thay vì chuỗi. Ví dụ:
setTimeout("document.querySelector('a').style.display = 'none';", 10);
tốt hơn là:
setTimeout(function () {
document.querySelector('a').style.display = 'none';
}, 10);
- Tránh tạo mẫu cùng dòng trong thời gian chạy: Nhiều thư viện tạo mẫu sử dụng
new Function()
một cách thoải mái để tăng tốc việc tạo mẫu trong thời gian chạy. Đó là ứng dụng hữu ích của lập trình động, nhưng có nguy cơ đánh giá văn bản độc hại. Một số khung hỗ trợ ngay từ đầu, quay lại trình phân tích cú pháp mạnh mẽ khi không cóeval
. Lệnh ng-csp của AngularJS là một ví dụ điển hình cho trường hợp này.
Tuy nhiên, lựa chọn tốt hơn là ngôn ngữ tạo mẫu, cung cấp
biên dịch trước (Thanh công cụ có,
chẳng hạn). Việc biên dịch trước các mẫu của bạn có thể giúp cải thiện trải nghiệm người dùng
nhanh hơn cách triển khai trong thời gian chạy nhanh nhất, đồng thời cũng an toàn hơn. Nếu eval và
các đoạn văn bản sang JavaScript rất cần thiết cho ứng dụng của bạn, bạn có thể
bật chúng bằng cách thêm 'unsafe-eval'
làm nguồn được phép trong script-src
nhưng chúng tôi tuyệt đối không khuyến khích điều này. Cấm khả năng thực thi
Chuỗi khiến kẻ tấn công khó thực thi quyền truy cập trái phép hơn nhiều
trên trang web của bạn.
Báo cáo
Việc CSP có thể chặn các tài nguyên không đáng tin cậy ở phía máy khách mang lại một lợi ích lớn
nhưng sẽ rất hữu ích nếu có một loại thông báo
gửi lại máy chủ để bạn có thể xác định và loại bỏ mọi lỗi cho phép
độc hại ngay từ đầu. Để đạt được mục tiêu này, bạn có thể hướng dẫn
trình duyệt đến POST
báo cáo lỗi vi phạm theo định dạng JSON cho một vị trí
được chỉ định trong lệnh report-uri
.
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
Các báo cáo đó sẽ trông giống như sau:
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
Đối tượng này chứa một phần thông tin hữu ích giúp bạn theo dõi
nguyên nhân cụ thể của vi phạm, bao gồm trang mà vi phạm
đã xảy ra (document-uri
), liên kết giới thiệu của trang đó (lưu ý rằng không giống như liên kết HTTP
trường tiêu đề, khoá không bị viết sai chính tả), tài nguyên đã vi phạm
chính sách của trang (blocked-uri
), chỉ thị cụ thể mà trang này đã vi phạm
(violated-directive
) và chính sách hoàn chỉnh của trang (original-policy
).
Chỉ báo cáo
Nếu mới bắt đầu sử dụng CSP, bạn nên đánh giá
của ứng dụng trước khi triển khai một chính sách hà khắc cho người dùng.
Là bước đệm để hoàn tất việc triển khai, bạn có thể yêu cầu trình duyệt giám sát
chính sách, báo cáo hành vi vi phạm nhưng không thực thi các quy định hạn chế. Thay vì
gửi tiêu đề Content-Security-Policy
, gửi
Tiêu đề Content-Security-Policy-Report-Only
.
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
Chính sách được chỉ định ở chế độ chỉ báo cáo sẽ không chặn tài nguyên bị hạn chế, mà ứng dụng sẽ gửi báo cáo vi phạm đến vị trí mà bạn chỉ định. Bạn thậm chí có thể gửi cả hai tiêu đề, thực thi một chính sách trong khi giám sát một chính sách khác. Đây là một trải nghiệm tuyệt vời cách đánh giá tác động của những thay đổi đối với CSP của ứng dụng: bật báo cáo chính sách mới, theo dõi báo cáo vi phạm và sửa mọi lỗi tăng âm lượng; khi bạn đã hài lòng với hiệu quả của chính sách, hãy bắt đầu thực thi chính sách mới.
Sử dụng thực tế
CSP 1 khá hữu dụng trong Chrome, Safari và Firefox, nhưng đã hạn chế hỗ trợ trong IE 10. Bạn có thể xem thông tin cụ thể tại caniuse.com. CSP cấp độ 2 đã có trong Chrome kể từ phiên bản 40. Các trang web lớn như Twitter và Facebook đã triển khai tiêu đề (Nghiên cứu điển hình của Twitter rất đáng để đọc) và tiêu chuẩn này rất sẵn sàng để bạn bắt đầu triển khai trên các trang web của mình.
Bước đầu tiên trong việc xây dựng chính sách cho ứng dụng của bạn là đánh giá mà bạn đang thực sự tải. Khi bạn nghĩ rằng mình đã hiểu được cách mọi thứ được tập hợp trong ứng dụng của bạn, hãy thiết lập chính sách dựa trên các yêu cầu liên quan. Hãy xem qua một vài trường hợp sử dụng phổ biến và xác định cách hỗ trợ họ hiệu quả nhất trong phạm vi bảo vệ của CSP.
Trường hợp sử dụng 1: tiện ích mạng xã hội
Nút +1 của Google bao gồm một tập lệnh từ
https://apis.google.com
và nhúng một<iframe>
từhttps://plusone.google.com
. Bạn cần một chính sách bao gồm cả hai nguồn gốc để nhúng nút. Chính sách tối thiểu sẽ làscript-src https://apis.google.com; child-src https://plusone.google.com
. Bạn cũng cần để đảm bảo rằng đoạn mã JavaScript mà Google cung cấp được kéo vào tệp JavaScript bên ngoài. Nếu bạn đã có chính sách dựa trên Cấp 1 bằng cách sử dụngframe-src
Cấp 2 yêu cầu bạn thay đổi thànhchild-src
. Việc này không cần thiết nữa trong CSP cấp 3.Nút thích của Facebook có một số cách triển khai. Chúng tôi khuyên bạn nên duy trì
<iframe>
vì phiên bản này được tạo hộp cát an toàn với phần còn lại của trang web. Nó cần có lệnhchild-src https://facebook.com
để hoạt động đúng cách. Ghi chú theo mặc định, mã<iframe>
mà Facebook cung cấp sẽ tải URL,//facebook.com
. Thay đổi điều đó để chỉ định rõ HTTPS:https://facebook.com
. Chẳng có lý do gì để sử dụng HTTP nếu bạn không cần.Nút tweet của Twitter dựa vào quyền truy cập vào tập lệnh và khung, cả hai đều được lưu trữ tại
https://platform.twitter.com
. (Twitter cũng cung cấp URL tương đối theo default; chỉnh sửa mã để chỉ định HTTPS khi sao chép/dán mã cục bộ.) Bạn sẽ thiết lập xong vớiscript-src https://platform.twitter.com; child-src https://platform.twitter.com
, miễn là bạn di chuyển đoạn mã JavaScript mà Twitter cung cấp trong tệp JavaScript bên ngoài.Các nền tảng khác có yêu cầu tương tự và có thể được giải quyết tương tự. Bạn chỉ nên đặt
default-src
là'none'
và xem bảng điều khiển của mình để xác định những tài nguyên bạn cần bật để tiện ích hoạt động.
Nhiều tiện ích rất đơn giản: bạn chỉ cần kết hợp chính sách nên chúng tôi muốn hợp nhất tất cả các tài nguyên thuộc cùng một loại thành một . Nếu bạn muốn sử dụng cả 3 tiện ích mạng xã hội, chính sách sẽ như sau:
script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com
Trường hợp sử dụng 2: khoá
Giả sử trong một khoảnh khắc mà bạn chạy trang web ngân hàng và muốn đảm bảo rằng
chỉ có thể tải những tài nguyên mà bạn tự viết. Trong trường hợp này,
bắt đầu bằng một chính sách mặc định chặn hoàn toàn mọi thứ (default-src 'none'
) và xây dựng từ đó.
Giả sử ngân hàng tải tất cả hình ảnh, kiểu và tập lệnh từ CDN tại
https://cdn.mybank.net
và kết nối qua XHR với https://api.mybank.com/
tới
kéo các bit dữ liệu khác nhau xuống. Khung được sử dụng, nhưng chỉ cho các trang cục bộ trên
(không có nguồn gốc của bên thứ ba). Không có Flash trên trang web, không có phông chữ, không
ứng dụng khác. Tiêu đề CSP có tính hạn chế nhất mà chúng tôi có thể gửi là:
Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'
Trường hợp sử dụng 3: Chỉ SSL
Một quản trị viên diễn đàn thảo luận về lễ cưới muốn đảm bảo rằng tất cả các tài nguyên đều được chỉ được tải qua các kênh bảo mật, nhưng không thực sự viết nhiều mã; viết lại nhiều phần lớn phần mềm diễn đàn của bên thứ ba được bổ sung đầy đủ kịch bản và phong cách cùng dòng vượt quá khả năng của anh. Chính sách sau đây sẽ là có hiệu lực:
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
Mặc dù https:
được chỉ định trong default-src
, nhưng tập lệnh và kiểu
không tự động kế thừa nguồn đó. Mỗi lệnh hoàn toàn
sẽ ghi đè giá trị mặc định cho loại tài nguyên cụ thể đó.
Tương lai
Chính sách bảo mật nội dung Cấp 2 là Đề xuất ứng cử viên. Nhóm làm việc về bảo mật ứng dụng web của W3C đã bắt đầu làm việc trong vòng lặp tiếp theo của quy cách, Chính sách bảo mật nội dung cấp 3
Nếu bạn quan tâm đến thảo luận về các tính năng sắp ra mắt này, duyệt qua kho lưu trữ danh sách gửi thư Public-webappsec@, hoặc tự tham gia.