Skip to content
Snippets Groups Projects
Verified Commit 54f05e4d authored by Vladimír Čunát's avatar Vladimír Čunát Committed by Petr Špaček
Browse files

mitigate NXNSAttack protocol vulnerability for unresolvable NS names

CWE-406: Insufficient Control of Network Message Volume (Network Amplification)

We now limit number of failed NS name resolution attempts for each
request. This does not prevent attacker from spoofing delegations
but it puts upper bound on amplification factor.
parent fdaa4150
Branches
Tags
1 merge request!1003NXNSAttack mitigation
......@@ -191,6 +191,7 @@ struct kr_request {
int vars_ref;
knot_mm_t pool;
unsigned int uid;
unsigned int count_no_nsaddr;
};
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 {
......
......@@ -52,6 +52,7 @@ static inline int KR_COLD kr_error(int x) {
#define KR_CNAME_CHAIN_LIMIT 13 /* Built-in maximum CNAME chain length */
#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
/*
* Defines.
......
......@@ -299,10 +299,10 @@ static int ns_fetch_cut(struct kr_query *qry, const knot_dname_t *requested_name
return KR_STATE_PRODUCE;
}
static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param)
static int ns_resolve_addr(struct kr_query *qry, struct kr_request *req)
{
struct kr_rplan *rplan = &param->rplan;
struct kr_context *ctx = param->ctx;
struct kr_rplan *rplan = &req->rplan;
struct kr_context *ctx = req->ctx;
/* Start NS queries from root, to avoid certain cases
......@@ -333,7 +333,9 @@ static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param)
return kr_error(EAGAIN);
}
/* No IPv4 nor IPv6, flag server as unusable. */
VERBOSE_MSG(qry, "=> unresolvable NS address, bailing out\n");
++req->count_no_nsaddr;
VERBOSE_MSG(qry, "=> unresolvable NS address, bailing out (counter: %u)\n",
req->count_no_nsaddr);
qry->ns.reputation |= KR_NS_NOIP4 | KR_NS_NOIP6;
kr_nsrep_update_rep(&qry->ns, qry->ns.reputation, ctx->cache_rep);
invalidate_ns(rplan, qry);
......@@ -1396,6 +1398,11 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
ns_election:
if (unlikely(request->count_no_nsaddr >= KR_COUNT_NO_NSADDR_LIMIT)) {
VERBOSE_MSG(qry, "=> too many unresolvable NSs, bail out "
"(mitigation for NXNSAttack CVE-2020-12667)\n");
return KR_STATE_FAIL;
}
/* If the query has already selected a NS and is waiting for IPv4/IPv6 record,
* elect best address only, otherwise elect a completely new NS.
*/
......
......@@ -227,6 +227,7 @@ struct kr_request {
int vars_ref; /**< Reference to per-request variable table. LUA_NOREF if not set. */
knot_mm_t pool;
unsigned int uid; /** for logging purposes only */
unsigned int count_no_nsaddr;
};
/** Initializer for an array of *_selected. */
......
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