Skip to content

authentication_required decorator does not prevent requests from reaching the endpoint as exepcted

Low
brassy-endomorph published GHSA-j857-9q45-73jr Nov 27, 2024

Package

hushline

Affected versions

>=0.2.0,< 0.3.21

Patched versions

0.3.21

Description

Summary

We have a decorated that goes on Flask endpoints called authentication_required that is supposed to prevent a request from reaching the endpoint (i.e., it should redirect to the login endpoint).

Details

The decorator is defined here:

def authentication_required(f: Callable[..., Any]) -> Callable[..., Any]:
@wraps(f)
def decorated_function(*args: Any, **kwargs: Any) -> Any:
if "user_id" not in session:
flash("👉 Please complete authentication.")
return redirect(url_for("login"))
if not session.get("is_authenticated", False):
return redirect(url_for("verify_2fa_login"))
return f(*args, **kwargs)
return decorated_function

One implementation is here:

@authentication_required
@bp.route("/alias/<int:username_id>", methods=["GET", "POST"])
async def alias(username_id: int) -> Response | str:
alias = db.session.scalars(
db.select(Username).filter_by(
id=username_id, user_id=session["user_id"], is_primary=False
)

While logged out, I got the following error:

2024-11-19 16:16:06,054:ERROR:Exception on /settings/alias/3 [GET]
Traceback (most recent call last):
  File "/root/.cache/pypoetry/virtualenvs/hushline-9TtSrW0h-py3.12/lib/python3.12/site-packages/flask/app.py", line 1473, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.cache/pypoetry/virtualenvs/hushline-9TtSrW0h-py3.12/lib/python3.12/site-packages/flask/app.py", line 882, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.cache/pypoetry/virtualenvs/hushline-9TtSrW0h-py3.12/lib/python3.12/site-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.cache/pypoetry/virtualenvs/hushline-9TtSrW0h-py3.12/lib/python3.12/site-packages/flask/app.py", line 865, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.cache/pypoetry/virtualenvs/hushline-9TtSrW0h-py3.12/lib/python3.12/site-packages/asgiref/sync.py", line 254, in __call__
    return call_result.result()
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/root/.cache/pypoetry/virtualenvs/hushline-9TtSrW0h-py3.12/lib/python3.12/site-packages/asgiref/sync.py", line 331, in main_wrap
    result = await self.awaitable(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/hushline/settings/__init__.py", line 758, in alias
    id=username_id, user_id=session["user_id"], is_primary=False
                            ~~~~~~~^^^^^^^^^^^
  File "/root/.cache/pypoetry/virtualenvs/hushline-9TtSrW0h-py3.12/lib/python3.12/site-packages/flask/sessions.py", line 84, in __getitem__
    return super().__getitem__(key)
           ^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 'user_id'

PoC

http -v https://tips.hushline.app/settings/alias/1
GET /settings/alias/1 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Host: tips.hushline.app
User-Agent: HTTPie/3.2.2



HTTP/1.1 500 Internal Server Error
CF-Cache-Status: MISS
CF-RAY: 8e518ce1ab3fe52b-TXL
Cache-Control: private
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Date: Tue, 19 Nov 2024 16:24:25 GMT
Server: cloudflare
Set-Cookie: __cf_bm=RX8FLnJQCa_dtOmHDxSZG86HDFN9vJxc3HpzDNJHAHo-1732033465-1.0.1.1-PWcJ_bhSUaXgnnsrd5XeC3KDyehaoGw4GSEYLSOI1TAbbjSOuHobzrOErnsmAx0oxOWNiN5m6MoDoct0NjOGnA; path=/; expires=Tue, 19-Nov-24 16:54:25 GMT; domain=.tips.hushline.app; HttpOnly; Secure; SameSite=None
Transfer-Encoding: chunked
alt-svc: h3=":443"; ma=86400
onion-location: http://hyewn4dvbedq7ooe3oxrhpceljd7ncfyeyts2c7nwsjp34i46smbzwid.onion/settings/alias/1
vary: Cookie, Accept-Encoding
x-do-app-origin: b54fdff4-850e-4601-b986-9c92ff4d2241
x-do-orig-status: 500

<!doctype html>
<html lang=en>
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>

Impact

I have not checked all endpoints, so I cannot confidently say to what extent C-I-A are affected, but this behavior is absolutely undesirable.

Severity

Low

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N

CVE ID

No known CVE

Credits