GHSA-j6f8-qcj9-gh4r: AshAuthentication log_out_everywhere leaves sessions valid after a password reset or non-atomic password change
Summary
Improper Session Invalidation after Authentication Credential Change vulnerability in team-alembic ashauthentication allows an attacker holding a victim's session token to stay signed in after the victim resets or changes their password.
With applyonpasswordchange? true, AshAuthentication.AddOn.LogOutEverywhere.Transformer adds OnPasswordChange to update actions as a global change guarded by where: changing(hashedpassword). That condition is evaluated before the action's beforeaction hooks run, but AshAuthentication.Strategy.Password.HashPasswordChange sets the new hash in a beforeaction hook, so for every non-atomic password change the condition is false and the user's stored tokens are not revoked. The generated password reset action and the installer's changepassword action are both non-atomic.
This issue affects ashauthentication: from 4.5.0 before 4.15.1 and from 5.0.0-rc.0 before 5.0.0-rc.16.
Configurations
The logouteverywhere add-on sets applyonpasswordchange? true, as mix ashauthentication.install writes, and the password is changed through a non-atomic update action, which includes the generated password reset action and the installer's changepassword action. The attacker must already hold one of the victim's session tokens.
Other sources
Improper Session Invalidation after Authentication Credential Change vulnerability in team-alembic ashauthentication allows an attacker holding a victim's session token to stay signed in after the victim resets or changes their password.
With applyonpasswordchange? true, AshAuthentication.AddOn.LogOutEverywhere.Transformer adds OnPasswordChange to update actions as a global change guarded by where: changing(hashedpassword). That condition is evaluated before the action's beforeaction hooks run, but AshAuthentication.Strategy.Password.HashPasswordChange sets the new hash in a beforeaction hook, so for every non-atomic password change the condition is false and the user's stored tokens are not revoked. The generated password reset action and the installer's changepassword action are both non-atomic.
This issue affects ashauthentication: from 4.5.0 before 4.15.1 and from 5.0.0-rc.0 before 5.0.0-rc.16.
— OSV
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
erlang/ash_authenticationto a version that resolves this vulnerability.Fixed in 4.15.1 - Upgrade
Upgrade
erlang/ash_authenticationto a version that resolves this vulnerability.Fixed in 5.0.0-rc.16 - Upgrade
Upgrade
ash_authenticationto a version that resolves this vulnerability.Fixed in 4.15.1 - Upgrade
Upgrade
ash_authenticationto a version that resolves this vulnerability.Fixed in 5.0.0-rc.16
Event History
Frequently Asked Questions
Which deployments are affected by this issue?
Affected deployments use ash_authentication versions 4.5.0 through before 4.15.1, or 5.0.0-rc.0 through before 5.0.0-rc.16. The log_out_everywhere add-on must have apply_on_password_change? enabled, as written by mix ash_authentication.install, and the password change must use a non-atomic update action.
What does an attacker need to exploit this?
An attacker needs to already possess a victim's valid session token. They can continue using that token after the victim resets or changes their password if token revocation is skipped.
Are the generated password reset and installer-provided password-change actions affected?
Yes. The generated password reset action and the installer's change_password action are non-atomic, so they meet the condition that causes stored tokens not to be revoked.
How can I determine whether my password-change flow is exposed?
Check whether log_out_everywhere is configured with apply_on_password_change? true and whether the relevant password update action is non-atomic. For such actions, the changing(hashed_password) guard is evaluated before the before_action hook that sets the new password hash, preventing the logout-everywhere change from running.