9 คะแนน โดย GN⁺ 2025-12-19 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • นักเรียนมัธยมปลายวัย 16 ปีได้สรุปและเผยแพร่กรณีที่สามารถโจมตีแบบ Cross-Site Scripting (XSS) บนเว็บไซต์เอกสารของบริษัทใหญ่ เช่น X, Vercel, Cursor และ Discord ได้ โดยอาศัย ช่องโหว่ของแพลตฟอร์ม Mintlify และได้รับ bug bounty 11,000 ดอลลาร์จากช่องโหว่นี้
  • พาธภายในของ Mintlify /_mintlify/static/[subdomain]/[...route] ถูกออกแบบให้ โหลดไฟล์ภายนอกได้โดยไม่มีการตรวจสอบโดเมน
  • ผู้โจมตีสามารถ ฝัง JavaScript ลงในไฟล์ SVG เพื่อรันสคริปต์อันตรายบนโดเมนของบริการหลักอย่าง Discord ได้
  • ช่องโหว่นี้ส่งผลกระทบต่อ ลูกค้าแทบทั้งหมดที่ใช้ Mintlify และเพียงแค่คลิกลิงก์ครั้งเดียวก็อาจถูกยึดบัญชีได้
  • เหตุการณ์นี้ถูกมองว่าเป็น ตัวอย่างที่แสดงให้เห็นว่าช่องโหว่เพียงจุดเดียวในความปลอดภัยของซัพพลายเชนสามารถนำไปสู่ความเสียหายในวงกว้างได้

การค้นพบบน Discord

  • การค้นหาช่องโหว่เริ่มต้นขึ้นเมื่อ Discord ย้ายไปใช้ Mintlify แพลตฟอร์มเอกสารที่ขับเคลื่อนด้วย AI ในเดือนพฤศจิกายน 2025
    • ทันทีหลังจากย้ายจากแพลตฟอร์มแบบคัสตอมเดิมมาเป็น Mintlify นักวิจัยได้วิเคราะห์โครงสร้างของระบบเอกสารใหม่
  • โดเมนเอกสารของ Discord (discord.mintlify.app) เปิดเผยพาธภายในของ Mintlify (/_mintlify/*) ออกมาตรง ๆ
    • พาธนี้จำเป็นต้องเข้าถึงได้เพื่อให้ฟีเจอร์สำคัญอย่างการยืนยันตัวตนทำงานได้

โครงสร้างแพลตฟอร์ม Mintlify

  • Mintlify เป็นบริการที่รองรับ การเขียนเอกสารด้วย Markdown และแปลงเป็นเอกสารเว็บโดยอัตโนมัติ
  • เว็บไซต์เอกสารทั้งหมดทำงานอยู่บนซับโดเมน *.mintlify.app หรือโดเมนแบบคัสตอม
  • ภายในใช้เอนด์พอยต์อย่าง /_mintlify/api/user, /_mintlify/markdown/, /_mintlify/static/ เป็นต้น

กระบวนการค้นหาช่องโหว่

  • พบว่าเอนด์พอยต์ /_mintlify/_markdown/_sites/[subdomain]/[...route] ส่งคืนไฟล์ของเอกสารอื่นได้โดยไม่มีการตรวจสอบโดเมน
    • อย่างไรก็ตาม พาธนี้ ส่งกลับเฉพาะข้อความ Markdown ที่ยังไม่เรนเดอร์ จึงไม่สามารถรันโค้ดได้
  • จากนั้นได้วิเคราะห์แพ็กเกจ Mintlify CLI และพบเอนด์พอยต์ /_mintlify/static/[subdomain]/[...route] เพิ่มเติม
    • พาธนี้ ส่งคืนไฟล์สแตติก และมีการใช้ whitelist ของนามสกุลไฟล์
    • แม้ไฟล์ HTML·JS จะถูกบล็อก แต่ ไฟล์ SVG ยังได้รับอนุญาต

การทำให้การโจมตีเกิดขึ้นจริง

  • ผู้โจมตีอัปโหลด ไฟล์ SVG ที่ฝัง JavaScript ไว้ลงในเอกสาร Mintlify ของตนเอง
  • เมื่อเรียกไฟล์ดังกล่าวจากโดเมนของ Discord (https://discord.com/_mintlify/_static/.../lmao.svg) ก็จะ มีการรันสคริปต์
  • ทำให้ไม่ใช่แค่ Discord เท่านั้น แต่ ทุกบริษัทที่ใช้ Mintlify สามารถถูกรัน XSS บนโดเมนเอกสารของตนได้

การประสานงานและการรายงาน

  • นักวิจัยได้ร่วมมือกับนักวิจัยด้านความปลอดภัยคนอื่น ๆ เพื่อตรวจสอบยืนยันช่องโหว่
  • Discord หลังได้รับรายงานก็ ปิดใช้งานเอกสารนักพัฒนาทั้งหมดเป็นเวลา 2 ชั่วโมง และหลังจากนั้น ย้อนกลับไปใช้แพลตฟอร์มเดิม
    • รายละเอียดของมาตรการที่เกี่ยวข้องถูกบันทึกไว้ใน หน้า Discord Status
  • Mintlify รับทราบช่องโหว่ผ่าน Discord ก่อนจะ เปิด Slack channel ระหว่างทีมวิศวกรรมกับนักวิจัย เพื่อดำเนินการแก้ไขทันที

ขอบเขตผลกระทบ

  • ลูกค้า Mintlify ส่วนใหญ่ เช่น X (Twitter), Vercel, Cursor และ Discord อยู่ในขอบเขตที่ได้รับผลกระทบ
  • บนโดเมนทางการของแต่ละบริษัท มีความเป็นไปได้ที่จะถูกยึดบัญชีได้ด้วยลิงก์อันตรายเพียงลิงก์เดียว
  • ช่องโหว่เพียงจุดเดียวในซัพพลายเชนสามารถ ก่อให้เกิดความเสี่ยงแบบลูกโซ่ต่อความปลอดภัยของบริษัทหลายร้อยแห่ง

รางวัลและบทสรุป

  • ทีมวิจัยได้รับ bug bounty รวมราว 11,000 ดอลลาร์
    • Discord จ่าย 4,000 ดอลลาร์ และ Mintlify จ่ายเพิ่มสำหรับแต่ละช่องโหว่
  • กรณีนี้กลายเป็น ตัวอย่างสำคัญที่แสดงถึงความสำคัญของความปลอดภัยซัพพลายเชนและอานุภาพของช่องโหว่ในแพลตฟอร์มเดียว

1 ความคิดเห็น

 
GN⁺ 2025-12-19
ความคิดเห็นจาก Hacker News
  • เอ็กซ์พลอยต์นี้เป็นกรณีที่น่ากลัวมาก
    แค่คลิกลิงก์เดียว เช่น https://discord.com/_mintlify/static/evil/exploit.svg JavaScript ก็จะถูกรันจากโดเมนของ Discord
    ผลก็คือเซสชันคุกกี้หรือโทเค็นอาจถูกขโมย ทำให้บัญชีถูกยึดได้ทั้งหมด รวมถึงสามารถแก้ไขแอปนักพัฒนาหรือเว็บฮุก ลบเซิร์ฟเวอร์ผ่าน API หรือใช้ข้อมูลการชำระเงินซื้อ Nitro ได้ ความเสียหายจึงรุนแรงมาก
    เมื่อคิดถึงขนาดความเสียหายแบบนี้ bug bounty $4,000 ดูเป็นรางวัลที่น้อยเกินไป

    • ถ้าจะขโมยคุกกี้หรือโทเค็น ต้องมี คุกกี้ที่ไม่ใช่ HTTP-only หรือมีโทเค็นอยู่ใน localStorage ก่อน เลยสงสัยว่า Discord เป็นโครงสร้างแบบนั้นแน่หรือไม่
      ถ้าตั้งค่าเซสชันคุกกี้ให้เป็น HTTP-only เสมอ จะทนต่อการโจมตีแบบนี้ได้มากขึ้นมาก
      น่าแปลกที่นักพัฒนาฝั่งฟรอนต์เอนด์จำนวนมากไม่รู้แนวคิดความปลอดภัยพื้นฐานแบบนี้
    • เห็นด้วยกับคำพูดที่ว่า “$4,000 น้อยเกินไป”
      ในตลาดมืดมันน่าจะมีมูลค่าสูงกว่านี้มาก
  • คิดว่าการที่ฝังสคริปต์ลงในไฟล์ SVG ได้ตั้งแต่แรกเป็น ความผิดพลาดด้านความปลอดภัย
    การทำเดโมแบบโต้ตอบหรือเกมทั้งชุดให้อยู่ใน SVG ไฟล์เดียวฟังดูเจ๋งก็จริง แต่ก็กลายเป็นแหล่งเพาะช่องโหว่ไปด้วย
    เพราะแบบนี้หลายแพลตฟอร์มจึงห้ามอัปโหลด SVG หรือบล็อกการพรีวิว
    ใน Discord เอง ถ้าอัปโหลด SVG ก็จะแสดงโค้ดตรง ๆ และบน Facebook Messenger หรือ WeChat ก็แชร์ไม่ได้เช่นกัน
    ถึงจะมีข้อดีเรื่องขนาดไฟล์เล็กและไม่ขึ้นกับความละเอียด แต่ก็ยังน่าเสียดายที่ในความเป็นจริง ฟอร์แมตรูปภาพแบบแรสเตอร์ ยังถูกใช้แพร่หลายกว่า

    • SVG ทุกไฟล์ควรถูก sanitize อย่างเข้มงวด ทั้งตอนอัปโหลดและตอนเรนเดอร์
      Active Storage ของ Rails ไม่ได้ sanitize SVG โดยปริยาย จึงต้องระวัง
    • ปัญหา XML External Entity (XXE) ก็เป็นกรณีคล้ายกัน
      ดูรายละเอียดได้ในเอกสาร OWASP
    • สงสัยว่าถ้าแอปแชตแค่ไม่สนใจแท็ก <script> จะเพียงพอไหม
      แต่แค่นั้นอาจยังไม่พอก็ได้
    • มันชวนให้นึกถึงบั๊กด้านความปลอดภัยในยุค Flash อีกครั้ง
    • ปัญหาใหญ่กว่าของ SVG คือผลลัพธ์การเรนเดอร์นั้น ต่างกันไปตามซอฟต์แวร์
      ในฟอร์แมตแรสเตอร์แทบไม่เจอปัญหาแบบนี้
  • เหตุการณ์นี้เหมือนสะท้อน อีกด้านของระบบนิเวศสตาร์ตอัป AI ยุคนี้
    สตาร์ตอัปเอกสาร AI ที่โตด้วยเงิน VC ได้ลูกค้ารายใหญ่โดยไม่มีการตรวจสอบความปลอดภัย และสุดท้ายทำให้ผู้ใช้นับล้านคนเสี่ยงอันตราย
    ไม่นานมานี้ Mintlify เพิ่งเขียนบล็อกอวดสถาปัตยกรรมแคชที่ซับซ้อน แต่ดูเหมือนในความเป็นจริงจะไม่เข้าใจแม้แต่พื้นฐานความปลอดภัย
    ในสถานการณ์แบบนี้ คนที่พบช่องโหว่กลับได้เงินแค่ $5,000
    คิดว่าเป็นตัวอย่างที่ชี้ให้เห็นว่าวัฒนธรรมการพัฒนาแบบ AI-based ทุกวันนี้เปราะบางแค่ไหน

    • ที่จริงแล้วสิ่งที่เปราะบางต่อการโจมตีแบบนี้ไม่ได้มีแค่สตาร์ตอัป AI แต่เป็น ปัญหาเชิงโครงสร้างของ ecosystem JavaScript ทั้งหมด
      ต้นเหตุจริงคือสายโซ่ dependency ที่ซับซ้อนและนรก DLL จาก third-party หลายชั้น
    • XSS ส่วนใหญ่เกิดจาก โครงสร้างโดเมนเดียว
      ถ้า Discord ไม่ได้เสิร์ฟเอกสาร API จาก discord.com โดยตรง ปัญหานี้ก็คงไม่เกิด
    • สงสัยว่าทำไมเว็บเอกสารถึงต้องมีโครงสร้างแคชซับซ้อนขนาดนั้น
      แค่ CDN อย่างเดียวไม่น่าจะพอหรือ
  • เป็นบั๊กที่ยึดบัญชีลูกค้าได้ทั้งหมด แต่ จำนวนเงินรางวัลกลับน้อยเกินไป
    ในยุคนี้ไม่ควรมีเหตุผลอะไรที่จะปล่อยให้เกิด XSS ได้แล้ว

    • XSS ยังไม่หายไปไหน และมาตรการป้องกันอย่าง CSP หรือ Trusted Types ก็ไม่ได้สมบูรณ์แบบ
      ใน Anubis ก็พบ reflected XSS ถึงสองครั้งในปีนี้
      ต้องตรวจสอบ dependency ของ third-party ให้แน่ชัด
      ดูประกาศด้านความปลอดภัยที่เกี่ยวข้องได้ที่นี่และที่นี่
    • โดยทั่วไปแล้วช่องโหว่ XSS แทบ ไม่มีมูลค่าในตลาด
      เพราะถ้าไม่ใช่โซเชียลเน็ตเวิร์กขนาดใหญ่ ก็ยากจะทำเงินจากมันได้
  • เห็นแล้วคิดว่าถ้าจ้าง แฮ็กเกอร์วัย 16 ปี คนที่หาช่องโหว่นี้ได้มาเป็นพนักงานประจำหรือพาร์ตไทม์ให้ตรวจความปลอดภัยอย่างต่อเนื่องจะเป็นอย่างไร
    จ่ายปีละ $50,000 ก็น่าจะยกระดับความปลอดภัยของบริษัทได้แบบก้าวกระโดด

    • แต่โครงสร้างสัญญาที่กดดันให้นักวิจัยต้อง ทำผลงาน นั้นไม่เหมาะสม
      bug bounty มีประสิทธิภาพกว่าเพราะจ่ายตามผลลัพธ์
      เพียงแต่ถ้ารางวัลต่ำ นักวิจัยก็อาจถูกล่อใจให้ขายต่อให้บุคคลที่สาม
    • ผู้เข้าร่วม bug bounty ส่วนใหญ่ต่างก็มี ความเชี่ยวชาญคนละด้าน
      ไม่ว่าจะ XSS, IAM, shell exploit ฯลฯ ต่างมีสายเฉพาะทางของตัวเอง จึงยากที่คนคนเดียวจะครอบคลุมทั้งหมด
    • พูดตรง ๆ คือบริษัทพวกนี้ ไม่ได้ใส่ใจเรื่องความปลอดภัยมากนัก
  • อายุ 16 แล้วยังหาช่องโหว่แบบนี้เจอได้ น่าทึ่งมาก
    แต่การเรียก XSS ว่าเป็น การโจมตีแบบ supply chain ฟังดูไม่ค่อยคุ้น

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

  • เห็นกรณีแบบนี้แล้ว
    1️⃣ ต้องตั้งค่า Content Security Policy (CSP) ให้ได้
    2️⃣ บนเซิร์ฟเวอร์ NodeJS ควรใช้ตัวเลือก --disallow-code-generation-from-strings เป็นค่าเริ่มต้น
    ผู้ให้บริการอย่าง Vercel ควรแสดงคำเตือนเมื่อไม่มีการใช้ CSP
    ธงด้านความปลอดภัยของ NodeJS เพิ่มเติมที่น่าสนใจถูกรวบรวมไว้ในบทความนี้

  • การ พร็อกซีบริการ third-party ผ่านเมนโดเมนหลัก ที่มีการยืนยันตัวตนผู้ใช้เป็นตัวเลือกที่แย่ที่สุด
    ควรแยก Mintlify ไปไว้ที่ซับโดเมนต่างหากอย่าง dev-docs.discord.com

    • ฉันเองก็ทำผลิตภัณฑ์คล้าย Mintlify แต่ ไม่รองรับการเข้าถึง codebase หรือการเชื่อม Git
      ต่อให้ลูกค้าต้องการก็เสี่ยงเกินไปในเชิงความปลอดภัย
      แต่ก็มีความต้องการเยอะที่จะเอาเอกสารไว้บนเมนโดเมนหลักเพราะ SEO
      ในมุมของ Mintlify เอง เหตุการณ์นี้ก็คงสร้างความเครียดอย่างมาก
    • แก่นของช่องโหว่นี้คือ การแยกโดเมนล้มเหลว
      ควรใช้ซับโดเมนสำหรับ third-party โดยเฉพาะ และจำกัดคุกกี้ยืนยันตัวตนของแอปหลักให้เป็น host-only
      ถ้าเป็นไปได้ การใช้โดเมนคนละตัวไปเลย (เช่น discorddocs.com) จะปลอดภัยกว่า
    • สาเหตุที่หลายบริษัทวางเว็บเอกสารไว้บนเมนโดเมนหลัก เป็นเพราะต้องการ แทรก API key จริงลงในตัวอย่างโค้ดแบบอัตโนมัติ
      แต่เมื่อเทียบกับความเสี่ยงด้านความปลอดภัยแล้ว มันเป็นทางเลือกที่อันตรายเกินไป
  • จากนี้ไป จะไม่เปิดไฟล์ SVG เด็ดขาด
    เด็กอายุ 16 ค้นพบเรื่องนี้ได้ บอกเลยว่าเป็นระดับตำนาน

    • แต่ถ้าจำเป็นต้องเปิดจริง ๆ ก็ควรเปิดเฉพาะใน สภาพแวดล้อมเบราว์เซอร์แบบ sandbox เท่านั้น