]> granicus.if.org Git - pdns/commitdiff
rec: Check the remote host on handleGenUDPQueryResponse()
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 13 Nov 2017 16:18:24 +0000 (17:18 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 12 Jan 2018 11:23:44 +0000 (12:23 +0100)
We do connect the socket before sending, but it looks like various
kernels have a race condition allowing an attacker to inject a
packet between the bind() and the connect() calls, which then does
not necessarily comes from the expected host. Have fun.

pdns/pdns_recursor.cc

index db8084825e01f498170bacbfc2d94181293a9dc2..cec4fd581d320f174b5e767dc73f07f9c1bb4788 100644 (file)
@@ -295,7 +295,15 @@ static void handleGenUDPQueryResponse(int fd, FDMultiplexer::funcparam_t& var)
 {
   PacketID pident=*any_cast<PacketID>(&var);
   char resp[512];
-  ssize_t ret=recv(fd, resp, sizeof(resp), 0);
+  ComboAddress fromaddr;
+  socklen_t addrlen=sizeof(fromaddr);
+
+  ssize_t ret=recvfrom(fd, resp, sizeof(resp), 0, (sockaddr *)&fromaddr, &addrlen);
+  if (fromaddr != pident.remote) {
+    L<<Logger::Notice<<"Response received from the wrong remote host ("<<fromaddr.toStringWithPort()<<" instead of "<<pident.remote.toStringWithPort()<<"), discarding"<<endl;
+
+  }
+
   t_fdm->removeReadFD(fd);
   if(ret >= 0) {
     string data(resp, (size_t) ret);
@@ -319,6 +327,7 @@ string GenUDPQueryResponse(const ComboAddress& dest, const string& query)
 
   PacketID pident;
   pident.sock=&s;
+  pident.remote=dest;
   pident.type=0;
   t_fdm->addReadFD(s.getHandle(), handleGenUDPQueryResponse, pident);