viernes, 30 de octubre de 2015

Sincronización de tiempos en Microsoft

Pégale un vistazo a otros posts de esta serie:

[6] Atacando la Infraestructura de Clave Pública (PKI)
[7] Otros ataques
[8] Herramientas de ayuda

Por supuesto, no podría acabar mis ejemplos sin hablar de Microsoft. De los sistemas operativos de escritorio con los que he estado haciendo pruebas, Microsoft tiene el sistema de sincronización de tiempos más segudo. Funciona de manera diferente en sistemas "standalone" que en miembros de un dominio, así que veamos ambas circunstancias.

En un Windows "standalone" la sincronización tiene lugar cada 7 días (domingos de madrugada para ser exactos) así que la única opción de interceptar las peticiones NTP es estar presentes el domingo o el lunes cuando el usuario arrnca el sistema por primera vez después de la hora de sincronización. Además, Windows tiene un límite de 15 horas para el cambio de la fecha, con lo que no podemos cambiar el reloj más de esas 15 horas para cada sincronización, lo cual es un verdadero problema para la mayoría de los ataques que veremos en los próximos artículos.

Esas 15 horas no son un valor escrito a fuego en el código, sino que está guardado en el registro de Windows, en las llaves "MaxPosPhaseCorrection" y "MaxNegPhaseCorrection", y pueden ser diferentes en diferentes sistemas, por ejemplo, en Windows 7/8 son 15 horas, pero en un Windows Server 2012 son 48 horas, y en servidores más antiguos será diferente también. También puede cambiar cuando se dan ciertos cambios en el sistema, por ejemplo cuando el equipo se une a un dominio Microsoft.


La combinación de ambas protecciones hace a los sistemas Windows bastante seguros en lo que a sincronización de tiempos se refiere. Sin embargo, si cualquiera de ellos es cambiado por el usuario, habría algunos vectores de ataques posibles. Por ejemplo, hay muchos tutoriales en internet explicando como cambiar la frecuencia de la sincronización de la hora, porque piensas (y probablemente están en lo cierto) que una vez a la semana no es suficiente para conseguir una buena precisión de reloj.


Bajo estas circunstancias, se me ocurrió un nuevo vector de ataque ¿Qué ocurre si un usuario configura su sistema para sincronizar la hora con más frecuencia que el limite que comentábamos antes? La respuesta es que un atacante podría interceptar la petición y cambiar la hora del equipo a unos pocos segundos antes de la próxima sincronización. Tras esos segundos interceptaría otra vez la petición y haría lo propio, y así sucesivamente hasta llegar a la fecha deseada. Llamé a este ataque "Time Skimming" porque es similar a un "Stone Skimming", que en Inglés es como se llama al efecto de tirar una piedra en un lago y que vaya saltando sobre la superficio, recorriendo grandes distancias. Este ataque también está implementado en Deloran:



Hay otra manera más de forzar la sincronización, pero requiere utilizar técnicas de ingeniería social. Cuando un usuario solicita una sincronización de hora manualmente usando el menú "Internet Time Settings" la hora se sincroniza sin ninguna restricción, pero no es tan fácil como en Mac OS X, ya que llegar a esta ventana requiere varios clicks.

Los miembros de un dominio funcionan de manera diferente. Los valores de Max[Pos|Neg]PhaseCorrction pasan a ser 0xFFFFFFFF que quiere decir "aceptar cualquier hora". Esto es un riesgo, pero han incluido firma en los paquetes para autenticar el origen de la respuesta:


Microsoft usa el estándar NTP de una forma creativa. El "Key ID" debería ser un valor que identificara qué clave debe ser usada para autenticar la respuesta. En una petición NTP normal debería tenr un valor 1 o 2, dependiendo de la cantidad de claves disponibles. Sin embargo, lo que hace Microsoft es identificar el sistema dentro del directorio activo que está realizando esta petición. Por ejmplo, si tenemos un KeyID 0x5e040000 necesitamos cambiar el orden de los bytes (endianess) y tendríamos 0x0000045e. El primer bit es un selector de clave (0 o 1), y el resto es el Relative ID (RID) del equipo.


Como probablemente sepais, tanto los equipos como los usuarios son objetos en un dirctorio activo. Los equipos son un tipo espcial de usuario. Ellos mismos crean una contraseña compartida para su usuario cuando se unen a un dominio, y esta contraseña se cambia automáticamente de forma periódica. Un controlador de dominio guarda los dos últimos  hashes de las contraseñas utilizadas, que es lo que selecciona el selector de clave que comentabamos antes.

/* Sign the NTP response with the unicodePwd */
MD5Init(&ctx);
MD5Update(&ctx, nt_hash->hash, sizeof(nt_hash->hash));
MD5Update(&ctx, sign_request.packet_to_sign.data, sign_request.packet_to_sign.length);
MD5Final(signed_reply.signed_packet.data + sign_request.packet_to_sign.length + 4, &ctx);


Las respuestas son firmadas usando MD5 ( md5(hashed_password+response_body) ), que no es el algoritmo de hashing más robusto del mundo, pero al menos yo no pude encontrar un ataque factible para un mensaje tan pequeño, así que en este momento opino que la sincronización de tiempos de un dominio Microsoft es la más robusta de las que he analizado.