summaryrefslogtreecommitdiff
path: root/lib/inets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets')
-rw-r--r--lib/inets/src/http_server/mod_alias.erl24
-rw-r--r--lib/inets/test/httpd_SUITE.erl45
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]).