From: Petr Špaček Date: Wed, 23 Jul 2025 18:26:43 +0000 (+0200) Subject: Test that fake child delegation cannot overwrite parent's glue RR X-Git-Tag: v9.21.17~14^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b5dc46fe6e0e8f05767377ae171c043ed72552d6;p=thirdparty%2Fbind9.git Test that fake child delegation cannot overwrite parent's glue RR In short, the attacker tries to spoof at least one answer that has the following form: rcode NOERROR flags QR ;QUESTION trigger$RANDOM.victim. IN TXT ;ANSWER ;AUTHORITY trigger$RANDOM.victim. 3600 IN NS ns.victim. ;ADDITIONAL ns.victim. 3600 IN A 10.53.0.3 This attack was originally reported as "test case 2". Co-authored-by: Michał Kępień --- diff --git a/bin/tests/system/bailiwick/ans2/ans.py b/bin/tests/system/bailiwick/ans2/ans.py index d0ddccbe62d..d1627fd5bd6 100644 --- a/bin/tests/system/bailiwick/ans2/ans.py +++ b/bin/tests/system/bailiwick/ans2/ans.py @@ -55,6 +55,28 @@ class UnsolicitedNsSpoofer(ResponseSpoofer, mode="unsolicited-ns"): yield DnsResponseSend(response, authoritative=True) +class ParentGlueSpoofer(ResponseSpoofer, mode="parent-glue"): + + qname = "trigger.victim." + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + response = qctx.prepare_new_response(with_zone_data=False) + + ns_rrset = dns.rrset.from_text( + "trigger.victim.", TTL, qctx.qclass, dns.rdatatype.NS, "ns.victim." + ) + response.authority.append(ns_rrset) + + glue_rrset = dns.rrset.from_text( + "ns.victim.", TTL, qctx.qclass, dns.rdatatype.A, ATTACKER_IP + ) + response.additional.append(glue_rrset) + + yield DnsResponseSend(response, authoritative=False) + + def main() -> None: spoofing_server().run() diff --git a/bin/tests/system/bailiwick/tests_bailiwick.py b/bin/tests/system/bailiwick/tests_bailiwick.py index 644fe5f24af..2e1c845a220 100644 --- a/bin/tests/system/bailiwick/tests_bailiwick.py +++ b/bin/tests/system/bailiwick/tests_bailiwick.py @@ -11,6 +11,8 @@ from typing import Dict +import time + import dns.message import pytest @@ -94,3 +96,16 @@ def test_bailiwick_unsolicited_authority(servers: Dict[str, NamedInstance]) -> N prime_cache(ns4) send_trigger_query(ns4, "trigger.victim.") check_domain_hijack(ns4) + + +def test_bailiwick_parent_glue(servers: Dict[str, NamedInstance]) -> None: + set_spoofing_mode(ans1="none", ans2="parent-glue") + + ns4 = servers["ns4"] + prime_cache(ns4) + send_trigger_query(ns4, "trigger.victim.") + + isctest.log.info("Waiting 61 seconds for the ns.victim. ADB entry to expire") + time.sleep(61) + + check_domain_hijack(ns4)