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

David Dworken
David Dworken

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

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

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

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

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

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

เมื่อเวลาผ่านไป เว็บได้พัฒนาขึ้นเรื่อยๆ และตอนนี้ก็แสดงเนื้อหาที่ไม่น่าเชื่อถือให้ง่ายขึ้นและปลอดภัยยิ่งขึ้น วิธีการต่างๆ มีอยู่หลายวิธี ดังนั้นเราจะสรุปโซลูชัน 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' เพื่อบล็อกไม่ให้มีการฝังปลายทาง
  • เนื้อหาของผู้ใช้แซนด์บ็อกซ์ในโดเมนย่อยที่แยกต่างหากด้วยการทำดังนี้
    • การแสดงเนื้อหาของผู้ใช้บนโดเมนย่อยที่แยกต่างหาก (เช่น 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 ทั้งหมดจะถูกกำหนดเส้นทางไปยังไฟล์ Shim แบบคงที่ ไฟล์ shim นี้มีข้อมูลโค้ด HTML และ JavaScript สั้นๆ ที่รอฟังเครื่องจัดการเหตุการณ์ message และแสดงเนื้อหาใดๆ ที่ได้รับ
  • หากต้องการใช้ตัวเลือกนี้ ผลิตภัณฑ์จะสร้าง iframe หรือป๊อปอัปไปยัง $RANDOM_VALUE.exampleusercontent.com/shim และใช้ postMessage เพื่อส่งเนื้อหาที่ไม่น่าเชื่อถือไปยัง Shim เพื่อแสดงผล
  • เนื้อหาที่แสดงผลจะมีการเปลี่ยนรูปแบบเป็น Blob และแสดงผลใน iframe ที่ทำแซนด์บ็อกซ์

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

บทสรุป

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