Update dynamic function blacklist for security enhancement

Added a mechanism to dynamically retrieve and merge updated WordPress function lists into the blacklist to prevent unsafe usage in dropdown options. Addresses a security issue (CVE-2025-47691) by using a JSON-based function source tied to WordPress versioning.
This commit is contained in:
Mykyta Synelnikov
2025-05-12 13:16:17 +03:00
parent 1181b7956d
commit 9d83fba560
7 changed files with 3941 additions and 5 deletions
+7 -1
View File
@@ -33,7 +33,13 @@
"phpcompatibility/phpcompatibility-wp": "*",
"wp-coding-standards/wpcs": "2.3.0",
"squizlabs/php_codesniffer": "3.*",
"phpdocumentor/phpdocumentor": "3.1.*"
"phpdocumentor/phpdocumentor": "3.1.*",
"sniccowp/php-scoper-wordpress-excludes": "6.8.*"
},
"scripts": {
"wordpress-excludes": [
"@php -r \"$dest = 'includes/lib/php-scoper-wordpress-excludes/'; if (!is_dir($dest)) { mkdir($dest, 0755, true); }; copy('vendor/sniccowp/php-scoper-wordpress-excludes/generated/exclude-wordpress-functions.json', $dest . 'exclude-wordpress-functions.json');\""
]
},
"extra": {
"installer-paths": {
+7 -1
View File
@@ -55,6 +55,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Builder' ) ) {
return $errors;
}
$functions_blacklist_error = UM()->builtin()->functions_blacklist_field_err( $submission_data['post'] );
if ( ! empty( $functions_blacklist_error ) ) {
$errors['_custom_dropdown_options_source'] = $functions_blacklist_error;
return $errors;
}
$field_attr = UM()->builtin()->get_core_field_attrs( $submission_data['field_type'] );
if ( ! array_key_exists( 'validate', $field_attr ) ) {
return $errors;
@@ -1151,7 +1157,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Builder' ) ) {
* @return boolean
*/
public function skip_field_validation( $skip, $post_input, $array ) {
if ( $post_input === '_options' && isset( $array['post']['_custom_dropdown_options_source'] ) ) {
if ( '_options' === $post_input && isset( $array['post']['_custom_dropdown_options_source'] ) ) {
$skip = function_exists( wp_unslash( $array['post']['_custom_dropdown_options_source'] ) );
}
+19
View File
@@ -193,6 +193,25 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
return 0;
}
/**
* Checks for a blacklist function in the custom callback field error.
*
* @param array $args Custom field submission data.
*
* @return int|string Empty or error string.
*/
public function functions_blacklist_field_err( $args ) {
if ( empty( $args['_custom_dropdown_options_source'] ) ) {
return 0;
}
if ( UM()->fields()->is_source_blacklisted( $args['_custom_dropdown_options_source'] ) ) {
return __( 'This is not possible for security reasons.', 'ultimate-member' );
}
return 0;
}
/**
* Check date range errors (start date)
*
+24 -2
View File
@@ -1379,8 +1379,30 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
public function dropdown_options_source_blacklist() {
$list = get_defined_functions();
$blacklist = ! empty( $list['internal'] ) ? $list['internal'] : array();
$blacklist = apply_filters( 'um_dropdown_options_source_blacklist', $blacklist );
return $blacklist;
// Get the saved version from the database
$wp_functions_version = get_option( 'um_wp_functions_version' );
if ( empty( $wp_functions_version ) || version_compare( UM_WP_FUNCTIONS_VERSION, $wp_functions_version, '>' ) ) {
// Load the JSON file's content
$jsonContent = file_get_contents( UM_PATH . 'includes/lib/php-scoper-wordpress-excludes/exclude-wordpress-functions.json' );
// Parse the JSON string into a PHP array
$um_wp_native_functions_list = json_decode( $jsonContent, true );
// Save the decoded JSON into wp_option
update_option( 'um_wp_functions_list', $um_wp_native_functions_list );
// Update the saved version in the database
update_option( 'um_wp_functions_version', UM_WP_FUNCTIONS_VERSION );
} else {
$um_wp_native_functions_list = get_option( 'um_wp_functions_list', array() );
}
if ( ! empty( $um_wp_native_functions_list ) ) {
$blacklist = array_merge( $blacklist, $um_wp_native_functions_list );
}
return apply_filters( 'um_dropdown_options_source_blacklist', $blacklist );
}
/**
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -167,10 +167,11 @@ No specific extensions are needed. But we highly recommended keep active these P
IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION
= 2.10.4 2025-05-xx =
= 2.10.4 2025-05-14 =
**Bugfixes**
* Fixed: Security issue CVE ID: CVE-2025-47691. Used "sniccowp/php-scoper-wordpress-excludes" for getting the recent WordPress functions list and added them to the dynamic blacklist based on the WordPress version.
* Fixed: The Action Scheduler action `um_set_default_account_status`. Case when some users were approved manually or deleted, and we need to reset the admin notice. Added `error_log()` to the wrong conditions.
= 2.10.3 2025-04-24 =
@@ -247,6 +248,9 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI
== Upgrade Notice ==
= 2.10.4 =
This version fixes a security related bug. Upgrade immediately.
= 2.10.2 =
This version fixes a security related bug. Upgrade immediately.
+1
View File
@@ -32,6 +32,7 @@ define( 'UM_PATH', plugin_dir_path( __FILE__ ) );
define( 'UM_PLUGIN', plugin_basename( __FILE__ ) );
define( 'UM_VERSION', $plugin_data['Version'] );
define( 'UM_PLUGIN_NAME', $plugin_data['Name'] );
define( 'UM_WP_FUNCTIONS_VERSION', '6.8.0' ); // Updates every major WordPress release.
// define( 'UM_DEV_MODE', true );
require_once 'includes/class-functions.php';