คู่มือฉบับสมบูรณ์เพื่อเสริมสร้างความปลอดภัยของ frontend โดยใช้ Content Security Policy (CSP) และ Cross-Origin Resource Sharing (CORS) เพื่อปกป้องเว็บแอปพลิเคชันของคุณจากภัยคุกคามสมัยใหม่
การเสริมความแข็งแกร่งด้านความปลอดภัยของ Frontend: Content Security Policy และ CORS
ในโลกดิจิทัลที่เชื่อมต่อถึงกันในปัจจุบัน ความปลอดภัยของ frontend ถือเป็นสิ่งสำคัญอย่างยิ่ง เว็บแอปพลิเคชันตกเป็นเป้าหมายของการโจมตีที่ซับซ้อนมากขึ้นเรื่อยๆ ทำให้มาตรการรักษาความปลอดภัยที่แข็งแกร่งเป็นสิ่งจำเป็น สององค์ประกอบที่สำคัญของสถาปัตยกรรม frontend ที่ปลอดภัยคือ Content Security Policy (CSP) และ Cross-Origin Resource Sharing (CORS) คู่มือฉบับสมบูรณ์นี้จะให้ข้อมูลเชิงลึกเกี่ยวกับเทคโนโลยีเหล่านี้ พร้อมตัวอย่างที่นำไปใช้ได้จริงและข้อมูลเชิงลึกที่นำไปปฏิบัติได้ เพื่อช่วยให้คุณเสริมความแข็งแกร่งให้กับเว็บแอปพลิเคชันของคุณจากภัยคุกคามสมัยใหม่
Content Security Policy (CSP) คืออะไร?
Content Security Policy (CSP) เป็นชั้นความปลอดภัยเพิ่มเติมที่ช่วยตรวจจับและบรรเทาการโจมตีบางประเภท รวมถึง Cross-Site Scripting (XSS) และการโจมตีแบบ data injection CSP ถูกนำมาใช้โดยเว็บเซิร์ฟเวอร์ที่ส่ง HTTP response header ชื่อ Content-Security-Policy ไปยังเบราว์เซอร์ header นี้จะกำหนด whitelist ของแหล่งที่มาที่เบราว์เซอร์ได้รับอนุญาตให้โหลดทรัพยากรได้ การจำกัดแหล่งที่มาของเนื้อหาที่เบราว์เซอร์สามารถโหลดได้ ทำให้ CSP สร้างความยากลำบากอย่างมากสำหรับผู้โจมตีในการแทรกโค้ดที่เป็นอันตรายเข้ามาในเว็บไซต์ของคุณ
CSP ทำงานอย่างไร
CSP ทำงานโดยสั่งให้เบราว์เซอร์โหลดเฉพาะทรัพยากร (เช่น สคริปต์, สไตล์ชีต, รูปภาพ, ฟอนต์) จากแหล่งที่มาที่ได้รับอนุมัติเท่านั้น แหล่งที่มาเหล่านี้จะถูกระบุไว้ใน CSP header โดยใช้ directives หากเบราว์เซอร์พยายามโหลดทรัพยากรจากแหล่งที่มาที่ไม่ได้รับอนุญาตอย่างชัดเจน เบราว์เซอร์จะบล็อกคำขอนั้นและรายงานการละเมิด
CSP Directives: ภาพรวมที่ครอบคลุม
CSP directives ควบคุมประเภทของทรัพยากรที่สามารถโหลดได้จากแหล่งที่มาที่เฉพาะเจาะจง นี่คือรายละเอียดของ directives ที่สำคัญที่สุดบางส่วน:
- default-src: ระบุแหล่งที่มาเริ่มต้นสำหรับเนื้อหาทุกประเภท นี่คือ directive สำรองที่จะถูกใช้เมื่อไม่มี directive ที่เฉพาะเจาะจงกว่า
- script-src: ระบุแหล่งที่มาที่สามารถโหลดสคริปต์ได้ นี่เป็นสิ่งสำคัญอย่างยิ่งในการป้องกันการโจมตีแบบ XSS
- style-src: ระบุแหล่งที่มาที่สามารถโหลดสไตล์ชีตได้
- img-src: ระบุแหล่งที่มาที่สามารถโหลดรูปภาพได้
- font-src: ระบุแหล่งที่มาที่สามารถโหลดฟอนต์ได้
- media-src: ระบุแหล่งที่มาที่สามารถโหลดเสียงและวิดีโอได้
- object-src: ระบุแหล่งที่มาที่สามารถโหลดปลั๊กอิน (เช่น Flash) ได้ มักจะตั้งค่าเป็น 'none' เพื่อปิดการใช้งานปลั๊กอินทั้งหมดเนื่องจากความเสี่ยงด้านความปลอดภัยที่มีอยู่
- frame-src: ระบุแหล่งที่มาที่สามารถโหลดเฟรม (เช่น <iframe>) ได้
- connect-src: ระบุ URL ที่ user agent สามารถเชื่อมต่อได้โดยใช้อินเทอร์เฟซสคริปต์ เช่น XMLHttpRequest, WebSocket และ EventSource
- base-uri: ระบุ URL ที่สามารถใช้ในองค์ประกอบ <base> ของเอกสารได้
- form-action: ระบุ URL ที่สามารถส่งการยื่นฟอร์มไปได้
- upgrade-insecure-requests: สั่งให้ user agent อัปเกรดคำขอที่ไม่ปลอดภัย (HTTP) เป็นคำขอที่ปลอดภัย (HTTPS) โดยอัตโนมัติ
- report-uri: ระบุ URL ที่เบราว์เซอร์ควรส่งรายงานเกี่ยวกับการละเมิด CSP directive นี้ถูกเลิกใช้แล้วและแนะนำให้ใช้ `report-to` แทน
- report-to: ระบุชื่อกลุ่มการรายงานที่กำหนดไว้ใน header `Report-To` ซึ่งเบราว์เซอร์ควรส่งรายงานเกี่ยวกับการละเมิด CSP ไปที่นั่น
คีย์เวิร์ดรายการแหล่งที่มาของ CSP
ภายใน CSP directives คุณสามารถใช้คีย์เวิร์ดรายการแหล่งที่มาเพื่อกำหนดแหล่งที่มาที่ได้รับอนุญาต นี่คือคีย์เวิร์ดทั่วไปบางส่วน:
- 'self': อนุญาตทรัพยากรจาก origin เดียวกัน (scheme และ host) กับเอกสาร
- 'none': ไม่อนุญาตทรัพยากรจากทุกแหล่งที่มา
- 'unsafe-inline': อนุญาตให้ใช้สคริปต์และสไตล์แบบ inline (เช่น แท็ก <script> และ thuộc tính style) โปรดใช้ด้วยความระมัดระวังอย่างยิ่ง เนื่องจากมันลดทอนการป้องกันของ CSP ต่อ XSS อย่างมาก
- 'unsafe-eval': อนุญาตให้ใช้ฟังก์ชันการประเมินโค้ดแบบไดนามิก เช่น
eval()และFunction()โปรดใช้ด้วยความระมัดระวังอย่างยิ่ง เนื่องจากมันนำมาซึ่งความเสี่ยงด้านความปลอดภัยที่สำคัญ - 'unsafe-hashes': อนุญาตให้ใช้ event handlers แบบ inline หรือแท็ก <style> ที่เฉพาะเจาะจงซึ่งตรงกับ hash ที่ระบุ ต้องมีการสนับสนุนจากเบราว์เซอร์ โปรดใช้ด้วยความระมัดระวัง
- 'strict-dynamic': ระบุว่าความไว้วางใจที่มอบให้กับสคริปต์ที่มีอยู่ใน markup อย่างชัดเจน โดยการแนบ nonce หรือ hash ไปด้วย จะถูกส่งต่อไปยังสคริปต์ทั้งหมดที่โหลดโดยสคริปต์หลักนั้น
- data: อนุญาต data: URIs (เช่น รูปภาพ inline ที่เข้ารหัสเป็น base64) โปรดใช้ด้วยความระมัดระวัง
- https:: อนุญาตให้โหลดทรัพยากรผ่าน HTTPS จากโดเมนใดก็ได้
- [hostname]: อนุญาตทรัพยากรจากโดเมนที่ระบุ (เช่น example.com) คุณยังสามารถระบุหมายเลขพอร์ตได้ด้วย (เช่น example.com:8080)
- [scheme]://[hostname]:[port]: URI ที่สมบูรณ์ อนุญาตทรัพยากรจาก scheme, host และ port ที่ระบุ
ตัวอย่างการใช้งาน CSP จริง
มาดูตัวอย่างการใช้งานจริงของ CSP headers กัน:
ตัวอย่างที่ 1: CSP พื้นฐานด้วย 'self'
นโยบายนี้อนุญาตทรัพยากรจาก origin เดียวกันเท่านั้น:
Content-Security-Policy: default-src 'self'
ตัวอย่างที่ 2: การอนุญาตสคริปต์จากโดเมนที่ระบุ
นโยบายนี้อนุญาตสคริปต์จากโดเมนของคุณเองและ CDN ที่เชื่อถือได้:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
ตัวอย่างที่ 3: การปิดใช้งานสคริปต์และสไตล์แบบ Inline
นโยบายนี้ไม่อนุญาตสคริปต์และสไตล์แบบ inline ซึ่งเป็นการป้องกันที่แข็งแกร่งต่อ XSS:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'
สำคัญ: การปิดใช้งานสคริปต์แบบ inline จำเป็นต้องมีการปรับโครงสร้าง HTML ของคุณเพื่อย้ายสคริปต์ inline ไปยังไฟล์ภายนอก
ตัวอย่างที่ 4: การใช้ Nonces สำหรับสคริปต์แบบ Inline
หากคุณจำเป็นต้องใช้สคริปต์แบบ inline ให้ใช้ nonces (โทเค็นแบบสุ่มทางการเข้ารหัสที่ใช้ครั้งเดียว) เพื่อ whitelist บล็อกสคริปต์ inline ที่เฉพาะเจาะจง วิธีนี้ปลอดภัยกว่า 'unsafe-inline' เซิร์ฟเวอร์ต้องสร้าง nonce ที่ไม่ซ้ำกันสำหรับแต่ละคำขอและรวมไว้ในทั้ง CSP header และแท็ก <script>
Content-Security-Policy: default-src 'self'; script-src 'nonce-r4nd0mN0nc3'; style-src 'self'
<script nonce="r4nd0mN0nc3"> console.log('Inline script'); </script>
หมายเหตุ: อย่าลืมสร้าง nonce ใหม่สำหรับทุกๆ คำขอ อย่าใช้ nonces ซ้ำ!
ตัวอย่างที่ 5: การใช้ Hashes สำหรับสไตล์แบบ Inline
เช่นเดียวกับ nonces, hashes สามารถใช้เพื่อ whitelist บล็อก <style> แบบ inline ที่เฉพาะเจาะจงได้ ซึ่งทำได้โดยการสร้าง hash แบบ SHA256, SHA384 หรือ SHA512 ของเนื้อหาสไตล์นั้นๆ
Content-Security-Policy: default-src 'self'; style-src 'sha256-HASHEDSTYLES'
<style sha256="HASHEDSTYLES"> body { background-color: #f0f0f0; } </style>
หมายเหตุ: Hashes มีความยืดหยุ่นน้อยกว่า nonces เนื่องจากการเปลี่ยนแปลงใดๆ ในเนื้อหาสไตล์จะทำให้ hash ไม่ถูกต้อง
ตัวอย่างที่ 6: การรายงานการละเมิด CSP
เพื่อตรวจสอบการละเมิด CSP ให้ใช้ directive report-uri หรือ report-to:
Content-Security-Policy: default-src 'self'; report-to csp-endpoint;
คุณจะต้องกำหนดค่า header Report-To ด้วย header Report-To จะกำหนดกลุ่มการรายงานหนึ่งกลุ่มหรือมากกว่า ซึ่งระบุว่าควรส่งรายงานไปที่ไหนและอย่างไร
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"https://example.com/csp-report"}]}
การทดสอบและปรับใช้ CSP
การนำ CSP มาใช้ต้องมีการวางแผนและทดสอบอย่างรอบคอบ เริ่มต้นด้วยนโยบายที่เข้มงวดและค่อยๆ ผ่อนปรนตามความจำเป็น ใช้ header Content-Security-Policy-Report-Only เพื่อทดสอบนโยบายของคุณโดยไม่บล็อกทรัพยากร header นี้จะรายงานการละเมิดโดยไม่บังคับใช้นโยบาย ทำให้คุณสามารถระบุและแก้ไขปัญหาก่อนที่จะปรับใช้นโยบายใน production
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint;
วิเคราะห์รายงานที่สร้างโดยเบราว์เซอร์เพื่อระบุการละเมิดใดๆ และปรับนโยบายของคุณตามนั้น เมื่อคุณมั่นใจว่านโยบายของคุณทำงานอย่างถูกต้องแล้ว ให้ปรับใช้โดยใช้ header Content-Security-Policy
แนวทางปฏิบัติที่ดีที่สุดสำหรับ CSP
- เริ่มต้นด้วย default-src: กำหนด
default-srcเสมอเพื่อสร้างนโยบายพื้นฐาน - ระบุให้เจาะจง: ใช้ directives และคีย์เวิร์ดรายการแหล่งที่มาที่เฉพาะเจาะจงเพื่อจำกัดขอบเขตของนโยบายของคุณ
- หลีกเลี่ยง 'unsafe-inline' และ 'unsafe-eval': คีย์เวิร์ดเหล่านี้ลดทอนความปลอดภัยของ CSP อย่างมากและควรหลีกเลี่ยงทุกครั้งที่ทำได้
- ใช้ nonces หรือ hashes สำหรับสคริปต์และสไตล์แบบ inline: หากคุณจำเป็นต้องใช้สคริปต์หรือสไตล์แบบ inline ให้ใช้ nonces หรือ hashes เพื่อ whitelist บล็อกโค้ดที่เฉพาะเจาะจง
- ตรวจสอบการละเมิด CSP: ใช้ directive
report-uriหรือreport-toเพื่อตรวจสอบการละเมิด CSP และปรับนโยบายของคุณตามนั้น - ทดสอบอย่างละเอียด: ใช้ header
Content-Security-Policy-Report-Onlyเพื่อทดสอบนโยบายของคุณก่อนที่จะปรับใช้ใน production - ทำซ้ำและปรับปรุง: CSP ไม่ใช่การกำหนดค่าครั้งเดียวจบ ควรตรวจสอบและปรับปรุงนโยบายของคุณอย่างต่อเนื่องเพื่อปรับให้เข้ากับการเปลี่ยนแปลงในแอปพลิเคชันของคุณและภูมิทัศน์ของภัยคุกคาม
Cross-Origin Resource Sharing (CORS) คืออะไร?
Cross-Origin Resource Sharing (CORS) เป็นกลไกที่อนุญาตให้หน้าเว็บจาก origin (โดเมน) หนึ่งเข้าถึงทรัพยากรจาก origin อื่นได้ โดยค่าเริ่มต้น เบราว์เซอร์จะบังคับใช้นโยบาย Same-Origin Policy ซึ่งป้องกันไม่ให้สคริปต์ส่งคำขอไปยัง origin ที่แตกต่างจากที่สคริปต์นั้นกำเนิดขึ้นมา CORS เป็นวิธีการผ่อนปรนข้อจำกัดนี้อย่างมีเงื่อนไข เพื่ออนุญาตคำขอข้าม origin ที่ถูกต้องตามกฎหมาย ในขณะที่ยังคงป้องกันการโจมตีที่เป็นอันตราย
ทำความเข้าใจนโยบาย Same-Origin Policy
นโยบาย Same-Origin Policy เป็นกลไกความปลอดภัยพื้นฐานที่ป้องกันไม่ให้สคริปต์ที่เป็นอันตรายจากเว็บไซต์หนึ่งเข้าถึงข้อมูลที่ละเอียดอ่อนบนเว็บไซต์อื่น origin ถูกกำหนดโดย scheme (โปรโตคอล), host (โดเมน) และ port URL สองแห่งจะมี origin เดียวกันก็ต่อเมื่อมี scheme, host และ port เหมือนกันเท่านั้น
ตัวอย่างเช่น:
https://www.example.com/app1/index.htmlและhttps://www.example.com/app2/index.htmlมี origin เดียวกันhttps://www.example.com/index.htmlและhttp://www.example.com/index.htmlมี origin ต่างกัน (scheme ต่างกัน)https://www.example.com/index.htmlและhttps://sub.example.com/index.htmlมี origin ต่างกัน (host ต่างกัน)https://www.example.com:8080/index.htmlและhttps://www.example.com:80/index.htmlมี origin ต่างกัน (port ต่างกัน)
CORS ทำงานอย่างไร
เมื่อหน้าเว็บส่งคำขอข้าม origin เบราว์เซอร์จะส่งคำขอ \"preflight\" ไปยังเซิร์ฟเวอร์ก่อน คำขอ preflight จะใช้เมธอด HTTP OPTIONS และมี headers ที่ระบุเมธอด HTTP และ headers ที่คำขอจริงจะใช้ จากนั้นเซิร์ฟเวอร์จะตอบกลับด้วย headers ที่ระบุว่าอนุญาตคำขอข้าม origin หรือไม่
หากเซิร์ฟเวอร์อนุญาตคำขอ จะรวม header Access-Control-Allow-Origin ไว้ในการตอบกลับ header นี้จะระบุ origin ที่ได้รับอนุญาตให้เข้าถึงทรัพยากร จากนั้นเบราว์เซอร์จะดำเนินการส่งคำขอจริง หากเซิร์ฟเวอร์ไม่อนุญาตคำขอ จะไม่รวม header Access-Control-Allow-Origin และเบราว์เซอร์จะบล็อกคำขอนั้น
CORS Headers: รายละเอียดเชิงลึก
CORS อาศัย HTTP headers ในการสื่อสารระหว่างเบราว์เซอร์และเซิร์ฟเวอร์ นี่คือ CORS headers ที่สำคัญ:
- Access-Control-Allow-Origin: ระบุ origin ที่ได้รับอนุญาตให้เข้าถึงทรัพยากร header นี้สามารถมี origin ที่เฉพาะเจาะจง (เช่น
https://www.example.com), a wildcard (*), หรือnullได้ การใช้*จะอนุญาตคำขอจากทุก origin ซึ่งโดยทั่วไปไม่แนะนำด้วยเหตุผลด้านความปลอดภัย การใช้ `null` เหมาะสมเฉพาะสำหรับ \"opaque responses\" เช่น เมื่อทรัพยากรถูกดึงมาโดยใช้โปรโตคอล `file://` หรือ data URI - Access-Control-Allow-Methods: ระบุเมธอด HTTP ที่ได้รับอนุญาตสำหรับคำขอข้าม origin (เช่น
GET, POST, PUT, DELETE) - Access-Control-Allow-Headers: ระบุ HTTP headers ที่ได้รับอนุญาตในคำขอข้าม origin ซึ่งสำคัญสำหรับการจัดการ custom headers
- Access-Control-Allow-Credentials: ระบุว่าเบราว์เซอร์ควรจะรวมข้อมูลประจำตัว (เช่น คุกกี้, authorization headers) ในคำขอข้าม origin หรือไม่ header นี้ต้องตั้งค่าเป็น
trueเพื่ออนุญาตข้อมูลประจำตัว - Access-Control-Expose-Headers: ระบุว่า headers ใดที่สามารถเปิดเผยให้ client เห็นได้ โดยค่าเริ่มต้น จะมีเพียงชุด headers ที่จำกัดเท่านั้นที่ถูกเปิดเผย
- Access-Control-Max-Age: ระบุระยะเวลาสูงสุด (เป็นวินาที) ที่เบราว์เซอร์สามารถแคชคำขอ preflight ได้
- Origin: นี่คือ request header ที่เบราว์เซอร์ส่งเพื่อระบุ origin ของคำขอ
- Vary: เป็น HTTP header ทั่วไป แต่มีความสำคัญสำหรับ CORS เมื่อ
Access-Control-Allow-Originถูกสร้างขึ้นแบบไดนามิก ควรจะรวม headerVary: Originไว้ในการตอบกลับเพื่อบอกกลไกการแคชว่าการตอบสนองจะแตกต่างกันไปตาม request headerOrigin
ตัวอย่างการใช้งาน CORS จริง
มาดูตัวอย่างการกำหนดค่า CORS จริงกัน:
ตัวอย่างที่ 1: การอนุญาตคำขอจาก Origin ที่ระบุ
การกำหนดค่านี้อนุญาตคำขอจาก https://www.example.com เท่านั้น:
Access-Control-Allow-Origin: https://www.example.com
ตัวอย่างที่ 2: การอนุญาตคำขอจากทุก Origin (ไม่แนะนำ)
การกำหนดค่านี้อนุญาตคำขอจากทุก origin โปรดใช้ด้วยความระมัดระวัง เนื่องจากอาจนำมาซึ่งความเสี่ยงด้านความปลอดภัย:
Access-Control-Allow-Origin: *
ตัวอย่างที่ 3: การอนุญาตเมธอดและ Headers ที่เฉพาะเจาะจง
การกำหนดค่านี้อนุญาตเมธอด GET, POST, และ PUT และ headers Content-Type และ Authorization:
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
ตัวอย่างที่ 4: การอนุญาตข้อมูลประจำตัว (Credentials)
เพื่ออนุญาตข้อมูลประจำตัว (เช่น คุกกี้) คุณต้องตั้งค่า Access-Control-Allow-Credentials เป็น true และระบุ origin ที่เฉพาะเจาะจง (คุณไม่สามารถใช้ * เมื่ออนุญาตข้อมูลประจำตัว):
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Credentials: true
คุณยังต้องตั้งค่า credentials: 'include' ในคำขอ JavaScript fetch/XMLHttpRequest ของคุณด้วย
fetch('https://api.example.com/data', {
credentials: 'include'
})
คำขอ Preflight ของ CORS
สำหรับคำขอข้าม origin บางประเภท (เช่น คำขอที่มี custom headers หรือเมธอดอื่นที่ไม่ใช่ GET, HEAD, หรือ POST ที่มี Content-Type เป็น application/x-www-form-urlencoded, multipart/form-data, หรือ text/plain) เบราว์เซอร์จะส่งคำขอ preflight โดยใช้เมธอด OPTIONS เซิร์ฟเวอร์ต้องตอบกลับคำขอ preflight ด้วย CORS headers ที่เหมาะสมเพื่อระบุว่าอนุญาตคำขอจริงหรือไม่
นี่คือตัวอย่างของคำขอและคำตอบ preflight:
คำขอ Preflight (OPTIONS):
OPTIONS /data HTTP/1.1
Origin: https://www.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization
คำตอบ Preflight (200 OK):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
header Access-Control-Max-Age ระบุระยะเวลาที่เบราว์เซอร์สามารถแคชการตอบสนอง preflight ได้ ซึ่งช่วยลดจำนวนคำขอ preflight ลง
CORS และ JSONP
JSON with Padding (JSONP) เป็นเทคนิคเก่าสำหรับหลีกเลี่ยงนโยบาย Same-Origin Policy อย่างไรก็ตาม JSONP มีความเสี่ยงด้านความปลอดภัยที่สำคัญและควรหลีกเลี่ยงเพื่อหันมาใช้ CORS แทน JSONP อาศัยการแทรกแท็ก <script> เข้าไปในหน้า ซึ่งสามารถรันโค้ดใดๆ ก็ได้ CORS เป็นวิธีที่ปลอดภัยและยืดหยุ่นกว่าในการจัดการคำขอข้าม origin
แนวทางปฏิบัติที่ดีที่สุดสำหรับ CORS
- หลีกเลี่ยงการใช้ *: หลีกเลี่ยงการใช้ wildcard (*) ใน header
Access-Control-Allow-Originเนื่องจากจะอนุญาตคำขอจากทุก origin แทนที่จะทำเช่นนั้น ให้ระบุ origin ที่เฉพาะเจาะจงที่ได้รับอนุญาตให้เข้าถึงทรัพยากร - ระบุเมธอดและ headers ให้เจาะจง: ระบุเมธอด HTTP และ headers ที่แน่นอนที่ได้รับอนุญาตใน headers
Access-Control-Allow-MethodsและAccess-Control-Allow-Headers - ใช้ Access-Control-Allow-Credentials ด้วยความระมัดระวัง: เปิดใช้งาน
Access-Control-Allow-Credentialsต่อเมื่อคุณต้องการอนุญาตข้อมูลประจำตัว (เช่น คุกกี้) ในคำขอข้าม origin เท่านั้น โปรดตระหนักถึงผลกระทบด้านความปลอดภัยของการอนุญาตข้อมูลประจำตัว - รักษาความปลอดภัยคำขอ preflight ของคุณ: ตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ของคุณจัดการคำขอ preflight อย่างถูกต้องและส่งคืน CORS headers ที่ถูกต้อง
- ใช้ HTTPS: ใช้ HTTPS เสมอสำหรับทั้ง origin และทรัพยากรที่คุณกำลังเข้าถึงข้าม origin ซึ่งช่วยป้องกันการโจมตีแบบ man-in-the-middle
- Vary: Origin: หากคุณสร้าง header `Access-Control-Allow-Origin` แบบไดนามิก ให้รวม header `Vary: Origin` เสมอเพื่อป้องกันปัญหาการแคช
การใช้ CSP และ CORS ในทางปฏิบัติ: แนวทางแบบผสมผสาน
แม้ว่า CSP และ CORS จะแก้ไขปัญหาด้านความปลอดภัยทั้งคู่ แต่พวกมันทำงานในชั้นที่แตกต่างกันและให้การป้องกันที่เสริมกัน CSP เน้นการป้องกันไม่ให้เบราว์เซอร์โหลดเนื้อหาที่เป็นอันตราย ในขณะที่ CORS เน้นการควบคุมว่า origin ใดสามารถเข้าถึงทรัพยากรบนเซิร์ฟเวอร์ของคุณได้
ด้วยการรวม CSP และ CORS เข้าด้วยกัน คุณสามารถสร้างท่าทีด้านความปลอดภัยที่แข็งแกร่งยิ่งขึ้นสำหรับเว็บแอปพลิเคชันของคุณ ตัวอย่างเช่น คุณสามารถใช้ CSP เพื่อจำกัดแหล่งที่มาที่สามารถโหลดสคริปต์ได้ และใช้ CORS เพื่อควบคุมว่า origin ใดสามารถเข้าถึง API endpoints ของคุณได้
ตัวอย่าง: การรักษาความปลอดภัย API ด้วย CSP และ CORS
สมมติว่าคุณมี API ที่โฮสต์อยู่ที่ https://api.example.com และคุณต้องการให้เข้าถึงได้จาก https://www.example.com เท่านั้น คุณสามารถกำหนดค่าเซิร์ฟเวอร์ของคุณให้ส่งคืน headers ต่อไปนี้:
API Response Headers (https://api.example.com):
Access-Control-Allow-Origin: https://www.example.com
Content-Type: application/json
และคุณสามารถกำหนดค่าเว็บไซต์ของคุณ (https://www.example.com) ให้ใช้ CSP header ต่อไปนี้:
Website CSP Header (https://www.example.com):
Content-Security-Policy: default-src 'self'; script-src 'self'; connect-src 'self' https://api.example.com;
นโยบาย CSP นี้อนุญาตให้เว็บไซต์โหลดสคริปต์และเชื่อมต่อกับ API ได้ แต่ป้องกันไม่ให้โหลดสคริปต์หรือเชื่อมต่อกับโดเมนอื่น
สรุป
Content Security Policy (CSP) และ Cross-Origin Resource Sharing (CORS) เป็นเครื่องมือที่จำเป็นสำหรับการเสริมความแข็งแกร่งด้านความปลอดภัยของแอปพลิเคชัน frontend ของคุณ ด้วยการกำหนดค่า CSP และ CORS อย่างรอบคอบ คุณสามารถลดความเสี่ยงของการโจมตีแบบ XSS, การโจมตีแบบ data injection และช่องโหว่ด้านความปลอดภัยอื่นๆ ได้อย่างมาก อย่าลืมเริ่มต้นด้วยนโยบายที่เข้มงวด ทดสอบอย่างละเอียด และตรวจสอบและปรับปรุงการกำหนดค่าของคุณอย่างต่อเนื่องเพื่อปรับให้เข้ากับการเปลี่ยนแปลงในแอปพลิเคชันของคุณและภูมิทัศน์ของภัยคุกคามที่เปลี่ยนแปลงตลอดเวลา ด้วยการให้ความสำคัญกับความปลอดภัยของ frontend คุณสามารถปกป้องผู้ใช้ของคุณและรับประกันความสมบูรณ์ของเว็บแอปพลิเคชันของคุณในโลกดิจิทัลที่ซับซ้อนขึ้นเรื่อยๆ ในปัจจุบันได้