Background
On 18 June 2022, security researcher Filip Dragovic published proof-of-concept code for a new forced authentication technique named DFSCoerce. This technique, inspired by other forced authentication techniques like PetitPotam and SpoolSample, often is used to force a victim Windows host to authenticate to an attacker’s machine. The attacker can then relay the credentials to gain additional access.
Detection Opportunities
The researcher mentions two methods to force the target to authenticate to a compromised host: NetrDfsRemoveStdRoot and NetrDfsAddStdRoot. While the PoC script does not use the latter, it does include the necessary classes to allow any attacker to modify the code and invoke the method. Luckily, both methods are simple to detect.
NetrDfsRemoveStdRoot’s vulnerability is very simple and reliable to execute against a domain controller (our target) and a host-with-responder (our listener), as shown in figure 1.
Compromised User: Vagrant
Compromised Host: 192.168.56.105 (listener)
Domain Controller: 192.168.56.102 (target)
Figure 1: Executing DFSCoerce.py (left) and receiving an authentication attempt from the target (right)
The log source we’re interested in is Microsoft-Windows-DFSN-Server/Admin. If we take a look at this log around the time we executed DFSCoerce.py, we can see a 515 event that reveals the share specified in the code (“test”) and the IP address of the compromised host (see figure 2).
Figure 2: A 515 event in Microsoft-Windows-DFSN-Server/Admin captures the NetrDfsRemoveStdRoot attack
For the NetrDfsAddStdRoot method we add a function to the TriggerAuth class in DFSCoerce.py:
def NetrDfsAddRoot(self, dce, listener): print("[-] Sending NetrDfsAddRoot!") try: request = NetrDfsAddRoot() request['ServerName'] = '%sx00' % listener request['RootShare'] = 'testx00' request['Comment'] = 'testx00' request['ApiFlags'] = 1 request.dump() resp = dce.request(request) except Exception as e: print(e)
Finally, we simply change trigger.NetrDfsRemoveStdRoot to trigger.NetrDfsAddRoot towards the bottom of the script, as seen in figure 3:
Figure 3: Altering DFSCoerce.py to execute the NetrDfsAddRoot function we added earlier.
This method yields similar results– a 514 event in Microsoft-Windows-DFSN-Server/Admin, as shown in figure 4.
Figure 4: A 514 event in Microsoft-Windows-DFSN-Server/Admin captures the NetrDfsAddStdRoot attack
Recommendation
The ideal solution is to implement Microsoft’s recommendations to prevent NTLM relay attacks. However, disabling NTLM is a costly and time-consuming action. Until your organization can disable NTLM, the best course of action is to detect and alert on any anomalous attempts to add or remove DFS namespaces. Forward logs in Microsoft-Windows-DFSN-Server/Admin on all domain controllers and DFS servers to your SIEM and alert on all 515 and 514 events. When these events do occur, investigate the IP or hostname specified in the DfsServer field.
Be sure to read more of our NTLM-related research. We discuss SMB relaying attacks here and the Portbender utility here.
Sigma Rules
title: Attempted Removal of DFS Namespace description: Alerts on all attempts to remove a DFS namespace which could be indicative of a DFSCoerce attack. author: Weston Walker reference: https://www.praetorian.com/blog/how-to-detect-dfscoerce/ logsource: product: windows detection: selection: EventLog: Microsoft-Windows-DFSN-Server/Admin EventID: 515 falsepositives: - unknown level: high
title: Attempted Creation of DFS Namespace description: Alerts on all attempts to create a DFS namespace which could be indicative of a DFSCoerce attack. author: Weston Walker reference: https://www.praetorian.com/blog/how-to-detect-dfscoerce/ logsource: product: windows detection: selection: EventLog: Microsoft-Windows-DFSN-Server/Admin EventID: 514 falsepositives: - unknown level: high