mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Check destination of DNS UDP query replies.
At any time, dnsmasq will have a set of sockets open, bound to random ports, on which it sends queries to upstream nameservers. This patch fixes the existing problem that a reply for ANY in-flight query would be accepted via ANY open port, which increases the chances of an attacker flooding answers "in the blind" in an attempt to poison the DNS cache. CERT VU#434904 refers.
This commit is contained in:
@@ -6,8 +6,12 @@ version 2.83
|
|||||||
dnsmasq with DNSSEC compiled in and enabled is vulnerable to this,
|
dnsmasq with DNSSEC compiled in and enabled is vulnerable to this,
|
||||||
referenced by CERT VU#434904.
|
referenced by CERT VU#434904.
|
||||||
|
|
||||||
|
Be sure to only accept UDP DNS query replies at the address
|
||||||
|
from which the query was originated. This keeps as much entropy
|
||||||
|
in the {query-ID, random-port} tuple as possible, help defeat
|
||||||
|
cache poisoning attacks. Refer: CERT VU#434904.
|
||||||
|
|
||||||
|
|
||||||
>>>>>>> Fix remote buffer overflow CERT VU#434904
|
|
||||||
version 2.82
|
version 2.82
|
||||||
Improve behaviour in the face of network interfaces which come
|
Improve behaviour in the face of network interfaces which come
|
||||||
and go and change index. Thanks to Petr Mensik for the patch.
|
and go and change index. Thanks to Petr Mensik for the patch.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
static struct frec *lookup_frec(unsigned short id, void *hash);
|
static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash);
|
||||||
static struct frec *lookup_frec_by_sender(unsigned short id,
|
static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||||
union mysockaddr *addr,
|
union mysockaddr *addr,
|
||||||
void *hash);
|
void *hash);
|
||||||
@@ -805,7 +805,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
crc = questions_crc(header, n, daemon->namebuff);
|
crc = questions_crc(header, n, daemon->namebuff);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!(forward = lookup_frec(ntohs(header->id), hash)))
|
if (!(forward = lookup_frec(ntohs(header->id), fd, family, hash)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef HAVE_DUMPFILE
|
#ifdef HAVE_DUMPFILE
|
||||||
@@ -2339,15 +2339,26 @@ struct frec *get_new_frec(time_t now, int *wait, struct frec *force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* crc is all-ones if not known. */
|
/* crc is all-ones if not known. */
|
||||||
static struct frec *lookup_frec(unsigned short id, void *hash)
|
static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash)
|
||||||
{
|
{
|
||||||
struct frec *f;
|
struct frec *f;
|
||||||
|
|
||||||
for(f = daemon->frec_list; f; f = f->next)
|
for(f = daemon->frec_list; f; f = f->next)
|
||||||
if (f->sentto && f->new_id == id &&
|
if (f->sentto && f->new_id == id &&
|
||||||
(!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
|
(!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
|
||||||
|
{
|
||||||
|
/* sent from random port */
|
||||||
|
if (family == AF_INET && f->rfd4 && f->rfd4->fd == fd)
|
||||||
return f;
|
return f;
|
||||||
|
|
||||||
|
if (family == AF_INET6 && f->rfd6 && f->rfd6->fd == fd)
|
||||||
|
return f;
|
||||||
|
|
||||||
|
/* sent to upstream from bound socket. */
|
||||||
|
if (f->sentto->sfd && f->sentto->sfd->fd == fd)
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2407,13 +2418,21 @@ void server_gone(struct server *server)
|
|||||||
static unsigned short get_id(void)
|
static unsigned short get_id(void)
|
||||||
{
|
{
|
||||||
unsigned short ret = 0;
|
unsigned short ret = 0;
|
||||||
|
struct frec *f;
|
||||||
|
|
||||||
do
|
while (1)
|
||||||
|
{
|
||||||
ret = rand16();
|
ret = rand16();
|
||||||
while (lookup_frec(ret, NULL));
|
|
||||||
|
|
||||||
|
/* ensure id is unique. */
|
||||||
|
for (f = daemon->frec_list; f; f = f->next)
|
||||||
|
if (f->sentto && f->new_id == ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!f)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user