Purging Old NT Security Protocols

Hi folks, Ned here again (with some friends). Everyone knows that Kerberos is Microsoft’s preeminent security protocol and that NTLM is both inefficient and, in some iterations, not strong enough to avoid concerted attack. NTLM V2 using complex passwords stands up well to common hash cracking tools like Cain and Abel, Ophcrack, or John the Ripper. On the other hand, NTLM V1 is defeated far faster and LM is effectively no protection at all.

I discussed NTLM auditing years ago, when Windows 7 and Windows Server 2008 R2 introduced the concept of NTLM blocking. That article was for well-controlled environments where you thought that there was some chance of disabling NTLM – only modern clients and servers, the latest applications, and Active Directory. In a few other articles, I gave some further details on the limitations of the Windows auditing system logging. It turns out that while we’re ok at telling when NTLM was used, we’re not great at describing which flavor. For instance, Windows Server 2008+security auditing can tell you about the NTLM version through the 4624 event that states a Package Name (NTLM only): NTLM V1 or Package Name (NTLM only): NTLM V2, but all prior operating systems cannot. None of the older auditing can tell you if LM is used either. Windows Server 2008 R2 NTLM auditing only shows you NTLM usage in general.

Today the troika of Dave, Jonathan, and Ned are here to help you discover which computers and applications are using NTLM V1 and LM security, regardless of your operating system. It’s safe to say that some people aren’t going to like our answers or how much work this entails, but that’s life; when LM security was created as part of LAN Manager and OS/2 by Microsoft and IBM, Dave and I were in grade school and Jonathan was only 48.

If you need to keep using NTLM V2 and simply want to hunt down the less secure precursors, this should help.

Finding NTLM V1 and LM Usage via network captures

The only universal, OS-agnostic way you can tell which clients are sending NTLMv1 and LM challenges is by examining a network trace taken from destination computers. Using Netmon 3.4 or another network capture tool, look for packets with a negotiated NTLM security mechanism.

This first example is with LMCompatibilityLevel set to 0 on clients. This example is an SMB session request packet, specifying NTLM authentication.

Here is the SMB SESSION SETUP request, which specifies the security token mechanism:

  Frame: Number = 15, Captured Frame Length = 220, MediaType = ETHERNET

+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-15-5D-05-B4-44],SourceAddress:[00-15-5D-05-B4-49]

+ Ipv4: Src = 10.10.10.20, Dest = 10.10.10.27, Next Protocol = TCP, Packet ID = 747, Total IP Length = 206

+ Tcp: Flags=...AP..., SrcPort=49235, DstPort=Microsoft-DS(445), PayloadLen=166, Seq=2204022974 - 2204023140, Ack=820542383, Win=32724 (scale factor 0x2) = 130896

+ SMBOverTCP: Length = 162

- SMB2: C   SESSION SETUP (0x1)

    SMBIdentifier: SMB

  + SMB2Header: C SESSION SETUP (0x1),TID=0x0000, MID=0x0002, PID=0xFEFF, SID=0x0000

  - CSessionSetup:

     StructureSize: 25 (0x19)

     VcNumber: 0 (0x0)

   + SecurityMode: 1 (0x1)

   + Capabilities: 0x1

     Channel: 0 (0x0)

     SecurityBufferOffset: 88 (0x58)

     SecurityBufferLength: 74 (0x4A)

     PreviousSessionId: 0 (0x0)

   - securityBlob:

    - GSSAPI:

     - InitialContextToken:

      + ApplicationHeader:

      + ThisMech: SpnegoToken (1.3.6.1.5.5.2)

      - InnerContextToken: 0x1

       - SpnegoToken: 0x1

        + ChoiceTag:

        - NegTokenInit:

         + SequenceHeader:

         + Tag0:

         + MechTypes: Prefer NLMP (1.3.6.1.4.1.311.2.2.10)

         + Tag2:

         + OctetStringHeader:

         -MechToken: NTLM NEGOTIATE MESSAGE

          - NLMP: NTLM NEGOTIATE MESSAGE

             Signature: NTLMSSP

             MessageType: Negotiate Message (0x00000001)

           + NegotiateFlags: 0xE2088297 (NTLM v2128-bit encryption, Always Sign)

           + DomainNameFields: Length: 0, Offset: 0

           + WorkstationFields: Length: 0, Offset: 0

           + Version: Windows 6.1 Build 7601 NLMPv15

Next, the server sends its NTLM challenge back to the client:

  Frame: Number = 16, Captured Frame Length = 447, MediaType = ETHERNET

+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-15-5D-05-B4-49],SourceAddress:[00-15-5D-05-B4-44]

+ Ipv4: Src = 10.10.10.27, Dest = 10.10.10.20, Next Protocol = TCP, Packet ID = 24310, Total IP Length = 433

+ Tcp: Flags=...AP..., SrcPort=Microsoft-DS(445), DstPort=49235, PayloadLen=393, Seq=820542383 - 820542776, Ack=2204023140, Win=512 (scale factor 0x8) = 131072

+ SMBOverTCP: Length = 389

- SMB2: R  - NT Status: System - Error, Code = (22) STATUS_MORE_PROCESSING_REQUIRED  SESSION SETUP (0x1), SessionFlags=0x0

    SMBIdentifier: SMB

  + SMB2Header: R SESSION SETUP (0x1),TID=0x0000, MID=0x0002, PID=0xFEFF, SID=0x0019

  - RSessionSetup:

     StructureSize: 9 (0x9)

   + SessionFlags: 0x0

     SecurityBufferOffset: 72 (0x48)

     SecurityBufferLength: 317 (0x13D)

   - securityBlob:

    - GSSAPI:

     - NegotiationToken:

      + ChoiceTag:

      - NegTokenResp:

       + SequenceHeader:

       + Tag0:

       + NegState: accept-incomplete (1)

       + Tag1:

       + SupportedMech: NLMP (1.3.6.1.4.1.311.2.2.10)

       + Tag2:

       + OctetStringHeader:

       - ResponseToken: NTLM CHALLENGE MESSAGE

        - NLMP: NTLM CHALLENGE MESSAGE

          Signature: NTLMSSP

           MessageType: Challenge Message (0x00000002)

        + TargetNameFields: Length: 12, Offset: 56

         + NegotiateFlags: 0xE2898215 (NTLM v2128-bit encryption, Always Sign)

         + ServerChallenge: 67F9C5F851F2CD73

           Reserved: Binary Large Object (8 Bytes)

         + TargetInfoFields: Length: 214, Offset: 68

         + Version: Windows 6.1 Build 7601 NLMPv15

           TargetNameString: CORP01

         + AvPairs: 7 pairs

The client calculates the response to the challenge, using the various available hashes of the password. Note how this response includes both LM and NTLMv1 challenge responses.

  Frame: Number = 17, Captured Frame Length = 401, MediaType = ETHERNET

+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-15-5D-05-B4-44],SourceAddress:[00-15-5D-05-B4-49]

+ Ipv4: Src = 10.10.10.20, Dest = 10.10.10.27, Next Protocol = TCP, Packet ID = 748, Total IP Length = 387

+ Tcp: Flags=...AP..., SrcPort=49235, DstPort=Microsoft-DS(445), PayloadLen=347, Seq=2204023140 - 2204023487, Ack=820542776, Win=32625 (scale factor 0x2) = 130500

+ SMBOverTCP: Length = 343

- SMB2: C   SESSION SETUP (0x1)

    SMBIdentifier: SMB

  + SMB2Header: C SESSION SETUP (0x1),TID=0x0000, MID=0x0003, PID=0xFEFF, SID=0x0019

  - CSessionSetup:

     StructureSize: 25 (0x19)

     VcNumber: 0 (0x0)

   + SecurityMode: 1 (0x1)

   + Capabilities: 0x1

     Channel: 0 (0x0)

   SecurityBufferOffset: 88 (0x58)

     SecurityBufferLength: 255 (0xFF)

     PreviousSessionId: 0 (0x0)

   - securityBlob:

    - GSSAPI:

     - NegotiationToken:

      + ChoiceTag:

      - NegTokenResp:

       + SequenceHeader:

       + Tag0:

       + NegState: accept-incomplete (1)

       + Tag2:

       + OctetStringHeader:

       - ResponseToken: NTLM AUTHENTICATE MESSAGEVersion:v1, Domain: CORP01, User: Administrator, Workstation: CONTOSO-CLI-01

        - NLMP: NTLM AUTHENTICATE MESSAGEVersion:v1, Domain: CORP01, User: Administrator, Workstation: CONTOSO-CLI-01

           Signature: NTLMSSP

           MessageType: Authenticate Message (0x00000003)

         + LmChallengeResponseFields: Length: 24, Offset: 154

         + NtChallengeResponseFields: Length: 24, Offset: 178

         + DomainNameFields: Length: 12, Offset: 88

         + UserNameFields: Length: 26, Offset: 100

         + WorkstationFields: Length: 28, Offset: 126

         + EncryptedRandomSessionKeyFields: Length: 16, Offset: 202

         + NegotiateFlags: 0xE2888215 (NTLM v2128-bit encryption, Always Sign)

         + Version: Windows 6.1 Build 7601 NLMPv15

         + MessageIntegrityCheckNotPresent: 6243C42AF68F9DFE30BD31BFC722B4C0

           DomainNameString: CORP01

           UserNameString: Administrator

           WorkstationString: CONTOSO-CLI-01

         + LmChallengeResponseStruct: 3995E087245B6F7100000000000000000000000000000000

         + NTLMV1ChallengeResponse: B0751BDCB116BA5737A51962328D5CCD19EEBEBB15A69B1E

         + SessionKeyString: 397DACB158C9F10EF4903F10D4CBE032

       + Tag3:

       + OctetStringHeader:

       + MechListMic: Version: 1

The server then responds with successful negotiation state:

  Frame: Number = 18, Captured Frame Length = 159, MediaType = ETHERNET

+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-15-5D-05-B4-49],SourceAddress:[00-15-5D-05-B4-44]

+ Ipv4: Src = 10.10.10.27, Dest = 10.10.10.20, Next Protocol = TCP, Packet ID = 24312, Total IP Length = 145

+ Tcp: Flags=...AP..., SrcPort=Microsoft-DS(445), DstPort=49235, PayloadLen=105, Seq=820542776 - 820542881, Ack=2204023487, Win=510 (scale factor 0x8) = 130560

+ SMBOverTCP: Length = 101

- SMB2: R   SESSION SETUP (0x1), SessionFlags=0x0

    SMBIdentifier: SMB

  + SMB2Header: R SESSION SETUP (0x1),TID=0x0000, MID=0x0003, PID=0xFEFF, SID=0x0019

  - RSessionSetup:

     StructureSize: 9 (0x9)

   + SessionFlags: 0x0

     SecurityBufferOffset: 72 (0x48)

     SecurityBufferLength: 29 (0x1D)

   - securityBlob:

    - GSSAPI:

     - NegotiationToken:

      + ChoiceTag:

      - NegTokenResp:

       + SequenceHeader:

       + Tag0:

       +NegState: accept-completed (0)

       + Tag3:

       + OctetStringHeader:

       + MechListMic: Version: 1

To contrast this, consider the challenge response packet when LMCompatibility is set to 4 or 5 on the client (meaning it is not allowed to send anything but NTLM V2). The LM response is null, while the NTLMv1 response isn't included at all.

  Frame: Number = 17, Captured Frame Length = 763, MediaType = ETHERNET

+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-15-5D-05-B4-44],SourceAddress:[00-15-5D-05-B4-49]

+ Ipv4: Src = 10.10.10.20, Dest = 10.10.10.27, Next Protocol = TCP, Packet ID = 844, Total IP Length = 749

+ Tcp: Flags=...AP..., SrcPort=49231, DstPort=Microsoft-DS(445), PayloadLen=709, Seq=4045369997 - 4045370706, Ack=881301203, Win=32625 (scale factor 0x2) = 130500

+ SMBOverTCP: Length = 705

- SMB2: C   SESSION SETUP (0x1)

    SMBIdentifier: SMB

  + SMB2Header: C SESSION SETUP (0x1),TID=0x0000, MID=0x0003, PID=0xFEFF, SID=0x0021

  - CSessionSetup:

     StructureSize: 25 (0x19)

     VcNumber: 0 (0x0)

  + SecurityMode: 1 (0x1)

   + Capabilities: 0x1

     Channel: 0 (0x0)

     SecurityBufferOffset: 88 (0x58)

     SecurityBufferLength: 617 (0x269)

     PreviousSessionId: 0 (0x0)

   - securityBlob:

    - GSSAPI:

     - NegotiationToken:

      + ChoiceTag:

      - NegTokenResp:

       + SequenceHeader:

       + Tag0:

       + NegState: accept-incomplete (1)

       + Tag2:

       + OctetStringHeader:

       - ResponseToken: NTLM AUTHENTICATE MESSAGEVersion:v2, Domain: CORP01, User: Administrator, Workstation: CONTOSO-CLI-01

        - NLMP: NTLM AUTHENTICATE MESSAGEVersion:v2, Domain: CORP01, User: Administrator, Workstation: CONTOSO-CLI-01

           Signature: NTLMSSP

           MessageType: Authenticate Message (0x00000003)

         + LmChallengeResponseFields: Length: 24, Offset: 154

         + NtChallengeResponseFields: Length: 382, Offset: 178

         + DomainNameFields: Length: 12, Offset: 88

         + UserNameFields: Length: 26, Offset: 100

         + WorkstationFields: Length: 28, Offset: 126

         + EncryptedRandomSessionKeyFields: Length: 16, Offset: 560

         + NegotiateFlags: 0xE2888215 (NTLM v2128-bit encryption, Always Sign)

         + Version: Windows 6.1 Build 7601 NLMPv15

         + MessageIntegrityCheck: 2B69C069DD922D4A841D0EC43939DF0F

           DomainNameString: CORP01

           UserNameString: Administrator

           WorkstationString: CONTOSO-CLI-01

         + LmChallengeResponseStruct: 000000000000000000000000000000000000000000000000

         + NTLMV2ChallengeResponse: CD22D7CC09140E02C3D8A5AB623899A8

         + SessionKeyString: AF31EDFAAF8F38D1900D7FBBDCB43760

       + Tag3:

       + OctetStringHeader:

       + MechListMic: Version: 1

By taking traces and filtering on the NTLMV1ChallengeResponse field, you find those hosts that are sending NTLMv1 responses and determine if you need to upgrade them or if they simply have the wrong LMcompatibility values set through security policy.

Finding LM usage via Netlogon debug logs

If you just want to detect LM authentication and not looking to spend time in network captures, you can instead enable Netlogon logging on all DCs and servers in the environment.

Nltest /dbflag:2080ffff
net stop NetLogon
net start NetLogon

This creates the netlogon.log in the C:\Windows\Debug folder and it can grow to a maximum of 20 Mb by default. At that point, the server renames the file to netlogon.bak and a new netlogon.log file started. At 20Mb, the server deletes netlogon.bak, renames the netlogon.log to netlogon.bak, and a new netlogon.log file started. To make these log files larger, you can use a registry entry or group policy:

Registry

Path: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters
Value Name: MaximumLogFileSize
Value Type: REG_DWORD
Value Data: <maximum log file size in bytes>

Group Policy

\Computer Configuration\Administrative Templates\System\Net Logon\Maximum Log File Size

You aren't trying to capture all data here - just useful samples - but if they wrap so much that you're unsure if they are accurate at all, increasing size is a good idea. As an alternative, you can create a scheduled task that runs ONSTART or a computer startup script. Either of them can use this batch file to make backups of the netlogon log by date/time and the computer name:

REM Sample script to copy the netlogon.bak to a netlogon_DATETIME_COMPUTERNAME.log backup form every 5 minutes

:start
if exist %windir%\debug\netlogon.bak goto copylog

:copylog_return
sleep 300
goto start

:copylog
for /f "tokens=1-7 delims=/:., " %%a in ("%DATE% %TIME%") do (set DATETIME=%%a-%%b-%%c_%%d-%%e-%%f)
copy /v %windir%\debug\netlogon.bak %windir%\debug\netlogon_%DATETIME%_%COMPUTERNAME%.log
if %ERRORLEVEL% EQU 0 del %windir%\debug\netlogon.bak
goto copylog_return

Periodically, gather all of the NetLogon logs from the DCs and servers and place them in a single folder. Once you have assembled the NetLogon logs into a single spot, you may then use the following LogParser command from that folder to parse them all for a count of unique UAS logons to the domain controller by workstation:

Logparser.exe "SELECT TO_UPPERCASE(EXTRACT_SUFFIX(TEXT,0,'returns ')) AS ERR, TO_UPPERCASE (extract_prefix(extract_suffix(TEXT, 0, 'NetrLogonUasLogon of '), 0, 'from ')) as USER, TO_UPPERCASE (extract_prefix(extract_suffix(TEXT, 0, 'from '), 0, 'returns ')) as WORKSTATION, COUNT(*) FROM '*netlogon.*' WHERE INDEX_OF(TO_UPPERCASE (TEXT),'LOGON') >0 AND INDEX_OF(TO_UPPERCASE(TEXT),'RETURNS') >0 AND INDEX_OF(TO_UPPERCASE(TEXT),'NETRLOGONUASLOGON') >0 GROUP BY ERR, USER, WORKSTATION ORDER BY COUNT(*) DESC" -i:TEXTLINE -rtp:-1 >UASLOGON_USER_BY_WORKSTATION.txt

UASLOGON_USER_BY_WORKSTATION.txt contains the unique computers and counts. LogParser is available for download from here.

FIND and PowerShell are options here as well. The simplest approach is just to return the lines, perhaps into a text file for later sorting in say, Excel (which is very fast at sorting and allows you to organize your data).

image

image

image

I'll wager someone in the comments will take on the rather boring challenge of exactly duplicating what LogParser does. I didn't have the energy this time around. :)

Final thoughts

Microsoft stopped using LM after Windows 95/98/ME. If you do find specific LM-only usage and you don't have any (unsupported) Win9X computers, this is a third party application. A really heinous one.

All supported versions of Windows obey the LMCompatibility registry setting, and can use NTLMv2 just as easily as NTLMv1. At that point, analyzing network traces just becomes useful for tracking down those hosts that have applied the policy, but have not yet been rebooted. Considering how unsafe LM and NTLMv1 are, enabling NoLMHash and LMCompatibility 4 or 5 on all computers may be a faster alternative to auditing. It could cause some temporary outages, but would definitely catch anyone requiring unsafe protocols. There's no better auditing that a complaining application administrator.

Finally, do not limit your NTLM inventory to domain controllers and file or application servers. A comprehensive project requires you examine all computers in the environment, as even a Windows XP workstation can be a "server" for some application. Use a multi-pronged approach, where you also inventory operating systems through network probing - if you have Windows 95 or old SAMBA lying around somewhere on a shop floor, they are almost guaranteed to use insecure protocols.

Until next time,

- Ned “and Dave and Jonathan and Jonathan's in-home elderly care nurse” Pyle