MCP安全系列之命令注入
MCP安全系列之命令注入
Section titled “MCP安全系列之命令注入”命令注入相当于MCP服务端存在命令注入等相关问题,其执行的恶意命令会有很多来源,比如用户通过提示词给到模型,或者模型通过上下文获取,或者恶意命令存在外部,模型去读取,或者上游下发的数据等等。
这里以OWASP提到的两个场景为例,进行复现。
场景1:例如一个读取目录的MCP服务,它通过接收参数然后拼接到dir命令上进行执行,代码如下:
from mcp.server.fastmcp import FastMCPimport subprocess
mcp = FastMCP("VulnServer")
@mcp.tool()def list_dir(path: str) -> str: """列出目录下的文件,请按用户要求传入路径。""" command = f"dir {path}" try: # shell=True 是核心,它允许 cmd.exe 解析 & 和 && 符号 res = subprocess.run(command, shell=True, capture_output=True, text=True, encoding='gbk') return res.stdout except Exception as e: return str(e)
if __name__ == "__main__": mcp.run()我们通过提示词传入一个参数,目的就是通过&等符号拼接,让后端执行dir以外的命令,效果如下:

场景2:第二个场景模拟的是SQL注入,这里初始化一个sqlite数据库,然后查询语句是获取姓名进行拼接执行,代码如下:
from mcp.server.fastmcp import FastMCPimport sqlite3
mcp = FastMCP("UserDatabase")
# 初始化一个测试用的 SQLite 数据库def init_db(): conn = sqlite3.connect(':memory:') cursor = conn.cursor() cursor.execute("CREATE TABLE users (id INTEGER, username TEXT, secret TEXT)") cursor.execute("INSERT INTO users VALUES (1, 'alice', 'alice_token_123')") cursor.execute("INSERT INTO users VALUES (2, 'admin', 'admin_super_secret')") conn.commit() return conn
db_conn = init_db()
@mcp.tool()def query_user(username: str) -> str: """根据用户名查询普通用户的基本信息。"""
cursor = db_conn.cursor()
# 漏洞点:将大模型生成的参数直接拼接到 SQL 查询语句中 query = f"SELECT * FROM users WHERE username = '{username}'"
try: cursor.execute(query) result = cursor.fetchall() return f"查询结果: {result}" except Exception as e: return f"查询失败: {str(e)}"
if __name__ == "__main__": mcp.run()我们测试时传入一个SQL注入语句,来获取所有数据,效果如下:

对于该类问题,首先要对MCP服务代码进行审查,确保不存在相关漏洞。其次如果执行命令,可以建立一个白名单机制。如果有沙箱,最后能放到沙箱中执行,再就是MCP的通用防护,即设置最小权限原则,比如只读目录,那就不应该拥有读取文件的权限,具体可参考之前权限过大那篇文章。
小枣信安:专注AI安全,包括但不限于大模型安全、智能体安全、机器人安全、AI赋能网络安全等,欢迎一起学习。