找回密码
 立即加入
搜索
进吧 门户 技巧分享 查看内容

SQL用户权限突然变成拥有所有权限排查

2026-5-13 13:31| 发布者: admin| 查看: 6| 评论: 0

摘要: 以用户AOI突然变成对MES数据全库可改进行示例代码操作:目标是确认它为什么会突然变成 MES 全库可改:是因为加入了 db_owner、被映射成 dbo、继承了某个角色、被授了 schema/database 级权限,还是甚至是 sysadmin。 ...
 以用户AOI突然变成对MES数据全库可改进行示例代码操作:

目标是确认它为什么会突然变成 MES 全库可改:是因为加入了 db_owner、被映射成 dbo、继承了某个角色、被授了 schema/database 级权限,还是甚至是 sysadmin

说明:Login 是服务器级(aoi),User 是数据库级(mes 里映射出来的用户)。权限通常来自:服务器角色数据库角色显式 GRANT对象级 GRANTschema 级 GRANT


SELECT IS_SRVROLEMEMBER(N'sysadmin', N'aoi') AS is_sysadmin;

如果结果是 1,基本可以直接定位原因:服务器级 sysadmin

同时列出它加入的所有服务器角色:

SELECT sp.name AS login_name, sr.name AS server_role
FROM sys.server_role_members rm
JOIN sys.server_principals sr ON rm.role_principal_id = sr.principal_id
JOIN sys.server_principals sp ON rm.member_principal_id = sp.principal_id
WHERE sp.name = N'aoi'
ORDER BY sr.name;

USE mes;
GO

SELECT 
    dp.name AS db_user,
    dp.type_desc,
    dp.authentication_type_desc
FROM sys.database_principals dp
WHERE dp.sid = SUSER_SID(N'aoi')
   OR dp.name = N'aoi';

你要记下查到的 db_user 名称(有时不叫 aoi)。下面我用 @dbuser 变量自动取出。


USE mes;
GO

DECLARE @dbuser sysname = (
    SELECT TOP(1) name 
    FROM sys.database_principals 
    WHERE sid = SUSER_SID(N'aoi')
    ORDER BY CASE WHEN name = N'dbo' THEN 0 ELSE 1 END, name
);

SELECT @dbuser AS mapped_db_user;

-- 是否为 db_owner
SELECT IS_ROLEMEMBER(N'db_owner', @dbuser) AS is_db_owner;

-- 数据库所有者是谁(若 aoi 变成 owner 也会很危险)
SELECT SUSER_SNAME(owner_sid) AS database_owner
FROM sys.databases
WHERE name = N'mes';

USE mes;
GO

DECLARE @dbuser sysname = (
    SELECT TOP(1) name 
    FROM sys.database_principals 
    WHERE sid = SUSER_SID(N'aoi')
);

SELECT 
    m.name AS user_name,
    r.name AS db_role
FROM sys.database_role_members drm
JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
WHERE m.name = @dbuser
ORDER BY r.name;

重点关注是否在这些角色里:db_owner / db_securityadmin / db_ddladmin / db_datawriter / db_datareader


USE mes;
GO

DECLARE @dbuser sysname = (
    SELECT TOP(1) name 
    FROM sys.database_principals 
    WHERE sid = SUSER_SID(N'aoi')
);

SELECT 
    dp.name AS user_name,
    perm.state_desc,
    perm.permission_name,
    perm.class_desc
FROM sys.database_permissions perm
JOIN sys.database_principals dp ON perm.grantee_principal_id = dp.principal_id
WHERE dp.name = @dbuser
  AND perm.class_desc = 'DATABASE'
ORDER BY perm.permission_name;
USE mes;
GO

DECLARE @dbuser sysname = (
    SELECT TOP(1) name 
    FROM sys.database_principals 
    WHERE sid = SUSER_SID(N'aoi')
);

SELECT
    dp.name AS user_name,
    perm.state_desc,
    perm.permission_name,
    s.name AS schema_name
FROM sys.database_permissions perm
JOIN sys.database_principals dp ON perm.grantee_principal_id = dp.principal_id
JOIN sys.schemas s ON perm.major_id = s.schema_id
WHERE dp.name = @dbuser
  AND perm.class_desc = 'SCHEMA'
ORDER BY s.name, perm.permission_name;

如果你看到对 dbo 或某个业务 schema 有 CONTROL/ALTERINSERT/UPDATE/DELETE,那基本就解释了“能改 MES 所有表”。


USE mes;
GO

DECLARE @dbuser sysname = (
    SELECT TOP(1) name 
    FROM sys.database_principals 
    WHERE sid = SUSER_SID(N'aoi')
);

SELECT
    dp.name AS user_name,
    perm.state_desc,
    perm.permission_name,
    sch.name AS schema_name,
    obj.name AS object_name,
    obj.type_desc
FROM sys.database_permissions perm
JOIN sys.database_principals dp ON perm.grantee_principal_id = dp.principal_id
JOIN sys.objects obj ON perm.major_id = obj.object_id
JOIN sys.schemas sch ON obj.schema_id = sch.schema_id
WHERE dp.name = @dbuser
ORDER BY sch.name, obj.name, perm.permission_name;

USE mes;
GO

DECLARE @dbuser sysname = (
    SELECT TOP(1) name 
    FROM sys.database_principals 
    WHERE sid = SUSER_SID(N'aoi')
);

EXECUTE AS USER = @dbuser;
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
REVERT;

如果这里出现 ALTER ANY SCHEMA / CONTROL / ALTER / INSERT / UPDATE / DELETE 等,就说明有效权限已超出只读。


最常见导致“突然全权限”的原因清单(你可以对照上面结果)

  1. aoi 被加入 sysadmin(服务器级)
  2. mes 库里 aoi 的用户被加入 db_owner
  3. aoi 被加入 db_datawriter 或被授了 schema 级写权限(对 dbo schema 很常见)
  4. aoi 在 mes 中被映射成 dbo 或者 mes 的 owner 变成了 aoi
  5. 有人直接对 aoi(或其所属角色)做了 GRANT CONTROL / ALTER(数据库或 schema 级)

解决方案:
  1. 先看 test 是否拥有对象(如果拥有对象,不能直接删,需要先转移所有权):
USE mes;
GO
SELECT 
  s.name AS schema_name
FROM sys.schemas s
WHERE s.principal_id = USER_ID(N'test');

如果有 schema 归属 test,需要先改回 dbo:

USE mes;
GO
ALTER AUTHORIZATION ON SCHEMA::[schema_name] TO dbo;
  1. 删除错误用户 test:
USE mes;
GO
DROP USER [test];
  1. 再绑定 AOI:
USE mes;
GO
ALTER USER [AOI] WITH LOGIN = [aoi];
USE mes;
GO
ALTER USER [test] WITH LOGIN = NULL;

然后再绑定 AOI:

USE mes;
GO
ALTER USER [AOI] WITH LOGIN = [aoi];

注意:ALTER USER ... WITH LOGIN = NULL 在部分版本/场景可能不允许;如果不行,就用方案A。


鲜花

握手

雷人

路过

鸡蛋

最新评论

本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件kf@jinb.top与我们联系处理。

手机版|小黑屋|进吧

GMT+8, 2026-5-13 19:21 , Processed in 0.081931 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

返回顶部