ลดการใช้ Cross-site Scripting (XSS) ด้วยนโยบายรักษาความปลอดภัยเนื้อหา (CSP) ที่เข้มงวด

Browser Support

  • Chrome: 52.
  • Edge: 79.
  • Firefox: 52.
  • Safari: 15.4.

Cross-site Scripting (XSS) ซึ่งเป็นความสามารถในการแทรกสคริปต์ที่เป็นอันตรายลงในเว็บแอป เป็นหนึ่งในช่องโหว่ด้านความปลอดภัยของเว็บที่ใหญ่ที่สุดมานานกว่าทศวรรษ

นโยบายรักษาความปลอดภัยเนื้อหา (CSP) เป็นการรักษาความปลอดภัยอีกชั้นหนึ่งที่ช่วยลดการโจมตี XSS หากต้องการกำหนดค่า CSP ให้เพิ่มส่วนหัว HTTP Content-Security-Policy ลงในหน้าเว็บและตั้งค่าที่ควบคุมทรัพยากรที่ User Agent สามารถโหลดสำหรับหน้านั้นได้

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

คำสำคัญ: Nonce คือตัวเลขสุ่มที่ใช้เพียงครั้งเดียวซึ่งคุณสามารถใช้เพื่อทำเครื่องหมายแท็ก <script> ว่าเชื่อถือได้

คำสำคัญ: ฟังก์ชันแฮชคือฟังก์ชันทางคณิตศาสตร์ที่แปลงค่าอินพุตเป็นค่าตัวเลขที่บีบอัดซึ่งเรียกว่าแฮช คุณสามารถใช้แฮช (เช่น SHA-256) เพื่อทำเครื่องหมายแท็ก <script> ในบรรทัดว่าเชื่อถือได้

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

เหตุใดคุณจึงควรใช้ CSP ที่เข้มงวด

หากเว็บไซต์ของคุณมี CSP ที่มีลักษณะเหมือน script-src www.googleapis.com อยู่แล้ว ก็อาจไม่มีประสิทธิภาพในการป้องกันการโจมตีแบบข้ามเว็บไซต์ CSP ประเภทนี้เรียกว่า CSP รายการที่อนุญาต เนื่องจากต้องมีการปรับแต่งจำนวนมากและผู้โจมตีสามารถข้ามได้

CSP ที่เข้มงวดซึ่งอิงตาม Nonce หรือแฮชของการเข้ารหัสจะหลีกเลี่ยงข้อผิดพลาดเหล่านี้

โครงสร้าง CSP ที่เข้มงวด

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

CSP แบบเข้มงวดที่อิงตาม Nonce

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';
วิธีการทำงานของ CSP แบบเข้มงวดที่อิงตาม Nonce

CSP แบบเข้มงวดที่อิงตามแฮช

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

พร็อพเพอร์ตี้ต่อไปนี้ทำให้ CSP มีลักษณะ "เข้มงวด" และปลอดภัย

  • โดยใช้ Nonce 'nonce-{RANDOM}' หรือแฮช 'sha256-{HASHED_INLINE_SCRIPT}' เพื่อระบุแท็ก <script> ที่นักพัฒนาเว็บไซต์เชื่อถือให้เรียกใช้ในเบราว์เซอร์ของผู้ใช้
  • โดยจะตั้งค่า 'strict-dynamic' เพื่อลดความพยายามในการติดตั้งใช้งาน CSP ที่อิงตาม Nonce หรือแฮชโดยการอนุญาตให้เรียกใช้สคริปต์ที่สคริปต์ที่เชื่อถือได้สร้างขึ้นโดยอัตโนมัติ นอกจากนี้ยังเลิกบล็อกการใช้ไลบรารีและวิดเจ็ต JavaScript ของบุคคลที่สามส่วนใหญ่ด้วย
  • ซึ่งไม่ได้อิงตามรายการที่อนุญาตของ URL จึงไม่ได้รับผลกระทบจากการข้าม CSP ทั่วไป
  • โดยจะบล็อกสคริปต์ในหน้าเว็บที่ไม่น่าเชื่อถือ เช่น ตัวจัดการเหตุการณ์ในหน้าเว็บหรือ URI javascript:
  • ซึ่งจะจำกัด object-src เพื่อปิดใช้ปลั๊กอินที่เป็นอันตราย เช่น Flash
  • โดยจะจำกัด base-uri เพื่อบล็อกการแทรกแท็ก <base> ซึ่งจะป้องกันไม่ให้ผู้โจมตีเปลี่ยนตำแหน่งของสคริปต์ที่โหลดจาก Relative URL

ใช้ CSP ที่เข้มงวด

หากต้องการใช้ CSP แบบเข้มงวด คุณต้องทำดังนี้

  1. ตัดสินใจว่าแอปพลิเคชันของคุณควรตั้งค่า CSP ที่อิงตาม Nonce หรือแฮชหรือไม่
  2. คัดลอก CSP จากส่วนโครงสร้าง CSP แบบเข้มงวด แล้วตั้งค่าเป็นส่วนหัวการตอบกลับในแอปพลิเคชัน
  3. เปลี่ยนโครงสร้างเทมเพลต HTML และโค้ดฝั่งไคลเอ็นต์เพื่อนำรูปแบบที่เข้ากันไม่ได้กับ CSP ออก
  4. ติดตั้งใช้งาน CSP

คุณสามารถใช้การตรวจสอบแนวทางปฏิบัติแนะนำของ Lighthouse (v7.3.0 ขึ้นไปที่มีแฟล็ก --preset=experimental) ตลอดกระบวนการนี้เพื่อตรวจสอบว่าเว็บไซต์มี CSP หรือไม่ และ CSP นั้นเข้มงวดพอที่จะป้องกัน XSS ได้หรือไม่

คำเตือนในรายงาน Lighthouse ที่ระบุว่าไม่พบ CSP ในโหมดบังคับใช้
หากเว็บไซต์ไม่มี CSP ทาง Lighthouse จะแสดงคำเตือนนี้

ขั้นตอนที่ 1: ตัดสินใจว่าคุณต้องการ CSP ที่อิงตาม Nonce หรือแฮชหรือไม่

CSP แบบเข้มงวดทั้ง 2 ประเภททำงานดังนี้

CSP ที่อิงตาม Nonce

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

ใช้ CSP แบบ Nonce สำหรับหน้า HTML ที่แสดงผลบนเซิร์ฟเวอร์ สำหรับหน้าเว็บเหล่านี้ คุณสามารถสร้างตัวเลขสุ่มใหม่สำหรับการตอบกลับทุกครั้ง

CSP แบบแฮช

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

ใช้ CSP แบบแฮชสำหรับหน้า HTML ที่แสดงแบบคงที่หรือหน้าที่ต้องแคช ตัวอย่างเช่น คุณสามารถใช้ CSP แบบแฮชสำหรับเว็บแอปพลิเคชันหน้าเดียวที่สร้างด้วยเฟรมเวิร์ก เช่น Angular, React หรืออื่นๆ ที่แสดงแบบคงที่โดยไม่มีการแสดงผลฝั่งเซิร์ฟเวอร์

ขั้นตอนที่ 2: ตั้งค่า CSP ที่เข้มงวดและเตรียมสคริปต์

เมื่อตั้งค่า CSP คุณมีตัวเลือกดังนี้

  • โหมดรายงานเท่านั้น (Content-Security-Policy-Report-Only) หรือโหมดบังคับใช้ (Content-Security-Policy) ในโหมดรายงานเท่านั้น CSP จะยังไม่บล็อกทรัพยากร ดังนั้นจึงไม่มีสิ่งใดในเว็บไซต์ที่เสียหาย แต่คุณจะเห็นข้อผิดพลาดและได้รับรายงานสำหรับสิ่งที่จะถูกบล็อก ในเครื่อง เมื่อคุณตั้งค่า CSP เรื่องนี้ไม่สำคัญนัก เนื่องจากทั้ง 2 โหมดจะแสดงข้อผิดพลาดในคอนโซลเบราว์เซอร์ โหมดบังคับใช้จะช่วยคุณค้นหาทรัพยากรที่ CSP ฉบับร่างบล็อกไว้ เนื่องจากบล็อกทรัพยากรอาจทำให้หน้าเว็บดูเสียหายได้ โหมดรายงานเท่านั้นจะมีประโยชน์มากที่สุดในภายหลังในกระบวนการ (ดูขั้นตอนที่ 5)
  • ส่วนหัวหรือแท็ก HTML <meta> สำหรับการพัฒนาในเครื่อง แท็ก <meta> อาจช่วยให้ปรับแต่ง CSP และดูผลกระทบต่อเว็บไซต์ได้อย่างรวดเร็วและสะดวกยิ่งขึ้น แต่มีเงื่อนไขดังนี้
    • ในภายหลัง เมื่อติดตั้งใช้งาน CSP ในเวอร์ชันที่ใช้งานจริง เราขอแนะนำให้ตั้งค่าเป็นส่วนหัว HTTP
    • หากต้องการตั้งค่า CSP ในโหมดรายงานเท่านั้น คุณจะต้องตั้งค่าเป็นส่วนหัว เนื่องจากเมตาแท็ก CSP ไม่รองรับโหมดรายงานเท่านั้น

ตัวเลือก ก: CSP ที่อิงตาม Nonce

ตั้งค่าส่วนหัวการตอบกลับ HTTP Content-Security-Policy ต่อไปนี้ในแอปพลิเคชัน

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

สร้าง Nonce สำหรับ CSP

Nonce คือตัวเลขสุ่มที่ใช้เพียงครั้งเดียวต่อการโหลดหน้าเว็บ CSP ที่ใช้ Nonce จะลดความเสี่ยงจาก XSS ได้ก็ต่อเมื่อผู้โจมตีไม่สามารถเดาค่า Nonce ได้ Nonce ของ CSP ต้องมีลักษณะดังนี้

  • ค่าสุ่มที่ปลอดภัยจากการเข้ารหัส (ควรมีความยาวมากกว่า 128 บิต)
  • สร้างขึ้นใหม่สำหรับทุกคำตอบ
  • เข้ารหัส Base64

ต่อไปนี้เป็นตัวอย่างวิธีเพิ่ม Nonce ของ CSP ในเฟรมเวิร์กฝั่งเซิร์ฟเวอร์

const app = express();

app.get('/', function(request, response) {
  // Generate a new random nonce value for every response.
  const nonce = crypto.randomBytes(16).toString("base64");

  // Set the strict nonce-based CSP response header
  const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`;
  response.set("Content-Security-Policy", csp);

  // Every <script> tag in your application should set the `nonce` attribute to this value.
  response.render(template, { nonce: nonce });
});

เพิ่มแอตทริบิวต์ nonce ลงในองค์ประกอบ <script>

เมื่อใช้ CSP ที่อิงตาม Nonce องค์ประกอบ <script> ทุกรายการต้องมีแอตทริบิวต์ nonce ที่ตรงกับค่า Nonce แบบสุ่มที่ระบุไว้ในส่วนหัว CSP สคริปต์ทั้งหมดสามารถมี Nonce เดียวกันได้ ขั้นตอนแรกคือการเพิ่มแอตทริบิวต์เหล่านี้ลงในสคริปต์ทั้งหมดเพื่อให้ CSP อนุญาตสคริปต์เหล่านั้น

ตัวเลือก ข: ส่วนหัวการตอบกลับ CSP แบบแฮช

ตั้งค่าส่วนหัวการตอบกลับ HTTP Content-Security-Policy ต่อไปนี้ในแอปพลิเคชัน

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

สำหรับสคริปต์ในบรรทัดหลายรายการ ไวยากรณ์จะเป็นดังนี้ 'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}'

โหลดสคริปต์ที่มาจากแหล่งที่มาแบบไดนามิก

คุณโหลดสคริปต์ของบุคคลที่สามแบบไดนามิกได้โดยใช้สคริปต์ในบรรทัด

ตัวอย่างวิธีแทรกสคริปต์ในบรรทัด
อนุญาตโดย CSP
<script>
  var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js'];

  scripts.forEach(function(scriptUrl) {
    var s = document.createElement('script');
    s.src = scriptUrl;
    s.async = false; // to preserve execution order
    document.head.appendChild(s);
  });
</script>
หากต้องการให้สคริปต์นี้ทำงาน คุณต้องคำนวณแฮชของสคริปต์ในบรรทัดและเพิ่มลงในส่วนหัวการตอบกลับ CSP โดยแทนที่ตัวยึดตำแหน่ง {HASHED_INLINE_SCRIPT} หากต้องการลดจำนวนแฮช คุณสามารถผสานสคริปต์ในบรรทัดทั้งหมดให้เป็นสคริปต์เดียวได้ หากต้องการดูการทำงานจริง โปรดดูตัวอย่างนี้และโค้ดของตัวอย่าง
ถูกบล็อกโดย CSP
<script src="https://example.org/foo.js"></script>
<script src="https://example.org/bar.js"></script>
CSP บล็อกสคริปต์เหล่านี้เนื่องจากไม่ได้เพิ่มแบบไดนามิกและไม่มีแอตทริบิวต์ integrity ที่ตรงกับแหล่งที่มาที่อนุญาต

ข้อควรพิจารณาในการโหลดสคริปต์

ตัวอย่างสคริปต์ในบรรทัดจะเพิ่ม s.async = false เพื่อให้แน่ใจว่า foo จะทำงานก่อน bar แม้ว่า bar จะโหลดก่อนก็ตาม ในข้อมูลโค้ดนี้ s.async = false จะไม่บล็อกโปรแกรมแยกวิเคราะห์ขณะที่สคริปต์โหลด เนื่องจากมีการเพิ่มสคริปต์แบบไดนามิก โปรแกรมแยกวิเคราะห์จะหยุดทำงานเฉพาะขณะที่สคริปต์ทำงาน เช่นเดียวกับสคริปต์ async อย่างไรก็ตาม โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อใช้ข้อมูลโค้ดนี้

  • สคริปต์อย่างน้อย 1 รายการอาจทำงานก่อนที่เอกสารจะดาวน์โหลดเสร็จ หากต้องการให้เอกสารพร้อมใช้งานเมื่อสคริปต์ทำงาน ให้รอเหตุการณ์ DOMContentLoaded ก่อนที่จะเพิ่มสคริปต์ หากวิธีนี้ทำให้เกิดปัญหาด้านประสิทธิภาพเนื่องจากสคริปต์ไม่เริ่มดาวน์โหลดเร็วพอ ให้ใช้แท็กพรีโหลดก่อนหน้านี้ในหน้าเว็บ
  • defer = true ไม่ทำงานใดๆ หากต้องการลักษณะการทำงานดังกล่าว ให้เรียกใช้สคริปต์ด้วยตนเองเมื่อจำเป็น

ขั้นตอนที่ 3: ปรับโครงสร้างเทมเพลต HTML และโค้ดฝั่งไคลเอ็นต์

คุณสามารถใช้ตัวแฮนเดิลเหตุการณ์ในบรรทัด (เช่น onclick="…", onerror="…") และ URI ของ JavaScript (<a href="javascript:…">) เพื่อเรียกใช้สคริปต์ได้ ซึ่งหมายความว่าผู้โจมตีที่พบข้อบกพร่อง XSS สามารถแทรก HTML ประเภทนี้และเรียกใช้ JavaScript ที่เป็นอันตรายได้ CSP ที่ใช้ Nonce หรือแฮชจะห้ามไม่ให้ใช้มาร์กอัปประเภทนี้ หากเว็บไซต์ใช้รูปแบบเหล่านี้ คุณจะต้องเปลี่ยนโครงสร้างภายในโค้ดให้เป็นทางเลือกที่ปลอดภัยกว่า

หากเปิดใช้ CSP ในขั้นตอนก่อนหน้า คุณจะเห็นการละเมิด CSP ในคอนโซลทุกครั้งที่ CSP บล็อกรูปแบบที่เข้ากันไม่ได้

รายงานการละเมิด CSP ในคอนโซลนักพัฒนาซอฟต์แวร์ Chrome
ข้อผิดพลาดในคอนโซลสำหรับโค้ดที่ถูกบล็อก

ในกรณีส่วนใหญ่ การแก้ไขจะตรงไปตรงมา ดังนี้

เปลี่ยนโครงสร้างเครื่องจัดการเหตุการณ์ในบรรทัดใหม่

อนุญาตโดย CSP
<span id="things">A thing.</span>
<script nonce="${nonce}">
  document.getElementById('things').addEventListener('click', doThings);
</script>
CSP อนุญาตให้ใช้ตัวจัดการเหตุการณ์ที่ลงทะเบียนโดยใช้ JavaScript
ถูกบล็อกโดย CSP
<span onclick="doThings();">A thing.</span>
CSP บล็อกตัวแฮนเดิลเหตุการณ์ในบรรทัด

เปลี่ยนโครงสร้าง URI javascript: รายการ

อนุญาตโดย CSP
<a id="foo">foo</a>
<script nonce="${nonce}">
  document.getElementById('foo').addEventListener('click', linkClicked);
</script>
CSP อนุญาตให้ใช้ตัวจัดการเหตุการณ์ที่ลงทะเบียนโดยใช้ JavaScript
ถูกบล็อกโดย CSP
<a href="javascript:linkClicked()">foo</a>
CSP บล็อก javascript: URI

นำ eval() ออกจาก JavaScript

หากแอปพลิเคชันของคุณใช้ eval() เพื่อแปลงการเรียงลำดับสตริง JSON เป็นออบเจ็กต์ JS คุณควรเปลี่ยนโครงสร้างภายในโค้ดของอินสแตนซ์ดังกล่าวเป็น JSON.parse() ซึ่งเร็วกว่าด้วย

หากไม่สามารถนำการใช้ eval() ทั้งหมดออกได้ คุณยังคงตั้งค่า CSP ที่อิงตาม Nonce ที่เข้มงวดได้ แต่ต้องใช้คีย์เวิร์ด CSP 'unsafe-eval' ซึ่งจะทำให้นโยบายมีความปลอดภัยน้อยลงเล็กน้อย

คุณดูตัวอย่างการเปลี่ยนโครงสร้างภายในโค้ดดังกล่าวและตัวอย่างอื่นๆ ได้ใน Codelab ของ CSP แบบเข้มงวดนี้

ขั้นตอนที่ 4 (ไม่บังคับ): เพิ่มทางเลือกสำรองเพื่อรองรับเบราว์เซอร์เวอร์ชันเก่า

Browser Support

  • Chrome: 52.
  • Edge: 79.
  • Firefox: 52.
  • Safari: 15.4.

หากต้องการรองรับเบราว์เซอร์เวอร์ชันเก่า ให้ทำดังนี้

  • การใช้ strict-dynamic ต้องเพิ่ม https: เป็นการกำหนดค่าสำรองสำหรับ Safari เวอร์ชันก่อนหน้า ซึ่งจะส่งผลดังต่อไปนี้
    • เบราว์เซอร์ทั้งหมดที่รองรับ strict-dynamic จะละเว้น https: สำรอง ดังนั้นจึงไม่ลดความเข้มงวดของนโยบาย
    • ในเบราว์เซอร์รุ่นเก่า สคริปต์ที่มาจากภายนอกจะโหลดได้ก็ต่อเมื่อมาจากต้นทาง HTTPS เท่านั้น วิธีนี้มีความปลอดภัยน้อยกว่า CSP ที่เข้มงวด แต่ก็ยังป้องกันสาเหตุ XSS ที่พบบ่อยได้ เช่น การแทรก URI javascript:
  • เพื่อให้มั่นใจว่าเข้ากันได้กับเบราว์เซอร์เวอร์ชันเก่ามาก (อายุ 4 ปีขึ้นไป) คุณสามารถเพิ่ม unsafe-inline เป็นทางเลือกสำรองได้ เบราว์เซอร์ล่าสุดทั้งหมดจะละเว้น unsafe-inline หากมี Nonce หรือแฮช CSP อยู่
Content-Security-Policy:
  script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';

ขั้นตอนที่ 5: ติดตั้งใช้งาน CSP

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

  1. (ไม่บังคับ) นำ CSP ไปใช้ในโหมดรายงานเท่านั้นโดยใช้ส่วนหัว Content-Security-Policy-Report-Only โหมดรายงานเท่านั้นมีประโยชน์ในการทดสอบการเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบ เช่น CSP ใหม่ในเวอร์ชันที่ใช้งานจริงก่อนที่คุณจะเริ่มบังคับใช้ข้อจำกัด CSP ในโหมดรายงานเท่านั้น CSP จะไม่ส่งผลต่อลักษณะการทำงานของแอป แต่เบราว์เซอร์จะยังคงสร้างข้อผิดพลาดในคอนโซลและรายงานการละเมิดเมื่อพบรูปแบบที่เข้ากันไม่ได้กับ CSP เพื่อให้คุณเห็นว่าสิ่งใดที่อาจทำให้ผู้ใช้ปลายทางใช้งานไม่ได้ ดูข้อมูลเพิ่มเติมได้ที่ Reporting API
  2. เมื่อมั่นใจว่า CSP จะไม่ทำให้เว็บไซต์ใช้งานไม่ได้สำหรับผู้ใช้ปลายทาง ให้ติดตั้งใช้งาน CSP โดยใช้ส่วนหัวการตอบกลับ Content-Security-Policy เราขอแนะนำให้ตั้งค่า CSP โดยใช้ส่วนหัว HTTP ฝั่งเซิร์ฟเวอร์เนื่องจากปลอดภัยกว่าแท็ก <meta> หลังจากทำขั้นตอนนี้เสร็จแล้ว CSP จะเริ่มปกป้องแอปของคุณจาก XSS

ข้อจำกัด

โดยทั่วไปแล้ว CSP ที่เข้มงวดจะช่วยเพิ่มความปลอดภัยอีกชั้นที่รัดกุมซึ่งช่วยลด XSS ได้ ในกรณีส่วนใหญ่ CSP จะลดพื้นที่การโจมตีได้อย่างมากโดยการปฏิเสธรูปแบบที่เป็นอันตราย เช่น URI javascript: อย่างไรก็ตาม ขึ้นอยู่กับประเภทของ CSP ที่คุณใช้ (nonces, hashes, มีหรือไม่มี 'strict-dynamic') มีบางกรณีที่ CSP ไม่ปกป้องแอปของคุณเช่นกัน

  • หากคุณใช้ Nonce กับสคริปต์ แต่มีการแทรกโดยตรงลงในเนื้อหาหรือพารามิเตอร์ src ขององค์ประกอบ <script> นั้น
  • หากมีการแทรกสคริปต์ลงในตำแหน่งของสคริปต์ที่สร้างขึ้นแบบไดนามิก (document.createElement('script')) รวมถึงฟังก์ชันไลบรารีที่สร้างโหนด DOM script โดยอิงตามค่าของอาร์กิวเมนต์ ซึ่งรวมถึง API ทั่วไปบางรายการ เช่น .html() ของ jQuery รวมถึง .get() และ .post() ใน jQuery < 3.0
  • หากมีการแทรกเทมเพลตในแอปพลิเคชัน AngularJS เวอร์ชันเก่า ผู้โจมตีที่สามารถแทรกโค้ดลงในเทมเพลต AngularJS จะใช้เทมเพลตดังกล่าวเพื่อเรียกใช้ JavaScript ที่กำหนดเองได้
  • หากนโยบายมี 'unsafe-eval' การแทรกใน eval(), setTimeout() และ API อื่นๆ ที่ไม่ค่อยได้ใช้

นักพัฒนาแอปและวิศวกรด้านความปลอดภัยควรให้ความสำคัญกับรูปแบบดังกล่าวเป็นพิเศษในระหว่างการรีวิวโค้ดและการตรวจสอบความปลอดภัย ดูรายละเอียดเพิ่มเติมเกี่ยวกับกรณีเหล่านี้ได้ในนโยบายความปลอดภัยของเนื้อหา: ความยุ่งเหยิงที่ประสบความสำเร็จระหว่างการทำให้ปลอดภัยยิ่งขึ้นและการลดความเสี่ยง

อ่านเพิ่มเติม