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.