elastic / elastic/detection-rules

[New Rule] Potential Non-Browser Process Connection to a DNS-over-HTTPS Resolver

Open
#6,608 1 comment 0 reactions 0 assignees View on GitHub
community
Dominant language
Python
Stars
2.7k
Forks
696
Avg merge
4d 17h
Merged PRs (30d)
87

Description

## Description

Detects a non-browser process on macOS opening a direct TLS connection to a well known DNS-over-HTTPS (DoH) resolver IP (Cloudflare, Google, Quad9). Tools that speak DoH for C2 or tunneling, such as Sliver or dnscat2, can use this to avoid classic DNS monitoring, since the query never appears as DNS traffic on the wire.

Checked before building: `defense_evasion_dns_over_https_enabled` only fires when a browser gets configured to turn DoH on (a Windows registry change). `command_and_control_ml_dns_tunneling` only looks at port 53 DNS volume, so it can't see DoH traffic at all. Neither covers a non-browser process using DoH as a channel directly.

**Update 2026-08-08**: the PR (#6612) went through a review round and two real bugs got found. First, the query used `event.action == "connected-to"`, an Auditbeat value that Elastic Defend never emits, so it could never have matched the rule's own `logs-endpoint.events.network*` index. That happened because the first round of testing used Auditbeat on a host without eBPF support, reshaped to look like the right schema, and never actually ran against real Elastic Defend. Second, the browser exclusion list checked `process.name`, but on macOS Safari and Chrome don't make their network connections under a process literally named that (Safari's is `com.apple.WebKit.Networking`, Chrome's is `Google Chrome Helper`; Firefox is the exception, its connecting process really is named `firefox`). Both are fixed now, and this issue is scoped down to macOS only, since that's what actually got tested end to end.

**Update 2026-08-11**: second review round is in, and the rule is now named "Potential Non-Browser Process Connection to a DNS-over-HTTPS Resolver" to reflect that the network event records the connection and not its contents. All of the reviewer's comments are addressed on #6612. The browser exclusion was rebuilt on executable path plus signing identity plus code signature trust, after confirming on a real host that `codesign -f -s - -i com.google.Chrome.helper` lets any unprivileged user forge a signing identity. Two things that only real testing would have caught: Safari's networking process is recorded by the sensor under its cryptex path (`/System/Volumes/Preboot/Cryptexes/Incoming/OS/System/Library/...`), not the logical `/System/Library/...` path `ps` reports, so anchoring on the latter would have left Safari alerting on ordinary browsing; and Chrome's helper path carries the browser version, so it needs a wildcard or the exclusion breaks on every update.

## Target Ruleset
endpoint

## Target Rule Type
Event Correlation (EQL)

## Tested ECS Version
Tested for real against a live Elastic Defend agent (9.4.1) on macOS 26 (arm64), not simulated. See the captured events below.

## Query

```eql
network where host.os.type == "macos" and event.action == "connection_attempted" and event.type == "start" and
destination.port == 443 and
cidrMatch(destination.ip, "1.1.1.1/32", "1.0.0.1/32", "8.8.8.8/32", "8.8.4.4/32", "9.9.9.9/32", "149.112.112.112/32") and
not (
process.code_signature.trusted == true and
(
(process.code_signature.signing_id == "com.apple.WebKit.Networking" and
process.executable like "*/System/Library/Frameworks/WebKit.framework/*/XPCServices/com.apple.WebKit.Networking.xpc/Contents/MacOS/com.apple.WebKit.Networking") or
(process.code_signature.signing_id == "com.google.Chrome.helper" and
process.executable like "/Applications/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/*/Helpers/Google Chrome Helper.app/Contents/MacOS/Google Chrome Helper") or
(process.code_signature.signing_id == "org.mozilla.firefox" and
process.executable == "/Applications/Firefox.app/Contents/MacOS/firefox")
)
)
```

## New fields required in ECS/data sources for this rule?
None. Standard `destination.ip`/`destination.port`/`process.code_signature.signing_id`/`trusted` and `process.executable` ECS fields.

## Related issues or PRs
#6612

## References
- https://attack.mitre.org/techniques/T1071/004/
- https://attack.mitre.org/techniques/T1572/
- https://blog.netlab.360.com/an-analysis-of-godlua-backdoor-en/
- https://github.com/SpiderLabs/DoHC2

## Redacted Example Data

Real true positive, `curl` (non-browser, matches):
```json
{
"event": { "action": ["connection_attempted", "disconnect_received"], "type": ["start", "end"], "category": ["network"] },
"host": { "os": { "type": "macos" } },
"process": {
"name": "curl",
"executable": "/usr/bin/curl",
"code_signature": { "signing_id": "com.apple.curl", "trusted": true }
},
"destination": { "ip": "1.1.1.1", "port": 443 }
}
```

Real negative control, Chrome (excluded):
```json
{
"event": { "action": ["connection_attempted"], "type": ["start"], "category": ["network"] },
"host": { "os": { "type": "macos" } },
"process": {
"name": "Google Chrome Helper",
"code_signature": { "signing_id": "com.google.Chrome.helper", "trusted": true }
},
"destination": { "ip": "1.1.1.1", "port": 443 }
}
```

Real negative control, Safari/WebKit (excluded):
```json
{
"event": { "action": ["connection_attempted"], "type": ["start"], "category": ["network"] },
"host": { "os": { "type": "macos" } },
"process": {
"name": "com.apple.WebKit.Networking",
"code_signature": { "signing_id": "com.apple.WebKit.Networking", "trusted": true }
},
"destination": { "ip": "1.1.1.1", "port": 443 }
}
```

Real negative control, Firefox (excluded):
```json
{
"event": { "action": ["connection_attempted"], "type": ["start"], "category": ["network"] },
"host": { "os": { "type": "macos" } },
"process": {
"name": "firefox",
"code_signature": { "signing_id": "org.mozilla.firefox", "trusted": true }
},
"destination": { "ip": "1.1.1.1", "port": 443 }
}
```

Contributor guide

Open the contributing guide

Research direction

Start with the EQL query and the captured Elastic Defend events in this issue, comparing the true-positive curl event with the Chrome, Safari/WebKit, and Firefox exclusions. Verify the macOS connection event fields, resolver IPs, trusted signing identities, and executable patterns; done means the rule detects non-browser connections without alerting on the documented browser processes.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos
Domain
security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.