Repository navigation
Add DNS PTR-Based Host Discovery Detection - #4332
MehrabBakhtar wants to merge 3 commits into
Conversation
| status: experimental | ||
| type: Anomaly | ||
| description: This detection identifies source systems generating a high number of unique DNS PTR queries, which may indicate host discovery or reverse DNS reconnaissance. This activity may be associated with tools such as Nmap when reverse DNS lookups are performed for discovered or scanned hosts. | ||
| data_source: [] |
There was a problem hiding this comment.
We require a data source to be used here except in edge cases. What data did you test against?
There was a problem hiding this comment.
I tested the detection using Windows DNS logs (MSAD:NT6:DNS). I couldn't find a matching data source definition in the repository, so I've uploaded sanitized JSON log samples for review.
The detection can also work with Zeek DNS and Stream DNS logs, provided the required fields are mapped to the Network_Resolution data model.
The goal is to identify a high number of distinct PTR queries generated by a single source. Nmap may perform reverse DNS lookups during host discovery, making this behavior useful for detecting potential network reconnaissance when appropriate thresholds and noise filtering are applied.
| tests: | ||
| - name: Manual Validation | ||
| description: Manually validate that a source generating at least 80 unique DNS PTR queries is returned by the detection. | ||
| test_type: experimental | ||
| attack_data: [] |
There was a problem hiding this comment.
We discourage having rules without data. Please upload your test data to https://github.com/splunk/attack_data and link it here.
Else, upload the log samples here and we will take care of it.
There was a problem hiding this comment.
Here are sample log events showing the burst of PTR queries generated during host discovery:
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"236.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"235.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"234.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"237.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"238.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"243.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"250.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"221.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"248.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"11.30.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"253.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"3.30.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"1.30.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"245.29.16.172.in-addr.arpa","record_type":"PTR"}}
| references: | ||
| - https://attack.mitre.org/techniques/T1018/ |
There was a problem hiding this comment.
We highly recommend putting useful references where possible. Could link to some public reference that talk about PTR/Attacks in that sense?
There was a problem hiding this comment.
references:
Added the official Nmap DNS Resolution documentation (https://nmap.org/book/host-discovery-dns.html). This confirms that Nmap, by default, initiates a reverse-DNS PTR query for every host that responds to host discovery probes. This effectively pairs each discovery attempt with a corresponding resolution request, creating the predictable pattern that this detection is designed to identify.
| description: This detection identifies source systems generating a high number of unique DNS PTR queries, which may indicate host discovery or reverse DNS reconnaissance. This activity may be associated with tools such as Nmap when reverse DNS lookups are performed for discovered or scanned hosts. | ||
| data_source: [] | ||
| search: |- | ||
| | tstats `security_content_summariesonly` min(_time) as firsttime max(_time) as lasttime dc(DNS.query) AS unique_queries FROM datamodel=Network_Resolution WHERE DNS.record_type="PTR" BY DNS.src |
There was a problem hiding this comment.
The output will contain src and queries, try and bring other useful to the output as well.
There was a problem hiding this comment.
The detection uses a threshold of 80 unique PTR queries per source to identify potential host discovery activity.
I avoided collecting all queried DNS names by default to keep the search efficient, as values(DNS.query) may increase resource usage and result size.
However, if you believe displaying the queried names would be more useful, we can modify the query as follows:
| tstats security_content_summariesonly min(_time) as firsttime max(_time) as lasttime dc(DNS.query) AS unique_queries values(DNS.query) as all_dns_queries FROM datamodel=Network_Resolution WHERE DNS.record_type="PTR" BY DNS.src
I'm happy to adjust the output based on your preference.
Co-authored-by: Nasreddine Bencherchali <nbencher@cisco.com>
MehrabBakhtar
left a comment
There was a problem hiding this comment.
Hi! This is my very first contribution to this project, so I really appreciate your patience and help.
I've addressed the feedback and updated the references and log samples. Looking forward to your next comments/feedback!
| status: experimental | ||
| type: Anomaly | ||
| description: This detection identifies source systems generating a high number of unique DNS PTR queries, which may indicate host discovery or reverse DNS reconnaissance. This activity may be associated with tools such as Nmap when reverse DNS lookups are performed for discovered or scanned hosts. | ||
| data_source: [] |
There was a problem hiding this comment.
I tested the detection using Windows DNS logs (MSAD:NT6:DNS). I couldn't find a matching data source definition in the repository, so I've uploaded sanitized JSON log samples for review.
The detection can also work with Zeek DNS and Stream DNS logs, provided the required fields are mapped to the Network_Resolution data model.
The goal is to identify a high number of distinct PTR queries generated by a single source. Nmap may perform reverse DNS lookups during host discovery, making this behavior useful for detecting potential network reconnaissance when appropriate thresholds and noise filtering are applied.
| description: This detection identifies source systems generating a high number of unique DNS PTR queries, which may indicate host discovery or reverse DNS reconnaissance. This activity may be associated with tools such as Nmap when reverse DNS lookups are performed for discovered or scanned hosts. | ||
| data_source: [] | ||
| search: |- | ||
| | tstats `security_content_summariesonly` min(_time) as firsttime max(_time) as lasttime dc(DNS.query) AS unique_queries FROM datamodel=Network_Resolution WHERE DNS.record_type="PTR" BY DNS.src |
There was a problem hiding this comment.
The detection uses a threshold of 80 unique PTR queries per source to identify potential host discovery activity.
I avoided collecting all queried DNS names by default to keep the search efficient, as values(DNS.query) may increase resource usage and result size.
However, if you believe displaying the queried names would be more useful, we can modify the query as follows:
| tstats security_content_summariesonly min(_time) as firsttime max(_time) as lasttime dc(DNS.query) AS unique_queries values(DNS.query) as all_dns_queries FROM datamodel=Network_Resolution WHERE DNS.record_type="PTR" BY DNS.src
I'm happy to adjust the output based on your preference.
| references: | ||
| - https://attack.mitre.org/techniques/T1018/ |
There was a problem hiding this comment.
references:
Added the official Nmap DNS Resolution documentation (https://nmap.org/book/host-discovery-dns.html). This confirms that Nmap, by default, initiates a reverse-DNS PTR query for every host that responds to host discovery probes. This effectively pairs each discovery attempt with a corresponding resolution request, creating the predictable pattern that this detection is designed to identify.
| tests: | ||
| - name: Manual Validation | ||
| description: Manually validate that a source generating at least 80 unique DNS PTR queries is returned by the detection. | ||
| test_type: experimental | ||
| attack_data: [] |
There was a problem hiding this comment.
Here are sample log events showing the burst of PTR queries generated during host discovery:
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"236.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"235.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"234.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"237.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"238.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"243.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"250.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"221.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"248.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"11.30.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"253.29.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"3.30.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"1.30.16.172.in-addr.arpa","record_type":"PTR"}}
{"preview":false,"result":{"_time":"2026-10-11T11:06:24.000+0330","src":"172.19.26.167","query":"245.29.16.172.in-addr.arpa","record_type":"PTR"}}
Summary
Add a detection for potential host discovery through high-volume DNS PTR queries.
Use the Network Resolution data model with tstats.
Identify source systems generating 80 or more unique PTR queries.
Include implementation guidance, false-positive considerations, and MITRE ATT&CK mapping to T1018 (Remote System Discovery).
Testing
Validated the detection using contentctl-ng build.
Confirmed the content build completed successfully.