9 điểm bởi GN⁺ 2025-12-19 | 1 bình luận | Chia sẻ qua WhatsApp
  • Một học sinh trung học 16 tuổi đã công khai tổng hợp một trường hợp có thể thực hiện tấn công cross-site scripting (XSS) trên các trang tài liệu của những công ty lớn như X, Vercel, Cursor, Discord bằng cách khai thác lỗ hổng của nền tảng Mintlify. Thông qua lỗ hổng này, người này đã nhận được 11.000 USD tiền thưởng bug bounty
  • Đường dẫn nội bộ của Mintlify /_mintlify/static/[subdomain]/[...route] được thiết kế theo cách có thể tải tệp bên ngoài mà không xác thực tên miền
  • Kẻ tấn công có thể chèn JavaScript vào tệp SVG để thực thi script độc hại trên tên miền của các dịch vụ lớn như Discord
  • Lỗ hổng này ảnh hưởng đến gần như mọi khách hàng sử dụng Mintlify, và chỉ với một lần nhấp vào liên kết là có thể chiếm đoạt tài khoản
  • Vụ việc này được đánh giá là một ví dụ cho thấy chỉ một lỗ hổng trong bảo mật chuỗi cung ứng cũng có thể dẫn đến thiệt hại trên diện rộng

Phát hiện trên Discord

  • Vào tháng 11 năm 2025, khi Discord chuyển sang nền tảng tài liệu AI Mintlify, quá trình tìm kiếm lỗ hổng bắt đầu
    • Ngay sau khi chuyển từ nền tảng tùy chỉnh cũ sang Mintlify, nhà nghiên cứu đã phân tích cấu trúc của hệ thống tài liệu mới
  • Tên miền tài liệu của Discord (discord.mintlify.app) đã lộ nguyên trạng đường dẫn nội bộ của Mintlify (/_mintlify/*)
    • Đường dẫn này bắt buộc phải có thể truy cập để phục vụ các chức năng quan trọng như xác thực

Cấu trúc nền tảng Mintlify

  • Mintlify là dịch vụ hỗ trợ soạn thảo tài liệu dựa trên Markdown và tự động chuyển chúng thành tài liệu web
  • Mọi trang tài liệu đều vận hành trên tên miền phụ *.mintlify.app hoặc tên miền tùy chỉnh
  • Bên trong, hệ thống sử dụng các endpoint như /_mintlify/api/user, /_mintlify/markdown/, /_mintlify/static/

Quá trình tìm kiếm lỗ hổng

  • Đã phát hiện endpoint /_mintlify/_markdown/_sites/[subdomain]/[...route] trả về tệp của tài liệu khác mà không xác thực tên miền
    • Tuy nhiên, đường dẫn này chỉ trả về văn bản Markdown chưa render, nên không thể thực thi mã
  • Sau đó, khi phân tích gói Mintlify CLI, nhà nghiên cứu tiếp tục phát hiện endpoint /_mintlify/static/[subdomain]/[...route]
    • Đường dẫn này trả về tệp tĩnh và áp dụng whitelist phần mở rộng tệp
    • Tệp HTML và JS bị chặn, nhưng tệp SVG lại được cho phép

Khai thác tấn công

  • Kẻ tấn công tải lên tài liệu Mintlify của mình một tệp SVG có nhúng JavaScript
  • Khi gọi tệp đó từ tên miền Discord (https://discord.com/_mintlify/_static/.../lmao.svg), script sẽ được thực thi
  • Nhờ vậy, không chỉ Discord mà mọi tên miền tài liệu của các công ty dùng Mintlify đều có thể bị thực thi XSS

Phối hợp và báo cáo

  • Nhà nghiên cứu đã hợp tác với các nhà nghiên cứu bảo mật khác để xác minh lỗ hổng
  • Ngay sau khi nhận được báo cáo, Discord đã vô hiệu hóa toàn bộ tài liệu dành cho nhà phát triển trong 2 giờ, sau đó quay lại nền tảng cũ
  • Sau khi biết về lỗ hổng thông qua Discord, Mintlify đã mở một kênh Slack giữa đội ngũ kỹ thuật và các nhà nghiên cứu để lập tức tiến hành khắc phục

Phạm vi ảnh hưởng

  • Phần lớn khách hàng của Mintlify như X(Twitter), Vercel, Cursor, Discord đều nằm trong vùng ảnh hưởng
  • Trên tên miền chính thức của từng công ty, chỉ một liên kết độc hại cũng có thể dẫn đến nguy cơ chiếm đoạt tài khoản
  • Một lỗ hổng duy nhất trong chuỗi cung ứng có thể gây ra rủi ro dây chuyền cho bảo mật của hàng trăm công ty

Phần thưởng và kết luận

  • Nhóm nghiên cứu đã nhận tổng cộng khoảng 11.000 USD tiền thưởng bug bounty
    • Discord trả 4.000 USD, Mintlify chi trả thêm cho từng lỗ hổng riêng lẻ
  • Đây là một trường hợp tiêu biểu cho thấy tầm quan trọng của bảo mật chuỗi cung ứng và mức độ lan rộng của lỗ hổng trên một nền tảng đơn lẻ

1 bình luận

 
GN⁺ 2025-12-19
Ý kiến trên Hacker News
  • Đây thực sự là một ví dụ exploit rất đáng sợ
    Chỉ cần nhấp vào một liên kết duy nhất, ví dụ như https://discord.com/_mintlify/static/evil/exploit.svg, là JavaScript sẽ chạy trên tên miền Discord
    Kết quả là cookie phiên hoặc token có thể bị đánh cắp, tài khoản có thể bị chiếm hoàn toàn, rồi ứng dụng dành cho nhà phát triển hay webhook bị thao túng, hoặc máy chủ bị xóa qua API, thậm chí thông tin thanh toán bị lợi dụng để mua Nitro, nên mức độ thiệt hại là rất lớn
    Xét quy mô thiệt hại như vậy thì bug bounty $4.000 có cảm giác là phần thưởng quá ít

    • Để đánh cắp cookie hoặc token thì phải có cookie không phải HTTP-only hoặc token nằm trong localStorage, nên tôi tò mò không biết Discord có cấu trúc như vậy không
      Nếu luôn đặt cookie phiên ở chế độ HTTP-only thì sẽ chống chịu tốt hơn nhiều trước kiểu tấn công này
      Thật ngạc nhiên là có nhiều lập trình viên frontend vẫn không biết những khái niệm bảo mật cơ bản như vậy
    • Tôi đồng ý với ý kiến “$4.000 là quá ít
      Ở chợ đen, nó hẳn đã có giá trị cao hơn nhiều
  • Tôi cho rằng ngay từ đầu việc cho phép nhúng script vào file SVG đã là một sai lầm về bảo mật
    Việc có thể làm demo tương tác hoặc game chỉ bằng một file SVG thì rất ngầu, nhưng cũng khiến nó trở thành ổ phát sinh lỗ hổng
    Vì vậy nhiều nền tảng cấm tải lên SVG hoặc chặn xem trước
    Ngay cả trên Discord, khi tải SVG lên thì mã sẽ hiện nguyên văn, còn trên Facebook Messenger hay WeChat cũng không thể chia sẻ được
    Dù có ưu điểm là kích thước file nhỏ và không phụ thuộc độ phân giải, thật đáng tiếc khi định dạng ảnh raster vẫn được dùng rộng rãi hơn

    • Mọi file SVG đều nên được sanitize triệt để cả khi tải lên lẫn khi render
      Active Storage của Rails mặc định không sanitize SVG, nên cần cẩn thận
    • Vấn đề XML External Entity (XXE) cũng là một trường hợp tương tự
      Xem thêm tài liệu OWASP
    • Tôi tự hỏi liệu có thể giải quyết bằng cách để ứng dụng nhắn tin đơn giản bỏ qua thẻ <script> hay không
      Nhưng chỉ như vậy có lẽ vẫn chưa đủ
    • Tình huống này làm tôi nhớ lại những lỗi bảo mật thời Flash
    • Vấn đề lớn hơn của SVG là kết quả render khác nhau giữa các phần mềm
      Với định dạng raster thì gần như không có chuyện đó
  • Vụ việc này dường như cho thấy một mặt cắt của hệ sinh thái startup AI hiện nay
    Một startup làm tài liệu AI lớn lên nhờ vốn VC có được khách hàng lớn mà không qua kiểm chứng bảo mật, và cuối cùng đẩy hàng triệu người vào rủi ro
    Mintlify gần đây còn viết blog khoe kiến trúc cache phức tạp, nhưng trên thực tế dường như lại không nắm nổi cả bảo mật cơ bản
    Trong tình huống như vậy, người phát hiện lỗ hổng chỉ nhận được vỏn vẹn $5.000
    Tôi nghĩ đây là một ví dụ cho thấy văn hóa phát triển dựa trên AI hiện nay mong manh đến mức nào

    • Thực ra không chỉ startup AI dễ dính kiểu tấn công này, mà đây còn là vấn đề cấu trúc của toàn bộ hệ sinh thái JavaScript
      Chuỗi phụ thuộc phức tạp và địa ngục DLL của nhiều bên thứ ba mới là nguyên nhân gốc rễ
    • Phần lớn XSS là do cấu trúc một tên miền duy nhất
      Nếu Discord không phục vụ tài liệu API trực tiếp từ discord.com thì đã không có chuyện này
    • Tôi không hiểu tại sao một trang tài liệu lại cần kiến trúc cache phức tạp đến vậy
      Chẳng phải chỉ CDN là đủ sao
  • Đây là lỗi có thể dẫn đến chiếm trọn tài khoản khách hàng, vậy mà mức thưởng quá thấp
    Thời nay không có lý do gì để vẫn cho phép XSS tồn tại

    • XSS vẫn chưa biến mất, và các biện pháp phòng thủ như CSP hay Trusted Types cũng không hoàn hảo
      Ngay cả Anubis năm nay cũng đã phát hiện hai lỗi reflected XSS
      Phụ thuộc bên thứ ba nhất định phải được kiểm tra
      Xem thông báo bảo mật liên quan ở đâyở đây
    • Nói chung lỗ hổng XSS gần như không có giá trị trên thị trường
      Vì ngoài các mạng xã hội lớn ra thì thường khó kiếm lợi nhuận tài chính từ nó
  • Tôi nghĩ hay là thuê luôn hacker 16 tuổi đã tìm ra lỗ hổng này làm chính thức hoặc bán thời gian để kiểm tra bảo mật thường trực
    Chỉ cần trả $50.000 mỗi năm thôi cũng có vẻ sẽ giúp bảo mật của công ty được nâng cấp đáng kể

    • Nhưng kiểu hợp đồng đặt áp lực thành tích lên nhà nghiên cứu là không phù hợp
      Bug bounty trả thưởng theo kết quả nên hiệu quả hơn
      Tuy vậy, nếu mức thưởng thấp thì nhà nghiên cứu sẽ dễ bị cám dỗ bán cho bên thứ ba
    • Đa số người tham gia bug bounty đều có chuyên môn khác nhau
      Mỗi người có lĩnh vực riêng như XSS, IAM, shell exploit..., nên một người khó mà bao quát hết mọi thứ
    • Nói thật thì những công ty kiểu này không mấy quan tâm đến bảo mật
  • Thật ấn tượng khi một người 16 tuổi lại phát hiện ra chuyện này
    Nhưng gọi XSS là tấn công chuỗi cung ứng (supply chain attack) thì nghe vẫn hơi lạ

    • Cách dùng thuật ngữ có vẻ hơi chưa chính xác, nhưng còn trẻ nên cũng có thể hiểu được
    • Dù vậy, nhìn từ góc độ chuỗi cung ứng thì cũng có lý
      Nếu sự cố xảy ra ở tầng trung gian như Mintlify thì người dùng cuối hoàn toàn không có cách phòng vệ
      Mã độc được chuyển đi bên trong một chuỗi tin cậy, nên cũng có thể xem là một dạng XSS ở cấp độ chuỗi cung ứng
  • Báo cáo của cộng tác viên còn bao gồm cả lỗ hổng RCE nghiêm trọng hơn
    Xem chi tiết trong blog này

  • Nhìn những trường hợp như thế này thì,
    1️⃣ Content Security Policy (CSP) nhất định phải được thiết lập
    2️⃣ Trên máy chủ NodeJS nên dùng mặc định tùy chọn --disallow-code-generation-from-strings
    Các nhà cung cấp dịch vụ như Vercel nên hiện cảnh báo khi không dùng CSP
    Ngoài ra, các cờ bảo mật NodeJS đáng tham khảo khác được tổng hợp trong bài viết này

  • Proxy sang dịch vụ bên thứ ba ngay trên tên miền chính có gắn xác thực người dùng là lựa chọn tệ nhất
    Đáng lẽ Mintlify phải được tách sang một subdomain riêng như dev-docs.discord.com

    • Tôi cũng vận hành một sản phẩm tương tự Mintlify, nhưng không hỗ trợ truy cập codebase hay tích hợp Git
      Dù khách hàng có muốn thì rủi ro bảo mật cũng quá lớn
      Tuy vậy, vì SEO nên có rất nhiều nhu cầu muốn đặt tài liệu trên tên miền chính
      Ở góc độ Mintlify, chuyện này chắc hẳn cũng rất căng thẳng
    • Cốt lõi của kiểu lỗ hổng này là thất bại trong việc tách biệt tên miền
      Cần dùng subdomain riêng cho bên thứ ba, và cookie xác thực của ứng dụng chính phải bị giới hạn ở chế độ host-only
      Nếu có thể thì dùng hẳn một tên miền khác hoàn toàn, ví dụ discorddocs.com, sẽ an toàn hơn
    • Lý do các công ty đặt trang tài liệu trên tên miền chính là để tự động chèn API key thật vào ví dụ mã
      Nhưng so với rủi ro bảo mật thì đây là một lựa chọn quá nguy hiểm
  • Từ giờ tôi sẽ không bao giờ mở file SVG nữa
    Một người 16 tuổi mà tìm ra được chuyện này thì đúng là huyền thoại

    • Nhưng nếu vẫn phải mở thì chỉ nên mở trong môi trường trình duyệt đã được sandbox