Fixed Multi-Factor Authentication bypass vulnerability (CVE-2024-4215). #7425

This commit is contained in:
Khushboo Vashi
2024-04-29 13:41:02 +05:30
committed by Akshay Joshi
parent e18a8bf620
commit f4761f55f7
35 changed files with 309 additions and 271 deletions

View File

@@ -28,7 +28,7 @@ from flask import current_app, render_template, url_for, make_response, \
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
@@ -64,6 +64,8 @@ from pgadmin.utils.constants import MIMETYPE_APP_JS, PGADMIN_NODE,\
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:
@@ -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."""
@@ -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 = []
@@ -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),
@@ -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 = []
@@ -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 = []
@@ -931,7 +932,7 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
@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."""

View File

@@ -14,7 +14,8 @@ from abc import ABCMeta, abstractmethod
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, \
@@ -162,7 +163,7 @@ class ServerGroupView(NodeView):
parent_ids = []
ids = [{'type': 'int', 'id': 'gid'}]
@login_required
@pga_login_required
def list(self):
res = []
@@ -176,7 +177,7 @@ class ServerGroupView(NodeView):
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"""
@@ -232,7 +233,7 @@ class ServerGroupView(NodeView):
return make_json_response(result=request.form)
@login_required
@pga_login_required
def update(self, gid):
"""Update the server-group properties"""
@@ -281,7 +282,7 @@ class ServerGroupView(NodeView):
)
)
@login_required
@pga_login_required
def properties(self, gid):
"""Update the server-group properties"""
@@ -299,7 +300,7 @@ class ServerGroupView(NodeView):
status=200
)
@login_required
@pga_login_required
def create(self):
"""Creates new server-group """
data = request.form if request.form else json.loads(
@@ -349,23 +350,23 @@ class ServerGroupView(NodeView):
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)
@@ -394,7 +395,7 @@ class ServerGroupView(NodeView):
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 = []

View File

@@ -13,7 +13,8 @@ import pgadmin.browser.server_groups as sg
from flask import render_template, request, make_response, jsonify, \
current_app, url_for, session
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 psycopg.conninfo import make_conninfo, conninfo_to_dict
from pgadmin.browser.server_groups.servers.types import ServerType
@@ -218,7 +219,7 @@ class ServerModule(sg.ServerGroupPluginModule):
return servers
@login_required
@pga_login_required
def get_nodes(self, gid):
"""Return a JSON document listing the server groups for the user"""
@@ -564,7 +565,7 @@ class ServerNode(PGChildNodeView):
data['connection_params'] = existing_conn_params
@login_required
@pga_login_required
def nodes(self, gid):
res = []
"""
@@ -650,7 +651,7 @@ class ServerNode(PGChildNodeView):
return make_json_response(result=res)
@login_required
@pga_login_required
def node(self, gid, sid):
"""Return a JSON document listing the server groups for the user"""
server = Server.query.filter_by(id=sid).first()
@@ -733,7 +734,7 @@ class ServerNode(PGChildNodeView):
success=0,
errormsg=e.message)
@login_required
@pga_login_required
def delete(self, gid, sid):
"""Delete a server node in the settings database."""
servers = Server.query.filter_by(user_id=current_user.id, id=sid)
@@ -783,7 +784,7 @@ class ServerNode(PGChildNodeView):
return make_json_response(success=1,
info=gettext("Server deleted"))
@login_required
@pga_login_required
def update(self, gid, sid):
"""Update the server settings"""
server = Server.query.filter_by(id=sid).first()
@@ -988,7 +989,7 @@ class ServerNode(PGChildNodeView):
).format(disp_lbl[arg])
)
@login_required
@pga_login_required
def list(self, gid):
"""
Return list of attributes of all servers.
@@ -1035,7 +1036,7 @@ class ServerNode(PGChildNodeView):
response=res
)
@login_required
@pga_login_required
def properties(self, gid, sid):
"""Return list of attributes of a server"""
@@ -1154,7 +1155,7 @@ class ServerNode(PGChildNodeView):
display_conn_string = make_conninfo(**con_info_ord)
return display_conn_string
@login_required
@pga_login_required
def create(self, gid):
"""Add a server node to the settings database"""
required_args = ['name', 'db']
@@ -1376,15 +1377,15 @@ class ServerNode(PGChildNodeView):
errormsg=str(e)
)
@login_required
@pga_login_required
def sql(self, gid, sid):
return make_json_response(data='')
@login_required
@pga_login_required
def modified_sql(self, gid, sid):
return make_json_response(data='')
@login_required
@pga_login_required
def statistics(self, gid, sid):
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
conn = manager.connection()
@@ -1408,11 +1409,11 @@ class ServerNode(PGChildNodeView):
)
)
@login_required
@pga_login_required
def dependencies(self, gid, sid):
return make_json_response(data='')
@login_required
@pga_login_required
def dependents(self, gid, sid):
return make_json_response(data='')