NT4.0的登录加密方案
作者: *Hobbit*, Avian Research, [email protected], January 1997
2000.12.10

Appendix A: Crypto
==================

There are two algorithms used to cryptographically secure the authentication data between a user and a server.  The earlier LANMAN-compatible algorithm uppercases the password, truncates or pads to 14 characters as needed, and derives therefrom a pair of odd-parity DES keys to ECB-encrypt a fixed 8-byte quantity described in CIFS as "available from Microsoft upon request" but already well-known to be the decryption of 0xAAD3B435B51404EE with a key of all zeros.  The second method is currently supported by NT and Samba, which preserves the case of the password up to 128 bytes, converts it to unicode, and runs the result through MD4.  Each algorithm outputs 16 bytes of cryptographic hash that securely represents the user's password.  These 16 bytes are called "OWF passwords" from the associated one-way function, and are stored in registries and Samba's alternate "smbpasswd" file.  Smbencrypt.c
in conjunction with the "libdes" routines handle most of this.

For challenge response, five more nulls are appended to either hash type and the 21 total bytes used as a key triple to DES encrypt the 8-byte challenge into three separate output blocks.  The final 24-byte output of this process is sent in the SMB in place of the plaintext password.  The password length normally sits at parameter word smb_vwv7 as Samba builds the block, and the buffer area farther along contains the response bytes.  Under NT LM dialect there are two password fields -- one for the all-uppercase LANMAN-compatible
password or hash thereof and one for the case-sensitive NT-style equivalent. The lengths sit at smb_vwv7 and smb_vwv8 respectively, and the corresponding data buffers are consecutive.  NT clients by default fill both buffers with the two types of encrypted 24-byte responses.  If told to use plaintext passwords, the NT client only sends a LANMAN password in smb_vwv7 but in *mixed* case.

This is open to more than one easy man-in-the-middle attack.  One is even documented in CIFS as the "downgrade attack", wherein a fake server response tells a client to use observable cleartext passwords.  Since the fake response packet only needs one changed payload bit and different checksums, this attack is undetectable since a later real response is simply discarded by the TCP transport.  A more interesting attack involves taking the cryptkey from one session and network-spoofing it into a victim's later one; the victim's resulting 24-byte response is used to authenticate the first session instead. Here, CIFS makes the cryptographically naive error of letting the client user
"sign" the arbitrary data in the cryptkey instead of a hash that includes it.

The application user interfaces in general encourage the historically bad practice for all users to choose the same password across many different machines, even across different NT domains.  This is held forth as a single-sign-on model, but standard elements of a real SSO system such as time-limited session credentials never enter the picture at all.  The implementation also is in many ways too restrictive for most real-world environments.  How does one go about the sounder practice of having separate accounts for separate machines or groups thereof?  Some utilities will ask for another password and try again if the cached login password isn't correct for a different server, but this doesn't work everywhere.  Example: The NT "net" utility accepts a "/USER:othername" switch when doing a "net use", but not when doing
a "net view".  Remote registry editing and related tools first try to use the credentials from the console login, and if that doesn't work either ask for an alternate password or simply fail.  Sometimes a way to specify a completely alternate login is necessary, but NT's designers seems to have ignored this and not even provided a global "net logon" facility like under WFWG.  Often one is forced to create new local accounts and passwords, or use some other band-aid workaround, just to authenticate some underdesigned application to a remote system.

The OWF hashes do not directly reveal a user's plaintext password but if somehow obtained, can be directly used for authentication as well as input to an offline dictionary attack.  Directly storing them therefore reduces the security to about the level of burying plaintext passwords inside scripts and thinking "well, the script is hidden, so the password is safe."  Microsoft tries to crock around this recognized decades-old problem by re-encrypting the hashes under some *other* key that is often stored in some obscure but nonetheless findable place.  Authentication information is also cached in various places such as .PWL files and registry entries, to support the "automatic drive reconnect" stuff.  NT apparently also stores information about the last ten domain-level user logons in the registry, for use in cases when the PDC is unreachable.

Since there is no salting in the OWF transform, even the generic old Unix crypt() algorithm is stronger than this scheme.  An entire dictionary's worth of passwords and permutations thereof can be *precomputed* and stored, which reduces an OWF dictionary attack to a big database lookup.  The block-mode ECB encryption scheme further implies that only the first 8 bytes of the OWF hash really need to be saved; a successful 8-byte match not only brackets a greatly reduced dictionary segment, it directly reveals the first seven characters of
a LANMAN-style password.  Related to this is that the challenge-response protocol also uses simple ECB of a known plaintext with no chaining or feedback.  Response keys derived from the OWF are invariant and can be similarly precomputed.  The first stage of an attack on a recorded session setup only requires the cryptkey and the first 8 bytes from both the precomputed response dictionary and the 24-byte response, and DES encryption of a single block determines whether to bother with the remaining two.  Again, cracking just the first block can index down to a much smaller chunk of the dictionary.  Under NT LM dialect, NT clients usually send *both* response
types in the SetupAndX, which again defeats the whole purpose of the NT style password since cracking the plaintext of the reduced keyspace LANMAN password can serve as a template for cracking the user's "real" NT password.

Normally the SAM registry section on an NT server is protected against reading.  An adminstrator can nonetheless take ownership of the whole SAM hive, and dump out various subkeys under Domains\Account\Users\{hex-values}. It is fairly clear from diffing ASCII hive dumps that the 32 bytes at the end of the respective "V" binary blocks correspond to OWF password storage.  We can observe corresponding changes to at least the same-length fields in the Samba "smbpasswd" file.  The 32 bytes represent the LANMAN and NT OWF hashes, but on NT are re-encrypted under some other set of keys.  Attempts to find these meta-keys by trying likely-looking DES-size blocks elsewhere around the registry have thus far failed, but the answer may be discoverable with a little more effort.  Anyone who already knows the true magic here is of course encouraged to speak up, even if anonymously.

Inter-domain trust relationships are another NT-specific issue and were not studied here, but surely need to be investigated more closely.  Various documentation mentions that a "secure channel" is established between domain controllers using the special DOMAIN$ accounts and a some kind of "secret object" which apparently is often derived from a human-chosen password.  The channel is apparently an RPC session, but is it truly encrypted, and if so, how?  Would this imply that some mechanism for encrypted SMB does exist after all, but for some reason is not made available to the end users?  What about backup domain-controller replication, which implies that one machine can suck down the entire SAM database of another?  How about an analysis of encryption across PPTP VPNs?  Someone else may be able to answer these questions too.