spf: limit recursion depth to prevent ddos (thanks tijay, iashiq5)

An attacker may use an infinite number of SPF referrals in his/her SPF
setting and can send an email to your mail server which would make
your SMTP server make a lot of DNS queries.  By exploiting this
vulnerability, an attacker can block your SMTP queue, flood the
associated recursive resolver, or any DNS authoritative server.

According to RFC recommendations
(https://datatracker.ietf.org/doc/html/rfc7208#section-4.6), a few DNS
lookup limits exist that an SMTP server needs to maintain while
resolving an SPF record.  That is, SPF implementations MUST limit the
total number of query-causing terms to 10 and the number of void
lookups to 2 to avoid unreasonable load on the DNS.

from:

Taejoong “Tijay” Chung (tijay@vt.edu)
Ishtiaq Ashiq (iashiq5@vt.edu)
This commit is contained in:
Ori Bernstein 2022-06-30 01:24:27 +00:00
parent 1f95e98ddd
commit e6d31c1715

View file

@ -387,7 +387,7 @@ lower(char *s)
} }
int int
spfquery(Squery *x, char *d, int include) spfquery(Squery *x, char *d, int include, int depth)
{ {
char *s, **t, *r, *p, *q, buf[10]; char *s, **t, *r, *p, *q, buf[10];
int i, n, c; int i, n, c;
@ -398,6 +398,10 @@ spfquery(Squery *x, char *d, int include)
fprint(2, "spf: include loop: %s (%s)\n", d, inc->s); fprint(2, "spf: include loop: %s (%s)\n", d, inc->s);
return -1; return -1;
} }
if(depth >= 10){
fprint(2, "spf: too much recursion %s\n", d);
return -1;
}
s = spffetch(x, d); s = spffetch(x, d);
if(!s) if(!s)
return -1; return -1;
@ -457,7 +461,7 @@ spfquery(Squery *x, char *d, int include)
if(rflag) if(rflag)
fprint(2, "I> %s\n", q); fprint(2, "I> %s\n", q);
addbegin(mod, r, q); addbegin(mod, r, q);
if(spfquery(x, q, 1) == -1){ if(spfquery(x, q, 1, depth+1) == -1){
ditch(); ditch();
addfail(); addfail();
}else }else
@ -704,7 +708,7 @@ main(int argc, char **argv)
goto loop; goto loop;
spfinit(&q, d, argc, argv); /* or s? */ spfinit(&q, d, argc, argv); /* or s? */
addbegin('+', ".", s); addbegin('+', ".", s);
if(spfquery(&q, s, 0) != -1) if(spfquery(&q, s, 0, 0) != -1)
break; break;
} }
if(eflag && nspf) if(eflag && nspf)