From 98cc73a372d61988b252794340daff68e2304a9d Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 9 Dec 2014 17:49:02 +0100 Subject: [PATCH] miniupnpd/upnphttp: Checking Host: HTTP request header to prevent DNS rebinding attack --- miniupnpd/Changelog.txt | 5 ++++- miniupnpd/upnphttp.c | 42 ++++++++++++++++++++++++++++++++++++++++- miniupnpd/upnphttp.h | 4 +++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 8c142c0..890dcc4 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.391 2014/12/09 09:48:04 nanard Exp $ +$Id: Changelog.txt,v 1.392 2014/12/09 16:41:21 nanard Exp $ + +2014/12/10: + Checking Host: HTTP request header to prevent DNS rebinding attack 2014/12/09: fix upnp_add_inboundpinhole() : check inet_pton() return diff --git a/miniupnpd/upnphttp.c b/miniupnpd/upnphttp.c index 7741e09..6f802cd 100644 --- a/miniupnpd/upnphttp.c +++ b/miniupnpd/upnphttp.c @@ -1,4 +1,4 @@ -/* $Id: upnphttp.c,v 1.96 2014/12/09 10:43:35 nanard Exp $ */ +/* $Id: upnphttp.c,v 1.98 2014/12/09 16:45:47 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard @@ -234,6 +234,17 @@ ParseHttpHeaders(struct upnphttp * h) printf(" readbufflen=%d contentoff = %d\n", h->req_buflen, h->req_contentoff);*/ } + else if(strncasecmp(line, "Host", 4)==0) + { + p = colon; + n = 0; + while(*p == ':' || *p == ' ' || *p == '\t') + p++; + while(p[n]>' ') + n++; + h->req_HostOff = p - h->req_buf; + h->req_HostLen = n; + } else if(strncasecmp(line, "SOAPAction", 10)==0) { p = colon; @@ -746,6 +757,35 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h) syslog(LOG_INFO, "HTTP REQUEST : %s %s (%s)", HttpCommand, HttpUrl, HttpVer); ParseHttpHeaders(h); + if(h->req_HostOff > 0 && h->req_HostLen > 0) { + syslog(LOG_DEBUG, "Host: %.*s", h->req_HostLen, h->req_buf + h->req_HostOff); + p = h->req_buf + h->req_HostOff; + if(*p == '[') { + /* IPv6 */ + p++; + while(p < h->req_buf + h->req_HostOff + h->req_HostLen) { + if(*p == ']') break; + /* TODO check *p in [0-9a-f:.] */ + p++; + } + if(*p != ']') { + syslog(LOG_NOTICE, "DNS rebinding attack suspected (Host: %.*s)", h->req_HostLen, h->req_buf + h->req_HostOff); + Send404(h);/* 403 */ + return; + } + p++; + /* TODO : Check port */ + } else { + for(i = 0; i < h->req_HostLen; i++) { + if(*p != ':' && *p != '.' && (*p > '9' || *p < '0')) { + syslog(LOG_NOTICE, "DNS rebinding attack suspected (Host: %.*s)", h->req_HostLen, h->req_buf + h->req_HostOff); + Send404(h);/* 403 */ + return; + } + p++; + } + } + } if(strcmp("POST", HttpCommand) == 0) { h->req_command = EPost; diff --git a/miniupnpd/upnphttp.h b/miniupnpd/upnphttp.h index 70fef8f..a060211 100644 --- a/miniupnpd/upnphttp.h +++ b/miniupnpd/upnphttp.h @@ -1,4 +1,4 @@ -/* $Id: upnphttp.h,v 1.39 2014/12/09 09:46:46 nanard Exp $ */ +/* $Id: upnphttp.h,v 1.40 2014/12/09 16:41:21 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -72,6 +72,8 @@ struct upnphttp { enum httpCommands req_command; int req_soapActionOff; int req_soapActionLen; + int req_HostOff; /* Host: header */ + int req_HostLen; #ifdef ENABLE_EVENTS int req_CallbackOff; /* For SUBSCRIBE */ int req_CallbackLen;