Identifier pourquoi un utilisateur peut supprimer une base de données

8

J'ai un utilisateur de serveur SQL qui a la possibilité de supprimer n'importe quelle base de données. J'ai exécuté le code ci-dessous pour vérifier les droits que l'utilisateur a sur SQL Server mais je n'ai pas pu identifier comment l'utilisateur a la possibilité de supprimer des bases de données. Existe-t-il un script SQL qui peut m'aider à identifier comment cet utilisateur peut supprimer des dbs? Existe-t-il une commande pour leur refuser de supprimer des bases de données? (SSMS n'affiche pas l'utilisateur dans le cadre du rôle dbcreator)

select USER_NAME(p.grantee_principal_id) AS principal_name,
    dp.type_desc AS principal_type_desc,
    p.class_desc,
    OBJECT_NAME(p.major_id) AS object_name,
    p.permission_name,
    p.state_desc AS permission_state_desc 
from    sys.database_permissions p
inner   JOIN sys.database_principals dp
on     p.grantee_principal_id = dp.principal_id
order by principal_name

La sortie de la requête ci-dessus fournit les trois enregistrements suivants pour l'utilisateur si cela est utile

class_desc nom_objet permission_name permission_state_desc OBJECT_OR_COLUMN xp_cmdshell EXECUTE GRANT DATABASE NULL CONNECT GRANT
DATABASE NULL CREATE DATABASE GRANT

Grumeleux
la source
Cet utilisateur supprime-t-il des bases de données?
Zane
Je peux supprimer des bases de données en tant qu'utilisateur. Oui. Si vous demandez si quelqu'un a utilisé le compte de manière ludique, je préfère ne pas attendre de le voir.
Lumpy
Quel est le niveau général d'autorisation de cet utilisateur? Est-ce également uniquement certaines bases de données ou ce serveur est-il étendu?
Zane
2
Examinez les autorisations requises ( msdn.microsoft.com/en-us/library/ms178613.aspx ) et inversez-les.
Thomas Stringer

Réponses:

4

La requête que vous y avez répertoriera uniquement les autorisations pour la base de données sur laquelle vous l'exécutez. Une façon d'obtenir l'autorisation de supprimer une base de données est ALTER ANY DATABASE, qui est une autorisation au niveau du serveur. Pour les vérifier, essayez cette requête:

SELECT 
  [srvprin].[name] [server_principal],
  [srvprin].[type_desc] [principal_type],
  [srvperm].[permission_name],
  [srvperm].[state_desc] 
FROM [sys].[server_permissions] srvperm
  INNER JOIN [sys].[server_principals] srvprin
    ON [srvperm].[grantee_principal_id] = [srvprin].[principal_id]
WHERE [srvprin].[type] IN ('S', 'U', 'G')
ORDER BY [server_principal], [permission_name];

En d'autres termes, l'utilisateur peut obtenir l'autorisation de supprimer des bases de données au niveau de la connexion au serveur plutôt qu'au niveau de l'utilisateur de la base de données.

mdoyle
la source
1
C'était la permission de modifier toute base de données
Lumpy
Oui, ce n'est certainement pas une autorisation que vous voulez que Joe in Accounting ait.
KeithS
6

Je suggère d'exécuter cette requête sur le maître

SELECT  
    [UserName] = CASE princ.[type] 
                    WHEN 'S' THEN princ.[name]
                    WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
                 END,
    [UserType] = CASE princ.[type]
                    WHEN 'S' THEN 'SQL User'
                    WHEN 'U' THEN 'Windows User'
                 END,  
    [DatabaseUserName] = princ.[name],       
    [Role] = null,      
    [PermissionType] = perm.[permission_name],       
    [PermissionState] = perm.[state_desc],       
    [ObjectType] = obj.type_desc,--perm.[class_desc],       
    [ObjectName] = OBJECT_NAME(perm.major_id),
    [ColumnName] = col.[name]
FROM    
    --database user
    sys.database_principals princ  
LEFT JOIN
    --Login accounts
    sys.login_token ulogin on princ.[sid] = ulogin.[sid]
LEFT JOIN        
    --Permissions
    sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id]
LEFT JOIN
    --Table columns
    sys.columns col ON col.[object_id] = perm.major_id 
                    AND col.[column_id] = perm.[minor_id]
LEFT JOIN
    sys.objects obj ON perm.[major_id] = obj.[object_id]
WHERE 
    princ.[type] in ('S','U')
UNION
--List all access provisioned to a sql user or windows user/group through a database or application role
SELECT  
    [UserName] = CASE memberprinc.[type] 
                    WHEN 'S' THEN memberprinc.[name]
                    WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
                 END,
    [UserType] = CASE memberprinc.[type]
                    WHEN 'S' THEN 'SQL User'
                    WHEN 'U' THEN 'Windows User'
                 END, 
    [DatabaseUserName] = memberprinc.[name],   
    [Role] = roleprinc.[name],      
    [PermissionType] = perm.[permission_name],       
    [PermissionState] = perm.[state_desc],       
    [ObjectType] = obj.type_desc,--perm.[class_desc],   
    [ObjectName] = OBJECT_NAME(perm.major_id),
    [ColumnName] = col.[name]
FROM    
    --Role/member associations
    sys.database_role_members members
JOIN
    --Roles
    sys.database_principals roleprinc ON roleprinc.[principal_id] = members.[role_principal_id]
JOIN
    --Role members (database users)
    sys.database_principals memberprinc ON memberprinc.[principal_id] = members.[member_principal_id]
LEFT JOIN
    --Login accounts
    sys.login_token ulogin on memberprinc.[sid] = ulogin.[sid]
LEFT JOIN        
    --Permissions
    sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
LEFT JOIN
    --Table columns
    sys.columns col on col.[object_id] = perm.major_id 
                    AND col.[column_id] = perm.[minor_id]
LEFT JOIN
    sys.objects obj ON perm.[major_id] = obj.[object_id]
UNION
--List all access provisioned to the public role, which everyone gets by default
SELECT  
    [UserName] = '{All Users}',
    [UserType] = '{All Users}', 
    [DatabaseUserName] = '{All Users}',       
    [Role] = roleprinc.[name],      
    [PermissionType] = perm.[permission_name],       
    [PermissionState] = perm.[state_desc],       
    [ObjectType] = obj.type_desc,--perm.[class_desc],  
    [ObjectName] = OBJECT_NAME(perm.major_id),
    [ColumnName] = col.[name]
FROM    
    --Roles
    sys.database_principals roleprinc
LEFT JOIN        
    --Role permissions
    sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
LEFT JOIN
    --Table columns
    sys.columns col on col.[object_id] = perm.major_id 
                    AND col.[column_id] = perm.[minor_id]                   
JOIN 
    --All objects   
    sys.objects obj ON obj.[object_id] = perm.[major_id]
WHERE
    --Only roles
    roleprinc.[type] = 'R' AND
    --Only public role
    roleprinc.[name] = 'public' AND
    --Only objects of ours, not the MS objects
    obj.is_ms_shipped = 0
ORDER BY
    princ.[Name],
    OBJECT_NAME(perm.major_id),
    col.[name],
    perm.[permission_name],
    perm.[state_desc],
    obj.type_desc--perm.[class_desc] 

Cela devrait vous donner une assez bonne idée des rôles qui ont accès à votre base de données principale et voir la météo ou non, l'utilisateur n'a aucun de ces rôles. Vous pouvez également l'exécuter sur n'importe laquelle de vos autres bases de données pour vérifier les autorisations de l'utilisateur sur une base de données par niveau de base de données. Cela devrait être un outil important pour aider à retrouver cette trace.

Zane
la source
Joli script ....
4

Existe-t-il un script SQL qui peut m'aider à identifier comment cet utilisateur peut supprimer des dbs?

Je l'ai utilisé plusieurs fois avec de bons résultats, la source du code ci-dessous peut être trouvée ici :


SELECT SP1.[name] AS 'Login', 'Role: ' + SP2.[name] COLLATE DATABASE_DEFAULT AS 'ServerPermission'  
FROM sys.server_principals SP1 
  JOIN sys.server_role_members SRM 
    ON SP1.principal_id = SRM.member_principal_id 
  JOIN sys.server_principals SP2 
    ON SRM.role_principal_id = SP2.principal_id 
UNION ALL 
SELECT SP.[name] AS 'Login' , SPerm.state_desc + ' ' + SPerm.permission_name COLLATE DATABASE_DEFAULT AS 'ServerPermission'  FROM sys.server_principals SP  
  JOIN sys.server_permissions SPerm  
    ON SP.principal_id = SPerm.grantee_principal_id  
ORDER BY [Login], [ServerPermission];

Existe-t-il une commande pour leur refuser de supprimer des bases de données?

En poursuivant la documentation ici , les exigences de sécurité pour qu'un utilisateur supprime une base de données sont les suivantes:

Nécessite l'autorisation CONTROL sur la base de données, ou l'autorisation ALTER ANY DATABASE, ou l'appartenance au rôle de base de données fixe db_owner

Vous pouvez explicitement refuser l'autorisation à l'un mentionné ci-dessus, mais comprenez que le niveau auquel vous le refusez peut ne pas avoir d'effet comme vous le pensez. Je me souviens d'avoir lu un livre blanc qui expliquait comment SQL Server procédait à la validation des autorisations d'un utilisateur lors de la connexion, mais ne pouvait pas le localiser pour le moment. Si je me souviens, je peux leur refuser la connexion à une base de données, mais le fait que l'utilisateur fasse partie du sysadminrôle prime.

J'examinerais l'audit spécifiquement pour que la DROP DATABASEcommande soit sûre.


la source
c'était la modification de toute autorisation de base de données. Je vous remercie.
Lumpy