-
Notifications
You must be signed in to change notification settings - Fork 696
[New Rule] Multiple DHCP Servers Responding to the Same Transaction #6263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+144
−0
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
cba766c
Multiple DHCP Servers Responding to the Same Transaction
eric-forte-elastic 2fc4d24
working RTA update maturity
eric-forte-elastic a68be9c
Add Windows OS tag
eric-forte-elastic 06e93f5
remove Windows specific language
eric-forte-elastic 37f08eb
Merge branch 'patch_tuesday_net_coverage' of https://github.com/elast…
eric-forte-elastic fbeda19
remove Windows tag
eric-forte-elastic 2e55b07
Update MITRE info
eric-forte-elastic 577d67b
remove duplicate ref
eric-forte-elastic 90cf264
Merge branch 'main' into patch_tuesday_net_coverage
eric-forte-elastic File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
144 changes: 144 additions & 0 deletions
144
rules/network/credential_access_dhcp_multiple_servers_same_transaction.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| [metadata] | ||
| creation_date = "2026/06/09" | ||
| integration = ["network_traffic"] | ||
| maturity = "production" | ||
| updated_date = "2026/06/09" | ||
|
|
||
| [rule] | ||
| author = ["Elastic"] | ||
| description = """ | ||
| Identifies two or more distinct DHCP servers sending an OFFER or ACK for the same transaction ID (xid) within a short | ||
| window, indicating a rogue DHCP server racing the legitimate one to win the client's handshake. This is the rogue-DHCP / | ||
| adversary-in-the-middle precondition (T1557.003) and is operating-system agnostic, since it keys only on server behavior | ||
| observed on the wire. Winning the race lets an attacker intercept traffic via a hostile gateway/DNS, bypass a VPN | ||
| (TunnelVision), or deliver a malformed response that exploits the client's DHCP parser for code execution. | ||
| """ | ||
| from = "now-9m" | ||
| language = "esql" | ||
| license = "Elastic License v2" | ||
| name = "Multiple DHCP Servers Responding to the Same Transaction" | ||
| note = """## Triage and analysis | ||
|
|
||
| > **Disclaimer**: | ||
| > This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs. | ||
|
|
||
| ### Investigating Multiple DHCP Servers Responding to the Same Transaction | ||
|
|
||
| DHCP is plaintext UDP and fully visible to any sensor on the broadcast segment. A rogue server (or an injected response | ||
| on the victim's L2 broadcast domain) that answers a transaction the legitimate server already owns is the defining | ||
| precondition for DHCP-based adversary-in-the-middle and for malformed-option client exploits. This rule flags exactly | ||
| that: two or more distinct server source IPs producing an OFFER/ACK for one transaction ID inside the same 30-second | ||
| window, and is operating-system agnostic, since it keys only on server behavior observed on the wire. | ||
|
|
||
| ### Possible investigation steps | ||
|
|
||
| - Identify the server source IPs in `Esql.values_server_ips` and `Esql.values_server_identifiers`. Determine which is | ||
| the sanctioned DHCP server and which is unexpected. | ||
| - Locate the rogue server on the segment (switch CAM/ARP tables, port, VLAN). It is on the same broadcast domain as the | ||
| victim by definition. | ||
| - Inspect the rogue OFFER/ACK options for an oversized or malformed payload (the overflow trigger) and for hostile | ||
| configuration such as an attacker-controlled default gateway (option 3), DNS server (option 6), WPAD/proxy | ||
| auto-config (option 252), or classless static routes (option 121, TunnelVision-style VPN bypass). | ||
| - Identify the client(s) acquiring leases on the segment (any OS, including Windows, Linux, macOS, iOS, IoT) and review their | ||
| endpoint telemetry for DHCP client service crashes, unexpected route/DNS/gateway changes, or follow-on code execution. | ||
| Where the target OS and DHCP client are known, check whether they are unpatched for the relevant CVE (e.g. | ||
| CVE-2026-44815 on Windows, CVE-2018-5732 on ISC dhclient). | ||
|
|
||
| ### False positive analysis | ||
|
|
||
| - DHCP failover pairs (Microsoft or ISC) are designed so that, for a given transaction, only one peer answers; two | ||
| peers answering the same xid within 30 seconds is not normal failover behavior. If a known active-active or | ||
| load-balancing architecture genuinely does this, add its server IPs to an exception. | ||
| - DHCP relay agents forward responses but the relayed source is the relay, and a single server still owns each | ||
| transaction. Anycast/VIP DHCP designs that present multiple real backend IPs on the wire are rare and would be a known | ||
| architectural fact, which can be excepted by those IPs. | ||
|
|
||
| ### Response and remediation | ||
|
|
||
| - Remove the rogue DHCP server from the segment, then patch the affected client DHCP stacks (e.g. June 2026 Patch | ||
| Tuesday for CVE-2026-44815 on Windows, or the fixed ISC dhclient for CVE-2018-5732 on Linux/Unix). | ||
| - Enable DHCP snooping on managed switches and restrict DHCP server responses to authorized server ports/MACs as a | ||
| compensating control, which protects clients of every OS and also mitigates TunnelVision-style route injection. | ||
| """ | ||
| references = [ | ||
| "https://nvd.nist.gov/vuln/detail/CVE-2026-44815", | ||
| "https://nvd.nist.gov/vuln/detail/CVE-2024-3661", | ||
| "https://www.leviathansecurity.com/blog/tunnelvision", | ||
| "https://nvd.nist.gov/vuln/detail/CVE-2018-5732", | ||
| "https://msrc.microsoft.com/update-guide", | ||
| ] | ||
| risk_score = 73 | ||
| rule_id = "44b8d933-8fed-485d-a0af-bd97d0093439" | ||
| setup = """## Setup | ||
|
|
||
| This rule requires the Elastic network_traffic (Packetbeat) integration capturing DHCP (UDP 67/68) on the broadcast | ||
| segment where clients acquire/renew leases, either Packetbeat running on the segment or a SPAN/mirror feeding it. A | ||
| sensor not on the same L2 broadcast domain (or not behind the relevant DHCP relay) will not observe competing OFFER/ACK | ||
| packets. | ||
|
|
||
| Zeek is intentionally not supported: the zeek.dhcp data stream does not expose a transaction ID and aggregates a full | ||
| DORA exchange into one record, so the per-transaction server-count comparison cannot be expressed on it. | ||
| """ | ||
| severity = "high" | ||
| tags = [ | ||
| "Domain: Network", | ||
| "Domain: Endpoint", | ||
| "Use Case: Threat Detection", | ||
| "Use Case: Vulnerability", | ||
| "Use Case: Network Security Monitoring", | ||
| "Tactic: Credential Access", | ||
| "Tactic: Execution", | ||
| "Data Source: Network Traffic", | ||
| "Resources: Investigation Guide", | ||
| ] | ||
| timestamp_override = "event.ingested" | ||
| type = "esql" | ||
|
|
||
| query = ''' | ||
| from logs-network_traffic.dhcpv4-*, packetbeat-* | ||
| | eval | ||
| message_type = TO_LOWER(COALESCE(network_traffic.dhcpv4.option.message_type, dhcpv4.option.message_type)), | ||
| Esql.transaction_id = COALESCE(network_traffic.dhcpv4.transaction_id, dhcpv4.transaction_id), | ||
| server_identifier = COALESCE(network_traffic.dhcpv4.option.server_identifier, dhcpv4.option.server_identifier) | ||
| | where message_type in ("offer", "ack") and Esql.transaction_id is not null and source.ip is not null | ||
| | eval Esql.time_window = DATE_TRUNC(30 seconds, @timestamp) | ||
| | stats | ||
| Esql.count_distinct_servers = COUNT_DISTINCT(source.ip), | ||
| Esql.values_server_ips = VALUES(source.ip), | ||
| Esql.values_server_identifiers = VALUES(server_identifier), | ||
| Esql.count_replies = COUNT(*) | ||
| by Esql.time_window, Esql.transaction_id | ||
| | where Esql.count_distinct_servers >= 2 | ||
| | keep Esql.transaction_id, Esql.time_window, Esql.count_distinct_servers, Esql.values_server_ips, Esql.values_server_identifiers, Esql.count_replies | ||
| ''' | ||
|
|
||
|
|
||
| [[rule.threat]] | ||
| framework = "MITRE ATT&CK" | ||
| [[rule.threat.technique]] | ||
| id = "T1557" | ||
| name = "Adversary-in-the-Middle" | ||
| reference = "https://attack.mitre.org/techniques/T1557/" | ||
| [[rule.threat.technique.subtechnique]] | ||
| id = "T1557.003" | ||
| name = "DHCP Spoofing" | ||
| reference = "https://attack.mitre.org/techniques/T1557/003/" | ||
|
|
||
|
|
||
| [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 = "T1203" | ||
| name = "Exploitation for Client Execution" | ||
| reference = "https://attack.mitre.org/techniques/T1203/" | ||
|
|
||
|
|
||
| [rule.threat.tactic] | ||
| id = "TA0002" | ||
| name = "Execution" | ||
| reference = "https://attack.mitre.org/tactics/TA0002/" | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.