diff options
Diffstat (limited to 'lib/inets')
-rw-r--r-- | lib/inets/src/http_server/mod_alias.erl | 24 | ||||
-rw-r--r-- | lib/inets/test/httpd_SUITE.erl | 45 |
2 files changed, 61 insertions, 8 deletions
diff --git a/lib/inets/src/http_server/mod_alias.erl b/lib/inets/src/http_server/mod_alias.erl index 35da39c53c..cb2d2c1ef4 100644 --- a/lib/inets/src/http_server/mod_alias.erl +++ b/lib/inets/src/http_server/mod_alias.erl @@ -195,22 +195,30 @@ append_index(RealName, [Index | Rest]) -> %% path -path(Data, ConfigDB, RequestURI) -> - InitPath = +path(Data, ConfigDB, RequestURI0) -> case proplists:get_value(real_name, Data) of undefined -> - {Prefix, DocumentRoot} = which_document_root(ConfigDB), - {Path, _AfterPath} = + {Prefix, DocumentRoot} = which_document_root(ConfigDB), + RequestURI = percent_decode_path(RequestURI0), + {Path, _AfterPath} = httpd_util:split_path(DocumentRoot ++ RequestURI), Prefix ++ Path; {Path, _AfterPath} -> Path - end, - case uri_string:percent_decode(InitPath) of - {error, _} -> InitPath; - P -> P end. +percent_decode_path(InitPath) -> + case uri_string:percent_decode(InitPath) of + {error, _} -> + InitPath; + Path0 -> %% Protect against vulnerabilities + case uri_string:normalize(Path0) of + {error, _, _} -> + InitPath; + Path -> + Path + end + end. %% %% Configuration %% diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index e4efeb1b81..027932caa2 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -155,6 +155,7 @@ http_head() -> http_get() -> [alias, get, + bad_dot_paths, %%actions, Add configuration so that this test mod_action esi, bad_hex, @@ -473,6 +474,50 @@ get(Config) when is_list(Config) -> {header, "Date"}, {header, "Server"}, {version, Version}]). + +bad_dot_paths() -> + [{doc, "Do not allow ..-paths to acesse files outside of doc root"}]. +bad_dot_paths(Config) when is_list(Config) -> + Version = proplists:get_value(http_version, Config), + Host = proplists:get_value(host, Config), + Type = proplists:get_value(type, Config), + + BadDotPath0 = "/..%2f..%2f...%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd ", + BadDotPath1 = "/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd ", + BadDotPath2 = "/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd ", + + ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host, + proplists:get_value(port, Config), + transport_opts(Type, Config), + proplists:get_value(node, Config), + http_request("GET " ++ BadDotPath0 , Version, Host), + [{statuscode, 404}, + {header, "Content-Type", "text/html"}, + {header, "Date"}, + {header, "Server"}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host, + proplists:get_value(port, Config), + transport_opts(Type, Config), + proplists:get_value(node, Config), + http_request("GET " ++ BadDotPath1, Version, Host), + [{statuscode, 404}, + {header, "Content-Type", "text/html"}, + {header, "Date"}, + {header, "Server"}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host, + proplists:get_value(port, Config), + transport_opts(Type, Config), + proplists:get_value(node, Config), + http_request("GET " ++ BadDotPath2, Version, Host), + [{statuscode, 404}, + {header, "Content-Type", "text/html"}, + {header, "Date"}, + {header, "Server"}, + {version, Version}]). basic_auth_1_1(Config) when is_list(Config) -> basic_auth([{http_version, "HTTP/1.1"} | Config]). |