Introducción
A partir de julio de 2019, Microsoft ha corregido alrededor de 43 errores en el motor de base de datos Jet. McAfee ha informado de un par de errores y, hasta ahora, hemos recibido 10 CVE de Microsoft. En nuestra publicación anterior, discutimos la causa raíz de CVE-2018-8423. Al analizar este CVE y el parche de Microsoft, descubrimos que había una forma de evitarlo que resultó en otro bloqueo. Lo informamos a Microsoft y lo arregló en el parche del 19 de enero el martes. Este problema fue asignado CVE-2019-0576. Recomendamos a nuestros usuarios que instalen parches adecuados y sigan la política de administración de parches adecuada y mantengan sus instalaciones de Windows actualizadas.
En esta publicación haremos el análisis de causa raíz de CVE-2019-0576. Para aprovechar esta vulnerabilidad, un atacante necesita usar técnicas de ingeniería social para convencer a una víctima de que abra un archivo JavaScript que utiliza un objeto de conexión ADODB para acceder a un archivo malicioso de la base de datos Jet. Una vez que se accede al archivo malicioso de Jet Database, llama a la función vulnerable en msrd3x40.dll que puede conducir a la explotación de esta vulnerabilidad.
Fondo
Como se mencionó en nuestra publicación anterior, CVE-2018-8423 puede activarse utilizando un archivo malicioso de la base de datos Jet y, según el análisis, este problema estaba en el campo de número de índice. Si el número de índice fuera demasiado grande, el programa se bloquearía en la siguiente ubicación:
Aquí, ecx contiene el número de índice malicioso. Al aplicar el parche de Microsoft para CVE-2018-8423 podemos ver que, al abrir este archivo malicioso, obtenemos el siguiente error que indica que el problema está solucionado y el bloqueo ya no se produce:
Analizando el parche
Decidimos profundizar y ver exactamente cómo se solucionó este problema. Al analizar la función "msrd3x40! TblPage :: CreateIndexes", podemos ver que hay una comprobación para ver si "IndexNumber" es mayor que 0xFF, o 256, como se puede ver a continuación:
Aquí, el ecx que contiene el número de índice tiene el valor malicioso de "00002300" y es mayor que 0xFF. Si vemos el código, hay una instrucción de salto. Si seguimos estas instrucciones de salto, llegaremos a la siguiente ubicación:
Podemos ver que hay una llamada a la función "msrd3x40! Err :: SetError", lo que significa que el archivo malicioso no se analizará si el valor del índice es mayor que 0xFF y el programa mostrará el mensaje de error "Formato de base de datos no reconocido" y Terminar.
Encontrar otro problema con el parche
Al observar el parche, era obvio que el programa finalizará si el valor del índice es mayor que 0xFF, pero decidimos probarlo con un valor de índice "00 00 00 20" que es menor que 0xFF, y tuvimos otro bloqueo en la función "msrd3x40! Table :: FindIndexFromName", como se puede ver a continuación:
Encontrar la causa raíz del nuevo problema
Como sabemos, si damos un valor de índice que sea inferior a 0xFF, obtenemos un bloqueo en la función "msrd3x40! Table :: FindIndexFromName", por lo que decidimos analizarlo más a fondo para descubrir por qué sucede eso.
El accidente está en la siguiente ubicación:
Parece que el programa está intentando acceder a la ubicación "(ebx + eax * 4 + 574h)" pero no es accesible, lo que significa que es un problema de lectura fuera de límite.
Este bloqueo parece familiar, ya que también se vio en CVE-2018-8423, excepto que fue una escritura fuera de límite, mientras que esto parece ser una lectura fuera de límite. Si miramos eax contiene "0055b7a8" que, cuando se multiplica por 4, se convierte en un valor muy grande.
Si miramos el archivo se ve así:
Como se puede ver en la imagen a continuación, si analizamos este archivo, este valor de "00 00 00 20" (en little endian de la imagen de arriba) indica el número de un índice cuyo nombre es "ParentIDName":
Al observar el depurador en el punto del bloqueo, parece que ebx + 574h apunta a una ubicación de memoria y eax contiene un valor de índice que se multiplica por 4. Ahora tenemos que descubrir lo siguiente:
- ¿Cuál será el valor de eax que causará el bloqueo? Sabemos que debería ser inferior a 0xFF. Pero, ¿cuál sería el valor más bajo?
- ¿Cuál es la causa raíz de este problema?
Al establecer un punto de interrupción en "msrd3x40! Table :: FindIndexFromName" y cambiar el número de índice a "0000001f", (que no causa un bloqueo pero ayuda con la depuración y la comprensión del flujo del programa) podemos ver que edx contiene el puntero para un nombre de índice que, en este caso, es "ParentIdName":
Depurando aún más podemos ver que el valor eax proviene de (ebp) y el valor ebp proviene de (ebx + 5F4h) como se puede ver a continuación:
Cuando miramos "ebx + 5F4" podemos ver lo siguiente:
Podemos ver que "ebx +5F4"Contiene el número de índice para todos los índices en el archivo. En nuestro caso, el archivo tiene dos índices y su número es "00 00 00 01" y "00 00 00 1f". Si revisamos cuidadosamente la memoria, podemos descubrir que el número máximo de índices que se pueden almacenar aquí son 0x20 o 32:
Lugar de inicio: 00718d54
Cada número de índice tiene 4 bytes de longitud. Entonces 0x20 * 4 + 00718d54 = 00718DD4
Después de esto, si miramos ebx +574 + 4, podemos ver que contiene el puntero para indexar nombres:
Entonces, la estructura general de la memoria es así:
Solo hay 0x80 o 128 bytes disponibles para guardar el puntero de nombre de índice en la ubicación EBX + 574. Cada puntero se guarda en una ubicación de número de índice, es decir, para el número de índice 1 se guardará en EBX + 574 + 1 * 4, la ubicación del número de índice 2 se guardará en EBX + 574 + 2 * 4 y así sucesivamente. (el número de índice comienza desde 0).
En este caso, si damos un número de índice que es más de 31, el programa sobrescribirá los datos más allá de 0x80 bytes, que estarán al comienzo de la ubicación EBX + 5F4, que es el número de índice del archivo malicioso. Entonces, en este caso, si le damos el valor "00 00 00 20" en lugar de "00 00 00 1f", sobrescribirá el número de índice en la ubicación EBX + 5F4, como se puede ver a continuación:
Ahora el programa intenta ejecutar esta instrucción en "msrd3x40! Table :: FindIndexFromName"
Mov ecx, dword ptr (ebx + eax * 4 + 574h)
Aquí, eax contiene el número de índice que debe ser "00 00 00 01" pero, dado que se sobrescribe con "0055b7a8", que es una dirección de memoria, al multiplicarlo por 4, se convierte en un número enorme y luego se agrega 574h a eso. Entonces, si esa área de memoria no existe y el programa intenta leer desde esa memoria, obtenemos un error de infracción de acceso.
Entonces, para responder las preguntas que teníamos:
- Cualquier valor que sea menor que 0xFF y mayor que 0x31 provocará un bloqueo si la ubicación de memoria resultante de (ebx + eax * 4 + 574h) no es accesible.
- La causa raíz es que una ubicación de memoria sobrescribe un número de índice, lo que provoca un acceso no válido a la memoria en este caso.
¿Cómo lo solucionó Microsoft en el parche del 19 de enero?
Nuevamente decidimos analizar el parche para ver cómo se solucionó este problema. Como queda claro en el análisis, cualquier valor que sea mayor o igual a 0x20 o 32 todavía causa un bloqueo, por lo que, idealmente, el parche debería verificar esto. Microsoft ha agregado esta verificación en la versión del parche del 19 de enero, como se puede ver a continuación:
Como se puede ver en la imagen de arriba, eax mantiene el valor del índice aquí y se compara con 0x20. Si es mayor o igual a 0x20, el programa salta a la ubicación 72fe1c00. Si vamos a esa ubicación, podemos ver lo siguiente:
Como se puede ver en la imagen de arriba, llama al destructor y luego llama a la función msrd3x40! Err :: SetError y regresa. Entonces, el programa mostrará un mensaje que dice "Formato de base de datos no reconocido" y luego finalizará.
Conclusión
Reportamos este problema a Microsoft en octubre de 2018 y solucionó este problema en el parche del 19 de enero el martes. Se le asignó CVE-2019-0576 a este problema. Recomendamos a nuestros usuarios que mantengan sus instalaciones de Windows actualizadas e instalen parches de proveedores regularmente.
Cobertura de McAfee:
Los clientes de McAfee Network Security Platform están protegidos de esta vulnerabilidad mediante los identificadores de firma 0x45251700 – HTTP: Vulnerabilidad de ejecución remota de código del motor de base de datos Microsoft JET (CVE-2018-8423) y 0x4525890 – HTTP: Vulnerabilidad de ejecución remota de código del motor de base de datos Microsoft JET (CVE-2019- 0576).
McAfee AV detecta el archivo malicioso como BackDoor-DKI.dr.
McAfee HIPS, la función de Protección de desbordamiento de búfer genérico (GBOP) a menudo cubrirá esto, dependiendo del proceso utilizado para explotar la vulnerabilidad.
Referencias