NT domain member to domain controller authentication protocol

Luke Kenneth Casson Leighton lkcl at switchboard.net
Fri Aug 29 11:21:33 GMT 1997


Paul Ashton <paul at argo.demon.co.uk> and
Luke Leighton <lkcl at switchboard.net> present the NT domain
authentication protocol. Comments and corrections are welcome.

Definitions
-----------

Add(A1,A2): Intel byte ordered addition of corresponding 4 byte
            words in arrays A1 and A2

E(K,D): DES ECB encryption of 8 byte data D using 7 byte key K

lmowf(): Lan man hash

ntowf(): NT hash

PW: md4(machine_password) == md4(lsadump $machine.acc)
                          == pwdump(machine$)
              (initially) == md4(lmowf(unicode(machine)))

RC4(K,Lk,D,Ld): RC4 encryption of data D of length Ld with key K
                of length Lk

v[m..n(,l)]: subset of v from bytes m to n, optionally padded 
             with zeroes to length l

Cred(K,D): E(K[7..7,7],E(K[0..6],D)) computes a credential

Time(): 4 byte current time

Cc,Cs: 8 byte client and server challenges
Rc,Rs: 8 byte client and server credentials

Protocol
--------

C->S ReqChal,Cc
S->C Cs

C & S compute session key Ks = E(PW[9..15],E(PW[0..6],Add(Cc,Cs)))

C: Rc = Cred(Ks,Cc)
C->S Authenticate,Rc
S: Rs = Cred(Ks,Cs), assert(Rc == Cred(Ks,Cc))
S->C Rs
C: assert(Rs == Cred(Ks,Cs))

On joining the domain the client will optionally attempt to change
its password and the domain controller may refuse to update it
depending on registry settings. This will also occur weekly
afterwards.

C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc)
C->S ServerPasswordSet,Rc',Tc,
       rc4(Ks[0..7,16],lmowf(randompassword())
C: Rc = Cred(Ks,Rc+Tc+1)
S: assert(Rc' == Cred(Ks,Rc+Tc)), Ts = Time()
S: Rs' = Cred(Ks,Rs+Tc+1)
S->C Rs',Ts
C: assert(Rs' == Cred(Ks,Rs+Tc+1))
S: Rs = Rs'

User: U with password P wishes to login to the domain (incidental
data such as workstation and domain omitted)

C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc)
C->S NetLogonSamLogon,Rc',Tc,U,
       rc4(Ks[0..7,16],16,ntowf(P),16),
       rc4(Ks[0..7,16],16,lmowf(P),16)
S: assert(Rc' == Cred(Ks,Rc+Tc)) assert(passwords match those
       in SAM)
S: Ts = Time()

S->C Cred(Ks,Cred(Ks,Rc+Tc+1)),userinfo(logon script,UID,SIDs,etc)
C: assert(Rs == Cred(Ks,Cred(Rc+Tc+1))
C: Rc = Cred(Ks,Rc+Tc+1)

Comments
--------

On first joining the domain the session key could be computed by
anyone listening in on the network as the machine password has
a well known value. Until the machine is rebooted it will use
this session key to encrypt NT and LM one way functions of
passwords which are password equivalents. Any user who logs
in before the machine has been rebooted a second time will have
their password equivalent exposed. Of course the new machine
password is exposed at this time anyway.

None of the returned user info such as logon script, profile path
and SIDs *appear* to be protected by anything other than the TCP
checksum.

The server time stamps appear to be ignored.

The client sends a ReturnAuthenticator in the SamLogon request
which I can't find a use for.  However its time is used as the
timestamp returned by the server.

The password OWFs should NOT be sent over the network reversibly
encrypted.  They should be sent using RC4(Ks,md4(owf)) with the
server computing the same function using the owf values in the
SAM.




More information about the samba mailing list