นโยบายรักษาความปลอดภัยเนื้อหา

นโยบายรักษาความปลอดภัยเนื้อหาสามารถลดความเสี่ยงและผลกระทบของการโจมตี Cross-site Scripting ในเบราว์เซอร์รุ่นใหม่ได้อย่างมาก

การสนับสนุนเบราว์เซอร์

  • 25
  • 14
  • 23
  • 7

แหล่งที่มา

โมเดลความปลอดภัยของเว็บจะอิงตามนโยบายต้นทางเดียวกัน ตัวอย่างเช่น โค้ดจาก https://mybank.com ต้องมีสิทธิ์เข้าถึงเฉพาะข้อมูลของ https://mybank.com และhttps://evil.example.com ต้องไม่เคยได้รับอนุญาตให้เข้าถึง ตามทฤษฎีแล้ว แต่ละต้นทางนั้นแยกออกจากเว็บอื่นๆ เพื่อให้นักพัฒนาซอฟต์แวร์มีแซนด์บ็อกซ์ที่ปลอดภัย แต่ในทางปฏิบัติ ผู้โจมตีค้นพบวิธี มากมายที่จะโค่นระบบ

ตัวอย่างเช่น การโจมตีแบบ cross-site Scripting (XSS) หลีกเลี่ยงนโยบายต้นทางเดียวกันโดยการหลอกให้เว็บไซต์ส่งโค้ดที่เป็นอันตรายไปพร้อมกับเนื้อหาที่ต้องการ ซึ่งเป็นปัญหาใหญ่เนื่องจากเบราว์เซอร์จะเชื่อถือโค้ดทั้งหมดที่ปรากฏในหน้าเว็บว่าเป็นส่วนหนึ่งของต้นทางการรักษาความปลอดภัยของหน้านั้นโดยชอบตามกฎหมาย Cheat Sheet ของ XSS เป็นวิธีการที่เก่าแล้วซึ่งนำมาจากวิธีการต่างๆ ที่ผู้โจมตีอาจใช้เพื่อละเมิดความเชื่อมั่นนี้โดยการแทรกโค้ดที่เป็นอันตราย หากผู้โจมตีแทรกโค้ดใดก็ตามได้สำเร็จ ผู้โจมตีจะบุกรุกเซสชันของผู้ใช้และเข้าถึงข้อมูลส่วนตัวได้

หน้านี้สรุปนโยบายรักษาความปลอดภัยเนื้อหา (CSP) ว่าเป็นกลยุทธ์ในการลดความเสี่ยงและผลกระทบของการโจมตี XSS ในเบราว์เซอร์สมัยใหม่

องค์ประกอบของ CSP

หากต้องการใช้ CSP ที่มีประสิทธิภาพ ให้ทำตามขั้นตอนต่อไปนี้

  • ใช้รายการที่อนุญาตเพื่อแจ้งลูกค้าว่าผลิตภัณฑ์ใดได้รับอนุญาตและไม่อนุญาต
  • ดูคำสั่งที่ใช้ได้
  • เรียนรู้เกี่ยวกับคำหลักที่ใช้
  • จำกัดการใช้โค้ดในบรรทัดและ eval()
  • รายงานการละเมิดนโยบายในเซิร์ฟเวอร์ก่อนที่จะบังคับใช้

รายการที่อนุญาตของแหล่งที่มา

การโจมตี XSS ใช้ประโยชน์จากการที่เบราว์เซอร์ไม่สามารถแยกความแตกต่างระหว่างสคริปต์ที่เป็นส่วนหนึ่งของแอปพลิเคชันของคุณกับสคริปต์ที่มีการแทรกโดยบุคคลที่สามอย่างมุ่งร้าย ตัวอย่างเช่น ปุ่ม Google +1 ที่ด้านล่างของหน้านี้จะโหลดและเรียกใช้โค้ดจาก https://apis.google.com/js/plusone.js ในบริบทของที่มาของหน้านี้ เราเชื่อถือโค้ดดังกล่าว แต่ไม่คาดคิดว่าเบราว์เซอร์จะทราบด้วยตนเองว่าโค้ดจาก apis.google.com นั้นปลอดภัยที่จะเรียกใช้ ในขณะที่โค้ดจาก apis.evil.example.com อาจไม่ใช่โค้ดที่ถูกต้อง เบราว์เซอร์จะดาวน์โหลดและเรียกใช้โค้ดที่หน้าเว็บร้องขอได้อย่างมีความสุขโดยไม่คำนึงถึงแหล่งที่มา

ส่วนหัว HTTP Content-Security-Policy ของ CSP ช่วยให้คุณสร้างรายการที่อนุญาตของแหล่งที่มาของเนื้อหาที่เชื่อถือได้ และบอกให้เบราว์เซอร์เรียกใช้หรือแสดงผลเฉพาะทรัพยากรจากแหล่งที่มาเหล่านั้น แม้ว่าผู้โจมตีจะพบช่องโหว่เพื่อแทรกสคริปต์ แต่สคริปต์จะไม่ตรงกับรายการที่อนุญาต ทำให้ไม่สามารถเรียกใช้สคริปต์ได้

เราเชื่อมั่นว่า apis.google.com จะส่งโค้ดที่ถูกต้องและเชื่อมั่นในการดำเนินการนี้ ต่อไปนี้เป็นนโยบายตัวอย่างที่อนุญาตให้สคริปต์ทำงานได้เฉพาะเมื่อมาจากแหล่งที่มา 1 ใน 2 แหล่งดังกล่าวเท่านั้น

Content-Security-Policy: script-src 'self' https://apis.google.com

script-src คือคำสั่งที่ควบคุมชุดสิทธิ์ที่เกี่ยวข้องกับสคริปต์สำหรับหน้าเว็บ ส่วนหัว 'self' นี้เป็นแหล่งที่มาของสคริปต์ที่ถูกต้องประเภทหนึ่ง และ https://apis.google.com เป็นอีกแหล่งที่มาหนึ่ง ตอนนี้เบราว์เซอร์จะดาวน์โหลดและเรียกใช้ JavaScript จาก apis.google.com ผ่าน HTTPS ได้ รวมถึงจากต้นทางของหน้าเว็บปัจจุบัน แต่จะดาวน์โหลดจากต้นทางอื่นๆ ไม่ได้ หากผู้โจมตีแทรกโค้ดลงในเว็บไซต์ เบราว์เซอร์จะแสดงข้อผิดพลาดและไม่เรียกใช้สคริปต์ที่แทรกไว้

ข้อผิดพลาดของคอนโซล: ปฏิเสธการโหลดสคริปต์ "http://evil.example.com/evil.js" เนื่องจากละเมิดคำสั่งของนโยบายรักษาความปลอดภัยเนื้อหาต่อไปนี้: Script-src "self" https://apis.google.com
คอนโซลจะแสดงข้อผิดพลาดเมื่อสคริปต์พยายามเรียกใช้จากต้นทางที่ไม่อยู่ในรายการที่อนุญาต

นโยบายมีผลกับทรัพยากรที่หลากหลาย

CSP มีชุดคำสั่งนโยบายที่ช่วยให้ควบคุมทรัพยากรที่หน้าเว็บโหลดได้อย่างละเอียด ซึ่งรวมถึง script-src จากตัวอย่างก่อนหน้านี้

รายการต่อไปนี้สรุปคำสั่งทรัพยากรส่วนที่เหลือในระดับ 2 ข้อกำหนดระดับ 3 มีการร่างไว้แล้ว แต่ยังไม่มีการใช้งานส่วนใหญ่ในเบราว์เซอร์หลัก

base-uri
จำกัด URL ที่ปรากฏในองค์ประกอบ <base> ของหน้าได้
child-src
ระบุ URL สำหรับผู้ปฏิบัติงานและเนื้อหาเฟรมที่ฝัง ตัวอย่างเช่น child-src https://youtube.com จะเปิดใช้การฝังวิดีโอจาก YouTube แต่ไม่ได้เปิดใช้จากต้นทางอื่นๆ
connect-src
จำกัดต้นทางที่เชื่อมต่อได้โดยใช้ XHR, WebSockets และ EventSource
font-src
ระบุต้นทางที่แสดงแบบอักษรสำหรับเว็บได้ ตัวอย่างเช่น คุณจะอนุญาตแบบอักษรเว็บของ Google โดยใช้ font-src https://themes.googleusercontent.com ได้
form-action
แสดงรายการปลายทางที่ถูกต้องสำหรับการส่งจาก <form> แท็ก
frame-ancestors
ระบุแหล่งที่มาที่ฝังหน้าปัจจุบันได้ คำสั่งนี้มีผลกับแท็ก <frame>, <iframe>, <embed> และ <applet> โดยจะใช้ในแท็ก <meta> หรือทรัพยากร HTML ไม่ได้
frame-src
คำสั่งนี้เลิกใช้งานแล้วในระดับ 2 แต่ได้รับการกู้คืนในระดับ 3 หากไม่ปรากฏ เบราว์เซอร์จะกลับไปใช้ child-src
img-src
กำหนดต้นทางที่โหลดรูปภาพได้
media-src
จำกัดต้นทางที่ได้รับอนุญาตให้แสดงวิดีโอและเสียง
object-src
ช่วยให้ควบคุม Flash และปลั๊กอินอื่นๆ ได้
plugin-types
จำกัดประเภทปลั๊กอินที่หน้าเว็บสามารถเรียกใช้ได้
report-uri
ระบุ URL ที่เบราว์เซอร์จะส่งรายงานเมื่อมีการละเมิดนโยบายความปลอดภัยของเนื้อหา ใช้คำสั่งนี้ใน <meta> แท็กไม่ได้
style-src
จำกัดต้นทางที่หน้าเว็บใช้สไตล์ชีตได้
upgrade-insecure-requests
สั่งให้ User Agent เขียนรูปแบบ URL ใหม่โดยการเปลี่ยน HTTP เป็น HTTPS คำสั่งนี้มีไว้สำหรับเว็บไซต์ที่มี URL เก่าจำนวนมากซึ่งจำเป็นต้องเขียนใหม่
worker-src
คำสั่งของ CSP ระดับ 3 ที่จำกัด URL ที่โหลดในฐานะผู้ปฏิบัติงาน ผู้ปฏิบัติงานที่แชร์ หรือโปรแกรมทำงานของบริการได้ ตั้งแต่เดือนกรกฎาคม 2017 คำสั่งนี้มีการติดตั้งใช้งานที่จำกัด

โดยค่าเริ่มต้น เบราว์เซอร์จะโหลดทรัพยากรที่เกี่ยวข้องจากต้นทางทั้งหมดโดยไม่มีข้อจำกัด เว้นแต่คุณจะตั้งค่านโยบายด้วยคำสั่งเฉพาะ หากต้องการลบล้างค่าเริ่มต้น ให้ระบุคำสั่ง default-src คำสั่งนี้จะกำหนดค่าเริ่มต้นสำหรับคำสั่งที่ไม่ได้ระบุที่ลงท้ายด้วย -src เช่น หากตั้งค่า default-src เป็น https://example.com และไม่ได้ระบุคำสั่ง font-src คุณจะโหลดแบบอักษรได้จาก https://example.com เท่านั้น

คำสั่งต่อไปนี้ไม่ได้ใช้ default-src เป็นรายการสำรอง โปรดทราบว่าการไม่ตั้งค่าก็เหมือนกับการอนุญาตให้ทำสิ่งต่างๆ ดังนี้

  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox

ไวยากรณ์พื้นฐานของ CSP

หากต้องการใช้คำสั่ง CSP ให้ระบุคำสั่งในส่วนหัว HTTP พร้อมคำสั่งที่คั่นด้วยโคลอน อย่าลืมระบุทรัพยากรที่จำเป็นทั้งหมดของประเภทหนึ่งๆ ในคำสั่งเดียว ดังนี้

script-src https://host1.com https://host2.com

ต่อไปนี้คือตัวอย่างของคำสั่งหลายคำสั่ง ในกรณีนี้สำหรับเว็บแอปที่โหลดทรัพยากรทั้งหมดจากเครือข่ายนำส่งข้อมูลเนื้อหาที่ https://cdn.example.net และไม่ได้ใช้เนื้อหาหรือปลั๊กอินที่เฟรม

Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

รายละเอียดการใช้งาน

เบราว์เซอร์ที่ทันสมัยรองรับส่วนหัว Content-Security-Policy ที่ไม่มีคำนำหน้า นี่เป็นส่วนหัวที่แนะนำ เราเลิกใช้งานส่วนหัว X-WebKit-CSP และ X-Content-Security-Policy ที่คุณอาจเห็นในบทแนะนำออนไลน์แล้ว

มีการกำหนด CSP แบบหน้าต่อหน้า คุณจะต้องส่งส่วนหัว HTTP ที่มีการตอบกลับทุกรายการที่ต้องการปกป้อง วิธีนี้จะช่วยให้คุณปรับแต่งนโยบายสำหรับ หน้าเว็บหนึ่งๆ ได้ตามความต้องการที่เฉพาะเจาะจง ตัวอย่างเช่น หากชุดหน้าเว็บหนึ่งในเว็บไซต์ของคุณมีปุ่ม +1 ในขณะที่หน้าอื่นๆ ไม่มี คุณสามารถอนุญาตให้โค้ดปุ่มโหลดได้เมื่อจำเป็นเท่านั้น

รายการแหล่งที่มาสำหรับแต่ละคำสั่งจะมีความยืดหยุ่น คุณสามารถระบุแหล่งที่มาตามรูปแบบ (data:, https:) หรือช่วงที่เจาะจงจากชื่อโฮสต์เท่านั้น (example.com ซึ่งจับคู่ต้นทางใดๆ ในโฮสต์นั้น เช่น สคีม พอร์ตใดก็ได้) กับ URI ที่มีคุณสมบัติครบถ้วน (https://example.com:443 ซึ่งจับคู่เฉพาะ HTTPS เท่านั้น example.com และเฉพาะพอร์ต 443) ระบบยอมรับไวลด์การ์ด แต่จะอยู่ในรูปแบบสคีม พอร์ต หรือในตำแหน่งด้านซ้ายสุดของชื่อโฮสต์เท่านั้น *://*.example.com:* จะตรงกับโดเมนย่อยทั้งหมดของ example.com (แต่ไม่ใช่ example.com) โดยใช้รูปแบบใดก็ได้ในพอร์ตใดก็ได้

รายการแหล่งที่มายอมรับคีย์เวิร์ด 4 คำดังนี้

  • 'none' ไม่ตรงกับข้อมูลใดๆ
  • 'self' ตรงกับต้นทางปัจจุบัน แต่ไม่ตรงกับโดเมนย่อย
  • 'unsafe-inline' อนุญาตให้ใช้ JavaScript และ CSS แบบอินไลน์ ดูข้อมูลเพิ่มเติมได้ที่หลีกเลี่ยงการใช้โค้ดในหน้า
  • 'unsafe-eval' อนุญาตให้ใช้กลไกที่แปลงข้อความเป็น JavaScript เช่น eval ดูข้อมูลเพิ่มเติมได้ที่หลีกเลี่ยง eval()

คีย์เวิร์ดเหล่านี้ต้องใช้เครื่องหมายคำพูดเดี่ยว ตัวอย่างเช่น script-src 'self' (ที่มีเครื่องหมายคำพูด) ให้สิทธิ์การดำเนินการของ JavaScript จากโฮสต์ปัจจุบัน script-src self (ไม่มีเครื่องหมายคำพูด) อนุญาตให้ใช้ JavaScript จากเซิร์ฟเวอร์ชื่อ "self" (และไม่ใช่จากโฮสต์ปัจจุบัน) ซึ่งอาจไม่ใช่สิ่งที่คุณหมายถึง

แซนด์บ็อกซ์หน้าเว็บของคุณ

มีคำสั่งอีก 1 รายการที่ควรพูดถึงคือ sandbox แอปนี้จะแตกต่างจากเวอร์ชันอื่นๆ ที่เราพิจารณามาเล็กน้อย เนื่องจากมีข้อจำกัดเกี่ยวกับการดำเนินการที่หน้าเว็บสามารถทำได้แทนที่จะใช้ทรัพยากรที่หน้าเว็บสามารถโหลดได้ หากมีคำสั่ง sandbox อยู่ ระบบจะปฏิบัติต่อหน้าเว็บเหมือนว่าโหลดภายใน <iframe> ที่มีแอตทริบิวต์ sandbox การทำเช่นนี้จะมีผลหลากหลายต่อหน้าเว็บ เช่น การบังคับให้หน้าเว็บทำงานในต้นทางที่ไม่ซ้ำกัน การป้องกันไม่ให้ส่งแบบฟอร์ม และอื่นๆ ซึ่งอาจอยู่นอกเหนือขอบเขตของหน้านี้เล็กน้อย แต่คุณดูรายละเอียดทั้งหมดเกี่ยวกับแอตทริบิวต์แซนด์บ็อกซ์ที่ถูกต้องได้ในส่วน "แซนด์บ็อกซ์" ของข้อกำหนด HTML5

เมตาแท็ก

กลไกการนำส่งที่ต้องการของ CSP คือส่วนหัว HTTP อย่างไรก็ตาม การกำหนดนโยบายในหน้าเว็บในมาร์กอัปโดยตรงก็อาจเป็นประโยชน์ โดยใช้แท็ก <meta> ที่มี แอตทริบิวต์ http-equiv ดังนี้

<meta http-equiv="Content-Security-Policy" content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'">

ใช้กับ frame-ancestors, report-uri หรือ sandbox ไม่ได้

หลีกเลี่ยงโค้ดในบรรทัด

รายการที่อนุญาตมีประสิทธิภาพเท่ากับรายการที่อนุญาตจากต้นทางที่ใช้ในคำสั่ง CSP แต่จะแก้ไขภัยคุกคามที่ใหญ่ที่สุดที่เกิดจากการโจมตี XSS ไม่ได้ ซึ่งก็คือการแทรกสคริปต์ในบรรทัด หากผู้โจมตีสามารถแทรกแท็กสคริปต์ที่มีเพย์โหลดที่เป็นอันตรายโดยตรง (เช่น <script>sendMyDataToEvilDotCom()</script>) เบราว์เซอร์จะไม่มีวิธีแยกความแตกต่างระหว่างแท็กดังกล่าวกับแท็กสคริปต์ในหน้าที่ถูกต้อง CSP แก้ปัญหานี้โดยการแบนสคริปต์ในหน้าโดยสิ้นเชิง

การแบนนี้ไม่ได้มีเพียงสคริปต์ที่ฝังในแท็ก script โดยตรง แต่ยังรวมถึงเครื่องจัดการเหตุการณ์แบบอินไลน์และ URL javascript: ด้วย คุณจะต้องย้ายเนื้อหาของแท็ก script ไปยังไฟล์ภายนอก แล้วแทนที่ URL จำนวน javascript: รายการและ <a ... onclick="[JAVASCRIPT]"> ด้วยการเรียก addEventListener() ที่เหมาะสม ตัวอย่างเช่น คุณอาจเขียนค่าต่อไปนี้ใหม่จาก

<script>
    function doAmazingThings() {
    alert('YOU ARE AMAZING!');
    }
</script>
<button onclick='doAmazingThings();'>Am I amazing?</button>

เป็นอย่างอื่น เช่น

<!-- amazing.html -->
<script src='amazing.js'></script>
<button id='amazing'>Am I amazing?</button>
// amazing.js
function doAmazingThings() {
    alert('YOU ARE AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('amazing')
    .addEventListener('click', doAmazingThings);
});

โค้ดที่เขียนขึ้นใหม่นี้ไม่เพียงแต่เข้ากันได้กับ CSP เท่านั้น แต่ยังสอดคล้องกับแนวทางปฏิบัติแนะนำในการออกแบบเว็บอีกด้วย JavaScript แบบอินไลน์จะผสมผสานโครงสร้างและลักษณะการทำงาน ในรูปแบบที่ทำให้โค้ดสับสน การแคชและคอมไพล์มีความซับซ้อนมากกว่า การย้ายโค้ดไปยังทรัพยากรภายนอกทำให้หน้าเว็บทำงานได้ดีขึ้น

เราขอแนะนำอย่างยิ่งให้ย้ายแท็ก style ในหน้าและแอตทริบิวต์ไปยังสไตล์ชีตภายนอกเพื่อปกป้องเว็บไซต์ของคุณจากการโจมตีการขโมยข้อมูลที่ใช้ CSS

วิธีอนุญาตสคริปต์และสไตล์ในบรรทัดชั่วคราว

คุณเปิดใช้สคริปต์และสไตล์ในบรรทัดได้โดยการเพิ่ม 'unsafe-inline' เป็นแหล่งที่มาที่ได้รับอนุญาตในคำสั่ง script-src หรือ style-src CSP ระดับที่ 2 ยังให้คุณเพิ่มสคริปต์ในหน้าที่ต้องการไปยังรายการที่อนุญาตโดยใช้ค่าที่ได้จากการเข้ารหัส (ใช้ครั้งเดียว) หรือแฮชดังต่อไปนี้

หากต้องการใช้ Nonce ให้กำหนดแท็กสคริปต์เป็นแอตทริบิวต์ nonce ค่าต้องตรงกับหนึ่งใน รายการแหล่งที่มาที่เชื่อถือได้ เช่น

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
    // Some inline code I can't remove yet, but need to as soon as possible.
</script>

เพิ่ม Nonce ลงในคำสั่ง script-src ตามหลังคีย์เวิร์ด nonce-

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

ต้องสร้าง Nonce ใหม่สำหรับทุกคำขอของหน้า และต้องเข้าใจได้

แฮชทำงานในลักษณะเดียวกัน สร้างแฮช SHA ของสคริปต์แล้วเพิ่มลงในคำสั่ง script-src แทนการเพิ่มโค้ดลงในแท็กสคริปต์ ตัวอย่างเช่น หากหน้าเว็บของคุณมีสิ่งต่อไปนี้

<script>alert('Hello, world.');</script>

นโยบายของคุณต้องมีข้อมูลต่อไปนี้

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

คำนำหน้า sha*- จะระบุอัลกอริทึมที่สร้างแฮช ตัวอย่างก่อนหน้านี้ใช้ sha256- แต่ CSP ยังรองรับ sha384- และ sha512- ด้วย เมื่อสร้างแฮช ให้ละเว้นแท็ก <script> การใช้อักษรตัวพิมพ์ใหญ่และช่องว่าง รวมถึงช่องว่างขึ้นต้นและต่อท้าย

โซลูชันสำหรับการสร้างแฮช SHA มีให้บริการในภาษาต่างๆ เมื่อใช้ Chrome 40 ขึ้นไป คุณจะเปิดเครื่องมือสำหรับนักพัฒนาเว็บแล้วโหลดหน้าเว็บซ้ำได้ แท็บคอนโซลจะแสดงข้อความแสดงข้อผิดพลาดพร้อมแฮช SHA-256 ที่ถูกต้องสำหรับสคริปต์ในบรรทัดแต่ละรายการ

หลีกเลี่ยงeval()

แม้ผู้โจมตีจะแทรกสคริปต์โดยตรงไม่ได้ แต่ก็อาจหลอกให้แอปพลิเคชันแปลงข้อความอินพุตเป็น JavaScript ปฏิบัติการได้ และจะดำเนินการแทนพวกเขาได้ eval(), new Function(), setTimeout([string], …) และ setInterval([string], ...) เป็นเวกเตอร์ที่ผู้โจมตีอาจใช้เพื่อเรียกใช้โค้ดที่เป็นอันตรายผ่านข้อความที่แทรก การตอบสนองเริ่มต้นของ CSP ต่อความเสี่ยงนี้คือการบล็อกเวกเตอร์เหล่านี้ทั้งหมดโดยสมบูรณ์

การดำเนินการดังกล่าวมีผลกระทบดังต่อไปนี้ต่อวิธีสร้างแอปพลิเคชัน

  • คุณต้องแยกวิเคราะห์ JSON โดยใช้ JSON.parse ในตัวแทนการใช้ eval การดำเนินการ JSON ที่ปลอดภัยพร้อมใช้งานในทุกเบราว์เซอร์ตั้งแต่ IE8
  • คุณต้องเขียนการเรียก setTimeout หรือ setInterval ใหม่ที่คุณใช้ฟังก์ชันอินไลน์แทนสตริง เช่น หากหน้าเว็บมีสิ่งต่อไปนี้

    setTimeout("document.querySelector('a').style.display = 'none';", 10);
    

    เขียนใหม่เป็น:

    setTimeout(function () {
        document.querySelector('a').style.display = 'none';
    }, 10);
      ```
    
  • หลีกเลี่ยงการใช้เทมเพลตแบบอินไลน์ระหว่างรันไทม์ ไลบรารีที่มีเทมเพลตจำนวนมากมักจะใช้ new Function() เพื่อเร่งการสร้างเทมเพลตให้เร็วขึ้นขณะรันไทม์ ซึ่งทำให้ประเมินข้อความที่เป็นอันตรายได้ บางเฟรมเวิร์กรองรับ CSP ตั้งแต่เริ่มใช้งาน และกลับไปใช้โปรแกรมแยกวิเคราะห์ที่มีประสิทธิภาพในกรณีที่ไม่มี eval ตัวอย่างที่ดีคือคำสั่ง ng-csp ของ AngularJS อย่างไรก็ตาม เราขอแนะนำให้ใช้ภาษาที่มีเทมเพลตไว้ให้แล้ว เช่น แฮนเดิล การคอมไพล์เทมเพลตล่วงหน้าอาจทำให้ผู้ใช้ได้รับประสบการณ์เร็วกว่าการใช้รันไทม์ที่รวดเร็วที่สุด และยังช่วยให้เว็บไซต์ปลอดภัยยิ่งขึ้นอีกด้วย

หากแอปพลิเคชันของคุณจำเป็นต้องใช้ eval() หรือฟังก์ชันการแปลงข้อความเป็น JavaScript ก็เปิดใช้ได้โดยเพิ่ม 'unsafe-eval' เป็นแหล่งที่มาที่อนุญาตในคำสั่ง script-src เราไม่แนะนำอย่างยิ่งเนื่องจากมีความเสี่ยง ที่เกิดจากการแทรกโค้ด

รายงานการละเมิดนโยบาย

หากต้องการแจ้งเซิร์ฟเวอร์เกี่ยวกับข้อบกพร่องที่อาจอนุญาตให้มีการแทรกที่เป็นอันตราย โปรดแจ้งเบราว์เซอร์ให้POSTรายงานการละเมิดในรูปแบบ JSON ไปยังตำแหน่งที่ระบุในคำสั่ง report-uri ดังนี้

Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

รายงานเหล่านี้จะมีลักษณะดังนี้

{
    "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"
    }
}

รายงานนี้มีข้อมูลที่เป็นประโยชน์ในการหาสาเหตุของการละเมิดนโยบาย ซึ่งรวมถึงหน้าเว็บที่เกิดขึ้น (document-uri), referrer ของหน้านั้น, ทรัพยากรที่ละเมิดนโยบายของหน้า (blocked-uri), คำสั่งเฉพาะเจาะจงที่หน้าเว็บละเมิด (violated-directive) และนโยบายทั้งหมดของหน้านั้น (original-policy)

รายงานเท่านั้น

หากคุณเพิ่งเริ่มต้นใช้ CSP เราขอแนะนำให้ใช้โหมดรายงานเท่านั้นเพื่อประเมินสถานะของแอปก่อนที่จะเปลี่ยนนโยบาย หากต้องการทำแบบนี้ ให้ส่งส่วนหัว Content-Security-Policy-Report-Only แทนการส่งส่วนหัว Content-Security-Policy

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

นโยบายที่ระบุในโหมดรายงานเท่านั้นจะไม่บล็อกทรัพยากรที่ถูกจำกัด แต่จะส่งรายงานการละเมิดไปยังตำแหน่งที่คุณระบุ หรือคุณจะส่งส่วนหัวทั้ง 2 แบบเพื่อบังคับใช้นโยบายหนึ่งไปพร้อมๆ กับตรวจสอบอีกนโยบายก็ได้ นี่เป็นวิธีที่ยอดเยี่ยมในการทดสอบการเปลี่ยนแปลงของ CSP ไปพร้อมๆ กับบังคับใช้นโยบายปัจจุบัน เช่น เปิดใช้การรายงานสำหรับนโยบายใหม่ ตรวจสอบรายงานการละเมิดและแก้ไขข้อบกพร่อง แล้วเริ่มบังคับใช้นโยบายนั้นเมื่อพึงพอใจกับนโยบายใหม่แล้ว

การใช้งานจริง

ขั้นตอนแรกในการกำหนดนโยบายสำหรับแอปคือการประเมินทรัพยากรที่โหลด เมื่อเข้าใจโครงสร้างของแอปแล้ว ให้สร้างนโยบายตามข้อกำหนดของแอป ส่วนต่อไปนี้จะอธิบายกรณีการใช้งานทั่วไปและกระบวนการตัดสินใจสำหรับการรองรับการใช้งานดังกล่าวตามหลักเกณฑ์ของ CSP

วิดเจ็ตโซเชียลมีเดีย

  • ปุ่มชอบของ Facebook มีตัวเลือกการใช้งานมากมาย เราขอแนะนำให้ใช้เวอร์ชัน <iframe> เพื่อคงแซนด์บ็อกซ์ไว้จากส่วนอื่นๆ ในเว็บไซต์ จำเป็นต้องมีคำสั่ง child-src https://facebook.com เพื่อให้ทำงานได้อย่างถูกต้อง
  • ปุ่มทวีตของ X ต้องใช้การเข้าถึงสคริปต์ ย้ายสคริปต์ที่สคริปต์ให้ไว้ไปยังไฟล์ JavaScript ภายนอก แล้วใช้คำสั่ง script-src https://platform.twitter.com; child-src https://platform.twitter.com
  • แพลตฟอร์มอื่นๆ มีข้อกำหนดที่คล้ายกันและสามารถแก้ไขได้ในลักษณะเดียวกัน หากต้องการทดสอบทรัพยากรเหล่านี้ เราขอแนะนำให้ตั้งค่า default-src เป็น 'none' และดูคอนโซลของคุณเพื่อดูว่าจะต้องเปิดใช้ทรัพยากรใด

หากต้องการใช้วิดเจ็ตหลายรายการ ให้รวมคำสั่งดังนี้

script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

การล็อกดาวน์

สำหรับบางเว็บไซต์ คุณควรตรวจสอบว่าสามารถโหลดได้เฉพาะทรัพยากรในเครื่องเท่านั้น ตัวอย่างต่อไปนี้พัฒนา CSP สำหรับเว็บไซต์ธนาคาร โดยเริ่มต้นด้วยนโยบายเริ่มต้นที่บล็อกทุกอย่าง (default-src 'none')

เว็บไซต์จะโหลดรูปภาพ รูปแบบ และสคริปต์ทั้งหมดจาก CDN ในเวลา https://cdn.mybank.net และเชื่อมต่อกับ https://api.mybank.com/ โดยใช้ XHR เพื่อดึงข้อมูล ใช้เฟรม แต่ใช้สำหรับหน้าเว็บในเครื่องของเว็บไซต์เท่านั้น (ไม่มีต้นทางของบุคคลที่สาม) ไซต์ไม่มี Flash, ไม่มีแบบอักษร, ไม่มีส่วนเพิ่มเติม ส่วนหัว CSP ที่เข้มงวดที่สุดที่ส่งได้มีดังนี้

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'

SSL เท่านั้น

ต่อไปนี้คือตัวอย่าง CSP สำหรับผู้ดูแลระบบฟอรัมที่ต้องการตรวจสอบว่าทรัพยากรทั้งหมดในฟอรัมจะโหลดโดยใช้ช่องทางที่ปลอดภัยเท่านั้น แต่ไม่มีประสบการณ์ในการเขียนโค้ดและไม่มีทรัพยากรในการเขียนซอฟต์แวร์ฟอรัมของบุคคลที่สามใหม่ซึ่งเต็มไปด้วยสคริปต์และรูปแบบในหน้า

Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'

แม้ว่าจะระบุ https: ใน default-src แต่คำสั่งของสคริปต์และสไตล์จะไม่รับค่าแหล่งที่มานั้นโดยอัตโนมัติ คำสั่งแต่ละรายการจะแทนที่ค่าเริ่มต้นของทรัพยากรประเภทนั้นๆ

การพัฒนามาตรฐาน CSP

นโยบายรักษาความปลอดภัยเนื้อหาระดับ 2 เป็นมาตรฐานที่แนะนำของ W3C คณะทำงานด้านความปลอดภัยของเว็บแอปพลิเคชันของ W3C กำลังพัฒนาข้อกำหนดฉบับถัดไป ซึ่งก็คือนโยบายรักษาความปลอดภัยเนื้อหาระดับ 3

หากต้องการติดตามการสนทนาเกี่ยวกับฟีเจอร์ที่กำลังจะมีขึ้นเหล่านี้ โปรดดูที่เก็บถาวรของรายชื่ออีเมลสาธารณะ@