From 3d99f030820877eb84835fb1be66a7db3f5b0c68 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 11 Aug 2010 00:05:34 +0000 Subject: [PATCH] uhttpd: add option to reject requests from RFC1918 IPs to public server IPs (DNS rebinding countermeasure) SVN-Revision: 22589 --- package/uhttpd/Makefile | 2 +- package/uhttpd/files/uhttpd.config | 5 +++++ package/uhttpd/files/uhttpd.init | 1 + package/uhttpd/src/uhttpd-utils.c | 15 +++++++++++++++ package/uhttpd/src/uhttpd-utils.h | 1 + package/uhttpd/src/uhttpd.c | 15 ++++++++++++++- package/uhttpd/src/uhttpd.h | 1 + 7 files changed, 38 insertions(+), 2 deletions(-) diff --git a/package/uhttpd/Makefile b/package/uhttpd/Makefile index 2ad0816e3aa1..8a7b5295d9ee 100644 --- a/package/uhttpd/Makefile +++ b/package/uhttpd/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uhttpd -PKG_RELEASE:=12 +PKG_RELEASE:=13 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DEPENDS := libcyassl liblua diff --git a/package/uhttpd/files/uhttpd.config b/package/uhttpd/files/uhttpd.config index acdd62ea4eb4..534e8f8b29da 100644 --- a/package/uhttpd/files/uhttpd.config +++ b/package/uhttpd/files/uhttpd.config @@ -12,6 +12,11 @@ config uhttpd main # Server document root option home /www + # Reject requests from RFC1918 IP addresses + # directed to the servers public IP(s). + # This is a DNS rebinding countermeasure. + option rfc1918_filter 1 + # Certificate and private key for HTTPS. # If no listen_https addresses are given, # the key options are ignored. diff --git a/package/uhttpd/files/uhttpd.init b/package/uhttpd/files/uhttpd.init index d543dd84b951..b00b2e281b97 100755 --- a/package/uhttpd/files/uhttpd.init +++ b/package/uhttpd/files/uhttpd.init @@ -75,6 +75,7 @@ start_instance() append_bool "$cfg" no_symlinks "-S" 0 append_bool "$cfg" no_dirlists "-D" 0 + append_bool "$cfg" rfc1918_filter "-R" 0 config_get http "$cfg" listen_http for listen in $http; do diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c index 60badf26df9c..4a1423c715d0 100644 --- a/package/uhttpd/src/uhttpd-utils.c +++ b/package/uhttpd/src/uhttpd-utils.c @@ -59,6 +59,21 @@ int sa_port(void *sa) return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); } +int sa_rfc1918(void *sa) +{ + struct sockaddr_in *v4 = (struct sockaddr_in *)sa; + unsigned long a = htonl(v4->sin_addr.s_addr); + + if( v4->sin_family == AF_INET ) + { + return ((a >= 0x0A000000) && (a <= 0x0AFFFFFF)) || + ((a >= 0xAC100000) && (a <= 0xAC1FFFFF)) || + ((a >= 0xC0A80000) && (a <= 0xC0A8FFFF)); + } + + return 0; +} + /* Simple strstr() like function that takes len arguments for both haystack and needle. */ char *strfind(char *haystack, int hslen, const char *needle, int ndlen) { diff --git a/package/uhttpd/src/uhttpd-utils.h b/package/uhttpd/src/uhttpd-utils.h index a6448b63bc1d..1b1826541791 100644 --- a/package/uhttpd/src/uhttpd-utils.h +++ b/package/uhttpd/src/uhttpd-utils.h @@ -49,6 +49,7 @@ struct path_info { const char * sa_straddr(void *sa); const char * sa_strport(void *sa); int sa_port(void *sa); +int sa_rfc1918(void *sa); char *strfind(char *haystack, int hslen, const char *needle, int ndlen); diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c index 82729627e08b..be882470ad0b 100644 --- a/package/uhttpd/src/uhttpd.c +++ b/package/uhttpd/src/uhttpd.c @@ -524,7 +524,7 @@ int main (int argc, char **argv) #endif while( (opt = getopt(argc, argv, - "fSDC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 + "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 ) { switch(opt) { @@ -648,6 +648,10 @@ int main (int argc, char **argv) conf.no_dirlists = 1; break; + case 'R': + conf.rfc1918_filter = 1; + break; + #ifdef HAVE_CGI /* cgi prefix */ case 'x': @@ -728,6 +732,7 @@ int main (int argc, char **argv) " -I string Use given filename as index page for directories\n" " -S Do not follow symbolic links outside of the docroot\n" " -D Do not allow directory listings, send 403 instead\n" + " -R Enable RFC1918 filter\n" #ifdef HAVE_LUA " -l string URL prefix for Lua handler, default is '/lua'\n" " -L file Lua handler script, omit to disable Lua\n" @@ -932,6 +937,14 @@ int main (int argc, char **argv) /* parse message header */ if( (req = uh_http_header_recv(cl)) != NULL ) { + /* RFC1918 filtering required? */ + if( conf.rfc1918_filter && sa_rfc1918(&cl->peeraddr) && + !sa_rfc1918(&cl->servaddr) ) + { + uh_http_sendhf(cl, 403, "Forbidden", + "Rejected request from RFC1918 IP to public server address"); + } + else #ifdef HAVE_LUA /* Lua request? */ if( L && uh_path_match(conf.lua_prefix, req->url) ) diff --git a/package/uhttpd/src/uhttpd.h b/package/uhttpd/src/uhttpd.h index c8fdaf484645..fd2176ebdd9c 100644 --- a/package/uhttpd/src/uhttpd.h +++ b/package/uhttpd/src/uhttpd.h @@ -69,6 +69,7 @@ struct config { int no_symlinks; int no_dirlists; int network_timeout; + int rfc1918_filter; #ifdef HAVE_CGI char *cgi_prefix; #endif -- 2.30.2