摘要

  • RFC 9987 的签名请求只携带公钥块、待签数据与标志,成功响应只返回签名。标准消息没有必填字段用来说明发起进程、操作人、目标主机、远端账户、命令或业务目的。
  • 代理协议自身不提供客户端认证与传输安全;访问本地端点通常就意味着能够请求密钥操作。代理转发不复制私钥,却会把调用能力带过主机边界,形成传递信任。
  • 确认、有效期、锁定、代理结果、服务器认证与应用授权是彼此独立的判定。Daniel Kade 提出六阶段“签名意图回执”,用最小化标识与摘要串联这些判定,不保存私钥、口令或敏感原文。

一条成功日志遮住了哪些问题

设想值班人员看到三项绿色结果:代理返回成功;签名校验通过;硬件设备证明私钥从未导出。页面于是把事件归类为“用户批准”。真正需要追问的内容却没有出现:哪个进程接入了代理端点,请求来自本机还是转发通道,当时加载的是哪一组约束,确认窗口向人展示了什么,目标 SSH 服务器最终又准许了哪一个账户和操作。

RFC 9987 于 2026 年 5 月以 IETF Proposed Standard 发布,规定客户端与 SSH 代理之间的请求—响应协议。代理可以保存私钥,也可以把私钥操作委托给令牌;客户端可以添加、删除和列举身份,请求签名,锁定代理,或使用扩展。这种边界清晰的标准化解决的是接口互操作问题,不是所有签名行为的机构解释问题。

SSH_AGENTC_SIGN_REQUEST 包含公钥块、数据字符串与 flags。成功时,SSH_AGENT_SIGN_RESPONSE 携带签名。消息没有要求填写可执行程序、自然人主体、目的主机、远端用户名、命令、变更单或授权规则。待签数据可能正是 SSH 用户认证结构,但通用代理消息并不承诺只有这一种用途,也不知道接收方以后会怎样使用签名。

因此,密码学事实应当被准确地表述为:某把密钥对给定字节执行了签名。它不能倒推出请求者被允许调用,也不能证明人理解了结果。Why BTW Media Exists 强调把可观察事实与附加叙事分开。这里可以观察的是密钥操作;同意和授权仍然需要各自的证据。

私钥留在原地,调用权仍会被窃取

RFC 9987 的安全章节明确指出,代理协议本身既不认证客户端,也不保护传输。在常见系统中,它运行于本地 socket 或命名管道,依赖操作系统权限限制访问者。谁能到达端点,谁往往就能要求代理使用其可见身份。于是,控制面至少有两个:私钥字节由谁保管,以及谁有资格让私钥执行动作。

恶意进程可能完全无法提取密钥,却可以利用可达且无约束的代理反复请求签名。标准还提醒,无约束代理会成为非常理想的侧信道观察 oracle。“不可导出”能够缩小秘密复制的风险,却不能排除盗用。一次处置如果只验证设备没有泄露密钥,而不封闭代理端点,就可能修错了层级。

硬件令牌进一步说明这种分层。把令牌上的身份加入代理,通常只是委托未来的私钥操作;从代理中移除身份,不应删除令牌里的钥匙。报告中的“密钥已删除”必须说明删除发生在代理清单、会话可见范围还是物理设备。若没有层级与时间,后来重新加载的同一身份会让所谓撤销失去意义。

The Policy Mirror 提供了治理准则:政策必须映射真实控制权。操作系统决定端点准入;代理决定是否执行并应用约束;令牌控制密钥材料及可能的本地在场;远端服务器判断该钥匙能否认证所请求的账户;应用继续判断会话能够做什么。签名经过这些层,却没有替任何一层取得最终决定权。

“受约束”不是密钥的永久属性

RFC 9987 支持带约束地加入密钥。生命周期约束要求代理在指定时长后移除身份;确认约束要求每次私钥操作前取得明确确认;命名扩展还可以表达其他边界。代理若不理解请求的约束,必须拒绝加入,而不能悄悄忽略限制。这个失败关闭原则很重要,但审计仍需证明约束在事件发生时确实处于生效状态。

同一密钥再次被加入时,新请求应替换旧约束,否则代理可以拒绝。由此可见,密钥指纹不能单独代表权限。需要为每次加载或替换建立 epoch,把签名关联到当时的生命周期、确认要求、扩展、可见范围与锁定状态。事故后的截图只展示“现在”,不一定能还原“当时”。

确认对话框也不能自动升格为知情同意。按钮点击只证明一个交互界面收到了肯定答复。若界面没有安全、准确地说明协议、目标、账户与后果,人就没有充分信息。直接展示原始数据可能泄露账户或协议内容;只显示“是否允许使用密钥”又过于空泛。合理做法是将可信界面上的易懂摘要、摘要版本和待签数据的抗碰撞哈希绑定起来。

锁定状态同样独立。代理被锁定后,至少应暂停私钥签名,直到正确口令解锁。解锁只改变能力是否可用,并没有识别下一位请求者、挑选目标,也没有批准所有未来操作。把解锁当作一段时间内的通用同意,会把一次本地状态变化错误地扩张成广泛授权。

转发没有移动密钥,却移动了能力

代理转发的吸引力在于:远端机器能够使用本地密钥,而不拿到私钥材料。这项保护是真实的,委托也同样真实。RFC 9987 将转发描述为传递信任,建议默认不启用,并要求不要向不完全可信的主机转发。攻击者控制远端主机后,可以通过已建立的通道请求本地代理签名,密钥仍可保持“未泄露”。

追溯还受到协议结构限制。agent-connect 没有携带区分来源 session channel 的标识。一条 SSH 连接可以同时承载多个会话,本地代理也可能同时看到多个转发连接。因此,“来自这条 SSH transport”未必能够进一步证明是哪一个 shell、进程或人发起。

Running Code Primary 要求以运行中的边界为第一证据。真正有用的是 socket 所有权与权限、可获得的 peer 信息、实际转发选择、约束 epoch、请求时序,以及目标验证方的结果。配置文件里写着“禁止转发”,不能替代某次签名所经过路径的实证。

认证结果在服务器手中

RFC 4252 把公钥用户认证的判定交给服务器。签名覆盖 SSH session identifier,以及用户名、服务、方法、算法与公钥等字段。服务器既要校验签名,也要判断该公钥是否能认证所请求账户;它还可以要求额外认证因素。完整成功由服务器发送 SSH_MSG_USERAUTH_SUCCESS 表示,而不是由更早的代理签名响应表示。

RFC 4253 建立受保护传输与会话标识,RFC 4254 规定认证后的通道和服务,RFC 4251 给出整体架构。这套分层意味着“密钥使用”“账户认证”“通道或命令授权”必须保留为三个事实。

算法登记的证据范围也很窄。RFC 8332 规定 SSH 中的 RSA SHA-2 签名,RFC 8709 规定 Ed25519 与 Ed448,RFC 8308 规定扩展协商。IANA SSH 参数注册表 让实现使用共同标识;它不证明部署、端点暴露、人工批准或业务授权。

六阶段签名意图回执

第一阶段记录请求者准入:本地或转发路径、环境能够可靠取得的最小 peer 引用、政策 epoch 与不透明请求编号。第二阶段记录密钥状态:公钥指纹、可见范围、加载或替换 epoch、生命周期、确认和扩展约束、令牌委托及锁定状态。

第三阶段记录操作:准确待签数据的长度、抗碰撞哈希、算法与 flags,不把敏感原文复制进遥测。第四阶段记录确认:是否要求确认、可信界面展示了哪种安全摘要、何时给出批准、拒绝或不可用。第五阶段记录代理成功或失败及拒绝类别。第六阶段记录依赖系统:协议、目标、会话、请求账户、验证结果、是否还需认证因素,以及后续授权结果与纠正路径。

这套回执是 Daniel Kade 的治理建议,并非 RFC 9987 的字段要求。它不要求代理理解业务,而是阻止一项窄小的技术成功冒充完整权力链。

资料来源