基于真实审计的 MCP Server 安全报告,指出路径遍历、命令注入等六类漏洞及可复制的修复代码,强调 path.resolve 后必须校验 target 在 base 目录下,而非清洗后再执行。
Bạn vừa dựng xong một MCP server cho agent nội bộ: nó đọc file, chạy lệnh, fetch URL theo yêu cầu của model. Vài tuần sau, một tài liệu độc hại lọt vào ngữ cảnh, và agent của bạn vô tình đọc /etc/passwd hoặc gọi lệnh shell do kẻ tấn công cài sẵn. Bài viết này liệt kê 6 lỗ hổng MCP server phổ biến nhất kèm code fix có thể copy-paste ngay, dựa trên một audit thực tế về MCP server và package AI/ML.
Vì sao MCP server là bề mặt tấn công mới
MCP (Model Context Protocol) server trao cho LLM các tool thật: đọc file, chạy lệnh, fetch URL. Vấn đề là tham số truyền vào các tool này lại đến từ nội dung không đáng tin — một trang web, một tài liệu, hay output của model khác. Đây là bề mặt injection kinh điển, và phần lớn MCP server đang mắc đúng 6 lỗ hổng lặp đi lặp lại.
Một tool read_file dùng open(base + user_path) sẽ lộ /etc/passwd ngay khi model được yêu cầu đọc ../../../../etc/passwd. Symlink và absolute path dễ dàng bypass các prefix check ngây thơ. Cách vá: resolve cả base lẫn target path, từ chối nếu target không nằm trong parents của base — không được "làm sạch" path rồi tiếp tục chạy, đó chính là cách lỗ hổng quay lại.
Đoạn code kiểu subprocess.run(f"convert {name}", shell=True) là dấu chấm hết, vì bất kỳ tham số nào model can thiệp được đều coi như do kẻ tấn công kiểm soát. Fix: luôn truyền argv dạng list với shell=False, whitelist tham số người dùng thực sự được phép chỉnh, và từ chối mọi thứ ngoài danh sách đó.
pickle.load, torch.load bản trước 2.6 (mặc định không an toàn), yaml.load không dùng safe loader, và numpy.load(allow_pickle=True) đều có thể thực thi code ngay khi load. Đây được ghi nhận là nhóm lỗi được trả thưởng nhiều nhất trên huntr cho MCP/AI. Dùng yaml.safe_load, torch.load(f, weights_only=True), và ưu tiên định dạng safetensors thay vì pickle cho model.
Một tool fetch_url sẵn sàng gọi tới http://169.254.169.254/ (cloud metadata) hoặc http://localhost:6379 nếu không kiểm soát. Trước khi connect, resolve hostname và chặn toàn bộ private range, đồng thời tắt redirect và giới hạn kích thước response.
Grep nhanh trong source trước khi release: tìm shell=True, os.system, subprocess.call(; tìm pickle.load, yaml.load(, torch.load(, allow_pickle=True; tìm open(, Path(, send_file, extractall. Sau đó bắn thử các payload tấn công thật — ../, 169.254.169.254, một pickle chứa __reduce__ — vào instance local và xác nhận từng cái đều bị từ chối.
Nếu team bạn đang build MCP server cho agent nội bộ, chạy ngay bộ grep checklist ở trên trên codebase hiện tại trước khi nghĩ đến tính năng mới. Đừng đợi security review hàng quý — mỗi tool mới thêm vào agent là một bề mặt tấn công mới cần soi qua đúng 6 nhóm lỗi này.
This article was originally published on NextFuture. Follow us for more fullstack & AI engineering content.