Skip to content

Commit

Permalink
inets,httpd: Assure relative paths can not be used to bypass server r…
Browse files Browse the repository at this point in the history
…oot directory

Use of uri_string:percent_decode in commmit 5f83a9d
needs to be combined with uri_string:normalize to assure valid paths.

Solves CVE-2021-27563
  • Loading branch information
IngelaAndin committed Feb 23, 2021
1 parent 5a3d03e commit 39f1494
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 8 deletions.
24 changes: 16 additions & 8 deletions lib/inets/src/http_server/mod_alias.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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
%%
Expand Down
45 changes: 45 additions & 0 deletions lib/inets/test/httpd_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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]).
Expand Down

0 comments on commit 39f1494

Please sign in to comment.