# Erlang/OTP inets Module Authentication Bypass Vulnerability (CVE-2020-28000) Fix Summary ## Vulnerability Overview This vulnerability exists in the `inets` module of Erlang/OTP, specifically affecting the `mod_auth` and `mod_cgi` modules. A security flaw occurs when `script_alias` (script alias) is configured and combined with `mod_auth` (module authentication) for directory-based access control. **Core Issue**: Authorization rules are evaluated against the alias URL path rather than the actual file system path where the script resides. **Consequence**: If CGI scripts are mapped outside the DocumentRoot, they may not be properly protected by directory authentication. An attacker can execute CGI scripts located outside the DocumentRoot by accessing the alias URL, thereby bypassing the authentication mechanism. ## Scope of Impact * **Affected Modules**: `http_server` module within `inets`. * **Affected Files**: * `lib/inets/src/http_server/mod_auth.erl` * `lib/inets/src/http_server/mod_cgi.erl` * **Trigger Scenario**: When the server is configured with `script_alias` and `mod_auth` is enabled for directory authentication. ## Remediation Plan Commit `8fc71ac` fixes this vulnerability by modifying the `store` function in both `mod_auth.erl` and `mod_cgi.erl`: 1. **mod_auth.erl**: Ensures `script_alias` is handled correctly within the `store` function, ensuring authorization rules are evaluated based on the actual file system path. 2. **mod_cgi.erl**: Adds a check for `script_alias` within the `store` function to ensure configurations are updated correctly when `script_alias` is present, thereby protecting CGI scripts mapped outside the DocumentRoot. 3. **Logic Correction**: Ensures the `which_document_root` and `which_alias` logic functions correctly to support authentication checks based on the actual path. ## POC/Testing Code The screenshot includes test code (`lib/inets/test/http_SUITE.erl`) used to verify the fix, demonstrating how to exploit the vulnerability (or verify the remediation): ```erlang 1148 + script_alias_auth_bypass(Config) -> 1149 + %% Test that mod_auth correctly protects script_alias directories 1150 + %% "outside DocumentRoot (CVE-2020-28000)" 1151 + Host = proplists:get_value(http_host, Config), 1152 + Version = proplists:get_value(http_version, Config), 1153 + Mod = proplists:get_value(http_mods, Config), 1154 + Script = 1155 + case os:type() of 1156 + {win32, _} -> "printenv.bat", 1157 + _ -> "printenv.sh" 1158 + end, 1159 + %% Unauthenticated request must be rejected with 401 1160 + ok = http_status("GET /http_script_alias_auth" ++ " " ++ Config, 1161 + [statuscode, 401]), 1162 + %% Authenticated request must succeed 1163 + ok = auth_status( 1164 + auth_request("/http_script_alias_auth" ++ Script, "one", "onePassword", 1165 + Config), 1166 + [statuscode, 200]), 1167 + %% Wrong password must be rejected 1168 + ok = auth_status( 1169 + auth_request("/http_script_alias_auth" ++ Script, "one", "WrongPassword", 1170 + Config), 1171 + [statuscode, 403]), ```