Skip to content

Commit

Permalink
Fixed Multi-Factor Authentication bypass vulnerability (CVE-2024-4215).
Browse files Browse the repository at this point in the history
  • Loading branch information
khushboovashi authored and akshay-joshi committed Apr 29, 2024
1 parent e18a8bf commit f4761f5
Show file tree
Hide file tree
Showing 35 changed files with 309 additions and 271 deletions.
5 changes: 3 additions & 2 deletions docs/en_US/release_notes_8_6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ Bug fixes
| `Issue #2410 <https://github.com/pgadmin-org/pgadmin4/issues/2410>`_ - Fixed all input boxes in pgAdmin to show browser auto-fill only where it is relevant.
| `Issue #7173 <https://github.com/pgadmin-org/pgadmin4/issues/7173>`_ - Install dbus-python, an in-direct dependency of the Keyring package as a system package for Debian platforms.
| `Issue #7275 <https://github.com/pgadmin-org/pgadmin4/issues/7275>`_ - Fixed an issue where debugger was not scrolling automatically on stepping.
| `Issue #7282 <https://github.com/pgadmin-org/pgadmin4/issues/7282>`_ - Fixed an XSS vulnerability in the /settings/store endpoint.
| `Issue #7282 <https://github.com/pgadmin-org/pgadmin4/issues/7282>`_ - Fixed an XSS vulnerability in the /settings/store endpoint (CVE-2024-4216).
| `Issue #7294 <https://github.com/pgadmin-org/pgadmin4/issues/7294>`_ - Fixed an issue where double dollar quoted code is treated as string in syntax highlighter.
| `Issue #7317 <https://github.com/pgadmin-org/pgadmin4/issues/7317>`_ - Fixed an issue where pressing backspace should remove the spaces and not the entire tab width, on enabling 'Use spaces?' in the preferences.
| `Issue #7334 <https://github.com/pgadmin-org/pgadmin4/issues/7334>`_ - Fixed an issue where incorrect select/exec scripts were generated for functions/procedures.
| `Issue #7372 <https://github.com/pgadmin-org/pgadmin4/issues/7372>`_ - Fixed an issue where connection to the database is not automatically re-established after connectivity drop.
| `Issue #7384 <https://github.com/pgadmin-org/pgadmin4/issues/7384>`_ - Fixed an issue when closing the view data second tab; it raises the error that the 'ViewCommand' object has no attribute 'auto_commit'.
| `Issue #7390 <https://github.com/pgadmin-org/pgadmin4/issues/7390>`_ - Fixed violates check constraint issue when creating a pgAgent schedule.
| `Issue #7390 <https://github.com/pgadmin-org/pgadmin4/issues/7390>`_ - Fixed violates check constraint issue when creating a pgAgent schedule.
| `Issue #7425 <https://github.com/pgadmin-org/pgadmin4/issues/7425>`_ - Fixed Multi-Factor Authentication bypass vulnerability (CVE-2024-4215).
7 changes: 4 additions & 3 deletions web/pgadmin/about/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

from flask import Response, render_template, request
from flask_babel import gettext
from flask_security import current_user, login_required
from flask_security import current_user
from pgadmin.user_login_check import pga_login_required
from pgadmin.utils import PgAdminModule
from pgadmin.utils.menu import MenuItem
from pgadmin.utils.constants import MIMETYPE_APP_JS
Expand Down Expand Up @@ -53,7 +54,7 @@ def get_exposed_url_endpoints(self):
# A test page
##########################################################################
@blueprint.route("/", endpoint='index')
@login_required
@pga_login_required
def index():
"""Render the about box."""
info = {}
Expand Down Expand Up @@ -138,7 +139,7 @@ def detect_browser(request):


@blueprint.route("/about.js")
@login_required
@pga_login_required
def script():
"""render the required javascript"""
return Response(
Expand Down
14 changes: 6 additions & 8 deletions web/pgadmin/authenticate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@
from flask_login import current_user
from flask_socketio import disconnect, ConnectionRefusedError


from pgadmin.model import db, User
from pgadmin.utils import PgAdminModule, get_safe_post_login_redirect, \
get_safe_post_logout_redirect
from pgadmin.utils.constants import KERBEROS, INTERNAL, OAUTH2, LDAP,\
MessageType
import pgadmin.utils as pga_utils
from pgadmin.authenticate.registry import AuthSourceRegistry

MODULE_NAME = 'authenticate'
Expand Down Expand Up @@ -84,7 +82,7 @@ def wrapped(*args, **kwargs):
return wrapped


class AuthenticateModule(PgAdminModule):
class AuthenticateModule(pga_utils.PgAdminModule):
def get_exposed_url_endpoints(self):
return ['authenticate.login']

Expand Down Expand Up @@ -135,7 +133,7 @@ def _login():
'Administrator.'),
MessageType.WARNING)
logout_user()
return redirect(get_safe_post_logout_redirect())
return redirect(pga_utils.get_safe_post_logout_redirect())

# Validate the user
if not auth_obj.validate():
Expand All @@ -161,7 +159,7 @@ def _login():
flash_login_attempt_error = None
flash(error, MessageType.WARNING)

return redirect(get_safe_post_logout_redirect())
return redirect(pga_utils.get_safe_post_logout_redirect())

# Authenticate the user
status, msg = auth_obj.authenticate()
Expand All @@ -177,7 +175,7 @@ def _login():
'authenticate.kerberos_login'), url_for('browser.index')))

flash(msg, MessageType.ERROR)
return redirect(get_safe_post_logout_redirect())
return redirect(pga_utils.get_safe_post_logout_redirect())

session['auth_source_manager'] = current_auth_obj

Expand All @@ -187,7 +185,7 @@ def _login():

if 'auth_obj' in session:
session.pop('auth_obj')
return redirect(get_safe_post_login_redirect())
return redirect(pga_utils.get_safe_post_login_redirect())

elif isinstance(msg, Response):
return msg
Expand Down
6 changes: 3 additions & 3 deletions web/pgadmin/authenticate/kerberos.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
current_app, render_template, flash, url_for
from flask_security.views import _security
from flask_security.utils import logout_user
from flask_security import login_required
from pgadmin.user_login_check import pga_login_required

import config
from pgadmin.model import User
Expand Down Expand Up @@ -97,7 +97,7 @@ def kerberos_logout():
@blueprint.route("/update_ticket",
endpoint="update_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
@pga_login_required
def kerberos_update_ticket():
"""
Update the kerberos ticket.
Expand Down Expand Up @@ -127,7 +127,7 @@ def kerberos_update_ticket():
@blueprint.route("/validate_ticket",
endpoint="validate_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
@pga_login_required
def kerberos_validate_ticket():
"""
Return the kerberos ticket lifetime left after getting the
Expand Down
6 changes: 3 additions & 3 deletions web/pgadmin/authenticate/mfa/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from flask import url_for, session, request, redirect
from flask_login.utils import login_url
from flask_security import current_user
from flask_security import current_user, login_required

import config
from pgadmin.model import UserMFA, db
Expand Down Expand Up @@ -279,7 +279,7 @@ def get_next_url():
registration_url = url_for('mfa.register')

if next_url.startswith(registration_url):
return url('browser.index')
return url_for('browser.index')

return next_url

Expand All @@ -290,8 +290,8 @@ def redirect_to_mfa_registration():
return redirect(login_url("mfa.register", next_url=get_next_url()))

@wraps(wrapped)
@login_required
def inner(*args, **kwargs):

def execute_func():
session['mfa_authenticated'] = True
return wrapped(*args, **kwargs)
Expand Down
17 changes: 9 additions & 8 deletions web/pgadmin/browser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
flash, Response, request, after_this_request, redirect, session
from flask_babel import gettext
from libgravatar import Gravatar
from flask_security import current_user, login_required
from flask_security import current_user
from flask_login.utils import login_url
from flask_security.changeable import send_password_changed_notice
from flask_security.decorators import anonymous_user_required
Expand Down Expand Up @@ -64,6 +64,8 @@
from pgadmin.authenticate import AuthSourceManager
from pgadmin.utils.exception import CryptKeyMissing

from pgadmin.user_login_check import pga_login_required

try:
from flask_security.views import default_render_json
except ImportError as e:
Expand Down Expand Up @@ -377,8 +379,7 @@ def gravatar(username):

@blueprint.route("/")
@pgCSRFProtect.exempt
@login_required
@mfa_required
@pga_login_required
def index():
"""Render and process the main browser window."""

Expand Down Expand Up @@ -471,7 +472,7 @@ def get_shared_storage_list():

@blueprint.route("/js/utils.js")
@pgCSRFProtect.exempt
@login_required
@pga_login_required
def utils():
layout = get_setting('Browser/Layout', default='')
snippets = []
Expand Down Expand Up @@ -592,7 +593,7 @@ def exposed_urls():

@blueprint.route("/js/error.js")
@pgCSRFProtect.exempt
@login_required
@pga_login_required
def error_js():
return make_response(
render_template('browser/js/error.js', _=gettext),
Expand All @@ -609,7 +610,7 @@ def messages_js():

@blueprint.route("/browser.css")
@pgCSRFProtect.exempt
@login_required
@pga_login_required
def browser_css():
"""Render and return CSS snippets from the nodes and modules."""
snippets = []
Expand All @@ -624,7 +625,7 @@ def browser_css():


@blueprint.route("/nodes/", endpoint="nodes")
@login_required
@pga_login_required
def get_nodes():
"""Build a list of treeview nodes from the child nodes."""
nodes = []
Expand Down Expand Up @@ -931,7 +932,7 @@ def set_master_password():
@blueprint.route("/change_password", endpoint="change_password",
methods=['GET', 'POST'])
@pgCSRFProtect.exempt
@login_required
@pga_login_required
def change_password():
"""View function which handles a change password request."""

Expand Down
25 changes: 13 additions & 12 deletions web/pgadmin/browser/server_groups/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

from flask import request, jsonify, render_template
from flask_babel import gettext
from flask_security import current_user, login_required
from flask_security import current_user
from pgadmin.user_login_check import pga_login_required
from pgadmin.browser import BrowserPluginModule
from pgadmin.browser.utils import NodeView
from pgadmin.utils.ajax import make_json_response, gone, \
Expand Down Expand Up @@ -162,7 +163,7 @@ class ServerGroupView(NodeView):
parent_ids = []
ids = [{'type': 'int', 'id': 'gid'}]

@login_required
@pga_login_required
def list(self):
res = []

Expand All @@ -176,7 +177,7 @@ def list(self):

return ajax_response(response=res, status=200)

@login_required
@pga_login_required
def delete(self, gid):
"""Delete a server group node in the settings database"""

Expand Down Expand Up @@ -232,7 +233,7 @@ def delete(self, gid):

return make_json_response(result=request.form)

@login_required
@pga_login_required
def update(self, gid):
"""Update the server-group properties"""

Expand Down Expand Up @@ -281,7 +282,7 @@ def update(self, gid):
)
)

@login_required
@pga_login_required
def properties(self, gid):
"""Update the server-group properties"""

Expand All @@ -299,7 +300,7 @@ def properties(self, gid):
status=200
)

@login_required
@pga_login_required
def create(self):
"""Creates new server-group """
data = request.form if request.form else json.loads(
Expand Down Expand Up @@ -349,23 +350,23 @@ def create(self):
success=0,
errormsg=gettext('No server group name was specified'))

@login_required
@pga_login_required
def sql(self, gid):
return make_json_response(status=422)

@login_required
@pga_login_required
def modified_sql(self, gid):
return make_json_response(status=422)

@login_required
@pga_login_required
def statistics(self, gid):
return make_json_response(status=422)

@login_required
@pga_login_required
def dependencies(self, gid):
return make_json_response(status=422)

@login_required
@pga_login_required
def dependents(self, gid):
return make_json_response(status=422)

Expand Down Expand Up @@ -394,7 +395,7 @@ def get_all_server_groups():
groups.append(group)
return groups

@login_required
@pga_login_required
def nodes(self, gid=None):
"""Return a JSON document listing the server groups for the user"""
nodes = []
Expand Down
Loading

0 comments on commit f4761f5

Please sign in to comment.