การโฮสต์ข้อมูลผู้ใช้อย่างปลอดภัยในเว็บแอปพลิเคชันสมัยใหม่

David Dworken
David Dworken

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

โซลูชันแบบคลาสสิกสำหรับการแยกเนื้อหาที่ไม่น่าเชื่อถือ

โซลูชันแบบคลาสสิกในการแสดงเนื้อหาที่ผู้ใช้ควบคุมอย่างปลอดภัยคือการใช้สิ่งที่เรียกว่าโดเมนแซนด์บ็อกซ์ แนวคิดพื้นฐานคือ หากโดเมนหลักของแอปพลิเคชันคือ example.com คุณจะแสดงเนื้อหาที่ไม่น่าเชื่อถือทั้งหมดใน exampleusercontent.com ได้ เนื่องจากโดเมน 2 โดเมนนี้เป็นโดเมนข้ามเว็บไซต์ เนื้อหาที่เป็นอันตรายใน exampleusercontent.com จึงไม่สามารถส่งผลกระทบต่อ example.com
แนวทางนี้สามารถใช้เพื่อแสดงเนื้อหาที่ไม่น่าเชื่อถือทุกประเภทได้อย่างปลอดภัย ซึ่งรวมถึงรูปภาพ การดาวน์โหลด และ HTML แม้ว่าอาจดูเหมือนว่าไม่จำเป็นต้องใช้กับรูปภาพหรือการดาวน์โหลด แต่การดำเนินการดังกล่าวจะช่วยหลีกเลี่ยงความเสี่ยงจากการสแกนเนื้อหา โดยเฉพาะในเบราว์เซอร์รุ่นเดิม
โดเมนแซนด์บ็อกซ์มีการใช้งานอย่างแพร่หลายในอุตสาหกรรมและใช้งานได้ดีมาเป็นเวลานาน แต่ก็มีข้อเสียที่สำคัญ 2 ข้อดังนี้

  • แอปพลิเคชันมักต้องจำกัดการเข้าถึงเนื้อหาไว้สำหรับผู้ใช้เพียงคนเดียว ซึ่งต้องใช้การตรวจสอบสิทธิ์และการให้สิทธิ์ เนื่องจากโดเมนแซนด์บ็อกซ์ไม่ได้แชร์คุกกีกับโดเมนแอปพลิเคชันหลักโดยเจตนา การดำเนินการนี้จึงทําได้ยากมาก หากต้องการรองรับการตรวจสอบสิทธิ์ เว็บไซต์จะต้องใช้ URL ความสามารถ หรือตั้งค่าคุกกี้การตรวจสอบสิทธิ์แยกต่างหากสำหรับโดเมนแซนด์บ็อกซ์ วิธีที่สองนี้ก่อให้เกิดปัญหาอย่างยิ่งในเว็บสมัยใหม่ซึ่งเบราว์เซอร์จํานวนมากจํากัดคุกกี้ข้ามเว็บไซต์โดยค่าเริ่มต้น
  • แม้ว่าเนื้อหาของผู้ใช้จะถูกแยกออกจากเว็บไซต์หลัก แต่จะไม่แยกออกจากเนื้อหาของผู้ใช้รายอื่น ซึ่งจะทำให้เกิดความเสี่ยงที่เนื้อหาที่เป็นอันตรายของผู้ใช้จะโจมตีข้อมูลอื่นๆ ในโดเมนแซนด์บ็อกซ์ (เช่น ผ่านการอ่านข้อมูลต้นทางเดียวกัน)

นอกจากนี้ โดเมนแซนด์บ็อกซ์ยังช่วยลดความเสี่ยงจากฟิชชิงด้วย เนื่องจากมีการแบ่งทรัพยากรไปยังโดเมนแยกต่างหากอย่างชัดเจน

โซลูชันสมัยใหม่สำหรับการแสดงเนื้อหาของผู้ใช้

เว็บได้พัฒนาไปเรื่อยๆ และตอนนี้มีวิธีแสดงเนื้อหาที่ไม่น่าเชื่อถือที่ง่ายและปลอดภัยยิ่งขึ้น แนวทางนี้มีหลากหลายวิธี เราจึงจะสรุป 2 โซลูชันที่ Google ใช้กันอย่างแพร่หลายในปัจจุบัน

แนวทางที่ 1: การแสดงเนื้อหาของผู้ใช้ที่ไม่ได้ใช้งาน

หากเว็บไซต์ต้องการแสดงเฉพาะเนื้อหาของผู้ใช้ที่ไม่ได้ใช้งาน (นั่นคือเนื้อหาที่ไม่ใช่ HTML หรือ JavaScript เช่น รูปภาพและการดาวน์โหลด) ตอนนี้คุณก็ทําได้อย่างปลอดภัยโดยไม่ต้องใช้โดเมนแซนด์บ็อกซ์แยกต่างหาก โดยขั้นตอนสำคัญมี 2 ขั้นตอนดังนี้

  • ตั้งค่าส่วนหัว Content-Type เป็นประเภท MIME ที่รู้จักกันดีซึ่งเบราว์เซอร์ทุกรุ่นรองรับและรับประกันว่าไม่มีเนื้อหาที่ใช้งานอยู่เสมอ (หากไม่แน่ใจ application/octet-stream เป็นตัวเลือกที่ปลอดภัย)
  • นอกจากนี้ ให้ตั้งค่าส่วนหัวการตอบกลับด้านล่างเสมอเพื่อให้เบราว์เซอร์แยกการตอบกลับออกอย่างสมบูรณ์
ส่วนหัวการตอบกลับ Purpose

X-Content-Type-Options: nosniff

ป้องกันการตรวจหาเนื้อหา

Content-Disposition: attachment; filename="download"

ทริกเกอร์การดาวน์โหลดแทนการแสดงผล

Content-Security-Policy: sandbox

วางเนื้อหาในกล่องทดสอบเสมือนว่าแสดงในโดเมนแยกต่างหาก

Content-Security-Policy: default-src ‘none'

ปิดใช้การเรียกใช้ JavaScript (และการรวมทรัพยากรย่อย)

Cross-Origin-Resource-Policy: same-site

ป้องกันไม่ให้รวมหน้าเว็บในหลายเว็บไซต์

การรวมส่วนหัวนี้ช่วยให้มั่นใจได้ว่าแอปพลิเคชันจะโหลดคำตอบเป็นทรัพยากรย่อยได้เท่านั้น หรือผู้ใช้จะดาวน์โหลดเป็นไฟล์ได้ นอกจากนี้ ส่วนหัวยังให้การปกป้องหลายชั้นจากข้อบกพร่องของเบราว์เซอร์ผ่านส่วนหัวแซนด์บ็อกซ์ CSP และข้อจํากัด default-src โดยรวมแล้ว การตั้งค่าที่ระบุไว้ข้างต้นมีความน่าเชื่อถือในระดับสูงว่าคำตอบที่แสดงด้วยวิธีนี้จะไม่ทำให้เกิดช่องโหว่ในการแทรกหรือแยก

การป้องกันเชิงลึก

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

  • ตั้งค่าส่วนหัว X-Content-Security-Policy: sandbox เพื่อความเข้ากันได้กับ IE11
  • ตั้งค่าส่วนหัว Content-Security-Policy: frame-ancestors 'none' เพื่อบล็อกไม่ให้ฝังปลายทาง
  • เนื้อหาของผู้ใช้ใน Sandbox ในโดเมนย่อยที่แยกต่างหากโดยทำดังนี้
    • การแสดงเนื้อหาของผู้ใช้ในโดเมนย่อยที่แยกต่างหาก (เช่น Google ใช้โดเมน เช่น product.usercontent.google.com)
    • ตั้งค่า Cross-Origin-Opener-Policy: same-origin และ Cross-Origin-Embedder-Policy: require-corp เพื่อเปิดใช้การแยกแบบข้ามต้นทาง

แนวทางที่ 2: การแสดงเนื้อหาต่อผู้ใช้ที่ใช้งานอยู่

นอกจากนี้ คุณยังแสดงเนื้อหาที่ใช้งานอยู่อย่างปลอดภัย (เช่น รูปภาพ HTML หรือ SVG) ได้โดยไม่ต้องอาศัยข้อเสียของแนวทางโดเมนแซนด์บ็อกซ์แบบคลาสสิก
ตัวเลือกที่ง่ายที่สุดคือใช้ประโยชน์จากส่วนหัว Content-Security-Policy: sandbox เพื่อบอกให้เบราว์เซอร์แยกการตอบกลับ แม้ว่าปัจจุบันเว็บเบราว์เซอร์บางรุ่นจะไม่ใช้การแยกกระบวนการสำหรับเอกสารในกล่องทราย แต่การปรับแต่งโมเดลกระบวนการของเบราว์เซอร์อย่างต่อเนื่องมีแนวโน้มที่จะปรับปรุงการแยกเนื้อหาในกล่องทรายออกจากแอปพลิเคชันการฝัง หากการโจมตี SpectreJS และการเจาะช่องโหว่โปรแกรมแสดงผลอยู่นอกรูปแบบภัยคุกคามของคุณ การใช้แซนด์บ็อกซ์ CSP อาจเป็นโซลูชันที่เพียงพอ
ที่ Google เราได้พัฒนาโซลูชันที่สามารถแยกเนื้อหาที่ใช้งานอยู่ซึ่งไม่น่าเชื่อถือออกได้อย่างสมบูรณ์โดยนำแนวคิดโดเมนแซนด์บ็อกซ์มาปรับให้ทันสมัย แนวคิดหลักคือ

  • สร้างโดเมนแซนด์บ็อกซ์ใหม่ซึ่งเพิ่มลงในรายการนามสกุลสาธารณะ ตัวอย่างเช่น การเพิ่ม exampleusercontent.com ลงใน PSL จะช่วยให้มั่นใจได้ว่า foo.exampleusercontent.com และ bar.exampleusercontent.com อยู่ในหลายเว็บไซต์และแยกจากกันโดยสมบูรณ์
  • URL ที่ตรงกับ *.exampleusercontent.com/shim ทั้งหมดจะส่งไปยังไฟล์ชิมแบบคงที่ ไฟล์ชิมนี้มีข้อมูลโค้ด HTML และ JavaScript สั้นๆ ที่คอยฟังเหตุการณ์ message และแสดงผลเนื้อหาที่ได้รับ
  • หากต้องการใช้ฟีเจอร์นี้ ผลิตภัณฑ์จะสร้าง iframe หรือป๊อปอัปไปยัง $RANDOM_VALUE.exampleusercontent.com/shim และใช้ postMessage เพื่อส่งเนื้อหาที่ไม่น่าเชื่อถือไปยังชิมเพื่อแสดงผล
  • ระบบจะเปลี่ยนรูปแบบเนื้อหาที่แสดงผลเป็น Blob และแสดงผลภายใน iframe ที่ทำแซนด์บ็อกซ์

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

บทสรุป

โซลูชันทั้ง 2 รายการนี้ช่วยให้คุณย้ายข้อมูลจากโดเมนแซนด์บ็อกซ์แบบคลาสสิก เช่น googleusercontent.com ไปยังโซลูชันที่ปลอดภัยกว่าซึ่งเข้ากันได้กับการบล็อกคุกกี้ของบุคคลที่สาม เราที่ Google ได้ย้ายข้อมูลผลิตภัณฑ์หลายรายการไปใช้โซลูชันเหล่านี้แล้ว และวางแผนที่จะย้ายข้อมูลเพิ่มเติมในปีหน้า