一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

AWS Labs 的 SQL Server MCP Server 如何阻止危险写入查询?

时间:2026-09-13 12:50:02 编辑:袖梨 来源:一聚教程网

AWS Labs 的 Microsoft SQL Server MCP Server 面向运行在 Amazon RDS 上的 SQL Server,让 MCP 客户端能够建立数据库连接、检查连接状态、读取表结构并运行查询。服务默认处于只读模式,会在查询到达数据库前执行关键词阻断、注入模式检测、事务隔离和强制回滚。

这些措施能拦住误操作和常见攻击,但项目文档明确指出:应用层只读属于尽力而为的保护,不是不可绕过的安全边界。生产环境必须创建数据库级只读用户,并将该用户凭据放入 AWS Secrets Manager。即使过滤器遗漏某种语法,SQL Server 权限仍应拒绝写入。

这套服务只针对 Microsoft SQL Server,尤其是 RDS for SQL Server。它不是通用关系数据库连接器,也不意味着可以把 RDS 主用户直接交给模型。正确方案是为每个目标实例和数据库建立最小权限身份,固定启动参数中的 secret ARN,并限制运行 MCP 进程的 AWS 身份权限。

服务提供哪些工具

run_query 用于执行 SQL 查询,get_table_schema 从 INFORMATION_SCHEMA 读取表列信息,connect_to_database 建立到 RDS SQL Server 的连接,is_database_connected 检查连接是否存在,get_database_connection_info 列出缓存的连接信息。

工具数量不多,攻击面相对清晰,但 run_query 仍然是高风险入口。自然语言模型可能生成错误 SQL,数据库中的提示文本也可能诱导模型发起意外查询。任何能够提交任意 SQL 的接口都必须按数据库管理入口对待。

连接池会缓存连接,并在一定时间后过期和刷新凭据。文档给出的默认池过期时间是 30 分钟。凭据轮换后仍需验证旧连接何时关闭,不要只看到 Secrets Manager 已更新就认为所有活动会话立即失效。

默认只读模式的四层保护

第一层是可变更关键词阻断。服务器检查 INSERT、UPDATE、DELETE、DROP、CREATE、ALTER、MERGE、TRUNCATE、EXEC 和 GRANT 等 DML、DDL 或权限关键词,命中后拒绝查询。

第二层是 SQL 注入模式检测。它会阻止常见堆叠查询、UNION SELECT、恒真条件、WAITFOR DELAY,以及对 sp_、xp_、rds_ 等系统、扩展或 RDS 存储过程的调用。

第三层把事务隔离级别设置为 READ COMMITTED。这个隔离级别主要定义读取一致性和锁行为,并不是只读权限;它本身不会禁止 INSERT 或 UPDATE。不能把事务隔离名称误解为安全控制。

第四层关闭自动提交,并在只读模式下每条查询后执行回滚。即使某个变更语句穿过过滤器,普通事务内的修改也不应提交。这个机制对事务型写入有帮助,但不能覆盖所有具有外部副作用、隐式提交或特殊过程的行为。

关键词过滤能阻止什么

模型直接生成常见写语句时,关键词过滤能快速给出错误,而不必等待数据库拒绝。它也能在开发人员误把修改查询复制到 MCP 会话时减少风险。

过滤还覆盖权限变更、对象创建、过程执行和批量访问相关关键词,因此不仅关注表数据。对 RDS 环境而言,阻止 rds_ 存储过程很重要,因为这些过程可能影响备份、恢复、任务和实例级行为。

不过,基于正则或文本的检测会遇到注释、编码、方言、新语法和上下文问题。过于严格会误伤合法查询,过于宽松又可能漏掉危险表达式。过滤器必须通过测试持续维护,但不能升级成唯一控制。

注入模式检测为什么仍不充分

堆叠语句利用分号附加第二条命令,UNION SELECT 可能绕过预期结果范围,恒真条件可扩大读取范围,WAITFOR DELAY 可用于时间型探测。对这些常见模式进行阻断有助于防止简单提示注入转化为数据库注入。

但 SQL Server 语法丰富,函数、视图、用户定义函数和存储过程可能隐藏内部行为。文档举出的风险是通过看似 SELECT 的表达式调用内部会写数据的函数,查询文本本身不一定包含被拦截关键词。

未来 T-SQL 新语法、边缘编码和驱动解析差异也可能绕过检测。只要 MCP 使用的数据库账户拥有写权限,就必须假设某一天应用层会漏判。

关闭自动提交与强制回滚的边界

关闭 autocommit 后,普通更新留在未提交事务中;查询完成时主动 rollback,可以撤销大多数事务型表修改。这是比只做关键词扫描更深的一层防护。

然而,并非所有副作用都能依靠回滚消除。调用外部系统、发送消息、写入事务之外的资源或触发高权限过程,可能在回滚前已经产生影响。某些数据库级操作也有特殊事务语义。

连接异常和进程崩溃通常会让数据库回滚未提交事务,但安全设计不能依赖正常清理路径。真正可靠的办法仍是让登录本身没有写权限。

不要随意启用写模式

启动参数 allow_write_query 会允许写查询。它会把服务从只读探索工具变成能够修改数据库的自动化执行入口,风险模型完全不同。

生产环境不应为了临时迁移或修复而在长期运行实例上添加该参数。如果确有写入需求,应创建独立服务、独立账户、独立 MCP 名称和短时运行窗口,并要求人工审批与变更工单。

写模式下使用主用户尤其危险。模型上下文中的错误指令、被污染的数据和误选数据库都可能导致不可逆结果。迁移和数据修复更适合经过审查的脚本与正式流水线。

创建 SQL Server 专用只读登录

由数据库管理员使用受控会话连接 RDS 实例,创建服务器级登录。示例口令必须替换为随机高强度秘密:

CREATE LOGIN mcp_readonly
WITH PASSWORD = 'replace-with-strong-secret';

切换到目标数据库,映射数据库用户并加入 db_datareader:

USE [application_reporting];
CREATE USER mcp_readonly FOR LOGIN mcp_readonly;
ALTER ROLE db_datareader ADD MEMBER mcp_readonly;

这个角色能读取目标数据库的用户表与视图,但不应加入 db_datawriter、db_owner 或服务器管理员角色。若只允许部分表,创建自定义数据库角色并逐个 GRANT SELECT 会比 db_datareader 更严格。

需要查看表、视图或过程定义时,可以按需授予 VIEW DEFINITION:

GRANT VIEW DEFINITION TO mcp_readonly;

对象定义可能包含敏感业务逻辑和注释。没有生成模式文档的需求时不要授权,或只对指定对象授予。

先用数据库账户验证硬边界

不要在创建账户后直接接入模型。先用相同凭据从普通 SQL 客户端连接,确认 SELECT 成功,INSERT、UPDATE、DELETE、CREATE、DROP 和过程执行均被数据库拒绝。

检查登录是否通过其他角色、组或显式授权继承额外权限。SQL Server 中 DENY 优先于 GRANT,但复杂角色关系不应靠猜测判断,可以查询有效权限并由第二位管理员复核。

如果用户能访问多个数据库,确认每个数据库中的映射和 guest 权限。目标是只看到批准的数据库,而不是仅在默认数据库只读。

把只读凭据存入 Secrets Manager

自定义秘密的值是包含 username 和 password 的 JSON 对象。名称应体现用途和环境,例如 mcp/mssql/reporting-readonly,避免与 RDS 主用户秘密混淆。

{
  "username": "mcp_readonly",
  "password": "replace-with-strong-secret"
}

创建秘密的命令或自动化不应把明文口令留在 shell 历史、构建日志或源代码。生产环境使用安全输入、受控部署系统或基础设施模板引用秘密值。

Secrets Manager 解决的是凭据存储、访问控制和轮换,不会降低数据库用户自身权限。若秘密里仍是主用户,应用层一旦绕过就拥有主用户能力。

自定义 secret ARN 为什么更安全

默认情况下,服务器可以发现 RDS 实例的 MasterUserSecret。生产部署应通过 secret_arn 显式指向只读用户秘密,避免意外回退到主账户。

secret_arn 只在服务启动时配置,不作为 MCP 工具参数暴露,因此模型不能在对话中随意选择另一个秘密 ARN。这缩小了提示注入能够改变凭据目标的空间。

启动时把实例标识、端点、区域、数据库和自定义秘密绑定:

awslabs.mssql-mcp-server 
  --connection_method MSSQL_PASSWORD 
  --instance_identifier reporting-sql 
  --db_endpoint reporting-sql.internal 
  --region us-east-1 
  --database application_reporting 
  --secret_arn <readonly-secret-arn>

不要把真实 ARN、账户号和端点写进公开文档。ARN 本身不是密码,但会暴露资源结构并帮助攻击者定位目标。

多个实例如何绑定秘密

secret_arn 参数可以重复使用,把特定实例标识绑定到特定秘密,也可以提供一个未绑定实例的默认 ARN。解析优先级是目标实例专用 ARN、裸默认 ARN、最后才是实例的 RDS 主秘密。

为了避免错误回退,生产环境应尽量为每个目标实例显式绑定只读秘密,并限制服务只能连接允许的实例。不要依赖裸默认 ARN 覆盖多个安全等级不同的数据库。

运行角色只需要读取这些指定秘密以及描述批准 RDS 实例所需的最小 AWS 权限。不能授予通配符读取整个账户所有秘密。

最小化 MCP 进程的 IAM 权限

MCP 进程需要访问 Secrets Manager 和发现 RDS 信息,但不需要创建、删除或修改 RDS 实例。IAM 策略应把资源限定到目标 secret ARN 和实例,并限制区域。

如果使用 KMS 客户管理密钥加密秘密,还需要对对应密钥的受限解密权限。KMS 条件可以绑定 Secrets Manager 服务和加密上下文,减少密钥被其他服务滥用。

部署在本地或非 AWS 环境时,避免长期访问密钥。优先使用短期身份、工作负载身份或受控凭据进程,并坚控 Secrets Manager 的读取事件。

TLS 默认行为

服务默认使用 require 模式建立加密连接,并根据系统 CA 存储验证服务器证书。加密防止链路被窃听,证书验证防止客户端连接到冒充的数据库。

Amazon RDS SQL Server 证书由 RDS CA 签发,系统信任库不一定预装。首次出现验证错误时,应从 AWS 官方信任库获取 CA bundle 并安装到系统证书存储,然后重启 MCP 服务。

不要把关闭证书验证当作快速修复。错误可能说明 CA 缺失、端点名称不匹配、代理劫持或系统时间异常,应该查明原因。

通过 SSH 隧道时是否关闭 TLS

文档允许在 SSH 隧道已经提供端到端加密时关闭 pymssql 层的 TLS,以避免本地转发地址与证书名称不匹配。但这会把数据库传输安全完全交给 SSH 隧道。

只有当隧道端点、主机密钥、用户身份和转发范围均受控时才考虑关闭。若可以通过正确的 server name、CA 和连接配置保留 TLS,双重加密通常比关闭验证更清晰。

隧道不得公共网卡,不应允许任意转发,也不要使用共享 root 密钥。连接断开与重连都应进入坚控。

连接参数应如何约束

instance_identifier、db_endpoint、region、database 和 port 在启动时提供,默认 SQL Server 端口为 1433。运行时 connect_to_database 不应成为连接任意公网主机的通用代理。

在网络层通过安全组只允许 MCP 主机访问目标 RDS 端口;RDS 不公开互联网入口;DNS 和路由只覆盖必要网段。即使模型构造恶意参数,也无法离开批准的网络范围。

数据库名称应指向具体业务只读库,不要默认使用 master。系统数据库能暴露实例元数据,非必要时不让专用账户访问。

如何测试关键词阻断

在隔离测试数据库和只读账户上运行一组负向用例。分别提交 INSERT、UPDATE、DELETE、DROP、CREATE、ALTER、MERGE、TRUNCATE、EXEC 与 GRANT,预期应在应用层被拒绝。

再测试大小写、空白、注释和 CTE 组合,确认过滤器不会因为简单变形漏判。负向测试的目标不是寻找可用于生产绕过的语句,而是验证升级后安全行为没有退化。

同时运行合法的复杂 SELECT,防止过滤规则误伤列名或字符串中的普通文本。把预期允许与拒绝用例纳入版本升级门禁。

如何测试注入模式检测

测试堆叠语句、UNION SELECT、恒真条件、延时语句和系统过程命名模式。每个请求都应返回明确拦截原因,并且数据库审计中不出现对应执行。

对表结构工具传入异常对象名,确认参数化查询不会把输入拼接成可执行 SQL。MCP 客户端发出的参数也要记录为结构化数据,而不是通过字符串模板组合。

任何新版本修改检测规则后都应复跑。项目文档已经声明检测不是安全边界,因此测试通过也不能取消数据库只读账户。

如何验证强制回滚

在专用一次性数据库中,用具有临时写权限的测试账户模拟过滤遗漏,确认执行后事务被回滚、数据和架构不变。该测试不能在生产数据库和正式只读账户上做。

检查异常路径,包括查询报错、超时、客户端断开和连接池回收。服务应回滚并释放连接,不能把污染的事务交给下一个请求。

完成测试后删除临时账户与数据库。不要因为回滚测试成功就给生产账户保留写权限。

数据库审计和 AWS 审计

启用 SQL Server 审计或适合 RDS 的数据库日志,记录只读账户的登录、查询失败和权限拒绝。日志中可能包含敏感查询文本,应限制访问与保留时间。

CloudTrail 坚控 Secrets Manager 读取、IAM 角色使用和 RDS 控制面操作。对异常区域、异常主体、读取频率突增和未批准秘密访问设置告警。

MCP 应用日志记录工具名称、目标连接、耗时、结果行数和拦截原因,但不要打印密码、完整 secret JSON 或包含个人数据的结果集。三层日志使用统一时间源和请求关联标识。

限制查询资源消耗

只读查询仍可能造成事故。无条件扫描大表、笛卡尔积、复杂排序、锁等待和延时语句会占用 CPU、内存、I/O 与连接池。

在数据库侧设置合理查询超时、工作负载限制和连接数;优先连接只读副本或报告库;要求模型先读取表结构和索引,再生成带过滤与 TOP 的查询。

对返回行数和单次响应大小设置上限。提示模型“只查询需要的列”不能替代强制限制,因为模型可能忽略提示或被外部内容诱导。

防止敏感数据过度暴露

db_datareader 能读取整个数据库中的用户表,范围可能仍过大。包含身份信息、支付数据、密钥、访问令牌或客户内容的表不应直接暴露。

为 MCP 创建脱敏视图,只选择必要列并对标识符聚合或遮罩,再让自定义只读角色仅访问这些视图。数据库层视图比依赖模型遵守提示更可靠。

get_table_schema 也会暴露列名和类型,可能泄露业务结构。必要时把 MCP 接到专用报告数据库,而不是生产事务库。

提示注入为何会影响数据库安全

Agent 读取的工单、文档、表字段和注释都可能包含看似指令的文本。模型可能误把这些内容当成系统目标并调用 run_query。

只读账户把最坏结果限制为数据读取和资源消耗,但仍可能造成机密泄露。应限制模型可用工具、数据库范围与结果行数,并对敏感查询要求人工确认。

不要让数据库中保存的文本决定 secret ARN、实例标识或是否开启写模式。这些控制参数只能由可信部署者在启动时配置。

常见错误与修复

默认使用 MasterUserSecret

主用户权限远超查询需求。立即创建只读登录和自定义秘密,通过实例绑定的 secret ARN 启动,并审查此前连接期间的数据库日志。

认为回滚等于绝对只读

回滚只覆盖可回滚事务内的修改。使用数据库权限拒绝写入,并禁用不必要的函数和过程执行权限。

遇到证书错误就关闭 TLS

先安装 RDS CA bundle、检查端点名称和系统时间。只有受控 SSH 隧道等明确场景才评估关闭数据库层 TLS。

给运行角色开放全部秘密

将 IAM Resource 收紧到指定只读 secret ARN,并增加区域、标签和 KMS 条件。检查 CloudTrail 是否有越界读取。

在长期服务上打开写模式

移除 allow_write_query,重启服务并验证启动参数。确需写入时建立独立短期流程,完成后销毁身份和服务。

推荐上线流程

第一步,在隔离 SQL Server 测试库创建只读用户,用普通客户端验证数据库层拒绝所有写入。第二步,把凭据存入独立 Secrets Manager secret,并给 MCP 运行身份最小读取权限。

第三步,以默认只读模式启动服务,安装正确 RDS CA,限制安全组和目标实例。第四步测试合法 SELECT、结构读取、关键词阻断、注入模式、回滚异常路径和连接池凭据刷新。

第五步启用数据库、应用与 AWS 审计,设置查询资源和结果上限。第六步只向经过授权的 MCP 客户端开放,并定期轮换秘密、更新依赖和复跑安全用例。

AWS Labs SQL Server MCP 的默认保护设计提供了有价值的纵深防御,但每一层都有明确边界。把关键词与注入检测当作早期阻断,把关闭自动提交和回滚当作补救,再以数据库专用只读账户、固定 secret ARN、最小 IAM、TLS 和网络隔离构成硬边界,才能真正降低 Agent 查询 RDS SQL Server 时的写入风险。

热门栏目