mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
- Fix CVE-2026-46582, A wildcard replay, as another piece of data,
triggers poisoning in the serve expired reply path. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
This commit is contained in:
+12
-3
@@ -439,10 +439,15 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||
* only improves security status
|
||||
* and bogus is set only once, even if we rechecked the status */
|
||||
if(sec > d->security) {
|
||||
int wc_expanded = 0;
|
||||
d->security = sec;
|
||||
if(sec == sec_status_secure)
|
||||
if(sec == sec_status_secure) {
|
||||
uint8_t* wc = NULL;
|
||||
size_t wclen = 0;
|
||||
d->trust = rrset_trust_validated;
|
||||
else if(sec == sec_status_bogus) {
|
||||
if(val_rrset_wildcard(rrset, &wc, &wclen) && wc)
|
||||
wc_expanded = 1;
|
||||
} else if(sec == sec_status_bogus) {
|
||||
size_t i;
|
||||
/* update ttl for rrset to fixed value. */
|
||||
d->ttl = ve->bogus_ttl;
|
||||
@@ -455,7 +460,11 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||
lock_basic_unlock(&ve->bogus_lock);
|
||||
}
|
||||
/* if status updated - store in cache for reuse */
|
||||
rrset_update_sec_status(env->rrset_cache, rrset, *env->now);
|
||||
/* For a wildcard rrset, that is secure, do not store this
|
||||
* into the cache, because it changes proofs around the
|
||||
* item. */
|
||||
if(!wc_expanded)
|
||||
rrset_update_sec_status(env->rrset_cache, rrset, *env->now);
|
||||
}
|
||||
|
||||
return sec;
|
||||
|
||||
+30
-1
@@ -1044,6 +1044,9 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
|
||||
size_t wl;
|
||||
int wc_cached = 0;
|
||||
int wc_NSEC_ok = 0;
|
||||
/* This is used to update the RRset cache, with the combination
|
||||
* of the dname expansion and this wildcard, for security status. */
|
||||
struct ub_packed_rrset_key* wc_rrset = NULL;
|
||||
int nsec3s_seen = 0;
|
||||
size_t i;
|
||||
struct ub_packed_rrset_key* s;
|
||||
@@ -1062,6 +1065,9 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
|
||||
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
|
||||
chase_reply->security = sec_status_bogus;
|
||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||
if(wc_rrset)
|
||||
((struct packed_rrset_data*)wc_rrset->
|
||||
entry.data)->security = sec_status_bogus;
|
||||
return;
|
||||
}
|
||||
if(wc && !wc_cached && env->cfg->aggressive_nsec) {
|
||||
@@ -1069,7 +1075,7 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
|
||||
env->alloc, *env->now);
|
||||
wc_cached = 1;
|
||||
}
|
||||
|
||||
if(wc) wc_rrset = s;
|
||||
}
|
||||
|
||||
/* validate the AUTHORITY section as well - this will generally be
|
||||
@@ -1126,6 +1132,9 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
|
||||
"did not exist");
|
||||
chase_reply->security = sec_status_bogus;
|
||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||
if(wc_rrset)
|
||||
((struct packed_rrset_data*)wc_rrset->
|
||||
entry.data)->security = sec_status_bogus;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1527,6 +1536,16 @@ validate_any_response(struct module_env* env, struct val_env* ve,
|
||||
"did not exist");
|
||||
chase_reply->security = sec_status_bogus;
|
||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||
/* Make the expanded name and wildcard RRSIG rrsets bogus */
|
||||
for(i=0; i<chase_reply->an_numrrsets; i++) {
|
||||
uint8_t* cwc = NULL;
|
||||
size_t cwl = 0;
|
||||
s = chase_reply->rrsets[i];
|
||||
if(val_rrset_wildcard(s, &cwc, &cwl) && cwc) {
|
||||
((struct packed_rrset_data*)s->
|
||||
entry.data)->security = sec_status_bogus;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1564,6 +1583,9 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
||||
uint8_t* wc = NULL;
|
||||
size_t wl;
|
||||
int wc_NSEC_ok = 0;
|
||||
/* This is used to update the RRset cache, with the combination
|
||||
* of the dname expansion and this wildcard, for security status. */
|
||||
struct ub_packed_rrset_key* wc_rrset = NULL;
|
||||
int nsec3s_seen = 0;
|
||||
size_t i;
|
||||
struct ub_packed_rrset_key* s;
|
||||
@@ -1584,6 +1606,7 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||
return;
|
||||
}
|
||||
if(wc) wc_rrset = s;
|
||||
|
||||
/* Refuse wildcarded DNAMEs rfc 4597.
|
||||
* Do not follow a wildcarded DNAME because
|
||||
@@ -1595,6 +1618,9 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
||||
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
|
||||
chase_reply->security = sec_status_bogus;
|
||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||
if(wc_rrset)
|
||||
((struct packed_rrset_data*)wc_rrset->
|
||||
entry.data)->security = sec_status_bogus;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1659,6 +1685,9 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
||||
"did not exist");
|
||||
chase_reply->security = sec_status_bogus;
|
||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||
if(wc_rrset)
|
||||
((struct packed_rrset_data*)wc_rrset->
|
||||
entry.data)->security = sec_status_bogus;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user