unbound: Fix CVE-2025-11411

Backport complete patch to fix CVE-2025-11411

The existing scarthgap patch is a partial backport with hardcoded logic,
causing incorrect behavior and ptest failures. Backport the full upstream
fix along with the follow-up patch to ensure correct functionality.

Add below patch to fix
0001-CVE-2025-11411-1.patch
0002-CVE-2025-11411-2.patch

Signed-off-by: Jackson James <jacksonj2@kpit.com>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
Jackson James 2026-04-10 12:11:12 +05:30 committed by Anuj Mittal
parent 07c2b52840
commit fc30bb5eed
4 changed files with 2029 additions and 49 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
From f6269baa605d31859f28770e01a24e3677e5f82c Mon Sep 17 00:00:00 2001
From: Yorgos Thessalonikefs <yorgos@nlnetlabs.nl>
Date: Wed, 26 Nov 2025 11:09:40 +0100
Subject: [PATCH] - Additional fix for CVE-2025-11411 (possible domain
hijacking attack), to include YXDOMAIN and non-referral nodata answers in
the mitigation as well, reported by TaoFei Guo from Peking University, Yang
Luo and JianJun Chen from Tsinghua University.
CVE: CVE-2025-11411
Upstream-Status: Backport [https://github.com/NLnetLabs/unbound/commit/f6269baa605d31859f28770e01a24e3677e5f82c]
Comment: Patch refreshed
Signed-off-by: Jackson James <jacksonj2@kpit.com>
---
iterator/iter_scrub.c | 39 +++++++++++++++++++++---
testdata/ratelimit.tdir/ratelimit.testns | 30 ++++++++++++++----
2 files changed, 59 insertions(+), 10 deletions(-)
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
index cc12f97..02f1b48 100644
--- a/iterator/iter_scrub.c
+++ b/iterator/iter_scrub.c
@@ -377,19 +377,21 @@ type_allowed_in_additional_section(uint16_t tp)
* @param qinfo: original query.
* @param region: where to allocate synthesized CNAMEs.
* @param env: module env with config options.
+ * @param zonename: name of server zone.
* @return 0 on error.
*/
static int
scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, struct regional* region,
- struct module_env* env)
+ struct module_env* env, uint8_t* zonename)
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
struct rrset_parse* rrset, *prev, *nsset=NULL;
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
- FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
+ FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN &&
+ FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_YXDOMAIN)
return 1;
/* For the ANSWER section, remove all "irrelevant" records and add
@@ -418,6 +420,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
&aliaslen, pkt)) {
verbose(VERB_ALGO, "synthesized CNAME "
"too long");
+ if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) {
+ prev = rrset;
+ rrset = rrset->rrset_all_next;
+ continue;
+ }
return 0;
}
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
@@ -587,6 +594,29 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
+ /* Also delete promiscuous NS for other RCODEs */
+ if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR
+ && env->cfg->iter_scrub_promiscuous) {
+ remove_rrset("normalize: removing promiscuous "
+ "RRset:", pkt, msg, prev, &rrset);
+ continue;
+ }
+ /* Also delete promiscuous NS for NOERROR with nodata
+ * for authoritative answers, not for delegations.
+ * NOERROR with an_rrsets!=0 already handled.
+ * Also NOERROR and soa_in_auth already handled.
+ * NOERROR with an_rrsets==0, and not a referral.
+ * referral is (NS not the zonename, noSOA).
+ */
+ if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR
+ && msg->an_rrsets == 0
+ && !(dname_pkt_compare(pkt, rrset->dname,
+ zonename) != 0 && !soa_in_auth(msg))
+ && env->cfg->iter_scrub_promiscuous) {
+ remove_rrset("normalize: removing promiscuous "
+ "RRset:", pkt, msg, prev, &rrset);
+ continue;
+ }
if(nsset == NULL) {
nsset = rrset;
} else {
@@ -947,7 +977,8 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
/* this is not required for basic operation but is a forgery
* resistance (security) feature */
if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR ||
- FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) &&
+ FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN ||
+ FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) &&
msg->qdcount == 0)
return 0;
@@ -961,7 +992,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
}
/* normalize the response, this cleans up the additional. */
- if(!scrub_normalize(pkt, msg, qinfo, region, env))
+ if(!scrub_normalize(pkt, msg, qinfo, region, env, zonename))
return 0;
/* delete all out-of-zone information */
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
diff --git a/testdata/ratelimit.tdir/ratelimit.testns b/testdata/ratelimit.tdir/ratelimit.testns
index 563c1db..5c22c29 100644
--- a/testdata/ratelimit.tdir/ratelimit.testns
+++ b/testdata/ratelimit.tdir/ratelimit.testns
@@ -3,13 +3,31 @@ $ORIGIN example.com.
$TTL 3600
ENTRY_BEGIN
-MATCH opcode qtype
+MATCH opcode qname qtype
REPLY QR AA NOERROR
-ADJUST copy_id copy_query
+ADJUST copy_id
SECTION QUESTION
-wild IN A
+www1 IN A
SECTION ANSWER
-wild IN A 10.20.30.40
-SECTION AUTHORITY
-example.com. IN NS ns.example.com.
+www1 IN A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+www2 IN A
+SECTION ANSWER
+www2 IN A 2.2.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+www3 IN A
+SECTION ANSWER
+www3 IN A 3.3.3.3
ENTRY_END
--
2.34.1

View File

@ -1,48 +0,0 @@
From 98fac0b396e1e85a6345baa59fc178b1f51759b8 Mon Sep 17 00:00:00 2001
From: Patrick Vogelaar <patrick.vogelaar@belden.com>
Date: Wed, 29 Oct 2025 13:33:23 +0100
Subject: [PATCH] Fix CVE-2025-11411 (possible domain hijacking attack)
This fixes CVE-2025-11411 by applying the minimal patch [1] listed in [2]
[1] https://nlnetlabs.nl/downloads/unbound/patch_CVE-2025-11411.diff
[2] https://www.nlnetlabs.nl/downloads/unbound/CVE-2025-11411.txt
CVE: CVE-2025-11411
Upstream-Status: Backport [minimal backport of https://github.com/NLnetLabs/unbound/commit/a33f0638e1dacf2633cf2292078a674576bca852]
Signed-off-by: Patrick Vogelaar <patrick.vogelaar@belden.com>
---
iterator/iter_scrub.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
index 48867e50..5beaa048 100644
--- a/iterator/iter_scrub.c
+++ b/iterator/iter_scrub.c
@@ -571,6 +571,22 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
+ /* If the NS set is a promiscuous NS set, scrub that
+ * to remove potential for poisonous contents that
+ * affects other names in the same zone. Remove
+ * promiscuous NS sets in positive answers, that
+ * thus have records in the answer section. Nodata
+ * and nxdomain promiscuous NS sets have been removed
+ * already. Since the NS rrset is scrubbed, its
+ * address records are also not marked to be allowed
+ * and are removed later. */
+ if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR &&
+ msg->an_rrsets != 0 &&
+ 1 /* env->cfg->iter_scrub_promiscuous */) {
+ remove_rrset("normalize: removing promiscuous "
+ "RRset:", pkt, msg, prev, &rrset);
+ continue;
+ }
if(nsset == NULL) {
nsset = rrset;
} else {
--
2.34.1

View File

@ -12,7 +12,8 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=5308494bc0590c0cb036afd781d78f06"
SRC_URI = "git://github.com/NLnetLabs/unbound.git;protocol=https;nobranch=1 \
file://CVE-2024-8508.patch \
file://CVE-2024-33655.patch \
file://CVE-2025-11411.patch \
file://0001-CVE-2025-11411-1.patch \
file://0002-CVE-2025-11411-2.patch \
file://CVE-2024-43167.patch \
file://CVE-2024-43168_1.patch \
file://CVE-2024-43168_2.patch \