ทำไมทั้งที่เขียนเองแท้ ๆ ทั้งหน้าบ้านหลังบ้าน แต่พอยิง API จากหน้าบ้านไปแล้วถึงติด”คอ” ได้?
“CORS” ตัวหนังสือสั้น ๆ 4 ตัวที่เป็นฝันร้ายของ Frontend Developer ที่คุยกับหลังบ้านไม่ได้ หรือที่ยิ่งเศร้ากว่าก็คือ Full-Stack Developer ที่แม้แต่ API ที่เขียนเองก็ยังยิงไม่ได้
พวกนี้มันเกิดจากอะไร ทำไมบางทีรันบนเครื่องไม่เป็น แต่เอาขึ้นไปแล้วเป็น? จะแก้ไขได้ต้องทำความเข้าใจก่อนว่า CORS คืออะไร แล้วมีไว้ทำไม?
CORS มีไว้ทำอะไร?
ก่อนจะรู้จัก CORS ต้องรู้จัก Same-Origin Policy ที่จะเป็นกลไกการรักษาความปลอดภัยในเบราว์เซอร์ของเราที่จะไม่ให้ส่ง HTTP Request ที่อยู่ต่าง Origin กัน
ต่าง Origin คือการที่โดเมน, พอร์ท หรือ Scheme* ไม่ตรงกัน ดังนั้น http://myweb.com และ http://api.myweb.com ก็ไม่ถือว่าเป็น Origin เดียวกัน
แต่ถ้า http://myweb.com กับ http://api.myweb.com คุยกันไม่ได้เว็บจะทำงานได้อย่างไร? ตรงนี้คือจุดที่ CORS หรือ Cross-Origin Resource Sharing เข้ามาช่วยให้ต่าง Origin คุยกันได้ โดยจะจำกัดว่ายอมให้ Origin ไหนเรียกใช้งานได้บ้าง
* Scheme คือการระบุโปรโตคอลที่จะใช้งานเช่น http:// ก็เป็นการระบุว่าจะใช้งาน HTTP
ถ้าไม่จำกัดโดเมนมันอันตรายขนาดไหน?
จากที่ได้กล่าวไปว่าถ้าต่าง Origin กันมาเรียกกันได้อาจไม่ปลอดภัยเพราะอะไร ส่วนนี้จะยกตัวอย่างด้วยการโจมตีแบบ Cross-Site Request Forgery หรือ CSRF
สมมุติว่าเว็บธนาคารที่เราเข้าใช้งานยอมให้ทุก Origin มาเรียกใช้งานได้ จะทำให้โดนโจมตีได้ดังนี้:
- เข้าสู่ระบบเพื่อเข้าไปใช้งานธนาคารผ่านเว็บตามปกติ
- ได้โทเคนมาเก็บไว้ในเบราว์เซอร์ เพื่อคงสถานะการเข้าสู่ระบบ
- ใช้งานเว็บธนาคารเสร็จก็ท่องเว็บไปเรื่อย แต่ดันเผลอไปเข้าเว็บที่ประสงค์ร้าย
- ในขณะที่เข้าชมเว็บนั้นอยู่ เบื้องหลังก็ส่ง Request ไปยังเว็บธนาคาร ซึ่งการที่เบราว์เซอร์เรามีโทเคนของธนาคารค้างไว้อยู่ ทำให้ Request นั้นเหมือนเราเป็นคนส่งออกไป ทำธุรกรรมแทนเราได้อย่างไม่รู้ตัว
เว็บนั้นอาจเป็นเว็บรวมรูปแมว, เว็บสูตรอาหาร หรืออื่น ๆ ที่ดูไม่มีพิษภัยอะไร แต่รู้ตัวอีกทีเงินก็อาจหมดบัญชีแล้วก็ได้ ดังนั้นนี่จึงเป็นเหตุผลว่าทำไมถึงต้องใช้ CORS มาจำกัดในส่วนนี้
หมายเหตุ - การตั้ง CORS ที่เหมาะสมไม่ได้ป้องกัน CSRF Attack ได้อย่าง 100% เพราะ CORS เป็นกลไกฝั่งเบราว์เซอร์เท่านั้น