- นักเรียนมัธยมปลายวัย 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 ชั่วโมง และหลังจากนั้น ย้อนกลับไปใช้แพลตฟอร์มเดิม
- Mintlify รับทราบช่องโหว่ผ่าน Discord ก่อนจะ เปิด Slack channel ระหว่างทีมวิศวกรรมกับนักวิจัย เพื่อดำเนินการแก้ไขทันที
ขอบเขตผลกระทบ
- ลูกค้า Mintlify ส่วนใหญ่ เช่น X (Twitter), Vercel, Cursor และ Discord อยู่ในขอบเขตที่ได้รับผลกระทบ
- บนโดเมนทางการของแต่ละบริษัท มีความเป็นไปได้ที่จะถูกยึดบัญชีได้ด้วยลิงก์อันตรายเพียงลิงก์เดียว
- ช่องโหว่เพียงจุดเดียวในซัพพลายเชนสามารถ ก่อให้เกิดความเสี่ยงแบบลูกโซ่ต่อความปลอดภัยของบริษัทหลายร้อยแห่ง
รางวัลและบทสรุป
- ทีมวิจัยได้รับ bug bounty รวมราว 11,000 ดอลลาร์
- Discord จ่าย 4,000 ดอลลาร์ และ Mintlify จ่ายเพิ่มสำหรับแต่ละช่องโหว่
- กรณีนี้กลายเป็น ตัวอย่างสำคัญที่แสดงถึงความสำคัญของความปลอดภัยซัพพลายเชนและอานุภาพของช่องโหว่ในแพลตฟอร์มเดียว
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เอ็กซ์พลอยต์นี้เป็นกรณีที่น่ากลัวมาก
แค่คลิกลิงก์เดียว เช่น https://discord.com/_mintlify/static/evil/exploit.svg JavaScript ก็จะถูกรันจากโดเมนของ Discord
ผลก็คือเซสชันคุกกี้หรือโทเค็นอาจถูกขโมย ทำให้บัญชีถูกยึดได้ทั้งหมด รวมถึงสามารถแก้ไขแอปนักพัฒนาหรือเว็บฮุก ลบเซิร์ฟเวอร์ผ่าน API หรือใช้ข้อมูลการชำระเงินซื้อ Nitro ได้ ความเสียหายจึงรุนแรงมาก
เมื่อคิดถึงขนาดความเสียหายแบบนี้ bug bounty $4,000 ดูเป็นรางวัลที่น้อยเกินไป
ถ้าตั้งค่าเซสชันคุกกี้ให้เป็น HTTP-only เสมอ จะทนต่อการโจมตีแบบนี้ได้มากขึ้นมาก
น่าแปลกที่นักพัฒนาฝั่งฟรอนต์เอนด์จำนวนมากไม่รู้แนวคิดความปลอดภัยพื้นฐานแบบนี้
ในตลาดมืดมันน่าจะมีมูลค่าสูงกว่านี้มาก
คิดว่าการที่ฝังสคริปต์ลงในไฟล์ SVG ได้ตั้งแต่แรกเป็น ความผิดพลาดด้านความปลอดภัย
การทำเดโมแบบโต้ตอบหรือเกมทั้งชุดให้อยู่ใน SVG ไฟล์เดียวฟังดูเจ๋งก็จริง แต่ก็กลายเป็นแหล่งเพาะช่องโหว่ไปด้วย
เพราะแบบนี้หลายแพลตฟอร์มจึงห้ามอัปโหลด SVG หรือบล็อกการพรีวิว
ใน Discord เอง ถ้าอัปโหลด SVG ก็จะแสดงโค้ดตรง ๆ และบน Facebook Messenger หรือ WeChat ก็แชร์ไม่ได้เช่นกัน
ถึงจะมีข้อดีเรื่องขนาดไฟล์เล็กและไม่ขึ้นกับความละเอียด แต่ก็ยังน่าเสียดายที่ในความเป็นจริง ฟอร์แมตรูปภาพแบบแรสเตอร์ ยังถูกใช้แพร่หลายกว่า
Active Storage ของ Rails ไม่ได้ sanitize SVG โดยปริยาย จึงต้องระวัง
ดูรายละเอียดได้ในเอกสาร OWASP
<script>จะเพียงพอไหมแต่แค่นั้นอาจยังไม่พอก็ได้
ในฟอร์แมตแรสเตอร์แทบไม่เจอปัญหาแบบนี้
เหตุการณ์นี้เหมือนสะท้อน อีกด้านของระบบนิเวศสตาร์ตอัป AI ยุคนี้
สตาร์ตอัปเอกสาร AI ที่โตด้วยเงิน VC ได้ลูกค้ารายใหญ่โดยไม่มีการตรวจสอบความปลอดภัย และสุดท้ายทำให้ผู้ใช้นับล้านคนเสี่ยงอันตราย
ไม่นานมานี้ Mintlify เพิ่งเขียนบล็อกอวดสถาปัตยกรรมแคชที่ซับซ้อน แต่ดูเหมือนในความเป็นจริงจะไม่เข้าใจแม้แต่พื้นฐานความปลอดภัย
ในสถานการณ์แบบนี้ คนที่พบช่องโหว่กลับได้เงินแค่ $5,000
คิดว่าเป็นตัวอย่างที่ชี้ให้เห็นว่าวัฒนธรรมการพัฒนาแบบ AI-based ทุกวันนี้เปราะบางแค่ไหน
ต้นเหตุจริงคือสายโซ่ dependency ที่ซับซ้อนและนรก DLL จาก third-party หลายชั้น
ถ้า Discord ไม่ได้เสิร์ฟเอกสาร API จาก discord.com โดยตรง ปัญหานี้ก็คงไม่เกิด
แค่ CDN อย่างเดียวไม่น่าจะพอหรือ
เป็นบั๊กที่ยึดบัญชีลูกค้าได้ทั้งหมด แต่ จำนวนเงินรางวัลกลับน้อยเกินไป
ในยุคนี้ไม่ควรมีเหตุผลอะไรที่จะปล่อยให้เกิด XSS ได้แล้ว
ใน Anubis ก็พบ reflected XSS ถึงสองครั้งในปีนี้
ต้องตรวจสอบ dependency ของ third-party ให้แน่ชัด
ดูประกาศด้านความปลอดภัยที่เกี่ยวข้องได้ที่นี่และที่นี่
เพราะถ้าไม่ใช่โซเชียลเน็ตเวิร์กขนาดใหญ่ ก็ยากจะทำเงินจากมันได้
เห็นแล้วคิดว่าถ้าจ้าง แฮ็กเกอร์วัย 16 ปี คนที่หาช่องโหว่นี้ได้มาเป็นพนักงานประจำหรือพาร์ตไทม์ให้ตรวจความปลอดภัยอย่างต่อเนื่องจะเป็นอย่างไร
จ่ายปีละ $50,000 ก็น่าจะยกระดับความปลอดภัยของบริษัทได้แบบก้าวกระโดด
bug bounty มีประสิทธิภาพกว่าเพราะจ่ายตามผลลัพธ์
เพียงแต่ถ้ารางวัลต่ำ นักวิจัยก็อาจถูกล่อใจให้ขายต่อให้บุคคลที่สาม
ไม่ว่าจะ XSS, IAM, shell exploit ฯลฯ ต่างมีสายเฉพาะทางของตัวเอง จึงยากที่คนคนเดียวจะครอบคลุมทั้งหมด
อายุ 16 แล้วยังหาช่องโหว่แบบนี้เจอได้ น่าทึ่งมาก
แต่การเรียก XSS ว่าเป็น การโจมตีแบบ 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
ต่อให้ลูกค้าต้องการก็เสี่ยงเกินไปในเชิงความปลอดภัย
แต่ก็มีความต้องการเยอะที่จะเอาเอกสารไว้บนเมนโดเมนหลักเพราะ SEO
ในมุมของ Mintlify เอง เหตุการณ์นี้ก็คงสร้างความเครียดอย่างมาก
ควรใช้ซับโดเมนสำหรับ third-party โดยเฉพาะ และจำกัดคุกกี้ยืนยันตัวตนของแอปหลักให้เป็น host-only
ถ้าเป็นไปได้ การใช้โดเมนคนละตัวไปเลย (เช่น discorddocs.com) จะปลอดภัยกว่า
แต่เมื่อเทียบกับความเสี่ยงด้านความปลอดภัยแล้ว มันเป็นทางเลือกที่อันตรายเกินไป
จากนี้ไป จะไม่เปิดไฟล์ SVG เด็ดขาด
เด็กอายุ 16 ค้นพบเรื่องนี้ได้ บอกเลยว่าเป็นระดับตำนาน