Microsoft Time Synchronization

Have a look to other posts of this serie:

[1] NTP MitM Attack using a Delorean
[2] Mac OS X Time Synchronization
[3] Fedora / Ubuntu Time Synchronization
[4] Microsoft Time Synchronization
[5] Attacking HTTP Strict Transport Security
[6] Attacking the Public Key Infrastructure
[7] Other Attacks
[8] Helper tools

Of course, I couldn't finish my examples without talking about Microsoft. From the desktop OS vendor that I have tested, Microsoft has the most robust one in terms of security. It works in a different way for standalone computers than in domain members, so let's cover both circumstances:

In a standalone Windows box, time synchronization takes place each 7 days (Sundays at 1-2am or so) so the only one option to intercept an NTP request is to be there on Sunday or Monday, whenever the victim boots the computer for the first time after the synchronization time. In addition, Windows has a clock drift limitation of 15 hours, so we can't change the clock more than 15 hours on each synchronization, which is a real problem for most attacks that we will see in the following posts.

The 15 hours value is not a harcoded value, it is stored in the registry, in a couple of keys called "MaxPosPhaseCorrection" and "MaxNegPhaseCorrection", and they change in different systems, for example, in a Windows 7/8 is 15 hours but in a Windows Server 2012 is 48 hours, and in older servers is different as well. It could also change when some changes happen in the box, for example when a box become a domain member.


In combination, both controls make Windows boxes pretty secure in terms of time synchronization. However, if any of both are changed by the user, there are some attack vectors that could be used. For example, there are many tutorials in the internet explaining how to change the time synchronization scheduled task, because they think (and probably they're right) that once a week is not enough for a good clock accuracy.


So, under this circumstance, a new attack vector came to my mind. What happen if the user configure his system to synchronize the time more often than the maximum clock drift allowed? The answer is than an attacker could intercept that NTP request and change the clock just a few seconds before the next scheduled time synchronization, then intercept the following NTP requst and do the same, and again, and again, and again until he reach the desired time. I called this attack "Time Skimming", because it's a similar idea than a stone skimming in a lake, and it's implemented in Delorean:



There's another way to force time synchronization, but it requires some kind of social engineering. When the user manually request a time synchronization using the "Internet Time Settings", but it's not as easy as in Mac OS X, since it takes several clicks.

Domain members work in a different way. The Max[Pos|Neg]PhaseCorrction value is set to 0xFFFFFFFF which means "accept any clock drift". That is a risk, but they include a packet signature in order to authenticate the source of the response:


They use the NTP standard in a creative way. Key ID should be a value that identify which key should be used to sign the response. In a regular NTP request it should be 1 or 2, depending on the number of keys available. However, what Microsoft did was use this to identify the computers username in the active directory that is requesting the time synchronization. For example, if we have a KeyID 0x5e040000 we need to change its endianess and then we have 0x0000045e. The first bit of this is a key selector (0 or 1), and the rest is the Relative ID (RID) for the computer.


As you probably know, both computers and users are objects in active directory. Computers are a special kind of users. They set a password for this user when they join the domain, and those passwords are changed in a regular basis. A Domain Controller store the last two known hashed passwords, so the key selector that we mentioned before identify this.

/* 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);


Response packets are signed using MD5 ( md5(hashed_password+response_body) ), which is not the most robust hashing algorithm in the world, but I couldn't find a working attack for such a small message, so at this point I think a Microsoft domain time synchronization is the most robust that I have seen in my research.
Written on October 30, 2015