]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Test that fake child delegation cannot overwrite parent's glue RR
authorPetr Špaček <pspacek@isc.org>
Wed, 23 Jul 2025 18:26:43 +0000 (20:26 +0200)
committerMichał Kępień <michal@isc.org>
Mon, 22 Dec 2025 10:58:39 +0000 (11:58 +0100)
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ń <michal@isc.org>
bin/tests/system/bailiwick/ans2/ans.py
bin/tests/system/bailiwick/tests_bailiwick.py

index d0ddccbe62db8479e33bc90b8499e8b9fcc9f46f..d1627fd5bd621891f648202ab8eae75d299754a6 100644 (file)
@@ -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()
 
index 644fe5f24afb66c7bf6eee5fe92a673a23a12f71..2e1c845a2202caf4cecf85ec9aad20dff19bf875 100644 (file)
@@ -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)