it-swarm.com.de

xp_cmdshell wird von der Prozedur WITH EXECUTE AS OWNER aufgerufen

Ich versuche, Details zum Umschließen der xp_cmdshell-Funktionalität in benutzerdefinierte gespeicherte Prozesse zu verstehen, sodass anderen Benutzern nur die Ausführungsberechtigung für die gespeicherten Prozesse anstelle von xp_cmdshell erteilt werden kann.

Die Schritte in diesem Szenario sind:

  1. xp_cmdshell ist bereits aktiviert und ein xp_cmdshell-Proxy wurde erstellt
  2. Ein Benutzer mit der Mitgliedschaft db_owner erstellt einen gespeicherten Prozess WITH EXECUTE AS OWNER, der xp_cmdshell aufruft
  3. Der Benutzer führt den gespeicherten Prozess aus und führt daher beliebigen Shell-Code aus

Das ist für mich unerwartet. Ich würde nicht erwarten, dass ein Benutzer mit nur db_owner dies erreichen kann. (Offensichtlich unter der Annahme, dass xp_cmdshell bereits von einem Systemadministrator aktiviert wurde.)

Wenn der Datenbankeigentümer von sa in ein anderes Login mit niedrigen Berechtigungen geändert wird, kann der vom Benutzer gespeicherte Prozess xp_cmdshell nicht mehr aufrufen.

USE MASTER;
CREATE DATABASE testdb;
CREATE LOGIN testuser WITH PASSWORD = 'password', CHECK_POLICY=OFF;
CREATE LOGIN dummyuser WITH PASSWORD = 'password', CHECK_POLICY=OFF;
SELECT * from sys.credentials WHERE NAME LIKE '%cmdshell%';
-- returned: 101 ##xp_cmdshell_proxy_account## .....

USE testdb;

EXEC sp_changedbowner 'sa';  
CREATE USER testuser FOR LOGIN testuser;
ALTER ROLE db_owner ADD MEMBER testuser;

EXECUTE AS LOGIN = 'testuser';
GO

CREATE PROCEDURE [dbo].[testproc]
WITH EXECUTE AS OWNER
AS
    SELECT SUSER_NAME() as [SUSER_NAME()], USER_NAME() as [USER_NAME()];  
    exec xp_cmdshell 'echo %time%';
GO

SELECT SUSER_NAME() as [SUSER_NAME()], USER_NAME() as [USER_NAME()];  

EXEC dbo.testproc; 
-- returned: sa dbo  proving that the call to xp_cmdshell has succeeded

EXEC xp_cmdshell 'echo %time%';
-- returned: The EXECUTE permission was denied on the object 'xp_cmdshell'

REVERT

EXEC sp_changedbowner 'dummyuser';  
EXECUTE AS LOGIN = 'testuser';
EXEC dbo.testproc; 
-- returned: The EXECUTE permission was denied on the object 'xp_cmdshell'
-- proving that the sysadmin role of the database owner is relevent

REVERT

Beachten Sie, dass ich keinem bestimmten Benutzer die Berechtigung zum Ausführen von xp_cmdshell erteilt habe.

Ich dachte, dass das Aktivieren von xp_cmdshell in Ordnung ist, wenn darauf geachtet wird, nur die Berechtigung zum Ausführen von xp_cmdshell sorgfältig zu erteilen, aber mein Beispiel scheint etwas anderes zu zeigen.

Zeigt dieses Beispiel ein ernstes Sicherheitsproblem, da ein Systemadministrator häufig ein Datenbankeigentümer ist, oder verstehe ich etwas falsch?

4
John Rees

zeigt dieses Beispiel ein ernstes Sicherheitsproblem oder verstehe ich etwas falsch?

Sie verstehen falsch, was hier tatsächlich vor sich geht.

der Datenbankeigentümer wird von sa in ein anderes Login mit niedrigen Berechtigungen geändert, und der vom Benutzer gespeicherte Prozess kann xp_cmdshell nicht mehr aufrufen.

Das ist in diesem Fall wahr, aber das liegt nur daran, wie Sie die Dinge konfiguriert haben (oder genauer gesagt: nicht) (mehr dazu gleich).

Ich dachte, dass das Aktivieren von xp_cmdshell in Ordnung ist, wenn darauf geachtet wird, nur die Berechtigung zum Ausführen von xp_cmdshell sorgfältig zu erteilen.

Es ist.

aber mein Beispiel scheint etwas anderes zu zeigen.

Dem würde ich nicht zustimmen. Dies ist nur eine Frage des Unverständnisses des Sicherheitsmechanismus, und dies ist zufällig ein schwieriger Fall, so dass dies durchaus verständlich ist.


Ein paar Dinge:

  1. EXECUTE AS OWNER ist nicht speziell das Problem. Sie hätten EXECUTE AS N'dbo' ausführen können, um den gleichen Effekt zu erzielen.

  2. Die Datenbank, die einer sysadmin gehört, ist nicht speziell das Problem. Sie hätten EXECUTE AS N'other' ausführen können, wobei other der Name eines Benutzers ist, der einem Login zugeordnet ist, dem ein Benutzer in [master] zugewiesen wurde, der für xp_cmdshell ausgeführt wurde, um den gleichen Effekt zu erzielen.

  3. Nein, Berechtigungen auf Serverebene werden nicht erteilt. Um dies zu beweisen, fügen Sie der gespeicherten Testprozedur die folgenden zwei Zeilen hinzu:

    EXEC sp_configure N'allow updates', 1; RECONFIGURE;
    SELECT * FROM sys.dm_exec_sessions;
    

    Gehen Sie voran und ändern Sie den Datenbankbesitzer zurück in sa und führen Sie den Prozess aus. Sie erhalten Fehler für sp_configure und RECONFIGURE, und . Sie erhalten nur 1 Zeile von sys.dm_exec_sessions, der Zeile Ihrer Sitzung, weil Sie haben nicht die Berechtigung VIEW SERVER STATE auf Serverebene, etwas, das sa definitiv hat.

Was Sie erleben, hängt von zwei Dingen ab:

  1. Sie haben das Proxy-Konto aktiviert, mit dem Nicht-Systemadministratoren dies ausführen können , wenn sie über Ausführungsberechtigungen verfügen (nicht sicher, warum Sie dies aktiviert haben, es sei denn, Sie möchten dies nicht Verwenden Sie das SQL Server-Dienstkonto. Dies ist eine gute Idee, funktioniert jedoch nicht für Systemadministratoren.
  2. die Datenbank gehörte einem Login, das einem in master vorhandenen Benutzer zugeordnet war, dem die Berechtigung zum Ausführen von xp_cmdshell erteilt wurde (diese Zuordnung wird vom EXECUTE AS in Kombination mit dem DB-Besitz abgeleitet).

Um dies zu beweisen, führen Sie Folgendes aus (am Ende Ihres aktuellen Testcodes in der Frage, wobei dummyuser die DB besitzt):

REVERT;
USE [master];
CREATE USER [dummyuser] FOR LOGIN [dummyuser];
GO
GRANT EXEC ON xp_cmdshell TO [dummyuser];
USE [testdb];

Dann mach:

EXECUTE AS LOGIN = 'testuser';
EXEC dbo.testproc; 

anstatt den Fehler "Berechtigung verweigert" zu erhalten, haben Sie entweder Erfolg mit xp_cmdshell oder Sie erhalten den folgenden Fehler, wenn das Proxy-Konto nicht konfiguriert ist:

Nachricht 15153, Ebene 16, Status 1, Prozedur xp_cmdshell, Zeile JJJJ [Stapelstartzeile XXXXX]
Die Informationen zum xp_cmdshell-Proxy-Konto können nicht abgerufen werden oder sind ungültig. Stellen Sie sicher, dass der Berechtigungsnachweis '## xp_cmdshell_proxy_account ##' vorhanden ist und gültige Informationen enthält.

Noch besser wäre es, Folgendes zu tun, wodurch die Berechtigung aus dummyuser entfernt wird, ein neues Konto mit geringen Berechtigungen erstellt wird und das gewährt wird. Konto die xp_cmdshell Berechtigung:

USE [master];
CREATE LOGIN [cmdshell] WITH PASSWORD = 'password', CHECK_POLICY=OFF;
CREATE USER [cmdshell] FOR LOGIN [cmdshell];
GRANT EXEC ON xp_cmdshell TO [cmdshell];

REVOKE EXEC ON xp_cmdshell FROM [dummyuser];

USE [testdb];
CREATE USER [cmdshell] FOR LOGIN [cmdshell];

Und dann ändern Sie die Klausel EXECUTE AS in der gespeicherten Prozedur in WITH EXECUTE AS 'cmdshell'. Führen Sie den Prozess erneut aus, und Sie haben entweder Erfolg oder den Proxy-Kontofehler, wenn er nicht eingerichtet ist. In diesem Fall:

  1. der Datenbankeigentümer hat keine Berechtigung
  2. sie sind in keiner Weise an ein sysadmin -Login gebunden.

Dies funktioniert, weil der Benutzer EXECUTE AS einem Login zugeordnet ist, für das ein Benutzer in master, dem die Ausführung gewährt wurde, auf xp_cmdshell zugewiesen wurde.

AUCH dieses Verhalten ist höchstwahrscheinlich an das Objekt (d. H. xp_cmdshell) gebunden, das tatsächlich in der Datenbank mssqlsystemresource vorhanden ist. Sie können kein Objekt in [master] erstellen und einen Benutzer gewähren (derselbe wird wie der EXECUTE AS Benutzer der gespeicherten Prozedur verwendet, selbst wenn dieser Benutzer dbo/OWNER und die Datenbank gehört sa) EXEC auf dem Benutzerprozess in [master] und lässt sie funktionieren (nicht ohne TRUSTWORTHY, was das solltest du nicht tun ). Nicht einmal, wenn die in [master] gespeicherte Prozedur des Benutzers als gespeicherte Systemprozedur markiert ist (ich habe es versucht).

Im Idealfall verwenden Sie Module Signing , um die Berechtigung anstelle von EXECUTE AS zu verwalten (entweder mit der Serverrolle sysadmin verknüpfen, um das SQL Server-Dienstkonto zu verwenden, oder mit dem Benutzer in [master] verknüpfen) das wurde EXECUTE auf xp_cmdshell gewährt, um ein Proxy-Konto zu verwenden, vorausgesetzt, es wurde konfiguriert).

3
Solomon Rutzky

xp_cmdshell Kann ohne direkte Ausführungsberechtigungen in einer sa-eigenen Datenbank ausgeführt werden, wenn die Datenbankoption cross database ownership chaining auf Serverebene DB_CHAINING Für testdb database oder EXECUTE AS OWNER ist im proc angegeben. Dies sind alles nicht standardmäßige Konfigurationen und standardmäßig deaktiviert. Wichtig ist, dass Nicht-Sysadmin-Rollenmitgliedern nicht gestattet wird, Objekte im Besitz von dbo in einer Datenbank im Besitz von sa zu erstellen, um eine Eskalation von Berechtigungen zu vermeiden.

Obwohl die Verwendung von xp_cmdshell In T-SQL im Allgemeinen eine zweifelhafte Praxis ist, kann xp_cmdshell In vom Benutzer gespeicherten Prozeduren sicher gekapselt werden, indem den gespeicherten Prozess mit einem Zertifikat signieren . Durch diese Kapselung wird vermieden, dass direkte Berechtigungen für xp_cmdshell Ausgeführt werden.

2
Dan Guzman