mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Test that positive answer cannot overwrite sibling NS RRs
Before the fixes for CVE-2025-40778, a positive answer was allowed to
overwrite sibling NS RRs. The answer had to be a positive AA=1 answer
with a fake NS along with it. This combination of conditions avoided
the code path with "unrelated <RRTYPE>" detection logic.
If it were some other answer, named from the main branch would detect
the attempt and log:
DNS format error from 10.53.0.1#16386 resolving trigger/A for <unknown>: unrelated NS victim in trigger authority section
In short, the attacker tries to spoof at least one answer that has the
following form:
opcode QUERY
rcode NOERROR
flags QR AA
;QUESTION
trigger$RANDOM. IN A
;ANSWER
trigger$RANDOM. 3600 IN A 10.53.0.3
;AUTHORITY
victim. 3600 IN NS ns.attacker.
;ADDITIONAL
ns.attacker. 3600 IN A 10.53.0.3
This attack was originally reported as "test case 1c".
Co-authored-by: Michał Kępień <michal@isc.org>
(cherry picked from commit 26eed16d61)
This commit is contained in:
parent
f5b5a94439
commit
0a00d3c2c9
2 changed files with 39 additions and 0 deletions
|
|
@ -29,6 +29,37 @@ ATTACKER_IP = "10.53.0.3"
|
|||
TTL = 3600
|
||||
|
||||
|
||||
class SiblingNsSpoofer(ResponseSpoofer, mode="sibling-ns"):
|
||||
|
||||
qname = "trigger."
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[ResponseAction, None]:
|
||||
response = qctx.prepare_new_response(with_zone_data=False)
|
||||
|
||||
txt_rrset = dns.rrset.from_text(
|
||||
qctx.qname,
|
||||
TTL,
|
||||
qctx.qclass,
|
||||
dns.rdatatype.TXT,
|
||||
'"spoofed answer with extra NS"',
|
||||
)
|
||||
response.answer.append(txt_rrset)
|
||||
|
||||
ns_rrset = dns.rrset.from_text(
|
||||
"victim.", TTL, qctx.qclass, dns.rdatatype.NS, "ns.attacker."
|
||||
)
|
||||
response.authority.append(ns_rrset)
|
||||
|
||||
a_rrset = dns.rrset.from_text(
|
||||
"ns.attacker.", TTL, qctx.qclass, dns.rdatatype.A, ATTACKER_IP
|
||||
)
|
||||
response.additional.append(a_rrset)
|
||||
|
||||
yield DnsResponseSend(response, authoritative=True)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
spoofing_server().run()
|
||||
|
||||
|
|
|
|||
|
|
@ -77,3 +77,11 @@ def check_domain_hijack(ns4: NamedInstance) -> None:
|
|||
"TXT",
|
||||
'"correct answer from the domain under attack"',
|
||||
)
|
||||
|
||||
|
||||
def test_bailiwick_sibling_ns_referral(servers: Dict[str, NamedInstance]) -> None:
|
||||
set_spoofing_mode(ans1="sibling-ns", ans2="none")
|
||||
|
||||
ns4 = servers["ns4"]
|
||||
send_trigger_query(ns4, "trigger.")
|
||||
check_domain_hijack(ns4)
|
||||
|
|
|
|||
Loading…
Reference in a new issue