Depuis quelques temps, les chercheurs d'ESET traquent les activités de Winnti, un groupe actif depuis 2012 et ciblant les chaînes d'approvisionnement de l'industrie du jeu vidéo et du logiciel. Une porte dérobée non enregistrée ciblant les systèmes Microsoft SQL (MSSQL) a été récemment découverte. Cette porte dérobée présente de nombreuses similitudes avec la porte dérobée PortReuse, un autre outil utilisé par le groupe Winnti et documenté pour la première fois en octobre 2019.
Les membres du groupe Winnti ont publié un nouvel échantillon de porte dérobée appelé Skip-2.0, qui a été détecté cette année. Cette porte dérobée cible les serveurs MSSQL 11 et 12 et permet à un attaquant de se connecter à n'importe quel compte MSSQL à l'aide d'un mot de passe magique tout en masquant automatiquement ces connexions dans les logs. Les attaquants peuvent utiliser des portes dérobées pour accéder à la base de données, copier, modifier ou supprimer son contenu, manipulant ainsi la monnaie du jeu à des fins financières. À notre connaissance, Skip-2.0 est la première porte dérobée de serveur MSSQL enregistrée publiquement.
Cet article se concentrera sur les détails techniques et les fonctions de la porte dérobée du serveur mssql, ainsi que sur les similitudes techniques entre skip.2-0 et l'arsenal connu de winnti (en particulier la porte dérobée portreuse et le shadowpad).
Nous avons trouvé skip-2.0 en recherchant un lanceur vmprotected, dont la charge utile est généralement portreuse ou shadowpad.
Comme les charges utiles chiffrées de Portreuse et Shadowpad, skip-2.0 est intégré dans le lanceur vmprotected comme le montre la figure 1 :
Comme les autres lanceurs utilisant VMProtect, la charge utile doit également être crypté. Cette méthode de cryptage utilise l'algorithme RC5 et la clé se compose de volumeID et de la chaîne « f@ukd!RCTO R$ ».
Comme pour portreuse et shadowpad, le programme de démarrage peut persister en exploitant un détournement de dll en l'installant dans c:windowssystem32tsvipsrv.dll. Cela amène le service Windows SessionEnv standard à charger la DLL au démarrage du système.
intègre le décryptage de la charge utile, qui est en fait un packer personnalisé du groupe winnti. Ce packager est le même code que nous avons documenté dans le livre blanc. L'outil a été utilisé pour empaqueter la porte dérobée PortReuse et intégrer la charge utile dans des jeux vidéo compromis.
La configuration de l'emballage du programme contient la clé requise pour décrypter le fichier binaire, ainsi que le nom, la taille et le type d'exécution (exe ou dll) du fichier d'origine. La configuration de la charge utile est présentée dans le tableau 1.
Comme le montre la configuration du packager, la charge utile est appelée un chargeur interne. Internal Loader est le nom d'un injecteur qui fait partie de l'arsenal du groupe winnti et est utilisé pour injecter la porte dérobée portreuse dans les processus écoutant sur des ports spécifiques.
Il s'agit d'une variante du chargeur interne qui, au lieu de rechercher un processus écoutant sur un port spécifique comme lors de l'injection de la porte dérobée portreuse, il recherche un processus nommé sqlserv.exe qui est un processus régulier pour le serveur mssql. nom. S'il est trouvé, le chargeur interne injecte la charge utile dans ce processus. Cette charge utile est conditionnée avec un packer personnalisé dont la configuration est répertoriée dans le tableau 2.
Le nom de fichier d'origine de cette charge utile injectée est skip-2.0.dll.
Après avoir été injecté et démarré par le chargeur interne, skip-2.0 vérifie d'abord s'il s'exécute dans le processus sqlserv.exe, et si c'est le cas, récupère un handle vers sqllang.dll, qui est chargé par sqlserv .exe . Continuez ensuite à rechercher et à accrocher plusieurs fonctions de cette DLL. La figure 2 décrit le processus d'exécution de skip-2.0.
skip-2.0 utilise un processus de hook très similaire à netagent, qui est le module portreuse responsable de l'installation des hooks réseau. Cette bibliothèque de hooks est construite sur le désassembleur open source distorm, qui est également utilisé par plusieurs frameworks de hooking open source. Une bibliothèque de désassemblage est nécessaire pour calculer correctement la taille des instructions à accrocher. Presque le même processus de hook est utilisé par NetAgent et Skip-2.0, comme le montre la figure ci-dessous.
Figure 3 Comparaison de sortie Hex-Rays entre les procédures de hooking NetAgent (à gauche) et skip-2.0 (à droite)
Une différence significative est que la fonction de hooking dans skip-2.0 prend l'adresse du hook à installer en paramètre Pour netagent, l’adresse du hook à installer est codée en dur. En effet, skip-2.0 doit accrocher plusieurs fonctions dans qllang.dll pour s'exécuter correctement, alors que netagent ne cible qu'une seule fonction.
Pour localiser chaque fonction sqllang.dll du hook, skip-2.0 récupère d'abord la taille de la dll chargée en mémoire (c'est-à-dire sa taille virtuelle) en analysant l'en-tête pe. Ensuite, le tableau d'octets qui doit correspondre dans sqllang.dll doit être initialisé, voir Figure 4. Une fois que l'adresse de la première correspondance avec le tableau d'octets est trouvée, le hook est installé à l'aide du processus illustré à la figure 3.
Ensuite, une fois le hook installé avec succès, il sera enregistré en texte clair. Le fichier se trouve dans le chemin codé en dur c: windowstemptsu 2ce1.tmp, comme le montre la figure 5.
Si la fonction cible n'est pas trouvée, le programme d'installation du hook recherchera une fonction de secours avec un ensemble différent de modèles d'octets.
En faisant correspondre la séquence d'octets pour localiser l'adresse de la fonction cible au lieu d'utiliser un décalage statique, couplé à l'utilisation d'une séquence d'octets de secours, skip-2.0 peut s'adapter de manière plus flexible aux mises à jour mssql et peut cibler plusieurs sqllang .dll mis à jour. La fonction objective de
skip-2.0 est liée à l'authentification et à la journalisation des événements. Les fonctions ciblées incluent :
CPwdPolicyManager::ValidatePwdForLogin CSECAuthenticate::AuthenticateLoginIdentity ReportLoginSuccess IssueLoginSuccessReport FExecuteLogonTriggers XeSqlPkg::sql_statement_completed::Publish XeSqlPkg::sql_batch_completed::Publish SecAuditPkg::audit_event::Publish XeSqlPkg::login::Publish XeSqlPkg::ual_instrument_called::Publish
La plus intéressante d'entre elles est la première (cpwdpolicymanager::validatepwdforlogin), qui se charge de valider le mot de passe fourni pour un utilisateur donné.
Le hook de cette fonction vérifie si le mot de passe fourni par l'utilisateur correspond au mot de passe magique ; si c'est le cas, la fonction d'origine ne sera pas appelée et le hook renverra 0, permettant la connexion. Ensuite, un indicateur global est configuré pour être vérifié par d'autres fonctions de hook responsables de la journalisation des événements. Le processus de décompilation correspondant est illustré à la figure 6. Avec cet indicateur global défini, la fonction de journalisation du hook reviendra silencieusement sans appeler sa fonction d'origine correspondante, donc l'opération ne sera pas journalisée.
Si vous vous connectez avec un mot de passe magique, les hooks reportloginsaccess et issueloginsuccessreport n'appelleront pas la fonction d'origine. Le même comportement s’applique aux feexecutelogontriggers. D'autres fonctionnalités de journalisation, telles que xesqlpkg::sql_completed::publish ou xesqlpkg::sql_batch_completed::publish, seront également désactivées dans les cas où l'utilisateur se connecte avec un mot de passe magique. Plusieurs événements d'audit sont également désactivés, notamment secauditpkg::audit_event::publish, xesqlpkg::login::publish et xesqlpkg::uau instrument_call::publish.
Non seulement cette série de hooks permet à l'attaquant d'obtenir un contrôle persistant sur le serveur mssql de la victime via un mot de passe spécial, mais lors de l'utilisation de ce mot de passe, plusieurs journaux sont désactivés, rendant l'attaquant indétectable.
Les chercheurs ont testé Skip-2.0 sur plusieurs versions de MSSQL Server et ont constaté qu'ils parvenaient à se connecter avec succès à l'aide des mots de passe pour MSSQL Server 11 et 12. Afin de vérifier si skip-2.0 cible une version spécifique de sqllang.dll, une règle yara a été créée et se trouve dans le référentiel github.
skip-2.0 présente de nombreuses similitudes avec d'autres outils de Winnti. Le lanceur vmprotected, le packager personnalisé, le chargeur interne et le framework hook font partie de l'ensemble d'outils winnti.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!