El salto de Winnti Group 2.0: una puerta trasera de Microsoft SQL Server


El notorio grupo de ciberespionaje degrada MSSQL

Durante un tiempo, los investigadores de ESET han estado rastreando las actividades del Grupo Winnti, activo desde al menos 2012 y responsable de ataques de alto perfil en la cadena de suministro contra la industria de videojuegos y software. Recientemente, descubrimos una puerta trasera previamente indocumentada dirigida a Microsoft SQL (MSSQL) que permite a los atacantes mantener una posición muy discreta dentro de las organizaciones comprometidas. Esta puerta trasera tiene múltiples similitudes con el PortReuse puerta trasera, otra herramienta utilizada por el Grupo Winnti que fue la primera documentado por ESET en octubre de 2019, como el uso del mismo empaquetador personalizado y lanzador protegido por VMP, por lo que atribuimos esta puerta trasera al Grupo Winnti.

A principios de este año, recibimos una muestra de esta nueva puerta trasera llamada skip-2.0 por sus autores y parte del arsenal del Grupo Winnti. Esta puerta trasera está dirigida a los servidores MSSQL 11 y 12, lo que permite que el atacante se conecte sigilosamente a cualquier cuenta MSSQL utilizando una contraseña mágica, mientras oculta automáticamente estas conexiones de los registros. Tal puerta trasera podría permitir que un atacante copie, modifique o elimine sigilosamente el contenido de la base de datos. Esto podría usarse, por ejemplo, para manipular monedas en el juego para obtener ganancias financieras. Las manipulaciones de la base de datos de divisas en el juego por parte de los operadores Winnti tienen ya ha sido reportado. A lo mejor de nuestro conocimiento, skip-2.0 es la primera puerta trasera del servidor MSSQL que se documenta públicamente. Tenga en cuenta que a pesar de que MSSQL Server 11 y 12 no son las versiones más recientes (lanzadas en 2012 y 2014, respectivamente), son las más utilizadas según Censys 's datos.

Recientemente publicamos un papel blanco actualizando nuestra comprensión del arsenal del Grupo Winnti, y eso expuso una puerta trasera previamente indocumentada de ellos llamada PortReuse. Utiliza un empaquetador idéntico al utilizado con la carga útil integrada en los videojuegos comprometidos descubierto por ESET en marzo de 2019. El lanzador protegido por VMP que suelta el PortReuse puerta trasera también se encontró que se utiliza para lanzar reciente ShadowPad versiones. En ese contexto, pudimos encontrar una nueva herramienta llamada skip.2-0 por su desarrollador. Utiliza el mismo iniciador protegido por VMP, así como el empaquetador personalizado de Winnti Group y exhibe múltiples similitudes con otras muestras del conjunto de herramientas de Winnti Group. Esto nos lleva a adscribir skip-2.0 a ese conjunto de herramientas también.

Este artículo se centrará en los detalles técnicos y la funcionalidad de esta puerta trasera del servidor MSSQL, así como en exponer las similitudes técnicas de skip.2-0 con el arsenal conocido del Grupo Winnti, en particular, con el PortReuse puerta trasera y ShadowPad. Puede encontrar una nota sobre los motivos por los que elegimos el nombre de "Grupo Winnti" en nuestro papel blanco.

VMProtected launcher

Nosotros encontramos skip-2.0 mientras busca lanzadores protegidos por VMP, para los cuales la carga útil suele ser PortReuse o ShadowPad.

Carga útil integrada

Al igual que con el cifrado PortReuse y ShadowPad cargas útiles, skip-2.0 está incrustado en la superposición del iniciador protegido por VMP, como se muestra en la Figura 1:

Figura 1. Encabezados del lanzador protegido por VMP. La carga útil está incrustada en la superposición de PE.

Cifrado

El cifrado de la carga útil es idéntico al utilizado en los otros lanzadores protegidos por VMP. Está cifrado con RC5 con una clave derivada de VolumeID y la cuerda f @ Ukd! rCto R $. – como se describe en nuestro Libro blanco anterior sobre el arsenal del Grupo Winnti.

Persistencia

Como en el caso de PortReuse y ShadowPad, el lanzador probablemente persiste explotando un Vulnerabilidad de secuestro de DLL al estar instalado en C: Windows System32 TSVIPSrv.DLL. Esto da como resultado que el Windows estándar cargue la DLL SessionEnv servicio al inicio del sistema.

Empaquetador personalizado de Winnti Group

Una vez descifrado, la carga útil integrada es en realidad el empaquetador personalizado de Winnti Group. Este empacador es el mismo código shell que fue documentado en nuestro Artículo anterior y papel blanco. Se utiliza para empacar el PortReuse puerta trasera, así como la carga útil integrada en los videojuegos comprometidos.

Configuración de empaquetador

Como se describe en nuestro artículo anterior, la configuración del empaquetador contiene la clave de descifrado del binario empaquetado, así como su nombre de archivo original, su tamaño y el tipo de ejecución (EXE o DLL). La configuración del empacador de la carga útil se muestra en la Tabla 1.

Padres SHA-1 Carga útil SHA-1 Llave RC4 Nombre del archivo Tipo de lanzamiento
9aafe81d07b3e5bb282608f0a2a4656eb485b7c9 a2571946ab181657eb825cde07188e8bcd689575 163716559 Inner-Loader.dll 2

Tabla 1. Configuración del empaquetador de carga útil

En la configuración del empaquetador se puede ver que la carga útil se llama Cargador interno. Cargador interno es el nombre de un inyector que forma parte del arsenal del Grupo Winnti utilizado para inyectar el PortReuse puerta trasera en procesos que escuchan en un puerto particular, como se describe en nuestra publicación anterior. Más allá de ese nombre idéntico, al analizar esta carga útil parece que es otra variante del Cargador interno inyector.

Inyector de cargador interno

Esta variante de Cargador interno, en lugar de buscar un proceso que escuche en un puerto en particular, como en el caso de inyectar PortReuse puerta trasera, busca un proceso llamado sqlserv.exe, que es el nombre de proceso convencional del servidor MSSQL. Si se encuentra, Cargador interno luego inyecta una carga útil en este proceso. Esta carga también se incluye con el empaquetador personalizado: la configuración del empacador de esa carga se muestra en la Tabla 2.

Padres SHA-1 Carga útil SHA-1 Llave RC4 Nombre del archivo Tipo de lanzamiento
a2571946ab181657eb825cde07188e8bcd689575
60b9428d00be5ce562ff3d888441220290a6dac7 923567961 skip-2.0.dll 2

Tabla 2. Configuración del empaquetador de la carga útil integrada en Inner-Loader

El nombre de archivo original de esta carga útil inyectada es skip-2.0.dll.

skip-2.0

Después de haber sido inyectado y lanzado por Cargador interno, skip-2.0 primero comprueba si se está ejecutando dentro de un sqlserv.exe proceso y si es así, recupera un identificador para sqllang.dll, que es cargado por sqlserv.exe. Luego procede a buscar y conectar múltiples funciones desde esa DLL. La figura 2 representa el skip-2.0 cadena de compromiso.

Figura 2. desempaque e inyección skip-2.0

Conexión de sqllang.dll

El procedimiento de enganche utilizado por skip-2.0 es muy similar a la utilizada por NetAgent, el PortReuse módulo responsable de instalar el enlace de red. Esta biblioteca de enganche se basa en distorm desensamblador de código abierto que es utilizado por múltiples marcos de conexión de código abierto. En particular, se necesita una biblioteca de desmontaje para calcular correctamente el tamaño de las instrucciones que se van a enganchar. Se puede ver en la Figura 3 que el procedimiento de enganche utilizado por NetAgent y skip-2.0 Son casi idénticos.

Figura 3. Comparación de salida de rayos hexadecimales entre los procedimientos de enganche NetAgent (izquierda) y skip-2.0 (derecha)

Hay una diferencia notable, que es el hecho de que la función de enganche de skip-2.0 toma la dirección del gancho que se instalará como argumento, mientras que para NetAgent, la dirección del gancho para instalar está codificada. Esto se debe al hecho de que skip-2.0 tiene que enganchar múltiples funciones en sqllang.dll para funcionar correctamente, mientras NetAgent apunta solo a una sola función.

Para ubicar cada sqllang.dll función para engancharse, skip-2.0 primero recupera el tamaño de la DLL una vez cargada en la memoria (es decir, su tamaño virtual) analizando sus encabezados PE. Luego, una matriz de bytes para que coincida con sqllang.dll se inicializa como se muestra en la Figura 4. Una vez que se encuentra la dirección de la primera aparición que coincide con la matriz de bytes, el gancho se instala utilizando el procedimiento que se muestra en la Figura 3.

Figura 4. Salida de rayos hexadecimales del procedimiento que inicializa la matriz de bytes para que coincida en sqllang.dll

El éxito de la instalación del gancho se registra en texto sin formato en un archivo de registro ubicado en la ruta codificada C: Windows Temp TS_2CE1.tmp y se muestra en la Figura 5.

Figura 5. Registro generado durante la instalación de ganchos

Si no se encuentra la función objetivo, el instalador de enlace busca una función alternativa, con un conjunto diferente de patrones de bytes.

Hacer coincidir una secuencia de bytes para ubicar la dirección de la función objetivo en lugar de usar un desplazamiento estático, además de usar una secuencia de bytes alternativa, permite skip-2.0 ser más resistente a las actualizaciones de MSSQL y potencialmente apuntar a múltiples sqllang.dll actualizaciones

Una contraseña para gobernarlos a todos

Las funciones a las que se dirige skip-2.0 están relacionados con la autenticación y el registro de eventos. Las funciones específicas incluyen:

  • CPwdPolicyManager :: ValidatePwdForLogin
  • CSECAuthenticate :: AuthenticateLoginIdentity
  • ReportLoginSuccess
  • IssueLoginSuccessReport
  • FExecuteLogonTriggers
  • XeSqlPkg :: sql_statement_completed :: Publicar
  • XeSqlPkg :: sql_batch_completed :: Publicar
  • SecAuditPkg :: audit_event :: Publicar
  • XeSqlPkg :: login :: Publicar
  • XeSqlPkg :: ual_instrument_called :: Publicar

La función más interesante es la primera (CPwdPolicyManager :: ValidatePwdForLogin), que es responsable de validar la contraseña proporcionada para un usuario determinado. El enlace de esta función verifica si la contraseña proporcionada por el usuario coincide con la contraseña mágica; si ese es el caso, no se llamará a la función original y el enlace devolverá 0, permitiendo la conexión aunque no se haya proporcionado la contraseña correcta. Luego se establece una bandera global que será verificada por las otras funciones enganchadas responsables del registro de eventos. El procedimiento descompilado correspondiente se muestra en la Figura 6. En el caso de que se establezca este indicador global, las funciones de registro enganchadas volverán en silencio sin llamar a sus funciones originales correspondientes, por lo que la acción no se registrará. En el caso de que se proporcione una contraseña diferente, se llama a la función original.

Figura 6. Salida de rayos hexadecimales del procedimiento responsable de hacer coincidir la contraseña proporcionada al iniciar sesión con la cadena codificada

Se utilizó una técnica de puerta trasera similar, basada en contraseñas codificadas, con Puertas traseras SSH descubiertas previamente por ESET. La diferencia aquí es que skip-2.0 está instalado en la memoria, mientras que en el caso de las puertas traseras SSH sshd ejecutable fue modificado antes de la ejecución.

Adicionalmente, CSECAuthenticate :: AuthenticateLoginIdentity se llamará desde su código de enlace pero el enlace siempre devolverá 0. El ReportLoginSucess y IssueLoginSuccessReport Hooks no llamará a las funciones originales si se usó la contraseña mágica para iniciar sesión. El mismo comportamiento se aplica a FEExecuteLogonTriggers. Otras funciones de registro como XeSqlPkg :: sql_statement_completed :: Publicar o XeSqlPkg :: sql_batch_completed :: Publicar también se deshabilitará en el caso en que el usuario haya iniciado sesión con la contraseña mágica. También se deshabilitan varios eventos de auditoría, incluidos SecAuditPkg :: audit_event :: Publicar, XeSqlPkg :: login :: Publicar y XeSqlPkg :: ual_instrument_called :: Publicar.

Esta serie de ganchos permite al atacante no solo obtener persistencia en el servidor MSSQL de la víctima mediante el uso de una contraseña especial, sino también permanecer sin ser detectado gracias a los múltiples mecanismos de publicación de eventos y registros que se desactivan cuando se usa esa contraseña.

Probamos skip-2.0 contra múltiples versiones de MSSQL Server y descubrimos que pudimos iniciar sesión con éxito usando la contraseña especial con MSSQL Server 11 y 12. Para verificar si un sqllang.dll la versión está dirigida por skip-2.0 (es decir, que coincide con los patrones de bytes), creamos una regla YARA, que se puede encontrar en nuestro Repositorio de GitHub.

Conexión con el grupo Winnti

Observamos similitudes múltiples entre skip-2.0 y otras herramientas del arsenal del Grupo Winnti. Su lanzador protegido por VMP, empaquetador personalizado, Cargador interno inyector y marco de enganche son parte del conjunto de herramientas ya conocido del Grupo Winnti. Esto nos lleva a pensar que skip-2.0 también es parte de ese conjunto de herramientas.

Conclusión

los skip-2.0 La puerta trasera es una adición interesante al arsenal del Grupo Winnti, ya que comparte muchas similitudes con el conjunto de herramientas ya conocido del grupo y permite al atacante lograr la persistencia en un servidor MSSQL. Teniendo en cuenta que se requieren privilegios administrativos para instalar los ganchos, skip-2.0 debe usarse en servidores MSSQL ya comprometidos para lograr persistencia y sigilo.

Continuaremos monitoreando nuevas actividades del Grupo Winnti y publicaremos información relevante en nuestro blog. Para cualquier consulta, contáctenos a la amenazaintel@eset.com.

Indicadores de compromiso (IoC)

Componente SHA-1 Nombre de detección de ESET
Cargador VMP 18E4FEB988CB95D71D81E1964AA6280E22361B9F
4AF89296A15C1EA9068A279E05CC4A41B967C956
Win64 / Packed.VMProtect.HX
Inyector de cargador interno A2571946AB181657EB825CDE07188E8BCD689575 Win64 / Injector.BS
skip-2.0 60B9428D00BE5CE562FF3D888441220290A6DAC7 Win32 / Agent.SOK
Conocido como objetivo sqllang.dll archivos (lista no exhaustiva) 4396D3C904CD340984D474065959E8DD11915444
BE352631E6A6A9D0B7BBA9B82D910FA5AB40C64E
D4ADBC3F77ADE63B836FC4D9E5915A3479F09BD4
0BBD3321F93F3DCDD2A332D1F0326142B3F4961A
FAE6B48F1D6EDDEC79E62844C444FE3955411EE3
A25B25FFA17E63C6884E28E96B487F58DF4502E7
DE76419331381C390A758E634BF2E165A42D4807
ED08E9B4BA6C4B5A1F26D671AD212AA2FB0874A2
1E1B0D91B37BAEBF77F85D1B7C640B8CC02FE11A
59FB000D36612950FEBC36004F1317F7D000AA0B
661DA36BDD115A1E649F3AAE11AD6F7D6FF2DB63
N / A

Técnicas MITRE ATT y CK

Táctica CARNÉ DE IDENTIDAD Nombre Descripción
Ejecución T1035 Servicio de ejecución skip-2.0 se inicia con el SessionEnv Servicio
Persistencia T1038 Secuestro de orden de búsqueda de DLL skip-2.0 probablemente utiliza una técnica de secuestro de DLL contra el SessionEnv Servicio
T1179 Enganche skip-2.0 engancha múltiples funciones en sqllang.dll servicio para evitar la autenticación y mantener el sigilo
Evasión de defensa T1054 Bloqueo de Indicadores skip-2.0 bloquea el registro de eventos
T1045 Embalaje de software skip.2-0 y Cargador interno se embalan con el empaquetador personalizado de Winnti. Además, el lanzador está protegido por VMP.
Descubrimiento T1057 Descubrimiento de procesos Cargador interno enumera los procesos en ejecución para encontrar el proceso que ejecuta el servidor MSSQL
Impacto T1485 Destrucción de datos skip-2.0 permite el acceso no autorizado a las bases de datos MSSQL, lo que permite la destrucción o manipulación de datos
T1494 Manipulación de datos en tiempo de ejecución skip-2.0 manipula el registro de eventos en tiempo de ejecución
T1492 Manipulación de datos almacenados skip-2.0 permite el acceso no autorizado a bases de datos MSSQL, lo que permite la manipulación de datos almacenados








Enlace a la noticia original