Một máy chủ MCP độc hại có thể lừa một ứng dụng được xây dựng trên MCP Python SDK chính thức bàn giao các thông tin xác thực OAuth mà nó sử dụng để đăng nhập vào một dịch vụ thực tế, các nhà duy trì SDK cho biết trong một tư vấn bảo mật.
Các phiên bản bị ảnh hưởng đã gửi client secret, mã ủy quyền (authorization code) và khóa chứng minh PKCE đến một endpoint nhận mã thông báo (token endpoint) do kẻ tấn công kiểm soát. Bản sửa lỗi đã có trong các phiên bản 1.30.0 và 2.2.0.
Model Context Protocol (MCP) là một tiêu chuẩn mở để kết nối các ứng dụng AI với các công cụ và dữ liệu bên ngoài, và gói này là SDK Python chính thức để xây dựng các máy chủ và máy khách MCP.
Với các thông tin xác thực bị đánh cắp, kẻ tấn công có thể yêu cầu một access token hợp lệ từ dịch vụ đăng nhập thực tế. Cycode, công ty bảo mật đã báo cáo lỗ hổng, đã trình diễn quá trình trao đổi đầy đủ này trong một thử nghiệm và cho biết mã thông báo thu được mang theo bất kỳ quyền hạn nào mà ứng dụng đã được cấp. Client secret có thời gian tồn tại lâu dài, vì vậy nó vẫn tiếp tục hoạt động cho đến khi được thay đổi.
Lỗ hổng được xếp hạng cao (7.5) đối với hai nhà cung cấp chạy mà không cần sự hiện diện của con người. Điểm số cho nhà cung cấp tương tác (interactive provider), nơi ai đó phải bắt đầu đăng nhập, là 6.5. Tính đến ngày 29 tháng 9, chưa có mã CVE nào được chỉ định.
Cách máy chủ đánh cắp thông tin xác thực
Khi một máy khách MCP cần đăng nhập, nó sẽ hỏi máy chủ mà nó đang kết nối rằng dịch vụ đăng nhập của nó (được gọi là authorization server) có thể được tìm thấy ở đâu. Trên các phiên bản bị ảnh hưởng, SDK không phải lúc nào cũng kiểm tra câu trả lời đó. Một máy chủ độc hại có thể trỏ nó đến một dịch vụ đăng nhập do kẻ tấn công chọn, bằng cách nêu tên máy chủ của chính kẻ tấn công hoặc cung cấp các chi tiết đăng nhập nêu tên dịch vụ thực của người dùng trong khi gửi thông tin xác thực đi nơi khác.
Sau đó, máy khách sẽ gửi secret, mã ủy quyền và khóa chứng minh PKCE của nó cho kẻ tấn công thay vì dịch vụ thực. Khóa chứng minh là một giá trị sử dụng một lần được thiết kế để ngăn mã ủy quyền bị đánh cắp khỏi bị tái sử dụng, vì vậy việc bàn giao nó cũng làm mất đi lớp bảo vệ đó.
Với nhà cung cấp tương tác, người dùng vẫn phải phê duyệt đăng nhập. Cycode cho biết trang mà họ phê duyệt là trang đăng nhập chính hãng, vì vậy không có gì trông bất thường. Hai nhà cung cấp machine-to-machine không cần đăng nhập và không cần con người can thiệp.
Những ai bị ảnh hưởng
Một ứng dụng bị ảnh hưởng nếu nó sử dụng SDK làm máy khách MCP qua HTTP với một trong các nhà cung cấp OAuth: OAuthClientProvider, ClientCredentialsOAuthProvider, PrivateKeyJWTOAuthProvider, hoặc RFC7523OAuthClientProvider phiên bản 1.x đã bị loại bỏ, và nó có thể kết nối với một máy chủ mà nó không hoàn toàn kiểm soát trong khi nắm giữ thông tin xác thực cho một dịch vụ đăng nhập thực tế. Các máy chủ MCP được xây dựng bằng SDK, máy khách cục bộ (stdio) và các máy khách tự đính kèm mã thông báo của riêng họ sẽ không bị ảnh hưởng.
| Dòng phiên bản | Bị ảnh hưởng | Đã sửa trong |
|---|---|---|
| 1.x | 1.9.1 đến 1.29.1 | 1.30.0 |
| 2.x | 2.0.0 đến 2.1.1 | 2.2.0 |
Cần làm gì
Nâng cấp lên 1.30.0 cho dòng 1.x hoặc 2.2.0 cho dòng 2.x. Trong các phiên bản đã sửa lỗi, máy khách sẽ xác định dịch vụ đăng nhập mà nó mong đợi trước khi lấy bất kỳ chi tiết nào và từ chối bất kỳ dịch vụ nào nêu tên một dịch vụ khác.
Việc nâng cấp không phải là toàn bộ giải pháp cho hai trong số các nhà cung cấp. Nếu bạn sử dụng ClientCredentialsOAuthProvider hoặc PrivateKeyJWTOAuthProvider, tư vấn cho biết
"việc nâng cấp không thay đổi gì cho đến khi bạn cũng truyền tham số issuer="để nêu tên dịch vụ đăng nhập mà các thông tin xác thực đó thuộc về. Nếu không có nó, chúng vẫn sẽ tuân theo bất kỳ máy chủ nào mà máy chủ MCP trỏ đến.
Trên phiên bản 1.30.0, cảnh báo về vấn đề này là một cảnh báo lỗi thời (deprecation warning) tiêu chuẩn, mà Python thường ẩn theo mặc định, nên rất dễ bị bỏ sót. RFC7523OAuthClientProvider đã lỗi thời hoàn toàn không có tùy chọn issuer=, vì vậy hãy chuyển sang một trong hai nhà cung cấp còn lại.
Sau khi nâng cấp, hãy xóa mọi đăng ký máy khách OAuth đã lưu một lần, vì các đăng ký cũ hơn không bị ràng buộc với dịch vụ đăng nhập và sẽ giữ nguyên như vậy. Nếu một máy khách có thể đã kết nối với một máy chủ không đáng tin cậy, hãy xoay vòng (rotate) client secret và thu hồi các mã thông báo của nó tại dịch vụ đăng nhập. Trên các phiên bản cũ hơn, không có cách giải quyết nào khác ngoài việc chỉ kết nối với các máy chủ MCP mà bạn tin tưởng.
Tiết lộ
Các kiểm tra issuer đã được đưa vào ghi chú phát hành 1.30.0 và 2.2.0 vào ngày 7 tháng 9, được liệt kê dưới dạng thay đổi hành vi thay vì bản sửa lỗi bảo mật. Bản tư vấn bảo mật được đưa ra sau đó vào ngày 28 tháng 9, cùng ngày Cycode công bố bài viết của họ. Bản tư vấn ghi nhận tám người báo cáo, bao gồm cả nhà nghiên cứu của Cycode.
Cả bản tư vấn và Cycode đều không báo cáo bất kỳ cuộc tấn công nào sử dụng lỗ hổng này và chưa có báo cáo nào được ghi nhận ở nơi khác.