diff -Nru pdns-recursor-3.5.3/debian/changelog pdns-recursor-3.5.3/debian/changelog --- pdns-recursor-3.5.3/debian/changelog 2013-09-22 08:46:16.000000000 -0400 +++ pdns-recursor-3.5.3/debian/changelog 2017-01-13 15:21:32.000000000 -0500 @@ -1,3 +1,36 @@ +pdns-recursor (3.5.3-1ubuntu~1) trusty-security; urgency=high + + * SECURITY UPDATE: + * References + * CVE-2014-8601: PowerDNS Recursor before 3.6.2 does not limit delegation + chaining, which allows remote attackers to cause a denial of service + ("performance degradations") via a large or infinite number of referrals, + as demonstrated by resolving domains hosted by ezdns.it. + - Added debian/patches/CVE-2014-8601.patch + * CVE-2015-1868: The label decompression functionality in PowerDNS Recursor + 3.5.x, 3.6.x before 3.6.3, and 3.7.x before 3.7.2 and Authoritative (Auth) + Server 3.2.x, 3.3.x before 3.3.2, and 3.4.x before 3.4.4 allows remote + attackers to cause a denial of service (CPU consumption or crash) via a + request with a name that refers to itself. + - Added debian/patches/CVE-2015-1868.patch + * CVE-2015-5470: The label decompression functionality in PowerDNS Recursor + before 3.6.4 and 3.7.x before 3.7.3 and Authoritative (Auth) Server before + 3.3.3 and 3.4.x before 3.4.5 allows remote attackers to cause a denial of + service (CPU consumption or crash) via a request with a long name that + refers to itself. NOTE: this vulnerability exists because of an incomplete + fix for CVE-2015-1868. + - Added debian/patches/CVE-2015-1868-2.patch + * CVE-2016-7068: Florian Heinz and Martin Kluge reported that pdns-recursor + parses all records present in a query regardless of whether they are + needed or even legitimate, allowing a remote, unauthenticated attacker to + cause an abnormal CPU usage load on the pdns server, resulting in a + partial denial of service if the system becomes overloaded. + - Added debian/patches/CVE-2016-7068.patch + * Add debian/patches/qtypes.patch so qtypes required for CVE-2016-7068.patch + are available + + -- Scott Kitterman Fri, 13 Jan 2017 15:20:50 -0500 + pdns-recursor (3.5.3-1) unstable; urgency=low * New upstream version diff -Nru pdns-recursor-3.5.3/debian/patches/CVE-2014-8601.patch pdns-recursor-3.5.3/debian/patches/CVE-2014-8601.patch --- pdns-recursor-3.5.3/debian/patches/CVE-2014-8601.patch 1969-12-31 19:00:00.000000000 -0500 +++ pdns-recursor-3.5.3/debian/patches/CVE-2014-8601.patch 2017-01-13 12:51:26.000000000 -0500 @@ -0,0 +1,56 @@ +commit 4c70f4747a6a49352130cf4e158cd6afbf373d5b +Author: Your Name +Date: Tue Dec 2 09:25:41 2014 +0000 + + backport query limiter to 3.5.3 + +diff --git a/pdns_recursor.cc b/pdns_recursor.cc +index dcadf1b..3708137 100644 +--- a/pdns_recursor.cc ++++ b/pdns_recursor.cc +@@ -533,7 +533,14 @@ void startDoResolve(void *p) + bool variableAnswer = false; + // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve + if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) { +- res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret); ++ try { ++ res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret); ++ } ++ catch(ImmediateServFailException &e) { ++ L<d_mdp.d_qname<<"' because: "<get()) { + if(res == RCode::NoError) { +diff --git a/syncres.cc b/syncres.cc +index afadfbc..f98f116 100644 +--- a/syncres.cc ++++ b/syncres.cc +@@ -915,6 +915,7 @@ int SyncRes::doResolveAt(set nameservers, string auth, + } + else { + s_outqueries++; d_outqueries++; ++ if(d_outqueries > 50) throw ImmediateServFailException("more than 50 queries sent while resolving "+qname); + TryTCP: + if(doTCP) { + LOG(prefix<toStringWithPort() < 1024) ++ throw MOADNSException("Total name too long"); + } + } + diff -Nru pdns-recursor-3.5.3/debian/patches/CVE-2015-1868.patch pdns-recursor-3.5.3/debian/patches/CVE-2015-1868.patch --- pdns-recursor-3.5.3/debian/patches/CVE-2015-1868.patch 1969-12-31 19:00:00.000000000 -0500 +++ pdns-recursor-3.5.3/debian/patches/CVE-2015-1868.patch 2017-01-13 12:59:14.000000000 -0500 @@ -0,0 +1,47 @@ +CVE: CVE-2015-1868 +Date: 23rd of April 2015 +Credit: Aki Tuomi +Affects: PowerDNS Recursor versions 3.5 and up; Authoritative Server 3.2 and up +Not affected: Recursor 3.6.3; Recursor 3.7.2; Auth 3.4.4 +Severity: High +Impact: Degraded service +Exploit: This problem can be triggered by sending queries for specifically configured domains +Risk of system compromise: No +Solution: Upgrade to any of the non-affected versions +Workaround: Run your Recursor under a supervisor. Exposure can be limited by configuring the **allow-from** setting so only trusted users can query your nameserver. + +A bug was discovered in our label decompression code, making it possible for +names to refer to themselves, thus causing a loop during decompression. This +loop is capped at a 1000 iterations by a failsafe, making the issue harmless +on most platforms. + +However, on specific platforms (so far, we are only aware of this happening on +RHEL5/CentOS5), the recursion involved in these 1000 steps causes memory +corruption leading to a quick crash, presumably because the default stack is +too small. + +Index: pdns-recursor-3.5.3/dnsparser.cc +=================================================================== +--- pdns-recursor-3.5.3.orig/dnsparser.cc 2017-01-13 12:59:06.053472869 -0500 ++++ pdns-recursor-3.5.3/dnsparser.cc 2017-01-13 12:59:06.049472869 -0500 +@@ -434,9 +434,10 @@ + + void PacketReader::getLabelFromContent(const vector& content, uint16_t& frompos, string& ret, int recurs) + { +- if(recurs > 1000) // the forward reference-check below should make this test 100% obsolete ++ if(recurs > 100) // the forward reference-check below should make this test 100% obsolete + throw MOADNSException("Loop"); + ++ int pos = frompos; + for(;;) { + unsigned char labellen=content.at(frompos++); + +@@ -449,7 +450,7 @@ + uint16_t offset=256*(labellen & ~0xc0) + (unsigned int)content.at(frompos++) - sizeof(dnsheader); + // cout<<"This is an offset, need to go to: "<= frompos-2) ++ if(offset >= pos) + throw MOADNSException("forward reference during label decompression"); + return getLabelFromContent(content, offset, ret, ++recurs); + } diff -Nru pdns-recursor-3.5.3/debian/patches/CVE-2016-7068.patch pdns-recursor-3.5.3/debian/patches/CVE-2016-7068.patch --- pdns-recursor-3.5.3/debian/patches/CVE-2016-7068.patch 1969-12-31 19:00:00.000000000 -0500 +++ pdns-recursor-3.5.3/debian/patches/CVE-2016-7068.patch 2017-01-13 13:23:00.000000000 -0500 @@ -0,0 +1,129 @@ +# PowerDNS Security Advisory 2016-02: Crafted queries can cause abnormal CPU usage + +CVE: CVE-2016-7068 +Date: December 15th 2016 +Credit: Florian Heinz and Martin Kluge +Affects: PowerDNS Authoritative Server up to and including 3.4.10, 4.0.1, PowerDNS Recursor up to and including 3.7.3, 4.0.3 +Not affected: PowerDNS Authoritative Server 3.4.11, 4.0.2 and PowerDNS Recursor 3.7.4, 4.0.4 +Severity: Medium +Impact: Degraded service or Denial of service +Exploit: This issue can be triggered by sending specially crafted query packets +Risk of system compromise: No +Solution: Upgrade to a non-affected version +Workaround: Run dnsdist with the rules provided below in front of potentially affected servers. + +An issue has been found in PowerDNS allowing a remote, unauthenticated attacker to cause an abnormal CPU usage load on the PowerDNS server by sending crafted DNS queries, which might result in a partial denial of service if the system becomes overloaded. This issue is based on the fact that the PowerDNS server parses all records present in a query regardless of whether they are needed or even legitimate. A specially crafted query containing a large number of records can be used to take advantage of that behaviour. This issue has been assigned CVE-2016-7068. + +PowerDNS Authoritative Server up to and including 3.4.10 and 4.0.1 are affected. PowerDNS Recursor up to and including 3.7.3 and 4.0.3 are affected. + +dnsdist can be used to block crafted queries, using `RecordsCountRule()` and `RecordsTypeCountRule()` to block queries with crafted records. + +We would like to thank Florian Heinz and Martin Kluge for finding and subsequently reporting this issue. +-- + +Index: pdns-recursor-3.5.3/dnsparser.cc +=================================================================== +--- pdns-recursor-3.5.3.orig/dnsparser.cc 2017-01-13 13:11:08.457491426 -0500 ++++ pdns-recursor-3.5.3/dnsparser.cc 2017-01-13 13:16:16.253499333 -0500 +@@ -138,7 +138,7 @@ + memcpy(&packet[pos], &drh, sizeof(drh)); pos+=sizeof(drh); + memcpy(&packet[pos], serialized.c_str(), serialized.size()); pos+=(uint16_t)serialized.size(); + +- MOADNSParser mdp((char*)&*packet.begin(), (unsigned int)packet.size()); ++ MOADNSParser mdp(false, (char*)&*packet.begin(), (unsigned int)packet.size()); + shared_ptr ret= mdp.d_answers.begin()->first.d_content; + ret->header.d_type=ret->d_qtype; + ret->label=mdp.d_answers.begin()->first.d_label; +@@ -195,7 +195,7 @@ + return zmakermap; + } + +-void MOADNSParser::init(const char *packet, unsigned int len) ++void MOADNSParser::init(bool query, const char *packet, unsigned int len) + { + if(len < sizeof(dnsheader)) + throw MOADNSException("Packet shorter than minimal header"); +@@ -209,6 +209,9 @@ + d_header.ancount=ntohs(d_header.ancount); + d_header.nscount=ntohs(d_header.nscount); + d_header.arcount=ntohs(d_header.arcount); ++ ++ if (query && (d_header.qdcount > 1)) ++ throw MOADNSException("Query with QD > 1 ("+lexical_cast(d_header.qdcount)+")"); + + uint16_t contentlen=len-sizeof(dnsheader); + +@@ -253,7 +256,13 @@ + dr.d_label=label; + dr.d_clen=ah.d_clen; + +- dr.d_content=boost::shared_ptr(DNSRecordContent::mastermake(dr, pr)); ++ if (query && (dr.d_place == DNSRecord::Answer || dr.d_place == DNSRecord::Nameserver || (dr.d_type != QType::OPT && dr.d_type != QType::TSIG && dr.d_type != QType::SIG) || ((dr.d_type == QType::TSIG || dr.d_type == QType::SIG) && dr.d_class != 0xff))) { ++ dr.d_content=boost::shared_ptr(new UnknownRecordContent(dr, pr)); ++ } ++ else { ++ dr.d_content=boost::shared_ptr(DNSRecordContent::mastermake(dr, pr)); ++ } ++ + d_answers.push_back(make_pair(dr, pr.d_pos)); + + if(dr.d_type == QType::TSIG && dr.d_class == 0xff) +Index: pdns-recursor-3.5.3/dnsparser.hh +=================================================================== +--- pdns-recursor-3.5.3.orig/dnsparser.hh 2017-01-13 13:11:08.457491426 -0500 ++++ pdns-recursor-3.5.3/dnsparser.hh 2017-01-13 13:11:08.453491426 -0500 +@@ -295,15 +295,15 @@ + { + public: + //! Parse from a string +- MOADNSParser(const string& buffer) : d_tsigPos(0) ++ MOADNSParser(bool query, const string& buffer) : d_tsigPos(0) + { +- init(buffer.c_str(), (unsigned int)buffer.size()); ++ init(query, buffer.c_str(), (unsigned int)buffer.size()); + } + + //! Parse from a pointer and length +- MOADNSParser(const char *packet, unsigned int len) : d_tsigPos(0) ++ MOADNSParser(bool query, const char *packet, unsigned int len) : d_tsigPos(0) + { +- init(packet, len); ++ init(query, packet, len); + } + + dnsheader d_header; +@@ -329,7 +329,7 @@ + } + private: + void getDnsrecordheader(struct dnsrecordheader &ah); +- void init(const char *packet, unsigned int len); ++ void init(bool query, const char *packet, unsigned int len); + vector d_content; + uint16_t d_tsigPos; + }; +Index: pdns-recursor-3.5.3/lwres.cc +=================================================================== +--- pdns-recursor-3.5.3.orig/lwres.cc 2017-01-13 13:11:08.457491426 -0500 ++++ pdns-recursor-3.5.3/lwres.cc 2017-01-13 13:11:08.453491426 -0500 +@@ -165,7 +165,7 @@ + lwr->d_result.clear(); + try { + lwr->d_tcbit=0; +- MOADNSParser mdp((const char*)buf.get(), len); ++ MOADNSParser mdp(false, (const char*)buf.get(), len); + lwr->d_aabit=mdp.d_header.aa; + lwr->d_tcbit=mdp.d_header.tc; + lwr->d_rcode=mdp.d_header.rcode; +Index: pdns-recursor-3.5.3/pdns_recursor.cc +=================================================================== +--- pdns-recursor-3.5.3.orig/pdns_recursor.cc 2017-01-13 13:11:08.457491426 -0500 ++++ pdns-recursor-3.5.3/pdns_recursor.cc 2017-01-13 13:22:47.661509387 -0500 +@@ -125,7 +125,7 @@ + + //! used to send information to a newborn mthread + struct DNSComboWriter { +- DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now), ++ DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(true, data, len), d_now(now), + d_tcp(false), d_socket(-1) + {} + MOADNSParser d_mdp; diff -Nru pdns-recursor-3.5.3/debian/patches/qtypes.patch pdns-recursor-3.5.3/debian/patches/qtypes.patch --- pdns-recursor-3.5.3/debian/patches/qtypes.patch 1969-12-31 19:00:00.000000000 -0500 +++ pdns-recursor-3.5.3/debian/patches/qtypes.patch 2017-01-13 15:23:12.000000000 -0500 @@ -0,0 +1,47 @@ +Description: Add missing qtypes + * Add debian/patches/qtypes.patch so qtypes required for CVE-2016-7068.patch + are available +Author: Scott Kitterman +Origin: upstream +Last-Update: 2017-01-13 + +--- pdns-recursor-3.5.3.orig/qtype.hh ++++ pdns-recursor-3.5.3/qtype.hh +@@ -77,8 +77,8 @@ public: + static int chartocode(const char *p); //!< convert a character string to a code + // more solaris fun + #undef DS +- enum typeenum {A=1,NS=2,CNAME=5,SOA=6, MR=9, PTR=12,HINFO=13,MX=15,TXT=16,RP=17,AFSDB=18,KEY=25,AAAA=28,LOC=29,SRV=33,NAPTR=35, KX=36, +- CERT=37,OPT=41, DS=43, SSHFP=44, IPSECKEY=45, RRSIG=46, NSEC=47, DNSKEY=48, DHCID=49, NSEC3=50, NSEC3PARAM=51, ++ enum typeenum {A=1,NS=2,CNAME=5,SOA=6, MR=9, PTR=12,HINFO=13,MX=15,TXT=16,RP=17,AFSDB=18, SIG=24, KEY=25,AAAA=28,LOC=29,SRV=33,NAPTR=35, KX=36, ++ CERT=37, A6=38, OPT=41, DS=43, SSHFP=44, IPSECKEY=45, RRSIG=46, NSEC=47, DNSKEY=48, DHCID=49, NSEC3=50, NSEC3PARAM=51, + TLSA=52, SPF=99, TSIG=250, AXFR=252, IXFR=251, ANY=255, URL=256, MBOXFW=257, CURL=258, ADDR=259, DLV=32769} types; + typedef pair namenum; + static vector names; +@@ -109,18 +109,25 @@ private: + qtype_insert("AAAA",28); + qtype_insert("LOC",29); + qtype_insert("SRV",33); ++ qtype_insert("NAPTR",35); ++ qtype_insert("KX",36); + qtype_insert("CERT", 37); + qtype_insert("A6",38); +- qtype_insert("NAPTR",35); ++ qtype_insert("OPT",41); + qtype_insert("DS", 43); + qtype_insert("SSHFP", 44); ++ qtype_insert("IPSECKEY", 45); + qtype_insert("RRSIG", 46); + qtype_insert("NSEC", 47); + qtype_insert("DNSKEY", 48); ++ qtype_insert("DHCID", 49); + qtype_insert("NSEC3", 50); + qtype_insert("NSEC3PARAM", 51); + qtype_insert("TLSA",52); + qtype_insert("SPF",99); ++ qtype_insert("EUI48",108); ++ qtype_insert("EUI64",109); ++ qtype_insert("TSIG", 250); + qtype_insert("IXFR",251); + qtype_insert("AXFR",252); + qtype_insert("ANY",255); diff -Nru pdns-recursor-3.5.3/debian/patches/series pdns-recursor-3.5.3/debian/patches/series --- pdns-recursor-3.5.3/debian/patches/series 2013-08-07 11:56:08.000000000 -0400 +++ pdns-recursor-3.5.3/debian/patches/series 2017-01-13 15:21:58.000000000 -0500 @@ -3,3 +3,8 @@ pdns-recursor-less-chatty hurd-ftbfs-patch remove-pdns_hw-patch +CVE-2014-8601.patch +CVE-2015-1868.patch +CVE-2015-1868-2.patch +CVE-2016-7068.patch +qtypes.patch