Skip to content

[Bug]: dns_security_scanner tool relies on the system DNS resolver which may strip DNSSEC data #5112

@UNakade

Description

@UNakade

Describe the Bug

The _check_dnssec function in tools/src/aden_tools/tools/dns_security_scanner/dns_security_scanner.py is unreliable because it depends on the default system resolver, which often strips DNSSEC data or fails to forward it. Additionally, the function only checks for the existence of DNSKEY records, which is insufficient to verify that the chain of trust has been validated.

This leads to two main issues:

  1. False Positives: The tool might report "Enabled" just because DNSKEY records exist, even if the resolver did not validate the signatures (no AD flag).
  2. False Negatives: The tool might report "Disabled" if the local resolver strips DNSSEC records, even for a signed domain.

To Reproduce

If your default system resolver does not support DNSSEC (try dig ietf.org +dnssec and look for the RRSIG entry), the following code will give an incorrect response for the ietf.org domain:

import dns.resolver
from tools.src.aden_tools.tools.dns_security_scanner import dns_security_scanner

domain = 'ietf.org'
resolver = dns.resolver.Resolver()
print(dns_security_scanner._check_dnssec(resolver, domain))

will result in:

{'enabled': False, 'issues': ['DNSSEC not enabled. The domain is vulnerable to DNS spoofing and cache poisoning.']}

If you instead use a resolver that can return DNSKEY information but strips the Authenticated Data (AD) flag, you cannot be sure that the response is authenticated. For example:

import dns.resolver
import dns.flags
from tools.src.aden_tools.tools.dns_security_scanner import dns_security_scanner

domain = 'ietf.org'
resolver = dns.resolver.Resolver()
resolver.nameservers = ['4.2.2.1']
response = resolver.resolve(domain, 'DNSKEY')
print(f"AD flag exists: {bool(response.response.flags & dns.flags.AD)}")
print('_check_dnssec result:', dns_security_scanner._check_dnssec(resolver, domain))

will result in

AD flag exists: False
_check_dnssec result: {'enabled': True, 'issues': []}

Expected Behavior

The tool should reliably detect DNSSEC validation status. To do this, it should:

  1. Configure the resolver to request DNSSEC data (DO bit).
  2. Use a resolver known to support validation (or check if the system resolver supports it).
  3. Verify the Authenticated Data (AD) flag in the response, not just the existence of DNSKEY.

Environment

  • OS: Ubuntu 24.04
  • Python version: 3.11.14
  • Docker version: N/A

Configuration

N/A - This is a logic issue in the dns_security_scanner tool.

Logs

N/A

Additional Context

The current _check_dnssec implementation provides a false sense of security by checking for record existence rather than validation status. The primary fix should be ensuring we are using a validating resolver path and checking the AD flag.

Proposed solution

import dns.resolver
import dns.flags

domain = 'ietf.org'
resolver = dns.resolver.Resolver()

# Use DNS nameservers known for validating data
resolver.nameservers = ['8.8.8.8', '1.1.1.1']

# Use the Extension mechanism for DNS (EDNS) to request for DNSSEC validation and 
# to increase the data packet size limit to 4096 Bytes from 512
resolver.use_edns(0, dns.flags.DO, 4096)

# Start of Authority (SOA) records are mandatory, so we can rely on their existence.
response = resolver.resolve(domain, 'SOA')

print(f"AD flag exists: {bool(response.response.flags & dns.flags.AD)}")

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions