Fixed a remote code execution issue in the validate binary path (CVE-2024-3116). #7326
parent
26b279cc8a
commit
fbbbfe22dd
|
@ -50,4 +50,4 @@ Bug fixes
|
|||
| `Issue #7305 <https://github.com/pgadmin-org/pgadmin4/issues/7305>`_ - Fix an issue in query tool where custom keyboard shortcuts are not working for some.
|
||||
| `Issue #7304 <https://github.com/pgadmin-org/pgadmin4/issues/7304>`_ - Fixed the issue where the update-user CLI command doesn't change the password.
|
||||
| `Issue #7308 <https://github.com/pgadmin-org/pgadmin4/issues/7308>`_ - Fixed issue related to email authentication of Two-factor authentication.
|
||||
|
||||
| `Issue #7326 <https://github.com/pgadmin-org/pgadmin4/issues/7326>`_ - Fixed a remote code execution issue in the validate binary path (CVE-2024-3116).
|
||||
|
|
|
@ -469,6 +469,26 @@ DEFAULT_BINARY_PATHS = {
|
|||
"ppas-16": ""
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
|
||||
# Admin can specify fixed binary paths to prevent users from changing.
|
||||
# It will take precedence over DEFAULT_BINARY_PATHS.
|
||||
|
||||
FIXED_BINARY_PATHS = {
|
||||
"pg": "",
|
||||
"pg-12": "",
|
||||
"pg-13": "",
|
||||
"pg-14": "",
|
||||
"pg-15": "",
|
||||
"pg-16": "",
|
||||
"ppas": "",
|
||||
"ppas-12": "",
|
||||
"ppas-13": "",
|
||||
"ppas-14": "",
|
||||
"ppas-15": "",
|
||||
"ppas-16": ""
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Test settings - used primarily by the regression suite, not for users
|
||||
##########################################################################
|
||||
|
|
|
@ -49,6 +49,10 @@ export default class BinaryPathSchema extends BaseUISchema {
|
|||
{
|
||||
id: 'binaryPath', label: gettext('Binary Path'), cell: 'file', type: 'file',
|
||||
isvalidate: true,
|
||||
disabled: function (state) {
|
||||
// If Fixed path is assigned, user will not able to edit it.
|
||||
return state?.isFixed ? state.isFixed : false;
|
||||
},
|
||||
controlProps: {
|
||||
dialogType: 'select_folder',
|
||||
supportedTypes: ['*', 'sql', 'backup'],
|
||||
|
|
|
@ -11,7 +11,6 @@ import os
|
|||
import json
|
||||
import config
|
||||
import copy
|
||||
|
||||
from flask import render_template
|
||||
from flask_babel import gettext as _
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
|
@ -240,15 +239,22 @@ class ServerType():
|
|||
"""
|
||||
is_default_path_set = ServerType.is_default_binary_path_set(bin_paths)
|
||||
for path in config.DEFAULT_BINARY_PATHS:
|
||||
path_value = config.DEFAULT_BINARY_PATHS[path]
|
||||
is_fixed_path = (path in config.FIXED_BINARY_PATHS and
|
||||
config.FIXED_BINARY_PATHS[path] != '' and
|
||||
config.FIXED_BINARY_PATHS[path] is not None)
|
||||
path_value = (is_fixed_path and config.FIXED_BINARY_PATHS[path]
|
||||
) or config.DEFAULT_BINARY_PATHS[path]
|
||||
|
||||
if path_value is not None and path_value != "" and \
|
||||
path.find(server_type) == 0 and len(path.split('-')) > 1:
|
||||
set_binary_path(path_value, bin_paths, server_type,
|
||||
path.split('-')[1])
|
||||
set_binary_path(
|
||||
path_value, bin_paths, server_type, path.split('-')[1],
|
||||
is_fixed_path=is_fixed_path)
|
||||
elif path_value is not None and path_value != "" and \
|
||||
path.find(server_type) == 0:
|
||||
set_binary_path(path_value, bin_paths, server_type,
|
||||
set_as_default=not is_default_path_set)
|
||||
set_as_default=not is_default_path_set,
|
||||
is_fixed_path=is_fixed_path)
|
||||
|
||||
|
||||
# Default Server Type
|
||||
|
|
|
@ -62,6 +62,8 @@ define('pgadmin.browser.utils',
|
|||
/* GET Binary Path Browse config */
|
||||
pgAdmin['enable_binary_path_browsing'] = '{{ current_app.config.get('ENABLE_BINARY_PATH_BROWSING') }}' == 'True';
|
||||
|
||||
pgAdmin['fixed_binary_paths'] = {{ current_app.config.get('FIXED_BINARY_PATHS') }};
|
||||
|
||||
/* GET the pgadmin server's locale */
|
||||
pgAdmin['pgadmin_server_locale'] = '{{pgadmin_server_locale}}';
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ from flask import render_template, Response, request, current_app
|
|||
from flask.helpers import url_for
|
||||
from flask_babel import gettext
|
||||
from flask_security import login_required
|
||||
from pathlib import Path
|
||||
from pgadmin.utils import PgAdminModule, replace_binary_path, \
|
||||
get_binary_path_versions
|
||||
from pgadmin.utils.csrf import pgCSRFProtect
|
||||
|
@ -234,7 +235,11 @@ def validate_binary_path():
|
|||
data = json.loads(data)
|
||||
|
||||
version_str = ''
|
||||
if 'utility_path' in data and data['utility_path'] is not None:
|
||||
|
||||
# Do not allow storage dir as utility path
|
||||
if 'utility_path' in data and data['utility_path'] is not None and \
|
||||
Path(config.STORAGE_DIR) != Path(data['utility_path']) and \
|
||||
Path(config.STORAGE_DIR) not in Path(data['utility_path']).parents:
|
||||
binary_versions = get_binary_path_versions(data['utility_path'])
|
||||
for utility, version in binary_versions.items():
|
||||
if version is None:
|
||||
|
@ -248,7 +253,8 @@ def validate_binary_path():
|
|||
return make_json_response(data=gettext(version_str), status=200)
|
||||
|
||||
|
||||
@blueprint.route("/upgrade_check", endpoint="upgrade_check", methods=['GET'])
|
||||
@blueprint.route("/upgrade_check", endpoint="upgrade_check",
|
||||
methods=['GET'])
|
||||
@login_required
|
||||
def upgrade_check():
|
||||
# Get the current version info from the website, and flash a message if
|
||||
|
|
|
@ -14,13 +14,14 @@ import subprocess
|
|||
from collections import defaultdict
|
||||
from operator import attrgetter
|
||||
|
||||
from pathlib import Path
|
||||
from flask import Blueprint, current_app, url_for
|
||||
from flask_babel import gettext
|
||||
from flask_security import current_user, login_required
|
||||
from flask_security.utils import get_post_login_redirect, \
|
||||
get_post_logout_redirect
|
||||
from threading import Lock
|
||||
|
||||
import config
|
||||
from .paths import get_storage_directory
|
||||
from .preferences import Preferences
|
||||
from pgadmin.utils.constants import UTILITIES_ARRAY, USER_NOT_FOUND, \
|
||||
|
@ -308,11 +309,18 @@ def does_utility_exist(file):
|
|||
:return:
|
||||
"""
|
||||
error_msg = None
|
||||
|
||||
if file is None:
|
||||
error_msg = gettext("Utility file not found. Please correct the Binary"
|
||||
" Path in the Preferences dialog")
|
||||
return error_msg
|
||||
|
||||
if Path(config.STORAGE_DIR) == Path(file) or \
|
||||
Path(config.STORAGE_DIR) in Path(file).parents:
|
||||
error_msg = gettext("Please correct the Binary Path in the Preferences"
|
||||
" dialog. pgAdmin storage directory can not be a"
|
||||
" utility binary directory.")
|
||||
|
||||
if not os.path.exists(file):
|
||||
error_msg = gettext("'%s' file not found. Please correct the Binary"
|
||||
" Path in the Preferences dialog" % file)
|
||||
|
@ -364,7 +372,8 @@ def get_binary_path_versions(binary_path: str) -> dict:
|
|||
|
||||
|
||||
def set_binary_path(binary_path, bin_paths, server_type,
|
||||
version_number=None, set_as_default=False):
|
||||
version_number=None, set_as_default=False,
|
||||
is_fixed_path=False):
|
||||
"""
|
||||
This function is used to iterate through the utilities and set the
|
||||
default binary path.
|
||||
|
@ -394,6 +403,8 @@ def set_binary_path(binary_path, bin_paths, server_type,
|
|||
if path_with_dir is not None else binary_path
|
||||
if set_as_default:
|
||||
path['isDefault'] = True
|
||||
# Whether the fixed path in the config file exists or not
|
||||
path['isFixed'] = is_fixed_path
|
||||
break
|
||||
break
|
||||
except Exception:
|
||||
|
|
Loading…
Reference in New Issue