MSSQL Injection
Injeção MSSQL
Enumeração do Active Directory
Pode ser possível enumerar usuários de domínio via injeção SQL dentro de um servidor MSSQL usando as seguintes funções MSSQL:
SELECT DEFAULT_DOMAIN()
: Obter o nome do domínio atual.master.dbo.fn_varbintohexstr(SUSER_SID('DOMÍNIO\Administrator'))
: Se você conhece o nome do domínio (DOMÍNIO neste exemplo), esta função retornará o SID do usuário Administrator no formato hexadecimal. Isso parecerá0x01050000000[...]0000f401
, observe como os últimos 4 bytes são o número 500 no formato big endian, que é o ID comum do usuário administrador. Esta função permitirá que você saiba o ID do domínio (todos os bytes exceto os últimos 4).SUSER_SNAME(0x01050000000[...]0000e803)
: Esta função retornará o nome de usuário do ID indicado (se houver), neste caso 0000e803 em big endian == 1000 (geralmente este é o ID do primeiro usuário regular criado). Então você pode imaginar que pode fazer força bruta nos IDs de usuário de 1000 a 2000 e provavelmente obter todos os nomes de usuário dos usuários do domínio. Por exemplo, usando uma função como a seguinte:
Vectores de Erro Alternativos
As injeções de SQL baseadas em erros geralmente se assemelham a construções como +AND+1=@@version--
e variantes baseadas no operador «OR». Consultas contendo tais expressões são geralmente bloqueadas por WAFs. Para contornar isso, concatene uma string usando o caractere %2b com o resultado de chamadas de função específicas que disparam um erro de conversão de tipo de dados nos dados procurados.
Alguns exemplos de tais funções:
SUSER_NAME()
USER_NAME()
PERMISSIONS()
DB_NAME()
FILE_NAME()
TYPE_NAME()
COL_NAME()
Exemplo de uso da função USER_NAME()
:
SSRF
Esses truques de SSRF foram retirados daqui
fn_xe_file_target_read_file
fn_xe_file_target_read_file
Requer permissão VIEW SERVER STATE
no servidor.
fn_get_audit_file
fn_get_audit_file
Requer permissão de CONTROL SERVER
.
fn_trace_gettabe
fn_trace_gettabe
Requer permissão de CONTROL SERVER
.
xp_dirtree
, xp_fileexists
, xp_subdirs
xp_dirtree
, xp_fileexists
, xp_subdirs
Procedimentos armazenados como xp_dirtree
, embora não documentados oficialmente pela Microsoft, foram descritos por outros online devido à sua utilidade em operações de rede dentro do MSSQL. Esses procedimentos são frequentemente usados na exfiltração de dados fora de banda, como demonstrado em vários exemplos e posts.
O procedimento armazenado xp_dirtree
, por exemplo, é usado para fazer solicitações de rede, mas está limitado apenas à porta TCP 445. O número da porta não é modificável, mas permite a leitura de compartilhamentos de rede. O uso é demonstrado no script SQL abaixo:
É importante notar que este método pode não funcionar em todas as configurações de sistema, como no Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)
em execução em um Windows Server 2016 Datacenter
com as configurações padrão.
Além disso, existem procedimentos armazenados alternativos como master..xp_fileexist
e xp_subdirs
que podem alcançar resultados semelhantes. Mais detalhes sobre xp_fileexist
podem ser encontrados neste artigo do TechNet.
xp_cmdshell
xp_cmdshell
Obviamente, você também pode usar xp_cmdshell
para executar algo que acione um SSRF. Para mais informações, leia a seção relevante na página:
Função Definida pelo Usuário MSSQL - SQLHttp
Criar uma UDF CLR (Função Definida pelo Usuário de Tempo de Execução Comum), que é um código desenvolvido em qualquer linguagem .NET e compilado em um DLL, para ser carregado dentro do MSSQL para executar funções personalizadas, é um processo que requer acesso dbo
. Isso significa que geralmente é viável apenas quando a conexão com o banco de dados é feita como sa
ou com uma função de Administrador.
Um projeto do Visual Studio e instruções de instalação são fornecidos neste repositório do Github para facilitar o carregamento do binário no MSSQL como um assembly CLR, permitindo assim a execução de solicitações HTTP GET de dentro do MSSQL.
O cerne dessa funcionalidade está encapsulado no arquivo http.cs
, que utiliza a classe WebClient
para executar uma solicitação GET e recuperar o conteúdo, conforme ilustrado abaixo:
Antes de executar o comando SQL CREATE ASSEMBLY
, é aconselhável executar o seguinte trecho de SQL para adicionar o hash SHA512 da assembly à lista de assemblies confiáveis do servidor (visível através de select * from sys.trusted_assemblies;
):
Depois de adicionar com sucesso a montagem e criar a função, o seguinte código SQL pode ser utilizado para realizar solicitações HTTP:
Exploração Rápida: Recuperando o Conteúdo Completo da Tabela em uma Única Consulta
Um método conciso para extrair o conteúdo completo de uma tabela em uma única consulta envolve a utilização da cláusula FOR JSON
. Esta abordagem é mais sucinta do que usar a cláusula FOR XML
, que requer um modo específico como "raw". A cláusula FOR JSON
é preferida por sua brevidade.
Veja como recuperar o esquema, tabelas e colunas do banco de dados atual:
Retrieving the Current Query
For users granted the VIEW SERVER STATE
permission on the server, it's possible to see all executing sessions on the SQL Server instance. However, without this permission, users can only view their current session. The currently executing SQL query can be retrieved by accessing sys.dm_exec_requests and sys.dm_exec_sql_text:
To check if you have the VIEW SERVER STATE permission, the following query can be used:
https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--
https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users--
https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--
Adicionando um exec() inútil no final e fazendo o WAF pensar que esta não é uma consulta válida
admina'union select 1,'admin','testtest123'exec('select 1')--
Isso será:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123' exec('select 1')--'
Usando consultas estranhamente construídas
admin'exec('update[users]set[password]=''a''')--
Isso será:
SELECT id, username, password FROM users WHERE username = 'admin' exec('update[users]set[password]=''a''')--'
Ou habilitando xp_cmdshell
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
Isso será
select * from users where username = ' admin' exec('sp_configure''show advanced option'',''1''reconfigure') exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
Last updated