Compare commits

...

8 commits

Author SHA1 Message Date
Alexandre Aubin
efc88ec3a5 Update changelog for 11.0.11.1 2023-01-19 19:11:31 +01:00
ewilly
e2114c0df5 Fix auth_header
If a colon is in the password, user and password are not well detected.
For example if user="me" and password="pass:word" the function give
user="me:pass" password="word"
2023-01-19 17:23:44 +01:00
Alexandre Aubin
226e3bdf4c Update changelog for 11.0.11 2023-01-10 14:04:43 +01:00
Alexandre Aubin
56c2726237 security: rework previous fixes to use the new use_remote_user_var_in_nginx_conf in ssowat conf introduced in yunohost 11.1.2 2023-01-10 14:02:51 +01:00
Alexandre Aubin
f939b63241 Stupid typo 2023-01-10 14:02:51 +01:00
Alexandre Aubin
f59accd10e Iterate on previous security fixes: ignore Auth header on PROPFIND routes, and don't drop Auth header which are not Basic auth 2023-01-10 14:02:51 +01:00
Alexandre Aubin
7e8b0e037f security: Also check client-provided auth headers to prevent impersonation 2023-01-10 14:02:51 +01:00
selfhoster1312
676f157194 Authentication headers are ONLY set when user is logged in and has access to app
Prevents impersonating users on public applications where the auth headers were not cleared
2023-01-10 14:02:51 +01:00
3 changed files with 82 additions and 27 deletions

View file

@ -315,9 +315,28 @@ for permission_name, permission_infos in pairs(conf["permissions"]) do
end
end
---
--- 5. CHECK CLIENT-PROVIDED AUTH HEADER (should almost never happen?)
---
if permission ~= nil then
perm_user_remote_user_var_in_nginx_conf = permission["use_remote_user_var_in_nginx_conf"]
if perm_user_remote_user_var_in_nginx_conf == nil or perm_user_remote_user_var_in_nginx_conf == true then
is_logged_in_with_basic_auth = hlp.validate_or_clear_basic_auth_header_provided_by_client()
-- NB: is_logged_in_with_basic_auth can be false, true or nil
if is_logged_in_with_basic_auth == false then
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
elseif is_logged_in_with_basic_auth == true then
is_logged_in = true
end
end
end
--
--
-- 5. APPLY PERMISSION
-- 6. APPLY PERMISSION
--
--
@ -333,7 +352,11 @@ if hlp.has_access(permission) then
-- add it to the response
if permission["auth_header"] then
hlp.set_headers()
else
hlp.clear_headers()
end
else
hlp.clear_headers()
end
return hlp.pass()

17
debian/changelog vendored
View file

@ -1,3 +1,20 @@
ssowat (11.0.11.1) stable; urgency=low
- Fix auth_header parsing when password contains semicolon ([#204](https://github.com/yunohost/ssowat/pull/204))
Thanks to all contributors <3 ! (ewilly)
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 19 Jan 2023 17:21:40 +0100
ssowat (11.0.11) stable; urgency=low
- Authentication headers are ONLY set when user is logged in and has access to app Prevents impersonating users on public applications where the auth headers were not cleared (676f157)
- security: Also check client-provided auth headers to prevent impersonation, based on new use_remote_user_var_in_nginx_conf in ssowatconf (7e8b0e0, f59accd, f939b63, 56c2726)
Thanks to all contributors <3 ! (selfhoster1312)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 10 Jan 2023 14:03:06 +0100
ssowat (11.0.9) stable; urgency=low
- Bump version for stable release

View file

@ -256,35 +256,40 @@ function refresh_logged_in()
return false
end
-- If client set the `Proxy-Authorization` header before reaching the SSO,
-- we want to match user and password against the user database.
--
-- It allows to bypass the cookie-based procedure with a per-request
-- authentication. This is useful to authenticate on the SSO during
-- curl requests for example.
local auth_header = ngx.req.get_headers()["Proxy-Authorization"]
if auth_header then
_, _, b64_cred = string.find(auth_header, "^Basic%s+(.+)$")
if b64_cred == nil then
return is_logged_in
end
_, _, user, password = string.find(ngx.decode_base64(b64_cred), "^(.+):(.+)$")
user = authenticate(user, password)
if user then
logger.debug("User got authenticated through basic auth")
authUser = user
is_logged_in = true
else
-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/407
ngx.status = 407
end
end
return is_logged_in
end
function validate_or_clear_basic_auth_header_provided_by_client()
-- Ignore if no Auth header
local auth_header = ngx.req.get_headers()["Authorization"]
if auth_header == nil then
return nil
end
-- Ignore if not a Basic auth header
_, _, b64_cred = string.find(auth_header, "^Basic%s+(.+)$")
if b64_cred == nil then
return nil
end
-- Try to authenticate the user,
-- or remove the Auth header if not valid
_, _, user, password = string.find(ngx.decode_base64(b64_cred), "^([^:]+):(.+)$")
user = authenticate(user, password)
if user then
logger.debug("User got authenticated through basic auth")
authUser = user
return true
else
ngx.req.clear_header("Authorization")
return false -- ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
end
-- Check whether a user is allowed to access a URL using the `permissions` directive
-- of the configuration file
function has_access(permission, user)
@ -413,6 +418,16 @@ function set_headers(user)
end
-- Removes the authentication headers. Call me when:
-- - app is public and user is not authenticated
-- - app requests that no authentication headers be sent
-- Prevents user from pretending to be someone else on public apps
function clear_headers()
-- NB: Basic Auth header is cleared in validate_or_clear_basic_auth_header_provided_by_client
for k, v in pairs(conf["additional_headers"]) do
ngx.req.clear_header(k)
end
end
function refresh_user_cache(user)
-- We definitely don't want to pass credentials on a non-encrypted