Detection rules › Elastic

Rare Connection to WebDAV Target

Status
production
Severity
medium
Time window
8h
Group by
Esql.server_webdav_server
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies rare connection attempts to a Web Distributed Authoring and Versioning (WebDAV) resource. Attackers may inject WebDAV paths in files or features opened by a victim user to leak their NTLM credentials via forced authentication.

MITRE ATT&CK coverage

Rule body elastic

[metadata]
creation_date = "2025/04/28"
integration = ["endpoint", "system", "windows", "m365_defender", "crowdstrike"]
maturity = "production"
updated_date = "2026/05/22"

[rule]
author = ["Elastic"]
description = """
Identifies rare connection attempts to a Web Distributed Authoring and Versioning (WebDAV) resource. Attackers may
inject WebDAV paths in files or features opened by a victim user to leak their NTLM credentials via forced
authentication.
"""
from = "now-8h"
interval="1h"
language = "esql"
license = "Elastic License v2"
name = "Rare Connection to WebDAV Target"
note = """## Triage and analysis

### Investigating Rare Connection to WebDAV Target

### Possible investigation steps

- Examine the reputation of the destination domain or IP address.
- Verify if the target user opened any attachments or clicked links pointing to the same target within seconds from the alert timestamp.
- Correlate the findings with other security logs and alerts to identify any patterns or additional indicators of compromise related to the potential relay attack.

### False positive analysis

- User accessing legit WebDAV resources.

### Response and remediation

- Conduct a password reset for the target account that may have been compromised or are at risk, ensuring the use of strong, unique passwords.
- Verify whether other users were targeted but did not open the lure..
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine the full scope of the breach.
- Conduct a post-incident review to identify any gaps in security controls and update policies or procedures to prevent recurrence, ensuring lessons learned are applied to improve overall security posture."""
references = ["https://attack.mitre.org/techniques/T1187/"]
risk_score = 47
rule_id = "6756ee27-9152-479b-9b73-54b5bbda301c"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Data Source: Elastic Defend",
    "Data Source: Windows Security Event Logs",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Crowdstrike",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-system.security-*, logs-windows.*, winlogbeat-*, logs-crowdstrike.fdr*, logs-m365_defender.event-* METADATA _id, _version, _index
| where
    event.category == "process" and
    event.type == "start" and
    process.name == "rundll32.exe" and
    process.command_line like "*DavSetCookie*"
| keep host.id, process.command_line, user.name, user.id
// extract domain or IP address from process cmdline
| grok process.command_line """(?<Esql.server_webdav_server>((http|https)://[a-zA-Z0-9-\.]{1,}\.[a-zA-Z]{2,3}[@\/]+)|(\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b)[@\/]+)"""
// remove sub domains from URL
| eval Esql.server_webdav_server = REPLACE(Esql.server_webdav_server, """((http|https)://[a-zA-Z0-9-]{1,}\.)""", "")
| eval Esql.server_webdav_server = REPLACE(Esql.server_webdav_server, "/", "")
| where
    Esql.server_webdav_server is not null and
    not Esql.server_webdav_server in ("www.google.com", "www.elastic.co", "sharepoint.com", "live.net", "google.com", "SHAREPOINT.COM", "github.com") and
    // excludes private IP ranges
    not Esql.server_webdav_server rlike """(10\.(\d{1,3}\.){2}\d{1,3}|172\.(1[6-9]|2\d|3[0-1])\.(\d{1,3}\.)\d{1,3}|192\.168\.(\d{1,3}\.)\d{1,3})"""
| stats
    Esql.event_count = count(*),
    Esql.host_id_count_distinct = count_distinct(host.id),
    Esql.host_id_values = values(host.id),
    Esql.user_name_values = values(user.name)
  by Esql.server_webdav_server
| where
    Esql.host_id_count_distinct == 1 and Esql.event_count <= 3
| eval host.id = MV_MIN(Esql.host_id_values), user.name = MV_MIN(Esql.user_name_values), destination.domain = MV_MIN(Esql.server_webdav_server)
| KEEP host.id, user.name, destination.domain, Esql.*
'''

setup = """## Setup

This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

### Additional data sources

This rule also supports the following third-party data sources. For setup instructions, refer to the links below:

- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
"""


[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1187"
name = "Forced Authentication"
reference = "https://attack.mitre.org/techniques/T1187/"

[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"

[[rule.threat.technique.subtechnique]]
id = "T1218.011"
name = "Rundll32"
reference = "https://attack.mitre.org/techniques/T1218/011/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

Stages and Predicates

Stage 1: from

from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-system.security-*, logs-windows.*, winlogbeat-*, logs-crowdstrike.fdr*, logs-m365_defender.event-* METADATA _id, _version, _index

Stage 2: where

| where
    event.category == "process" and
    event.type == "start" and
    process.name == "rundll32.exe" and
    process.command_line like "*DavSetCookie*"

Stage 3: keep

| keep host.id, process.command_line, user.name, user.id

Stage 4: grok

| grok process.command_line """(?<Esql.server_webdav_server>((http|https)://[a-zA-Z0-9-\.]{1,}\.[a-zA-Z]{2,3}[@\/]+)|(\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b)[@\/]+)"""

Stage 5: eval

| eval Esql.server_webdav_server = REPLACE(Esql.server_webdav_server, """((http|https)://[a-zA-Z0-9-]{1,}\.)""", "")

Stage 6: eval

| eval Esql.server_webdav_server = REPLACE(Esql.server_webdav_server, "/", "")

Stage 7: where

| where
    Esql.server_webdav_server is not null and
    not Esql.server_webdav_server in ("www.google.com", "www.elastic.co", "sharepoint.com", "live.net", "google.com", "SHAREPOINT.COM", "github.com") and
    not Esql.server_webdav_server rlike """(10\.(\d{1,3}\.){2}\d{1,3}|172\.(1[6-9]|2\d|3[0-1])\.(\d{1,3}\.)\d{1,3}|192\.168\.(\d{1,3}\.)\d{1,3})"""

Stage 8: stats

| stats
    Esql.event_count = count(*),
    Esql.host_id_count_distinct = count_distinct(host.id),
    Esql.host_id_values = values(host.id),
    Esql.user_name_values = values(user.name)
  by Esql.server_webdav_server

Stage 9: where

| where
    Esql.host_id_count_distinct == 1 and Esql.event_count <= 3

Stage 10: eval

| eval host.id = MV_MIN(Esql.host_id_values), user.name = MV_MIN(Esql.user_name_values), destination.domain = MV_MIN(Esql.server_webdav_server)

Stage 11: keep

| KEEP host.id, user.name, destination.domain, Esql.*

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
Esql.server_webdav_serverinSHAREPOINT.COM, github.com, google.com, live.net, sharepoint.com, www.elastic.co, www.google.com
Esql.server_webdav_serverregex_match(10.(\d{1,3}.){2}\d{1,3}|172.(1[6-9]|2\d|3[0-1]).(\d{1,3}.)\d{1,3}|192.168.(\d{1,3}.)\d{1,3})

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
Esql.event_countle
  • 3
Esql.host_id_count_distincteq
  • 1
Esql.server_webdav_serveris_not_null
  • (no value, null check)
event.categoryeq
  • process corpus 128 (elastic 128)
event.typeeq
  • start corpus 606 (elastic 606)
process.command_linewildcard
  • *DavSetCookie*
process.nameeq
  • rundll32.exe corpus 60 (elastic 34, splunk 26)

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
host.idKEEP host.id
user.nameKEEP user.name
destination.domainKEEP destination.domain
Esql.*KEEP Esql.*