From abb114c375c79f8f2ca70e68e34aae1a24387430 Mon Sep 17 00:00:00 2001 From: Jurjen de Jonge Date: Sat, 4 Jun 2022 21:27:30 +0300 Subject: [PATCH] security: delay server response whenever username is non existing (#1338) * Delay server response whenever username is non existing * utilize hasher to achieve constant timing Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com> --- mealie/core/security/security.py | 12 +++++++++--- mealie/routes/auth/auth.py | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mealie/core/security/security.py b/mealie/core/security/security.py index 90f53fd9ec78..0e9188a26723 100644 --- a/mealie/core/security/security.py +++ b/mealie/core/security/security.py @@ -79,15 +79,21 @@ def authenticate_user(session, email: str, password: str) -> PrivateUser | bool: settings = get_app_settings() db = get_repositories(session) - user: PrivateUser = db.users.get(email, "email", any_case=True) + user = db.users.get_one(email, "email", any_case=True) if not user: - user = db.users.get(email, "username", any_case=True) + user = db.users.get_one(email, "username", any_case=True) if settings.LDAP_AUTH_ENABLED and (not user or user.password == "LDAP"): return user_from_ldap(db, session, email, password) - if not user or not verify_password(password, user.password): + if not user: + # To prevent user enumeration we perform the verify_password computation to ensure + # server side time is relatively constant and not vulnerable to timing attacks. + verify_password("abc123cba321", "$2b$12$JdHtJOlkPFwyxdjdygEzPOtYmdQF5/R5tHxw5Tq8pxjubyLqdIX5i") + return False + + elif not verify_password(password, user.password): return False return user diff --git a/mealie/routes/auth/auth.py b/mealie/routes/auth/auth.py index 61b5ff7d40cd..c5ed2885bdee 100644 --- a/mealie/routes/auth/auth.py +++ b/mealie/routes/auth/auth.py @@ -49,6 +49,7 @@ class MealieAuthToken(BaseModel): @public_router.post("/token") def get_token(data: CustomOAuth2Form = Depends(), session: Session = Depends(generate_session)): + email = data.username password = data.password