NTLMv2, as it's called, has some additional safeguards thrown into the recipe that make it more complex and hopefully more secure than its predecessors. There are, however, two small problems with NTLMv2:
Regarding the first point, Appendix B of Luke K. C. Leighton's book DCE/RPC over SMB: Samba and Windows NT Domain Internals provides a recipe for NTLMv2 authentication. We'll do our best to expand on Luke's description. The other option, of course, is to look at available Open Source code. The second point is really a conjecture, based in part on the fact that it took a very long time to get NTLMv2 implemented in Samba and few seemed to care. Indeed, NTLMv2 support had already been added to Samba-TNG by Luke and crew, and needed only to be copied over. It seems that the delay in adding it to Samba was not a question of know-how, but of priorities. Another factor is that NTLMv2 is not required by default on most Windows systems. When challenge/response is negotiated, even newer Windows versions will default to using the LM/NTLM combination unless they are specifically configured not to. 15.5.1 The NTLMv2 ToolboxWe have already fussed with the DES algorithm and toyed with the MD4 algorithm. Now we get to use the HMAC-MD5 Message Authentication Code hash. This one's a power tool with razor -sharp keys and swivel-action hashing. The kind of thing your Dad would never let you play with when you were a kid. Like all good tools, though, it's neither complex nor dangerous once you learn how it works. HMAC-MD5 is actually a combination of two different algorithms: HMAC and MD5. HMAC is a M essage A uthentication C ode (MAC) algorithm that takes a hashing function (such as MD5) and adds a secret key to the works so that the resulting hash can be used to verify the authenticity of the data. The MD5 algorithm is basically an industrial-strength version of MD4. Put them together and you get HMAC-MD5. HMAC-MD5 is quite well documented, [13] and there are a lot of implementations available. It's also much less complicated than it appears in Figure 15.3, so we won't need to go into any of the details. For our purposes, what you need to know is that the HMAC_MD5() function takes a key and some source data as inputs, and returns a 16-byte (128-bit) output.
Figure 15.3. HMAC-MD5The HMAC-MD5 is a popular tool for use in message authentication. It is lightweight, powerful, efficient, and ergonomic.
Hmmm... Well, it's not actually quite that simple. See, MD4, MD5, and HMAC-MD5 all work with variable-length input, so they also need to know how big their input parameters are. The function call winds up looking something like this: hash16 = HMAC_MD5(Key, KeySize, Data, DataSize); There is, as it turns out, more than one way to skin an HMAC-MD5. Some implementations use a whole set of functions to compute the result:
Conceptually, though, the multi-function approach is the same as the simpler example shown above. That is: Key and Data in, 16-byte hash out. Not Quite Entirely Unlike Standard Alert
Another important tool is the older NTLM hash algorithm. It was described earlier but it is simple enough that we can present it again, this time in pseudo-code: uchar *NTLMhash(uchar *password) { UniPasswd = UCS2LE(password); KeySize = 2 * strlen(password); return(MD4(UniPasswd, KeySize)); } The ASCII password is converted to Unicode UCS-2LE format, which requires two bytes per character. The KeySize is simply the length of that (Unicode) password string, which we calculate here by doubling the ASCII string length (which is probably cheating). Finally, we generate the MD4 hash (that's MD 4 , not MD 5 ) of the password, and that's all there is to it. Note that the string terminator is not counted in the KeySize . That is common behavior for NTLM and NTLMv2 challenge/response when working with Unicode strings. The NTLM Hash is of interest because the SMB/CIFS designers at Microsoft (if indeed such people truly exist any more, except in legend) used it to cleverly avoid upgrade problems. With LM and NTLM, the hash is created from the password. Under NTLMv2, however, the older NTLM (v1) Hash is used instead of the password to generate the new hash. A server or Domain Controller being upgraded to use NTLMv2 may already have the older NTLM hash values in its authentication database. The stored values can be used to generate the new hashes no password required. That avoids the nasty chicken-and-egg problem of trying to upgrade to NTLMv2 Hashes on a system that only allows NTLMv2 authentication. 15.5.2 The NTLMv2 Password HashThe NTLMv2 Hash is created from:
The process works as shown in the following pseudo-code example: v1hash = NTLMhash(password); UniUser = UCS2LE(upcase(user)); UniDest = UCS2LE(upcase(destination)); data = uni_strcat(UniUser, UniDest); datalen = 2 * (strlen(user) + strlen(destination)); v2hash = HMAC_MD5(v1hash, 16, data, datalen); Let's clarify that, shall we? v1hash
UniUser
UniDest
data
datalen
v2hash
A bit more explanation is required regarding the destination value (which gets converted to UniDest ). In theory, the client can use NTLMv2 challenge/response to log into a standalone server or to log into an NT Domain. In the former case, the server will have an authentication database of its very own, but an NT Domain logon requires authentication against the central database maintained by the Domain Controllers. So, in theory, the destination name could be either the NetBIOS name of the standalone server or the NetBIOS name of the NT Domain (no NetBIOS suffix byte in either case). In practice, however, the server logon doesn't seem to work reliably. The Windows systems used in testing were unable to use NTLMv2 authentication with one another when they were in standalone mode, but once they joined the NT Domain NTLMv2 logons worked just fine. [14]
15.5.3 The NTLMv2 ResponseThe NTLMv2 Response is calculated using the NTLMv2 Hash as the Key . The Data parameter is composed of the challenge plus a blob of data which we will refer to as "the blob." The blob will be explained shortly. For now, just think of it as a mostly-random bunch of garblement. The formula is shown in this pseudo-code example: blob = RandomBytes(blobsize); data = concat(ServerChallenge, 8, blob, blobsize); hmac = HMAC_MD5(v2hash, 16, data, (8 + blobsize)); v2resp = concat(hmac, 16, blob, blobsize); Okay, let's take a closer look at that and see if we can force it to make some sense.
If the client sends the NTLMv2 Response, it will take the place of the NTLM Response in the SESSION_SETUP_ANDX.Case Sensitive -Password field. Note that, unlike the older NTLM Response, the NTLMv2 Response algorithm uses 128-bit encryption all the way through. 15.5.4 Creating the BlobIf you have ever taken a college-level Invertebrate Zoology course, you may find the dissection of the blob to be nauseatingly familiar. The rest of you... try not to be squeamish. One more warning before we cut into this: The blob's structure may not matter at all. We'll explain why a little later on. Okay, now that the disclaimers are out of the way, we can get back to work. The blob does have a structure, which is more or less as follows: 4 bytes
4 bytes
8 bytes
8 bytes
4 bytes
variable length
4 bytes
2 bytes
2 bytes
variable length
The blob structure is probably related to (the same as?) data formats used in the more advanced security systems available under Extended Security. [15]
15.5.5 Improved Security Through ConfusionNow that we have the formula worked out, let's take a closer look at the NTLMv2 challenge/response algorithm and see how much better it is than NTLM. With the exception of the password itself, all of the inputs to NTLMv2 are known or knowable from a packet capture. Even the blob can be read off the wire, since it is sent as part of the response. That means that the problem is still a not-so-simple case of solving for a single variable: the password. The NTLMv2 Hash is derived directly from the NTLM (v1) Hash. Since there is no change to the initial input (the password), the keyspace is exactly the same. The only change is that the increased complexity of the algorithm means that there are more encryption hoops through which to jump compared to the simpler NTLM process. It takes more computer time to generate a v2 response, which doesn't impact a normal login but will slow down dictionary and brute force attacks against NTLMv2 (though Moore's Law may compensate). Weak passwords (those that are near the beginning of the password dictionary) are still vulnerable. Another thing to consider is the blob. If the blob were zero length (empty), the NTLMv2 Response formula would reduce to: v2resp = HMAC_MD5(v2hash, ServerChallenge); which would still be pretty darn secure. So the question is this: Does the inclusion of the blob improve the NTLMv2 algorithm and, if so, how? Well, see, it's like this... Instead of being produced by the key and challenge alone, the NTLMv2 Response involves the hash of a chunk of semi-random data. As a result, the same challenge will not always generate the same response. That's good, because it prevents replay attacks... in theory. In practice, the randomness of the challenge should be enough to prevent replay attacks. Even if that were not the case, the only way that the blob could help would be if it, too, were non-repeating and if the server could somehow verify that the blob was not a repeat. That, quite possibly, is why the timestamp is included. The timestamp could be used to let the server know that the blob is "fresh" that is, that it was created a reasonably short amount of time before it was received. Fresh packets can't easily be forged because the response is HMAC-signed using the v2hash as the key (and that's based on the password which is the very thing the cracker doesn't know). Of course, the timestamp test won't work unless the client and server clocks are synchronized, which is not always the case. In all likelihood the contents of the blob are never tested at all. There is code and commentary in the Samba-TNG source showing that they have done some testing, and that their results indicate that a completely random blob of bytes works just fine. If that's true, then the blob does little to improve the security of the algorithm except perhaps by adding a few more CPU cycles to the processing time. Bottom line: NTLMv2 challenge/response provides only a minimal improvement over its predecessor. This isn't the first time that we have put a lot of effort into figuring out some complex piece of the protocol only to discover that it's almost pointless, and it probably won't be the last time either.
15.5.6 Insult to Injury: LMv2There is yet one more small problem with the NTLMv2 Response, and that problem is known as pass-through authentication. Simply put, a server can pass the authentication process through to an NT Domain Controller. The trouble is that some servers that use pass-through assume that the response string is only 24 bytes long. You may recall that both the LM and NTLM responses are, in fact, 24 bytes long. Because of the blob, however, the NTLMv2 response is much longer. If a server truncates the response to 24 bytes before forwarding it to the NT Domain Controller almost all of the blob will be lost. Without the blob, the Domain Controller will have no way to verify the response so authentication will fail. To compensate, a simpler response known as the LMv2 response is also calculated and returned alongside the NTLMv2 response. The formula is identical to that of NTLMv2, except that the blob is really small. blip = RandomBytes(8); data = concat(ServerChallenge, 8, blip, 8); hmac = HMAC_MD5(v2hash, 16, data, 16); LMv2resp = concat(hmac, 16, blip, 8); The "blip," as we've chosen to call it, is sometimes referred to as the "Client Challenge." If you go back and look, you'll find that the blip value is also included in the blob, just after the timestamp. It is fairly easy to spot in packet captures. The blip is 8 bytes long so that the resulting LMv2 Response will be 24 bytes, exactly the size needed for pass-through authentication. If it is true that the contents of the blob are not checked, then the LMv2 Response isn't really any less secure than the NTLMv2 Response even though the latter is bigger. The LMv2 Response takes the place of the LM Response in the SESSION_SETUP_ANDX.CaseInsensitivePassword field. 15.5.7 Choosing NTLMv2The use of NTLMv2 is not negotiated between the client and the server. There is nothing in the protocol to determine which challenge/response algorithms should be used. So, um... how does the client know what to send, and how does the server know what to expect? The default behavior for Windows clients is to send the LM and NTLM responses, and the default for Windows servers is to accept them. Changing these defaults requires fiddling in the Windows registry. Fortunately, the fiddles are well known and documented so we can go through them quickly and get them out of the way. [16]
The registry path to look at is: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA On Windows 9x the variable is called LMCompatibility , but on Windows NT and 2000 it is LMCompatibilityLevel . That variable may not be present in the registry, so you might have to add it. In general, it's best to follow Microsoft's instructions when editing the registry. [17]
The settings for LMCompatibilityLevel are as follows:
That's just a quick overview of the settings and their meanings. The important points are these:
|