zap*_*san 8 security sql-server service-broker sql-server-2012
我有一个在 SQL-Server 2012 DBMS 上运行的数据库。考虑到运行 SQL Server 的服务器不是网络域的一部分。当我执行这个 sql 命令时
ALTER DATABASE myDatabase SET TRUSTWORTHY ON;
Run Code Online (Sandbox Code Playgroud)
服务代理队列(早期设置和工作)接收消息,但与队列关联的活动存储过程没有启动。消息继续流入队列,但没有其他任何事情发生。在 SQL SERVER 日志中,我发现了这条消息
在队列“proofSCHEMA.myQueue”上运行的激活过程“proofSchema.mySP”输出以下内容:“主数据库中记录的数据库所有者 SID 与数据库“myDatabase”中记录的数据库所有者 SID 不同。您应该通过使用 ALTER AUTHORIZATION 语句重置数据库“myDatabase”的所有者来纠正这种情况。
如果我在网络域内的机器上运行相同的配置,则一切正常。
我不明白发生了什么以及为什么值得信赖的使用服务代理队列。
在每个数据库中都存在一个dbo用户。该用户(数据库级)始终存在,但它映射到的 SID(安全标识符)并不总是相同;它将映射到在创建数据库时或更改为具有新的“数据库所有者”时指定的任何登录(实例级别)。该dbo用户是在一个条目sys.database_principals。
当在最初设置的数据库所有者CREATE DATABASE,或稍后改变时,“所有者”的SID不仅放入sys.database_principals,但也被记录在master.sys.databases。如果数据库从不离开创建它的实例,则sys.database_principals和 中的 SID 值之间不应存在不匹配master.sys.databases。但是,如果数据库曾经恢复或附加到(或从)另一个实例,则 SID 值可能不匹配。您可以使用以下查询检查两个地方的值:
USE [tempdb]; -- Change to whatever DB you want to check
SELECT msd.owner_sid,
msp.[name]
FROM [master].[sys].[databases] msd
INNER JOIN [master].[sys].[server_principals] msp
ON msp.[sid] = msd.[owner_sid]
WHERE msd.[database_id] = DB_ID();
SELECT sdp.[sid]
FROM [sys].[database_principals] sdp
WHERE sdp.[name] = N'dbo';
Run Code Online (Sandbox Code Playgroud)
现在,默认情况下,TRUSTWORTHY设置为OFF并且涉及模拟(即EXECUTE AS)的操作的权限仅限于执行操作的数据库。在模拟数据库用户,尝试访问另一个数据库(甚至服务器/实例级资源,我相信)时,SQL Server 将假定当前数据库用户的 SID(即被模拟的用户)具有匹配的登录名,因此它可以在这些权限上。此被阻止时TRUSTWORTHY是OFF,但将其设置到ON升降机的数据库级隔离,并允许模拟延伸超出初始数据库。的 SIDdbo用户肯定作为登录存在,但如果它不是映射为数据库所有者的同一个 SIDsys.databases,那么这清楚地表明某些事情不正确(并且很可能该数据库来自另一个实例),并且请求的操作中可能存在恶意意图。
小智 5
当您还原在另一台服务器上创建的数据库,而数据库所有者登录帐户在您还原到的服务器上不存在或具有不同的 SID 时,可能会发生这种情况。
选择您对拥有数据库感到满意的登录名,然后执行以下操作:
ALTER AUTHORIZATION ON DATABASE:: [Database Name Here] TO [Login Name];
Run Code Online (Sandbox Code Playgroud)