Tấn công mạng sử dụng AI: Cách phát hiện, ngăn chặn và phòng thủ trước các mối đe dọa thông minh

Đọc ngay
Chúng tôi sử dụng trí tuệ nhân tạo để dịch trang web và trong khi chúng tôi cố gắng đạt được độ chính xác, chúng có thể không phải lúc nào cũng chính xác 100%. Sự hiểu biết của bạn được đánh giá cao.

Phát hiện kỹ thuật về Mongoose CVE-2025-23061 và CVE-2024-53900

bằng cách OPSWAT
Chia sẻ bài viết này

Mongoose là một thư viện Mô hình hóa dữ liệu đối tượng (ODM) cho MongoDB giúp đơn giản hóa các tương tác cơ sở dữ liệu trong các ứng dụng Node.js. Bằng cách cung cấp giải pháp dựa trên lược đồ, Mongoose cho phép ánh xạ các đối tượng JavaScript vào các tài liệu MongoDB, hoạt động như một lớp trừu tượng giúp cấu trúc dữ liệu để quản lý và xác thực dễ dàng hơn. Với các tính năng như phần mềm trung gian để thực thi logic tùy chỉnh và hệ thống xây dựng truy vấn trực quan, Mongoose nâng cao hiệu quả làm việc với MongoDB. Mongoose, được mô tả là "mô hình hóa đối tượng MongoDB thanh lịch cho Node.js", đã đạt được 27 nghìn sao trên GitHub, phản ánh việc sử dụng rộng rãi và đánh giá cao trong số các nhà phát triển.

OPSWAT Chương trình học bổng và khám phá lỗ hổng quan trọng

Chương trình Học bổng Sau đại học về An ninh mạng OPSWAT cơ sở hạ tầng trọng yếu có trụ sở tại Việt Nam, cung cấp cho sinh viên sau đại học kinh nghiệm thực tế trong việc bảo mật cơ sở hạ tầng trọng yếu . Là một phần của chương trình này, các học viên có cơ hội phân tích và giải quyết các lỗ hổng an ninh mạng, hợp tác với OPSWAT các chuyên gia giải quyết những thách thức thực tế trong các lĩnh vực như phát hiện phần mềm độc hại, Bảo mật tập tin và ngăn chặn mối đe dọa. 

Trong suốt OPSWAT Chương trình học bổng, những người tham gia sẽ điều tra và tái tạo một cách có hệ thống các CVE đã biết trên nhiều sản phẩm, thư viện và hệ điều hành khác nhau. Là một phần của sáng kiến này, Dat Phung - một trong những thành viên xuất sắc của chúng tôi - đã chọn nghiên cứu Mongoose do nó được áp dụng rộng rãi trong môi trường sản xuất. Vào tháng 11 năm 2024, anh đã phát hiện ra một lỗ hổng nghiêm trọng trong Mongoose khi thực hiện phân tích chuyên sâu về thư viện. Lỗ hổng này cho phép kẻ tấn công khai thác giá trị $where , có khả năng dẫn đến Thực thi mã từ xa (RCE) trên máy chủ ứng dụng Node.js. Sau khi báo cáo sự cố kịp thời cho Mongoose, một bản vá đã được phát hành như một phần của phiên bản 8.8.3 và CVE-2024-53900 đã được tiết lộ trong Cơ sở dữ liệu lỗ hổng quốc gia (NVD).

Dòng thời gian CVE-2024-53900 & CVE-2025-23061

  • Ngày 7 tháng 11 năm 2024: Đạt Phụng đã xác định được lỗ hổng nghiêm trọng trong Mongoose và gửi báo cáo bảo mật cho Snyk. 
  • Ngày 26 tháng 11 năm 2024: Mongoose phát hành phiên bản 8.8.3 để giải quyết và khắc phục lỗ hổng bảo mật này. 
  • Ngày 2 tháng 12 năm 2024: Cơ sở dữ liệu lỗ hổng quốc gia (NVD) đã công bố CVE-2024-53900 cho lỗ hổng này. 
  • Ngày 17 tháng 12 năm 2024: Khi phân tích bản vá 8.8.3 của Mongoose, Dat Phung đã tìm thấy một cách bỏ qua vẫn cho phép RCE (Thực thi mã từ xa). Một báo cáo bảo mật chi tiết đã được gửi tới Tidelift. 
  • Ngày 13 tháng 1 năm 2025: Mongoose phát hành phiên bản 8.9.5, giới thiệu bản vá nâng cao giúp giải quyết vấn đề bỏ qua một cách hiệu quả. 
  • Ngày 15 tháng 1 năm 2025: Cơ sở dữ liệu lỗ hổng quốc gia (NVD) chính thức công bố CVE-2025-23061, nhấn mạnh mức độ nghiêm trọng của lỗ hổng mới được xác định.

Phương pháp Populate() của Mongoose

Mongoose cũng cung cấp một tính năng hữu ích gọi là populate() giúp tăng cường khả năng làm việc với các mối quan hệ giữa các tài liệu. Trong khi các phiên bản MongoDB ≥ 3.2 có toán tử tổng hợp $lookup cho các phép nối, populate() của Mongoose cung cấp một giải pháp thay thế mạnh mẽ hơn để tự động thay thế một tham chiếu bằng dữ liệu tương ứng từ các tài liệu liên quan. Điều này đặc biệt hữu ích để quản lý các mối quan hệ giữa các bộ sưu tập MongoDB khác nhau, chẳng hạn như khi một tài liệu tham chiếu đến một tài liệu khác theo _id của nó. [2] 

Mã JavaScript định nghĩa lược đồ Mongoose cho tác giả với các trường tên, tuổi và tiểu sử
Sơ đồ tác giả
Mã JavaScript xác định lược đồ Mongoose cho sách, bao gồm tiêu đề, mô tả, giá và tham chiếu tác giả
Sơ đồ sách
Đoạn mã JavaScript cho tuyến đường Node.js để lấy thông tin chi tiết về sách và điền vào các trường tác giả hoặc đánh giá
Nodejs application

Khi định nghĩa một lược đồ trong Mongoose, một trường có thể được thiết lập để tham chiếu đến một mô hình khác bằng tùy chọn ref. Sau đó, phương thức populate() được sử dụng để thay thế trường được tham chiếu (ObjectId) bằng toàn bộ tài liệu từ mô hình liên quan. Ví dụ, trong ứng dụng cửa hàng sách, trường tác giả trong bookSchema tham chiếu đến tài liệu Tác giả và trường đánh giá tham chiếu đến tài liệu Đánh giá . Phương thức populate() cho phép các nhà phát triển thay thế trường tác giả (là ObjectId) bằng toàn bộ tài liệu Tác giả khi truy vấn mô hình sách.

Phương thức populate() cho phép các nhà phát triển thay thế trường tác giả (là một ObjectId) bằng toàn bộ tài liệu Tác giả khi truy vấn mô hình sách :

Biểu diễn JSON của tài liệu MongoDB lưu trữ thông tin chi tiết về sách mà không có thông tin tác giả mở rộng
Không sử dụng populate()
Biểu diễn JSON của tài liệu MongoDB với thông tin chi tiết về tác giả được mở rộng bằng cách sử dụng hàm populate
Sử dụng populate()

Hơn nữa, phương thức populate() của Mongoose hỗ trợ các truy vấn tùy chỉnh để xác định các tài liệu liên quan nào được truy xuất và cách chúng được truy xuất. Các thuộc tính như matchoptions cho phép các nhà phát triển lọc, sắp xếp, giới hạn và bỏ qua các tài liệu liên quan, cung cấp khả năng truy xuất dữ liệu linh hoạt.

Mã JavaScript minh họa truy vấn tùy chỉnh sử dụng hàm populate của Mongoose để lọc tác giả theo độ tuổi
Truy vấn tùy chỉnh trong populate() trong Mongoose

Phân tích CVE-2024-53900

Là một phần của OPSWAT Chương trình Học bổng sau đại học về an ninh mạng, trong khi phân tích Mongoose để tái tạo các CVE đã biết, Dat Phung đã tiến hành đánh giá toàn diện về hoạt động bên trong của phương thức populate(), đóng vai trò quan trọng trong việc xử lý các mối quan hệ giữa các tài liệu MongoDB. Phương thức populate() hỗ trợ cả đối số chuỗi và đối tượng, và các nhà phát triển có thể sử dụng tùy chọn match để áp dụng các bộ lọc cụ thể trên dữ liệu đang được truy xuất:

Mã JavaScript giới thiệu cách sử dụng toán tử $where để lọc tác giả theo độ tuổi trong truy vấn

Trong ví dụ trên, tùy chọn match là một đối tượng bộ lọc có thể bao gồm các toán tử truy vấn MongoDB, như được trình bày chi tiết trong Query and Projection Operators - MongoDB Manual v8.0 . Một toán tử đáng chú ý là $where , cho phép thực thi JavaScript trực tiếp trên máy chủ MongoDB. Tuy nhiên, việc thực thi này trên máy chủ MongoDB bị hạn chế, chỉ hỗ trợ các hoạt động và chức năng cơ bản.

Bảng liệt kê các hàm và thuộc tính JavaScript có sẵn cho các hoạt động map-reduce của MongoDB

Dat Phung đã tiến hành phân tích chuyên sâu mã nguồn Mongoose để hiểu quy trình làm việc của phương thức populate() . Anh xác định rằng sau khi ứng dụng gọi phương thức populate() trên mô hình, hàm populate() sẽ được kích hoạt. Trong hàm này, Mongoose gọi hàm _execPopulateQuery() , hàm này thực thi truy vấn với toán tử $where trên máy chủ MongoDB. Sau đó, tất cả các tài liệu từ bộ sưu tập nước ngoài được truy xuất để điền vào các bước tiếp theo.

Ảnh chụp màn hình phiên gỡ lỗi VS Code phân tích quá trình thực thi truy vấn điền Mongoose

Sau khi lấy dữ liệu từ MongoDB, Mongoose thực thi hàm gọi lại _done() , gọi _assign() để chuẩn bị dữ liệu trước khi "nối" hai mô hình bằng cách gọi hàm assignmentVals() .

Phiên gỡ lỗi trong VS Code hiển thị mã JavaScript được tô sáng liên quan đến truy vấn $where trong Mongoose

Lỗ hổng có thể phát sinh khi dữ liệu được truy xuất được xử lý bởi hàm assignmentVals() của Mongoose. Hàm này kiểm tra xem tùy chọn match có phải là một mảng hay không và nếu có, sẽ truyền từng toán tử cho hàm sift() . Hàm sift() , được nhập từ một thư viện bên ngoài cùng tên, xử lý các truy vấn này cục bộ trên máy chủ ứng dụng. Quá trình xử lý cục bộ này gây ra rủi ro bảo mật, đặc biệt là khi xử lý dữ liệu đầu vào do người dùng kiểm soát.

Phiên gỡ lỗi VS Code hiển thị các phép gán biến bên trong hàm JavaScript

Để điều tra sâu hơn về vấn đề này, Đạt Phụng đã sửa đổi các giá trị trong tùy chọn khớp để đảm bảo các điều kiện được đáp ứng, do đó sử dụng hàm sift() để phân tích thêm luồng dữ liệu.

Một đoạn mã JavaScript minh họa truy vấn Mongoose với điều kiện lọc $where

Với điều kiện được đặt ra, toán tử $where sau đó được truyền cho hàm sift() .

Phiên gỡ lỗi VS Code hiển thị các giá trị đã lọc trong hàm JavaScript

Thư viện sift là một tiện ích JavaScript nhẹ được thiết kế để lọc và truy vấn các tập hợp dữ liệu như mảng hoặc đối tượng JSON bằng cú pháp giống MongoDB. Theo tài liệu chính thức, "Sift là một thư viện nhỏ để sử dụng các truy vấn MongoDB trong JavaScript." Hàm sift() đánh giá các hoạt động lọc giống MongoDB trên máy chủ ứng dụng thay vì máy chủ cơ sở dữ liệu, điều này có thể khiến hệ thống gặp rủi ro bảo mật đáng kể khi xử lý đầu vào không đáng tin cậy.

Một đoạn mã JavaScript đơn giản sử dụng Sift.js để lọc một mảng các đối tượng dựa trên tiêu chí độ tuổi
Một ví dụ về mã Sift

Tiếp tục phân tích của mình, Fellow của chúng tôi đã xác định một vấn đề trong hàm createDefaultQueryTester() của thư viện sift. Hàm này chuyển đổi từng thao tác trong mảng match thành các hàm JavaScript có thể thực thi, sau đó được sử dụng để lọc và xử lý dữ liệu tài liệu MongoDB cục bộ. Để đạt được điều này, createDefaultQueryTester() gọi hàm createNamedOperation() , truyền các thao tác như $where từ mảng match làm đối số. 

Phiên gỡ lỗi VS Code tập trung vào các hoạt động truy vấn và thực thi hàm

Đối với mỗi thao tác trong mảng khớp , createNamedOperation sẽ kiểm tra xem thao tác đó có được hỗ trợ hay không, sau đó truyền thao tác đó cho hàm tương ứng.

Phiên gỡ lỗi JavaScript hiển thị các toán tử truy vấn như $where, $eq và $exists

Nếu phép toán là $where , một hàm JavaScript sẽ được tạo bằng cách sử dụng giá trị "params" thô, được lấy từ toán tử $where trong mảng match và có thể được kiểm soát bởi người dùng.

Một đoạn mã JavaScript được tô sáng minh họa việc thực thi chức năng khi CSP (Chính sách bảo mật nội dung) được bật

CVE-2024-53900: Chi tiết khai thác

Trong khi MongoDB giới hạn việc thực thi các hàm JavaScript thông qua thao tác $where , như đã phân tích trước đó, thì hàm sift() cho phép các hàm này được thực thi mà không có những hạn chế như vậy. Việc thiếu xác thực đầu vào và hạn chế này tạo ra một lỗ hổng bảo mật đáng kể, vì giá trị "params" - được kiểm soát trực tiếp bởi đầu vào của người dùng - có thể bị khai thác, có khả năng dẫn đến các cuộc tấn công tiêm mã. Để xem xét vấn đề này kỹ lưỡng hơn, Dat Phung đã xây dựng truy vấn sau:

Một đoạn mã JavaScript hiển thị truy vấn Mongoose sử dụng điều kiện $where với khả năng thực thi hàm không an toàn

Ban đầu, truy vấn không thực hiện được quy trình khác, dẫn đến lỗi sau:

Nhật ký lỗi MongoDB hiển thị lỗi thực thi máy chủ do tham chiếu toàn cục không xác định

Lỗi này cho biết Mongoose cố gắng thực hiện thao tác $where trên máy chủ MongoDB trước khi chuyển quyền điều khiển cho hàm sift(). Tuy nhiên, do các hạn chế về hàm JavaScript trong mệnh đề $where của MongoDB, một lỗi xảy ra, ngăn không cho truy vấn thực hiện. Do đó, Mongoose dừng quy trình trước khi nó có thể tiếp cận hàm sift() .

Để bỏ qua hạn chế này, Fellow của chúng tôi đã tận dụng biến "toàn cục" có trên máy chủ ứng dụng, biến này không tồn tại trên máy chủ MongoDB. Cách tiếp cận này cho phép anh ấy bỏ qua hạn chế trên máy chủ MongoDB và cho phép truy vấn tiếp cận hàm sift() :

Màn hình máy tính hiển thị dòng chữ "mã không hoạt động", nêu bật một vấn đề trong quá trình mã hóa

Với giá trị này, khi Mongoose thực thi thao tác $where trên MongoDB, việc không có biến "global" sẽ khiến toán tử ba ngôi (typeof global != "undefined" ?global.process.mainModule.constructor._load("child_process").exec("calc") : 1) trả về 1, ngăn MongoDB báo lỗi. Do đó, truy vấn được thực thi trên máy chủ MongoDB mà không có vấn đề gì.

Tuy nhiên, khi giá trị tương tự đạt đến hàm sift() chạy trên máy chủ ứng dụng có biến "toàn cục", nó sẽ kích hoạt việc tạo hàm sau:

Màn hình đơn sắc có cụm từ "hello world" được in đậm

Bằng chứng khái niệm thực thi mã từ xa (RCE)

Trong ví dụ ứng dụng được cung cấp ở đầu blog, nếu kẻ tấn công gửi yêu cầu sau, chúng có thể thực hiện thành công cuộc tấn công Thực thi mã từ xa (RCE):

Màn hình đen trắng hiển thị dòng chữ "the new york times" nổi bật bằng phông chữ đậm
Sơ đồ minh họa các chi tiết kỹ thuật của lỗ hổng CVE Mongoose, hiển thị luồng dữ liệu và các điểm vi phạm bảo mật

Video trình bày Bằng chứng khái niệm cho CVE-2024-53900 ảnh hưởng đến các phiên bản Mongoose trước 8.8.3, thiếu xác thực đầu vào phù hợp để ngăn chặn việc sử dụng sai toán tử $where cùng với thư viện sift .

Bản sửa lỗi chưa hoàn thiện và CVE-2025-23061

Dựa trên báo cáo bảo mật của Dat Phung, Mongoose đã giới thiệu một bản vá nhằm giải quyết lỗ hổng đã xác định trước đó (CVE-2024-53900) trước khi công khai. Bản vá có liên quan ( Automattic/mongoose@33679bc ) đã thêm một kiểm tra để không cho phép sử dụng $where trong thuộc tính match được truyền cho populate() .

Đoạn mã này kiểm tra xem thuộc tính match được truyền vào populate() có phải là một mảng không. Nếu có, mã sẽ lặp qua từng đối tượng trong mảng để xem nó có chứa toán tử $where không. Nếu phát hiện thấy $where , một lỗi sẽ được đưa ra, ngăn chặn payload độc hại lan truyền đến hàm sift() rủi ro.  

Do đó, tải trọng khai thác CVE-2024-53900 không vượt qua được kiểm tra này vì một đối tượng trong mảng khớp chứa $where , do đó chặn không cho nó tiếp cận sift() .

Mặc dù bản cập nhật này chặn đúng cách việc sử dụng trực tiếp $where trong một cấp độ lồng nhau duy nhất, nhưng nó lại không phát hiện được $where khi nhúng bên trong toán tử $or - một cấu trúc mà cả MongoDB và thư viện sift đều hỗ trợ đầy đủ.

MongoDB hỗ trợ toán tử $or
Thư viện Sift hỗ trợ toán tử $or

Kết quả là, kẻ tấn công có thể lồng $where bên dưới $or để tránh kiểm tra một cấp của bản vá. Vì Mongoose chỉ kiểm tra các thuộc tính cấp cao nhất của mỗi đối tượng trong mảng khớp, nên tải trọng bỏ qua vẫn không bị phát hiện và cuối cùng sẽ đến được thư viện sift, cho phép RCE độc hại.

Tải trọng được sử dụng để bỏ qua bản sửa lỗi trong mongoose 8.8.3

Bằng chứng về khái niệm cho CVE-2025-23061

Để minh họa bản chất chưa hoàn thiện của bản sửa lỗi, Dat Phung đã xây dựng lại ứng dụng ví dụ bằng phiên bản Mongoose 8.9.4 (sau 8.8.3). Bằng cách lồng $wher e bên trong mệnh đề $or , kẻ tấn công có thể bỏ qua thành công việc kiểm tra và đạt được RCE.

Bản khai thác bằng chứng khái niệm cho thấy CVE-2025-23061 có thể được kích hoạt trong các phiên bản Mongoose trước 8.9.5, cho phép kẻ tấn công thực thi mã tùy ý trên máy chủ:

Giảm nhẹ và hướng dẫn

Để giảm thiểu các lỗ hổng mà chúng tôi đã thảo luận ở trên, vui lòng đảm bảo hệ thống của bạn được cập nhật lên phiên bản mới nhất của Mongoose.

MetaDefender Core Sử dụng SBOM Engine có thể phát hiện lỗ hổng này

OPSWAT MetaDefender Core , được trang bị SBOM tiên tiến ( Software Khả năng của Bill of Materials), cho phép các tổ chức có cách tiếp cận chủ động trong việc giải quyết các rủi ro bảo mật. Bằng cách quét các ứng dụng phần mềm và các phụ thuộc của chúng, MetaDefender Core xác định các lỗ hổng đã biết, chẳng hạn như CVE-2024-53900 và CVE-2025-23061, trong các thành phần được liệt kê. Điều này trao quyền cho các nhóm phát triển và bảo mật ưu tiên các nỗ lực vá lỗi, giảm thiểu các rủi ro bảo mật tiềm ẩn trước khi chúng có thể bị các tác nhân độc hại khai thác. 

Dưới đây là ảnh chụp màn hình của CVE-2024-53900 và CVE-2025-23061, được phát hiện bởi MetaDefender Core với SBOM:

Ngoài ra, CVE cũng có thể được phát hiện bởi MetaDefender Software Supply Chain , tận dụng MetaDefender Core với SBOM để xác định những lỗ hổng này.

Luôn cập nhật với OPSWAT!

Đăng ký ngay hôm nay để nhận thông tin cập nhật mới nhất về công ty, câu chuyện, thông tin sự kiện và nhiều thông tin khác.