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

การรองรับเบราว์เซอร์

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

แหล่งที่มา

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

นโยบายรักษาความปลอดภัยเนื้อหา (CSP) เป็นการรักษาความปลอดภัยอีกชั้นหนึ่งที่ช่วยลดความเสี่ยงของ XSS หากต้องการกําหนดค่า CSP ให้เพิ่มส่วนหัว Content-Security-Policy HTTP ลงในหน้าเว็บและกําหนดค่าที่จะควบคุมทรัพยากรที่ 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 หรือ Hash โดยอนุญาตให้เรียกใช้สคริปต์ที่สคริปต์ที่เชื่อถือสร้างขึ้นโดยอัตโนมัติ ซึ่งจะเป็นการเลิกบล็อกการใช้ไลบรารีและวิดเจ็ต JavaScript ของบุคคลที่สามส่วนใหญ่ด้วย
  • ไม่ได้อิงตามรายการที่อนุญาตของ URL จึงไม่ต้องกังวลเกี่ยวกับการหลบเลี่ยง CSP ที่พบบ่อย
  • โดยจะบล็อกสคริปต์ในบรรทัดที่ไม่เชื่อถือ เช่น ตัวจัดการเหตุการณ์ในบรรทัดหรือ javascript: URI
  • โดยจะจำกัด object-src ให้ปิดใช้ปลั๊กอินที่เป็นอันตราย เช่น Flash
  • ซึ่งจะจํากัด base-uri ไม่ให้แทรกแท็ก <base> ซึ่งจะช่วยป้องกันไม่ให้ผู้โจมตีเปลี่ยนตำแหน่งของสคริปต์ที่โหลดจาก URL แบบสัมพัทธ์

ใช้ CSP แบบเข้มงวด

หากต้องการใช้ CSP ที่เข้มงวด คุณต้องดำเนินการต่อไปนี้

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

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

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

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

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)
  • แท็กส่วนหัวหรือ <meta> ของ HTML สําหรับการพัฒนาในเครื่อง แท็ก <meta> อาจสะดวกกว่าในการปรับแต่ง CSP และดูผลลัพธ์ที่ส่งผลต่อเว็บไซต์ได้อย่างรวดเร็ว อย่างไรก็ตาม
    • ในภายหลัง เมื่อติดตั้งใช้งาน CSP ในระบบที่ใช้งานจริง เราขอแนะนำให้ตั้งค่า CSP เป็นส่วนหัว HTTP
    • หากต้องการตั้งค่า CSP ในโหมดรายงานเท่านั้น คุณจะต้องตั้งค่าเป็นส่วนหัว เนื่องจากเมตาแท็ก CSP ไม่รองรับโหมดรายงานเท่านั้น

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

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

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

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

  • ค่าสุ่มที่รัดกุมทางวิทยาการเข้ารหัส (ควรมีความยาวมากกว่า 128 บิต)
  • สร้างใหม่สําหรับคําตอบแต่ละรายการ
  • เข้ารหัส Base64

ตัวอย่างวิธีเพิ่ม CSP nonce ในเฟรมเวิร์กฝั่งเซิร์ฟเวอร์มีดังนี้

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 อนุญาต

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

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 จะโหลดก่อนก็ตาม ในสnippet นี้ s.async = false ไม่ได้บล็อกโปรแกรมแยกวิเคราะห์ขณะที่โหลดสคริปต์ เนื่องจากมีการเพิ่มสคริปต์แบบไดนามิก ตัวแยกวิเคราะห์จะหยุดเฉพาะขณะที่สคริปต์ทำงาน เช่นเดียวกับสคริปต์ async อย่างไรก็ตาม โปรดทราบว่า

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

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

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

หากเปิดใช้ 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' ซึ่งทําให้นโยบายมีความปลอดภัยน้อยลงเล็กน้อย

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

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

การรองรับเบราว์เซอร์

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

แหล่งที่มา

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

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

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

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

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

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

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

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