ป้องกันการโจมตีผ่าน CDN ด้วย Subresource Integrity

Nuttavut Thongjor

หลายคนที่เคยใช้งานไลบรารี่จาก CDN เช่น Bootstrap 4 จะพบว่าลิงก์จาก CDN นั้นมีอักขระยึกยือติดมาด้วย

HTML
1<link
2 rel="stylesheet"
3 href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"
4 integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4"
5 crossorigin="anonymous"

ตัวอักษรอันยืดยาวราวกับปริศนาธรรมนี้มีชื่อเรียกกิ๊บเก๋ว่า Subresource Integrity แต่จะมีความสำคัญยังไงนั้น เชิญเสพฮะ~

CDN อาจไม่ปลอดภัยเสมอไป

บริการออนไลน์อย่าง CDN แม้จะช่วยให้เพิ่มประสิทธิภาพในการเข้าถึงข้อมูล ไม่ว่าจะเป็น JavaScript หรือ Stylesheet แต่ไม่ได้หมายความว่าบริการนี้จะปลอดภัยเสมอไป

เพราะเหล่าแฮ็กเกอร์รู้ดีว่า CDN ที่เปิดกว้างนั้นเป็นบริการที่มีหลายเว็บไซต์ใช้งานอยู่ หากเขาได้สิทธิ์ในการเข้าถึงเหล่าผู้โจมตีคงมิปล่อยโอกาสทองเป็นแน่ อย่างน้อย ๆ ก็แค่ดัดแปลงไฟล์ซักนิด ยัดโค้ดไว้โจมตีซักหน่อย ก่อนจะจรลีไปจิบกาแฟต่อที่สตาร์บัค

สถานการณ์ที่ไม่สู้ดีเช่นนี้ ในฐานะที่เราเป็นเบราเซอร์ก็คงทำได้อย่างเดียวคือขอตรวจสอบดูซักหน่อยว่าไฟล์ที่กำลังจะใช้งานนั้นมีข้อมูลเหมือนต้นฉบับหรือไม่ หากมีสิ่งแปลกปลอมเราก็คงขอ #ตายแผล็บ

แล้วเว็บเบราเซอร์จะรู้ได้ยังไงว่าข้อมูลในไฟล์นั้นถูกเปลี่ยนแปลงมาแล้วหรือไม่?

ตรวจสอบข้อมูลด้วย Integrity

เพื่อเป็นการยืนยันว่าข้อมูลที่เราจะได้รับจาก CDN นั้นไม่ได้ถูกแก้ไขโดยผู้ประสงค์ร้าย เราจึงต้องมี flag บางอย่างให้เบราเซอร์คอยตรวจสอบได้ flag ที่ว่านี้ก็คือแอตทริบิวต์ที่ชื่อ integrity นั่นเอง

ทราบกันดีว่าหากเรามีข้อมูลชุดหนึ่ง หลังจากผ่าน hash function แล้วเราจะได้ค่าคงที่เสมอ ๆ อาศัยความจริงข้อนี้เราจึงโยนข้อมูลในไฟล์ของเราลง hash function แล้วจัดการนำค่าที่ได้ไปใส่ใน integrity เพียงแต่ว่าก่อนจะนำค่านี้ไปใส่ เราก็ทำการแปลงเป็น base64 เสียก่อน

ภายหลังที่เว็บเบราเซอร์ได้รับข้อมูลของไฟล์ที่อยู่ในแท็ก <script> หรือ <link> หากมี integrity มันจึงสามารถตรวจสอบว่าไฟล์นี้ถูกแก้ไขหรือไม่ด้วยการดูรหัสดังกล่าว หากข้อมูลเป็นเช่นเดิมข้อมูลที่เบราเซอร์ดูดมาพอผ่าน hash ก็ต้องได้ค่าเดียวกันกับค่าใน integrity

เราสามารถสร้างค่าข้อมูลนี้ได้โดยอาศัยเครื่องมืออย่าง openssl

Code
1cat <FILENAME> | openssl dgst -sha384 -binary | openssl enc -base64 -A

จากคำสั่งข้างต้นจะสังเกตเห็นว่าเราต้องมีการระบุอัลกอริทึมของการแฮชด้วย (ในตัวอย่างคือ SHA384) นั่นแสดงว่าเมื่อข้อมูลมาถึงเบราเซอร์ ตัวมันเองก็ต้องทราบว่าจะเทียบค่าด้วยการใช้อัลกอริทึมของ hash ตัวใดเช่นกัน กรณีของการระบุค่า integrity เราจึงจำเป็นต้องใส่อัลกอริทึมที่ใช้นำหน้า ตามด้วยเครื่องหมายขีด และค่าที่ได้จากการทำ base64 ของค่าแฮช เช่น

Code
1sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4

จะเกิดอะไรขึ้นเมื่อค่า integrity เปลี่ยนไป

ภายใต้แท็ก HTML อันสวยงาม หากเบราเซอร์พบแท็ก <script> หรือ <link> ที่มีการระบุแอตทริบิวต์ที่ชื่อ integrity ภายหลังการโหลดข้อมูลเสร็จสิ้นเว็บเบราเซอร์จะไม่ทำการประมวลผลข้อมูลในไฟล์ทันที แต่จะทำการตรวจสอบเนื้อหากับค่าจาก integrity ว่าตรงกันหรือไม่ ถ้าโอเคก็ปล่อยผ่าน แต่ถ้าโป๊ะเช๊ะว่าไม่ใช่เบราเซอร์ก็เลือกที่จะเมินหน้าหนีพร้อมปฏิเสธอย่างนางงามว่า Network Error

เอกสารอ้างอิง

Subresource Integrity. Retrieved May, 18, 2018, from https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity

สารบัญ

สารบัญ

  • CDN อาจไม่ปลอดภัยเสมอไป
  • ตรวจสอบข้อมูลด้วย Integrity
  • จะเกิดอะไรขึ้นเมื่อค่า integrity เปลี่ยนไป
  • เอกสารอ้างอิง