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

CSP (Content Security Policy) คือ response header ที่บอกเบราว์เซอร์ว่าสคริปต์ตัวไหนรันได้ โดเมนไหนโหลดทรัพยากรได้ ต้อง deploy เป็นสามขั้นตอน: เริ่มจาก Report-Only 14 วันเพื่อเก็บแหล่งที่ละเมิด แล้วค่อยรวบรวม whitelist ให้สะอาด

CSP部署:报告模式先跑两周再切强制CSP: report-only for two weeks, then enforce 一上来就enforce会把站内第三方脚本全打挂Enforcing on day one breaks every third-party script 1 Report-Only1 Report-Only 只收集违规 不拦截Collect violations, no block 跑14天 收集所有来源Run 14 days to collect sources 2 白名单收敛2 Whitelist tuning 按报告加域名 不violent-inlineAdd domains from reports sha256 hash 替代unsafe-inlinesha256 instead of unsafe-inline 3 Enforce3 Enforce 违规日志为0再切Switch when reports hit 0 保留report-uri 继续监控Keep report-uri watching 核心指令Core directives default-src 兜底 script-src 控脚本default-src fallback, script-src controls JS object-src ‘none’ frame-ancestors 防嵌套object-src none, frame-ancestors 红线Red lines 别开 * 通配符 等于没配Wildcard * equals no CSP unsafe-inline 留着等于被绕过unsafe-inline defeats the purpose 判定:报告模式跑满14天且违规数降到个位数,再切EnforceDecision: enforce after 14 days of near-zero reports 反直觉:CSP不是越严越安全,配错了比不配更危险Counterintuitive: misconfigured CSP is worse than none 先报告后强制,把违规源一个个收进白名单Report first, enforce later
ติดตั้ง CSP สามขั้นตอน: Report-Only เก็บข้อมูล, รวบรวม whitelist, บังคับใช้ Enforce

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

สรุปก่อน: CSP (Content Security Policy) คือ response header ที่บอกเบราว์เซอร์ว่าสคริปต์ตัวไหนรันได้ โดเมนไหนโหลดทรัพยากรได้ ต้อง deploy เป็นสามขั้นตอน: เริ่มจาก Report-Only 14 วันเพื่อเก็บแหล่งที่ละเมิด แล้วค่อยรวบรวม whitelist ให้สะอาด รอให้ log การละเมิดเหลือหลักหน่วยก่อนจึงสลับเป็น Enforce ข้อสังเกตที่ขัดกับสัญชาตญาณคือ CSP ที่ตั้งค่าผิดอันตรายกว่าไม่ตั้งเลย เพราะการเปิด unsafe-inline เท่ากับสร้างกำแพงทิ้งเปล่า

หนึ่ง CSP กันอะไรได้จริง

CSP ส่งกฎผ่าน HTTP response header เบราว์เซอร์ใช้กฎนี้ตัดสินใจว่าทรัพยากรใดโหลดได้ ป้องกันปัญหาหลักสองอย่าง: สคริปต์อันตรายจากการฉีด XSS และโดเมนบุคคลที่สามที่ไม่ได้รับอนุญาตถูกฝังเข้าไปในหน้าเว็บ

มันไม่ใช่ไฟร์วอลล์ CSP กัน SQL injection ไม่ได้ และกันเซิร์ฟเวอร์ถูกบุกรุกก็ไม่ได้ มันดูแลการโหลดทรัพยากรฝั่งเบราว์เซอร์ ทำงานร่วมกับ HTTPS และ HSTS วิธีตั้งค่า HTTPS ดูที่การตั้งค่า HTTPS สำหรับเว็บไซต์อิสระ。

ปัญหาที่เว็บไซต์อิสระเจอบ่อยคือสคริปต์บุคคลที่สามเยอะเกินไป: GA4, GTM, Hotjar, แชทออนไลน์, พิกเซลโฆษณา ทุกครั้งที่เพิ่มสคริปต์ ต้องเพิ่มโดเมนใน whitelist ของ CSP ไม่งั้นเบราว์เซอร์จะบล็อกสคริปต์ การจัดการสคริปต์บุคคลที่สามดูที่การจัดการสคริปต์บุคคลที่สามสำหรับเว็บไซต์อิสระ。

ข้อเท็จจริงที่มักถูกมองข้ามคือ CSP แทบไม่มีผลเสียต่อ SEO Googlebot เองไม่ได้จำกัดทรัพยากรนอกเหนือจาก JS การตั้งค่า CSP ที่ดีไม่กระทบการจัดเก็บข้อมูล กังวลว่า CSP จะกระทบการครอว์ลนั้นเกินเหตุ

คำสั่ง ควบคุมอะไร ค่าที่แนะนำ
default-src ทรัพยากรทั้งหมดเป็นค่าเริ่มต้น ‘self’
script-src แหล่งที่มาของสคริปต์ JS ‘self’ + โดเมนสถิติ
style-src แหล่งที่มาของ CSS ‘self’ ‘unsafe-inline’
img-src แหล่งที่มาของรูปภาพ ‘self’ data: + CDN
object-src ปลั๊กอิน ‘none’ (ต้องปิด)
frame-ancestors ใครฝังเว็บนี้ได้ ‘none’

สอง ขั้นตอนการติดตั้งสามระยะ: รายงาน, รวบรวม, บังคับใช้

ข้อผิดพลาดที่พบบ่อยที่สุดคือใส่ header Content-Security-Policy ไปเลย วิธีนี้จะบล็อกสคริปต์ทั้งหมดในเว็บที่ไม่อยู่ใน whitelist ทันที GA4, แชทออนไลน์, พิกเซลพังหมด ฝ่ายธุรกิจจะร้องเรียนทันที

วิธีที่ถูกต้องคือใช้ header Content-Security-Policy-Report-Only ก่อน เบราว์เซอร์จะรายงานการละเมิดเท่านั้น ไม่บล็อก เก็บ log สองสัปดาห์ แล้วเพิ่มโดเมนที่ใช้จริงทั้งหมดเข้า whitelist

ตัวอย่างสถานการณ์ที่หนึ่ง: เพิ่ม CSP ให้เว็บ WordPress เริ่มจากส่ง Report-Only

สองวันต่อมาในรายงานปรากฏโดเมน googletagmanager.com, hotjar.com, youtube.com สามโดเมน

เพิ่มทีละรายการเข้า script-src และ frame-src สองสัปดาห์ต่อมารายงานเหลือแค่หลักหน่วยต่อวัน จึงสลับเป็นโหมดบังคับใช้

ระยะ response header การกระทำ ระยะเวลา
ขั้นแรก Content-Security-Policy-Report-Only รายงานอย่างเดียว ไม่บล็อก 14 วัน
ขั้นที่สอง เหมือนเดิม ค่อย ๆ เพิ่มไวท์ลิสต์ การละเมิดลดลงทุกวัน จนเหลือหลักหน่วย
ขั้นที่สาม Content-Security-Policy บล็อกจริง ระยะยาว
ตลอดกระบวนการ เพิ่ม report-to หรือ report-uri เก็บรายงานการละเมิด เปิดไว้ตลอด

สคริปต์อินไลน์คือหลุมที่ใหญ่ที่สุด ธีม WordPress และปลั๊กอินหลายตัวเขียน <script> ลงในหน้าเว็บโดยตรง ซึ่ง CSP บล็อกอินไลน์ไว้เป็นค่าเริ่มต้น มีสองวิธี วิธีแรกคือย้ายสคริปต์อินไลน์ออกไปเป็นไฟล์ js ภายนอก วิธีที่สองคือใช้แฮช sha256 เพื่ออนุญาตเฉพาะบล็อกนั้น ไม่ใช่เปิด unsafe-inline เพราะขี้เกียจ

style-src ผ่อนกว่า script-src ตัวแก้ไข Gutenberg และธีมหลายตัวจะส่ง style อินไลน์ออกมา ถ้า style-src เปิด unsafe-inline ไว้ชั่วคราวก็ไม่ใช่เรื่องใหญ่

แต่ script-src ห้ามเปิด unsafe-inline เด็ดขาด เพราะนี่คือแนวป้องกันหลักของ CSP ในการกัน XSS มาตรฐานความเข้มงวดของสองคำสั่งนี้ต้องแยกกัน

สาม ความเสี่ยงในการถูกหลบเลี่ยง อย่าให้ CSP เป็นแค่ป้าย

ตั้งค่า CSP ผิดก็เหมือนไม่ได้ตั้ง สามรูปแบบต่อไปนี้ทำให้กำแพงนี้ใช้ไม่ได้ทันที

แบบแรกคือเปิด unsafe-inline มันอนุญาตให้สคริปต์อินไลน์ใด ๆ ทำงานได้ สคริปต์อันตรายที่ถูกฉีดผ่าน XSS ก็รันได้ แนวป้องกันหลักของ CSP ก็พัง แบบที่สองคือเปิดไวลด์การ์ด * เท่ากับไม่จำกัดแหล่งที่มา แบบที่สามคือลืม object-src เบราว์เซอร์เก่ายังหลบผ่าน Flash หรือปลั๊กอินได้

ตัวอย่างสถานการณ์ที่สอง ขี้เกียจเลยเขียน ‘unsafe-inline’ ลงใน script-src

สองเดือนต่อมา เว็บไซต์ถูกฝังสคริปต์ฟิชชิงแบบอินไลน์ และ CSP ก็ไม่สามารถบล็อกได้เลย

วิธีที่ถูกต้องคือใช้ nonce สุ่มค่าใหม่ทุกครั้งที่ร้องขอ อนุญาตเฉพาะสคริปต์อินไลน์ที่มีค่านี้

วิธีเขียนที่ผิด ความเสี่ยง ทางเลือกทดแทน
script-src * สคริปต์บุคคลที่สามใด ๆ โหลดได้ ระบุโดเมนในไวท์ลิสต์ทีละราย
script-src ‘unsafe-inline’ สคริปต์ที่ฉีดผ่าน XSS ยังรันตามปกติ ย้ายออกเป็นไฟล์ภายนอกหรือใช้ nonce/แฮช
ไม่เขียน object-src ปลั๊กอินเก่าถูกใช้ในทางที่ผิดได้ object-src ‘none’
ไม่ตั้งค่า frame-ancestors หน้าถูกฝังใน iframe โดยไม่หวังดี frame-ancestors ‘none’

CSP กับความสอดคล้องตามกฎหมายเป็นคนละเรื่อง การยินยอมคุกกี้ตาม GDPR เป็นอีกกลไกหนึ่ง ดูที่ความสอดคล้อง GDPR สำหรับเว็บไซต์อิสระ CSP ป้องกันการฉีดสคริปต์ ไม่ได้แก้ปัญหาการยินยอมคุกกี้ ส่วนการเข้าสู่ระบบและสิทธิ์ไฟล์ระดับเซิร์ฟเวอร์ดูที่การเสริมความปลอดภัยเว็บไซต์อิสระ。

เลือก nonce หรือแฮชอย่างไร สคริปต์อินไลน์แบบคงที่ใช้แฮช สคริปต์อินไลน์ที่สร้างแบบไดนามิกใช้ nonce โค้ดติดตามแบบคงที่ในธีม WordPress นับเป็นแฮชเพื่ออนุญาต บล็อกสคริปต์ที่เนื้อหาเปลี่ยนทุกครั้งที่ร้องขอใช้ nonce

ตำแหน่งที่ติดตั้งก็มีข้อควรพิจารณา ควรส่ง CSP response header จากชั้น Nginx หรือ CDN ไม่ควรพึ่งให้แอป PHP ส่งออก เพราะการส่งจากชั้นแอปจะหายไปเมื่อ PHP ทำงานผิดพลาด แต่การส่งจากชั้น CDN เสถียรกว่า

ตำแหน่งติดตั้ง ความเสถียร เหมาะกับ
การตั้งค่า Nginx สูง แอปล่มก็ยังอยู่ เซิร์ฟเวอร์ที่สร้างเอง
กฎ CDN สูง มีผลทั่วโลก ใช้ Cloudflare เป็นต้น
ส่งออกจากแอป PHP ต่ำ หายเมื่อเกิดข้อขัดข้อง ทดสอบชั่วคราว

ปลายทางรับรายงานก็ต้องสร้างแยกต่างหาก ที่อยู่ที่ report-uri ชี้ไปต้องไม่ถูก CSP บล็อกเอง ไม่งั้นรายงานก็ส่งออกไม่ได้

เว็บไซต์ standalone สามารถใช้บริการเก็บ report สำเร็จรูป หรือจะตั้ง log endpoint เฉพาะใน Nginx เพื่อรับ report แล้วเขียนลงไฟล์ log แยกต่างหาก ไม่ปนกับ log ทราฟฟิกของเว็บหลัก

เมื่อปริมาณ report เยอะขึ้นต้องทำ aggregation วันหนึ่งอาจได้ report หลายร้อยรายการ ดูทีละรายการไม่ไหว ให้จัดกลุ่มตาม directive ที่ถูกละเมิดและโดเมนที่ถูกบล็อก แล้วโฟกัสที่โดเมนใหม่ที่เพิ่มขึ้นในแต่ละวัน

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

ดังนั้นหลังจากเปลี่ยนเป็น Enforce แล้ว ห้ามปิด report-uri เพราะมันคือสัญญาณเดียวที่บอกคุณว่า “สคริปต์ที่เพิ่งเพิ่มลืมใส่ whitelist”

เรื่องการรองรับของเบราว์เซอร์ก็ต้องพูดถึง เบราว์เซอร์สมัยใหม่ (Chrome, Edge, Firefox, Safari เวอร์ชันสองปีล่าสุด) รองรับ CSP 3 ครบถ้วน ส่วน IE เก่าข้ามไปได้เลย เพราะผู้เข้าชมเว็บไซต์ standalone แบบ B2B แทบไม่ใช้ IE

ยังมีรายละเอียดตอน deploy อีกอย่าง คือ header CSP ต้องส่งทั้ง http และ https ถ้าส่งเฉพาะ https คำขอช่วง http ต้นทางจะไม่ได้รับการป้องกันจาก CSP

หลังจากเปลี่ยนเป็น Enforce แนะนำให้คง header Report-Only ไว้ทำงานคู่กันสักระยะ ทั้งบล็อกทั้งรายงาน เผื่อมีอะไรตกหล่นจะได้เห็นใน report

CSP ไม่ใช่โปรเจกต์ที่ทำครั้งเดียวจบ ทุกครั้งที่เพิ่มสคริปต์บุคคลที่สามใหม่ (แชท คุย วิดีโอ โฆษณา) ต้องดูก่อนในโหมด report ว่ามันโผล่มาในรายการละเมิด แล้วค่อยเพิ่มโดเมนนั้นเข้า whitelist จากนั้นจึงเปลี่ยนเป็น production

ใส่การตรวจ CSP เข้าไปในเช็กลิสต์ก่อนอัปสคริปต์ใหม่ พอเพิ่มสคริปต์ก็เพิ่ม whitelist ไปพร้อมกัน ไม่ต้องรอให้ผู้ใช้แจ้งว่า “ปุ่มไม่แสดง” หลังอัปแล้วค่อยนึกถึง CSP

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

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

หน้าที่สุ่มตรวจไม่ผ่าน ให้กลับไปหาโดเมนที่เกี่ยวข้องใน report เพิ่มเข้า whitelist แล้วเฝ้าดูอีกหนึ่งวัน วนแบบนี้สองสามรอบก็จะนิ่ง

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

แหล่งที่มาของ report ความหมาย วิธีจัดการ
ละเมิด script-src สคริปต์ใหม่ยังไม่ได้ใส่ whitelist เพิ่มโดเมนหรือแยกเป็นไฟล์ภายนอก
ละเมิด img-src รูปที่ลิงก์ภายนอกมาจากโดเมนใหม่ เพิ่ม CDN หรือเปลี่ยนเป็น path สัมพัทธ์
ละเมิด frame-src มีการฝัง iframe ใหม่ เพิ่มโดเมนวิดีโอหรือเอาออก
ละเมิด base-uri หน้าถูก inject แท็ก base ตรวจ XSS ทันที

FAQ คำถามที่พบบ่อย

CSP ควรใช้โหมดบังคับตั้งแต่เปิดใช้งานเลยไหม?
ไม่ต้อง เริ่มจากโหมดรายงาน Content-Security-Policy-Report-Only ไปก่อน 14 วัน เบราว์เซอร์จะรายงานการละเมิดเท่านั้น ไม่บล็อก นำโดเมนจริงที่ปรากฏในรายงานมาใส่ใน whitelist ทีละโดเมน พอ log การละเมิดลดลงเหลือหลักหน่วย ค่อยสลับไปใช้โหมดบังคับ Content-Security-Policy ถ้าบังคับตั้งแต่แรกจะทำให้ GA4 ระบบแชทลูกค้า และ pixel โฆษณาพังทั้งหมด
สคริปต์ inline ใน WordPress theme ถูก CSP บล็อกทำอย่างไร?
อย่าเปิด unsafe-inline เพราะขี้เกียจ มีสองวิธีที่ถูกต้อง วิธีแรก ดึงสคริปต์ inline ออกมาเป็นไฟล์ js แยก แล้วเรียกด้วย src วิธีที่สอง สำหรับสคริปต์ inline ที่จำเป็นต้องเก็บไว้ ให้คำนวณ sha256 hash แล้วอนุญาต hash นั้นใน script-src การใช้ unsafe-inline จะทำให้สคริปต์อันตรายที่ถูก inject ผ่าน XSS รันได้ด้วย เท่ากับตั้งค่า CSP ทิ้งเปล่า
CSP กับ HTTPS และ HSTS เกี่ยวข้องกันอย่างไร?
ทั้งสามทำงานร่วมกันแต่ไม่ทับซ้อนกัน HTTPS ดูแลการเข้ารหัสการรับส่งข้อมูล HSTS บังคับให้เบราว์เซอร์ใช้ HTTPS เท่านั้น CSP ดูแลว่าฝั่งเบราว์เซอร์โหลดสคริปต์และทรัพยากรอะไรได้บ้าง การติดตั้ง HTTPS เป็นเงื่อนไขพื้นฐาน CSP เป็นการป้องกัน XSS และสคริปต์บุคคลที่สามที่ไม่ได้รับอนุญาตบน HTTPS อีกชั้น ถ้าติดตั้งแค่ CSP ไม่ติดตั้ง HTTPS ก็ไม่มีความหมาย
ทำไมรายงาน CSP ของฉันมีแต่การละเมิด?
แสดงว่า whitelist ยังไม่ครบ แต่ละรายงานการละเมิดจะระบุว่าสคริปต์ที่ถูกบล็อกมาจากโดเมนไหน ให้นำโดเมนนั้นใส่ใน directive ที่ตรงกัน (script-src, img-src, frame-src ฯลฯ) สถิติบุคคลที่สาม ระบบแชทลูกค้า และวิดีโอฝัง เป็นตัวการที่หลุดบ่อยที่สุด ความหมายของโหมดรายงานอยู่ตรงนี้ เก็บให้ครบก่อนแล้วค่อยบังคับ
CSP ป้องกัน SQL injection ได้ไหม?
ไม่ได้ CSP ทำงานฝั่งเบราว์เซอร์ ควบคุมแค่การโหลดทรัพยากร ป้องกัน SQL injection ฝั่งเซิร์ฟเวอร์ไม่ได้ SQL injection ต้องแก้ด้วย prepared statement ของฐานข้อมูลและการกรองข้อมูลนำเข้า CSP ป้องกันหลักๆ คือ XSS สคริปต์อันตรายที่ผู้โจมตี inject เข้ามาจะถูก CSP บล็อกไม่ให้รัน แต่การ inject เองเกิดขึ้นที่เซิร์ฟเวอร์แล้ว
ยังต้องเก็บ report-uri ไว้ไหม?
ต้อง ถึงจะสลับไปโหมดบังคับ Enforce แล้ว ก็ยังต้องเก็บ report-to หรือ report-uri ไว้เพื่อเก็บการละเมิดใหม่ที่เกิดขึ้นต่อเนื่อง สคริปต์บุคคลที่สามที่เพิ่มใหม่และโค้ด inline ที่มาจากการอัปเดต theme จะปรากฏในรายงานก่อนทั้งนั้น แนะนำให้ส่งรายงานการละเมิดไปยัง log service แล้วดูโดเมนผิดปกติวันละครั้ง

ทิ้งท้าย

จุดยากของ CSP ไม่ได้อยู่ที่การเขียนกฎ แต่อยู่ที่ความอดทนในการรันโหมดรายงาน ระยะสังเกตสองสัปดาห์แลกกับการควบคุมสคริปต์ได้อีกหลายปี คุ้มค่า

สามขั้นตอนลงมือทำ เริ่มจากเปิด Report-Only รัน 14 วัน จากรายงานนำโดเมนจริงมาใส่ whitelist ทีละโดเมน ใช้ hash แทน unsafe-inline พอการละเมิดลดลงเหลือหลักหน่วยค่อยสลับเป็นโหมดบังคับ พร้อมเก็บ report ไว้เฝ้าต่อ

ประโยคที่จำได้ง่ายๆ ระดับความปลอดภัยของ CSP ขึ้นอยู่กับว่า whitelist สะอาดแค่ไหน ถ้ายังเก็บ unsafe-inline และ wildcard ไว้ กำแพงนี้ก็เท่ากับไม่ได้ก่อ

crater
crater ผู้เชี่ยวชาญ环形山

ทางการขององค์กร · 环形山 Crater

环形山 (Crater) เป็นบริษัทให้บริการขยายตลาดต่างประเทศที่เชี่ยวชาญการพัฒนาเว็บไซต์ WordPress แบบ Independent Site + Google SEO + GEO เพื่อการเติบโตแบบครบวงจร ให้บริการในกลุ่มธุรกิจ Smart Hardware, Industrial Equipment, SaaS, New Energy และอื่นๆ

ความสามารถของผลิตภัณฑ์ไวท์เปเปอร์ระเบียบวิธีรายงานอุตสาหกรรม
965แชร์
78บทความในคลังความรู้