From - Fri Sep 12 14:23:03 1997 Path: news.mitre.org!blanket.mitre.org!nntprelay.mathworks.com!howland.erols.net!feed1.news.erols.com!dispatch.news.demon.net!demon!argo.demon.co.uk!not-for-mail From: Paul Ashton Newsgroups: sci.crypt,comp.protocols.smb,comp.os.ms-windows.nt.admin.security Subject: NT domain member to domain controller authentication protocol Date: Thu, 28 Aug 1997 22:10:59 +0100 Organization: Argo Systems Message-ID: <3405E963.77BE@argo.demon.co.uk> NNTP-Posting-Host: argo.demon.co.uk X-NNTP-Posting-Host: argo.demon.co.uk [158.152.32.217] X-Mailer: Mozilla 3.01 (WinNT; I) MIME-Version: 1.0 CC: ntbugtraq@rc.on.ca, ntsecurity@iss.net Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Lines: 103 Xref: news.mitre.org sci.crypt:70013 comp.protocols.smb:15721 comp.os.ms-windows.nt.admin.security:5125 Paul Ashton and Luke Leighton 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.