模拟用户或登录映射到证书

i-o*_*one 4 security sql-server signature certificate impersonation

假设在数据库中创建了一个证书

create certificate certName
    with subject = 'subj';
GO
Run Code Online (Sandbox Code Playgroud)

和映射到此证书的用户

create user userName
    from certificate certName;
GO
Run Code Online (Sandbox Code Playgroud)

试图直接冒充此用户

execute as user = 'userName';
GO
Run Code Online (Sandbox Code Playgroud)

execute as在模块的子句中指定用户

create procedure procName
with execute as 'userName'
as
    set nocount on;
GO
Run Code Online (Sandbox Code Playgroud)

返回错误

消息 15517,级别 16,状态 1 ...
无法作为数据库主体执行,因为主体“userName”不存在、无法模拟此类主体或您没有权限。

但是,我找不到文档中提到的这个限制(这里这里),唯一相关的声明似乎是

user_name 必须存在于当前数据库中并且必须是单例帐户。user_name 不能是组、角色、证书、密钥或内置帐户,例如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。

是否可以模拟映射到证书的用户(或登录)?

Sol*_*zky 5

不能模拟从证书和非对称密钥创建的登录名和用户。它们只是一组权限的代理,这些权限将添加到使用相同证书或非对称密钥签名的任何模块中。

此外,模拟这些登录名和用户并没有多大意义,因为:

  1. 这些代理权限被添加到当前安全上下文(已签名的执行模块的)而不是替换安全上下文,这正是 Impersonation 所做的。这是一种完全不同的方法,而不仅仅是针对本质上相同的事物的不同机制。
  2. 模块签名不适用于即席查询。使模块签名比 Impersonation 更安全的部分原因是授予提升权限的人(通过签署模块将其与一组额外的权限关联)知道代码在做什么,并且一旦代码被赋予提升的权限,不能改变它做其他事情,例如做模块签名的人不会同意的事情。这是通过在对签名模块进行任何更改时删除签名来处理的,并且模块的文本(包括语句的可选EXECUTE AS子句CREATE)用于创建签名这一事实。如果文本更改,则签名将不匹配。

最后,使用从非对称密钥和证书创建的登录名和/或用户取代了对模拟的需要。

尽管如此,如果要寻找更官方的指标,CREATE USER的 MSDN 页面指出:

无法进行身份验证的用户 这些用户无法登录 SQL Server 或 SQL 数据库。

  • 没有登录的用户。无法登录但可以授予权限。CREATE USER CustomApp WITHOUT LOGIN;
  • 基于证书的用户。无法登录但可以被授予权限并且可以签署模块。CREATE USER TestProcess FOR CERTIFICATE CarnationProduction50;
  • 基于非对称密钥的用户。无法登录但可以被授予权限并且可以签署模块。CREATE User TestProcess FROM ASYMMETRIC KEY PacificSales09;

但是,无法登录/身份验证并不意味着“无法模拟”,因为没有登录的用户在该列表中,您可以执行EXECUTE AS USER='{user_without_login}';.

CREATE LOGIN的 MSDN 页面指出:

从证书或非对称密钥创建的登录仅用于代码签名。它们不能用于连接到 SQL Server。

虽然第二句话重复了CREATE USER文档所说的内容,但第一句话更具体一点:它们仅用于代码签名。

最后,您在EXECUTE ASEXECUTE AS 子句的文档中找到的限制声明是正确的,即使它们的措辞令人困惑。他们声明(加粗强调):

name必须是单例帐户,不能是组、角色、证书、密钥或内置帐户,例如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。

该引用取自EXECUTE AS文档,并且EXECUTE AS Clause在问题中引用了文档(几乎相同的措辞)。虽然这两个页面都使用了“证书”和“密钥”这两个术语,但它们的真正含义分别是“基于证书的登录/用户”和“基于非对称密钥的登录/用户”。我假设这是基于这样一个事实,即给定的主要类型列表都可以在sys.server_principals(对于登录)和sys.database_principals(对于用户)中找到,并且证书和非对称密钥都不会在这两个系统目录视图中列出。