mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-04-06 02:58:15 +00:00
feat(cloudflare): expand wildcard check to include MX and SRV records
Wildcard MX records can allow mail interception for arbitrary subdomains. Wildcard SRV records can expose services on any subdomain.
This commit is contained in:
@@ -9,8 +9,8 @@
|
||||
"Severity": "medium",
|
||||
"ResourceType": "DNSRecord",
|
||||
"ResourceGroup": "network",
|
||||
"Description": "**Cloudflare DNS records** are assessed for **wildcard usage** by checking if A, AAAA, or CNAME records use wildcard entries (*.example.com) which can **increase attack surface** and expose unintended services.",
|
||||
"Risk": "**Wildcard DNS records** can expose unintended services and increase attack surface.\n- **Confidentiality**: any subdomain resolves, potentially exposing internal naming conventions\n- **Integrity**: attackers can access unintended services via arbitrary subdomains\n- **Availability**: wildcard records may route traffic to services not designed for public access",
|
||||
"Description": "**Cloudflare DNS records** are assessed for **wildcard usage** by checking if A, AAAA, CNAME, MX, or SRV records use wildcard entries (*.example.com) which can **increase attack surface**, expose unintended services, or allow mail interception.",
|
||||
"Risk": "**Wildcard DNS records** can expose unintended services and increase attack surface.\n- **Confidentiality**: any subdomain resolves, potentially exposing internal naming conventions; wildcard MX allows mail interception\n- **Integrity**: attackers can access unintended services via arbitrary subdomains\n- **Availability**: wildcard records may route traffic or services not designed for public access",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/"
|
||||
@@ -32,5 +32,5 @@
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Wildcard DNS records (*.example.com) cause any subdomain query to resolve. While useful for some applications, they can expose services unintentionally and make subdomain enumeration easier for attackers."
|
||||
"Notes": "Wildcard DNS records (*.example.com) cause any subdomain query to resolve. While useful for some applications, they can expose services unintentionally and make subdomain enumeration easier for attackers. Wildcard MX records can accept mail for any subdomain, and wildcard SRV records can expose services on arbitrary subdomains."
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
from prowler.lib.check.models import Check, CheckReportCloudflare
|
||||
from prowler.providers.cloudflare.services.dns.dns_client import dns_client
|
||||
|
||||
# Record types where wildcards pose security risks:
|
||||
# - A, AAAA: Wildcard resolves any subdomain to an IP, exposing services
|
||||
# - CNAME: Wildcard aliases any subdomain, potential for subdomain takeover
|
||||
# - MX: Wildcard accepts mail for any subdomain, potential mail interception
|
||||
# - SRV: Wildcard exposes services on any subdomain
|
||||
WILDCARD_RISK_TYPES = {"A", "AAAA", "CNAME", "MX", "SRV"}
|
||||
|
||||
|
||||
class dns_record_no_wildcard(Check):
|
||||
"""Ensure that wildcard DNS records are not configured for the zone.
|
||||
@@ -9,15 +16,16 @@ class dns_record_no_wildcard(Check):
|
||||
an explicit record, which can unintentionally expose services or create
|
||||
security risks. Attackers may discover hidden services, and wildcard
|
||||
certificates combined with wildcard DNS can increase the attack surface
|
||||
for subdomain takeover vulnerabilities.
|
||||
for subdomain takeover vulnerabilities. Wildcard MX records can allow
|
||||
mail interception for arbitrary subdomains.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[CheckReportCloudflare]:
|
||||
"""Execute the wildcard DNS record check.
|
||||
|
||||
Iterates through all A, AAAA, and CNAME DNS records and identifies
|
||||
those configured as wildcard records (starting with *.). Wildcard
|
||||
records may expose unintended services.
|
||||
Iterates through all security-relevant DNS records (A, AAAA, CNAME, MX, SRV)
|
||||
and identifies those configured as wildcard records (starting with *.).
|
||||
Wildcard records may expose unintended services or create security risks.
|
||||
|
||||
Returns:
|
||||
A list of CheckReportCloudflare objects with PASS status if the
|
||||
@@ -26,8 +34,8 @@ class dns_record_no_wildcard(Check):
|
||||
findings = []
|
||||
|
||||
for record in dns_client.records:
|
||||
# Only check A, AAAA, and CNAME records for wildcards
|
||||
if record.type not in ("A", "AAAA", "CNAME"):
|
||||
# Check record types where wildcards pose security risks
|
||||
if record.type not in WILDCARD_RISK_TYPES:
|
||||
continue
|
||||
|
||||
report = CheckReportCloudflare(
|
||||
|
||||
@@ -244,3 +244,102 @@ class Test_dns_record_no_wildcard:
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "is not a wildcard record" in result[0].status_extended
|
||||
|
||||
def test_mx_record_wildcard(self):
|
||||
dns_client = mock.MagicMock
|
||||
dns_client.records = [
|
||||
CloudflareDNSRecord(
|
||||
id="record-1",
|
||||
zone_id=ZONE_ID,
|
||||
zone_name=ZONE_NAME,
|
||||
name="*.example.com",
|
||||
type="MX",
|
||||
content="10 mail.example.com",
|
||||
)
|
||||
]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_cloudflare_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.cloudflare.services.dns.dns_record_no_wildcard.dns_record_no_wildcard.dns_client",
|
||||
new=dns_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.cloudflare.services.dns.dns_record_no_wildcard.dns_record_no_wildcard import (
|
||||
dns_record_no_wildcard,
|
||||
)
|
||||
|
||||
check = dns_record_no_wildcard()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "is a wildcard record" in result[0].status_extended
|
||||
|
||||
def test_mx_record_not_wildcard(self):
|
||||
dns_client = mock.MagicMock
|
||||
dns_client.records = [
|
||||
CloudflareDNSRecord(
|
||||
id="record-1",
|
||||
zone_id=ZONE_ID,
|
||||
zone_name=ZONE_NAME,
|
||||
name="example.com",
|
||||
type="MX",
|
||||
content="10 mail.example.com",
|
||||
)
|
||||
]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_cloudflare_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.cloudflare.services.dns.dns_record_no_wildcard.dns_record_no_wildcard.dns_client",
|
||||
new=dns_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.cloudflare.services.dns.dns_record_no_wildcard.dns_record_no_wildcard import (
|
||||
dns_record_no_wildcard,
|
||||
)
|
||||
|
||||
check = dns_record_no_wildcard()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "is not a wildcard record" in result[0].status_extended
|
||||
|
||||
def test_srv_record_wildcard(self):
|
||||
dns_client = mock.MagicMock
|
||||
dns_client.records = [
|
||||
CloudflareDNSRecord(
|
||||
id="record-1",
|
||||
zone_id=ZONE_ID,
|
||||
zone_name=ZONE_NAME,
|
||||
name="*._tcp.example.com",
|
||||
type="SRV",
|
||||
content="10 5 5060 sip.example.com",
|
||||
)
|
||||
]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_cloudflare_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.cloudflare.services.dns.dns_record_no_wildcard.dns_record_no_wildcard.dns_client",
|
||||
new=dns_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.cloudflare.services.dns.dns_record_no_wildcard.dns_record_no_wildcard import (
|
||||
dns_record_no_wildcard,
|
||||
)
|
||||
|
||||
check = dns_record_no_wildcard()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "is a wildcard record" in result[0].status_extended
|
||||
|
||||
Reference in New Issue
Block a user