Verified Commit ba7b89db authored by Vladimír Čunát's avatar Vladimír Čunát Committed by Petr Špaček
Browse files

mitigate NXNSAttack protocol vulnerability for wildcards in victim zone

Attacker might generate fake NS records pointing to victim's DNS zone.
If the zone contains wildcard the attacker might force us into packet
exchange with a (lame) DNS server on that IP address.

We now limit number of consecuctive failures and kill whole request if
limit is exceeded.
parent 54f05e4d
......@@ -192,6 +192,7 @@ struct kr_request {
knot_mm_t pool;
unsigned int uid;
unsigned int count_no_nsaddr;
unsigned int count_fail_row;
};
enum kr_rank {KR_RANK_INITIAL, KR_RANK_OMIT, KR_RANK_TRY, KR_RANK_INDET = 4, KR_RANK_BOGUS, KR_RANK_MISMATCH, KR_RANK_MISSING, KR_RANK_INSECURE, KR_RANK_AUTH = 16, KR_RANK_SECURE = 32};
struct kr_cdb_stats {
......
......@@ -53,6 +53,7 @@ static inline int KR_COLD kr_error(int x) {
#define KR_TIMEOUT_LIMIT 4 /* Maximum number of retries after timeout. */
#define KR_QUERY_NSRETRY_LIMIT 4 /* Maximum number of retries per query. */
#define KR_COUNT_NO_NSADDR_LIMIT 5
#define KR_CONSUME_FAIL_ROW_LIMIT 3 /* Maximum number of KR_STATE_FAIL in a row. */
/*
* Defines.
......
......@@ -869,7 +869,8 @@ static int process_stub(knot_pkt_t *pkt, struct kr_request *req)
}
/** Error handling, RFC1034 5.3.3, 4d. */
/** Error handling, RFC1034 5.3.3, 4d.
* NOTE: returing this does not prevent further queries (by itself). */
static int resolve_error(knot_pkt_t *pkt, struct kr_request *req)
{
return KR_STATE_FAIL;
......
......@@ -939,6 +939,23 @@ int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, k
qry->flags.RESOLVED = false;
}
/* For multiple errors in a row; invalidate_ns() is not enough. */
if (!qry->flags.CACHED) {
if (request->state & KR_STATE_FAIL) {
if (++request->count_fail_row > KR_CONSUME_FAIL_ROW_LIMIT) {
if (VERBOSE_STATUS || kr_log_rtrace_enabled(request)) {
kr_log_req(request, 0, 2, "resl",
"=> too many failures in a row, "
"bail out (mitigation for NXNSAttack "
"CVE-2020-12667)");
}
return KR_STATE_FAIL;
}
} else {
request->count_fail_row = 0;
}
}
/* Pop query if resolved. */
if (request->state == KR_STATE_YIELD) {
return KR_STATE_PRODUCE; /* Requery */
......
......@@ -228,6 +228,7 @@ struct kr_request {
knot_mm_t pool;
unsigned int uid; /** for logging purposes only */
unsigned int count_no_nsaddr;
unsigned int count_fail_row;
};
/** Initializer for an array of *_selected. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment