保护中转服务
中转服务默认仅对本地用户和激活它的 Visual Studio 会话中涉及的进程可用。 在这些默认值下,中转服务的安全注意事项与在这些进程中运行的其他代码不同,其中包括:
- 从威胁模型的角度来看,假定在 Visual Studio 进程中运行的扩展是完全信任的。 进程不足的扩展应将 Visual Studio 服务调用视为越过信任边界。
- 代码必须在入口点验证参数,以确认它们属于预期模式/范围。
- 从磁盘读取数据时,请考虑数据可能被篡改。
- 从网络或 Internet 接收数据时,在分析或反序列化数据以避免常见漏洞时要谨慎。
在向标志集注册 ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients 服务时,会应用几个关键的附加安全注意事项。 本文的其余部分重点介绍这些注意事项。
敏感操作的授权检查
获取授权服务
中转服务应具有采用参数的构造函数 AuthorizationServiceClient 。 参数应存储在字段中,并在服务 Dispose() 的方法中释放。
class Calculator : ICalculator, IDisposable
{
private readonly AuthorizationServiceClient authorizationService;
internal Calculator(AuthorizationServiceClient authorizationService)
{
this.authorizationService = authorizationService;
}
public void Dispose()
{
this.authorizationService.Dispose();
}
}
你提供的服务工厂稍有更改,以支持此新参数。 提供委托,而不是向方法提供 BrokeredServiceFactory IBrokeredServiceContainer.Proffer AuthorizingBrokeredServiceFactory 委托。 此委托接收 AuthorizationServiceClient 需要传递给中转服务的信息。
对教授代码的此更改可能如下所示:
container.Proffer(
CalculatorService,
- (moniker, options, serviceBroker, cancellationToken) => new ValueTask<object?>(new CalculatorService()));
+ (moniker, options, serviceBroker, authorizationService, cancellationToken) => new ValueTask<object?>(new CalculatorService(authorizationService)));
使用授权服务
任何可能披露敏感信息或改变用户状态的操作都应使用AuthorizationServiceClient.AuthorizeOrThrowAsync授权服务检查。
若要断言调用方是代码的所有者(与 Live Share 主机的操作员相同的标识),可以使用以下代码:
private static readonly ProtectedOperation ClientIsOwner = WellKnownProtectedOperations.CreateClientIsOwner();
public ValueTask ResetOperationCounterAsync(CancellationToken cancellationToken)
{
// Resetting the counter should only be allowed if the user is the owner.
await this.authorizationService.AuthorizeOrThrowAsync(ClientIsOwner, cancellationToken);
// Proceed with the operation.
this.operationCounter = 0;
}
类中 WellKnownProtectedOperations 定义了各种其他授权级别。
当服务客户端在同一台计算机和用户帐户中运行时,始终批准所有授权检查。 他们还被批准为在主机所在的同一 Microsoft 帐户下运行的 Live Share 来宾。
当请求的操作 未 获得授权时, AuthorizeOrThrowAsync 将引发一个 UnauthorizedAccessException。 Live Share 主机可能会通知所有者失败的尝试,使主机有机会在识别操作时授予完成操作 ProtectedOperation 所需的权限,以便客户端上的后续尝试可能会成功。
在本地AuthorizationServiceClient缓存所有授权检查,以便重复的授权检查速度很快。 如果用户的权限集发生更改(例如 Live Share 主机更改来宾的权限),则会自动刷新本地缓存。
使用其他中转服务
当中转服务本身需要访问另一个中转服务时,它应使用 IServiceBroker 提供给其服务工厂的代理服务。 它不应使用全局 Service Broker,因为不知道此特定中转服务实例的上下文,并且客户端必须激活和调用其他行为的授权。
如果计算器服务需要其他中转服务来实现其行为,我们将修改构造函数以接受:IServiceBroker
internal class Calculator : ICalculator
{
private readonly IServiceBroker serviceBroker;
private readonly AuthorizationServiceClient authorizationService;
internal class Calculator(IServiceBroker serviceBroker, AuthorizationServiceClient authorizationService)
{
this.serviceBroker = serviceBroker;
this.authorizationService = authorizationService;
}
}
此附加参数将影响服务工厂提供代码:
container.Proffer(
CalculatorService,
(moniker, options, serviceBroker, authorizationService, cancellationToken)
- => new ValueTask<object?>(new CalculatorService(authorizationService)));
+ => new ValueTask<object?>(new CalculatorService(serviceBroker, authorizationService)));
有限的中转服务可用性
当中转服务的客户端是 Live Share 来宾(在主机所有者的帐户下),上下文服务代理将仅激活其他已将标志设置为 AllowTransitiveGuestClients 安全预防措施的中转服务。 尝试激活不符合资格的中转服务将引发一个 UnauthorizedAccessException。
如果中转服务需要另一个缺少 AllowTransitiveGuestClients 标志的中转服务,则可以使用全局 Service Broker 获取它,但必须考虑从中转服务获取的中转服务不知道不受信任的来宾是最终客户端。 应遵循下一部分中关于调用其他 VS 服务或其他 API 的所有相同预防措施。
使用其他 VS 服务或其他 API
在向 Live Share 来宾公开的中转服务中,允许调用标准 Visual Studio 服务、第三方库或标准 .NET API,但应仔细编写此类调用,并首先验证所有输入。
应仔细检查文件路径或 URL,以确保它们有效,并位于来宾有权访问的预期子路径中。
例如,如果中转服务允许基于路径读取或写入文件,则应检查路径位于打开的解决方案下,并且来宾实际上具有写入权限(如果适用)。
如果考虑 ..
得当,验证文件路径可能很困难,其他方法使它看起来像路径以正确的前缀开头,但随后转义允许的解决方案目录。
在调用任何没有自己的权限的 API 之前,请根据需要使用AuthorizationServiceClient上述部分中所述的内容来断言客户端具有权限检查内置。 应仅假定 Visual Studio 中内置的中转服务包含自己的授权检查,这依赖于使用上下文服务代理获取这些中转服务,如上一部分所述。
所有其他 API(包括使用全局 Service Broker 获取的非中转 Visual Studio 服务或中转服务)都可以在指导它们时执行,而不考虑 Live Share 来宾的权限级别,使你自己的授权检查保护 Live Share 主机的安全性至关重要。
避免从中转服务公开另一个 Visual Studio 中转服务在增加攻击面时已经公开的功能。
跨中转服务实例共享状态
当中转服务需要跨服务的多个实例共享状态时,此数据可能会向具有不同权限集的多个用户公开。 中转服务在这些用户中保护此数据至关重要。 使用 STRIDE 模型 来帮助识别、分类并最终缓解威胁。
你可以决定将共享状态视为受信任状态,因此,可以授予它以在内部执行所需的任何操作的权限(例如,访问 VS 服务或使用全局服务代理)。 在这种情况下,它将成为单个中转服务实例负责保护对其共享状态发出的调用,以确保所有输入都适合使用授权服务自己的用户权限。
Microsoft 威胁建模工具是保护共享状态和用户的有用工具。