- Fix CVE-2026-42923, Degradation of service with unbounded NSEC3

hash calculations. Thanks to Qifan Zhang, Palo Alto Networks, for
  the report.
This commit is contained in:
W.C.A. Wijngaards
2026-05-20 10:20:02 +02:00
parent a794c87578
commit c343fff3a4
4 changed files with 36 additions and 6 deletions
+3
View File
@@ -16,6 +16,9 @@
- Fix CVE-2026-42534, Jostle logic bypass degrades resolution
performance. Thanks to Qifan Zhang, Palo Alto Networks, for the
report.
- Fix CVE-2026-42923, Degradation of service with unbounded NSEC3
hash calculations. Thanks to Qifan Zhang, Palo Alto Networks, for
the report.
23 April 2026: Wouter
- Merge #1441: Fix buffer overrun in
+27 -1
View File
@@ -62,6 +62,13 @@
#include "sldns/rrdef.h"
#include "sldns/sbuffer.h"
/**
* The maximum salt length that the negative cache is willing to use.
* Larger salt increases the computation time, while recommendations are
* for zero salt length for zones.
*/
#define MAX_SALT_LENGTH 64
int val_neg_data_compare(const void* a, const void* b)
{
struct val_neg_data* x = (struct val_neg_data*)a;
@@ -826,7 +833,11 @@ void neg_insert_data(struct val_neg_cache* neg,
(slen != 0 && zone->nsec3_salt && s
&& memcmp(zone->nsec3_salt, s, slen) != 0))) {
if(slen > 0) {
if(slen > MAX_SALT_LENGTH) {
/* RFC 9276 s3.1: operators SHOULD NOT use a salt; large
* salts inflate per-hash block count. Decline to cache. */
return;
} else if(slen > 0) {
uint8_t* sa = memdup(s, slen);
if(sa) {
free(zone->nsec3_salt);
@@ -1165,6 +1176,15 @@ neg_find_nsec3_ce(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
uint8_t hashce[NSEC3_SHA_LEN];
uint8_t b32[257];
size_t celen, b32len;
int hashmax = MAX_NSEC3_CALCULATIONS;
if(qlabs > hashmax) {
/* strip leading labels so the walk costs at most
* MAX_NSEC3_CALCULATIONS hashes, mirroring val_nsec3.c */
while(qlabs > hashmax) {
dname_remove_label(&qname, &qname_len);
qlabs--;
}
}
*nclen = 0;
while(qlabs > 0) {
@@ -1265,6 +1285,12 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
if(!zone->nsec3_hash)
return NULL; /* not nsec3 zone */
if(!topname && qlabs > zone->labs + 1)
return NULL; /* iterator caller; opt-out proof would be discarded
* at the !topname check below anyway.
* The qlabs check allows the exact-match for
* the one-label-below-zone case. */
if(!(data=neg_find_nsec3_ce(zone, qname, qname_len, qlabs, buf,
hashnc, &nclen))) {
return NULL;
-5
View File
@@ -59,11 +59,6 @@
#include "sldns/sbuffer.h"
#include "util/config_file.h"
/**
* Max number of NSEC3 calculations at once, suspend query for later.
* 8 is low enough and allows for cases where multiple proofs are needed.
*/
#define MAX_NSEC3_CALCULATIONS 8
/**
* When all allowed NSEC3 calculations at once resulted in error treat as
* bogus. NSEC3 hash errors are not cached and this helps breaks loops with
+6
View File
@@ -98,6 +98,12 @@ struct sldns_buffer;
/** The SHA1 hash algorithm for NSEC3 */
#define NSEC3_HASH_SHA1 0x01
/**
* Max number of NSEC3 calculations at once, suspend query for later.
* 8 is low enough and allows for cases where multiple proofs are needed.
*/
#define MAX_NSEC3_CALCULATIONS 8
/**
* Cache table for NSEC3 hashes.
* It keeps a *pointer* to the region its items are allocated.