From fb37b1cfc7e6b71dd75dc137ac823df50f0b0244 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 27 Jun 2023 10:24:54 +0300 Subject: [PATCH] - fixed vulnerability with banned keys in usermeta; --- includes/core/class-user.php | 74 +++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/includes/core/class-user.php b/includes/core/class-user.php index 918708e7..598a6f31 100644 --- a/includes/core/class-user.php +++ b/includes/core/class-user.php @@ -78,6 +78,8 @@ if ( ! class_exists( 'um\core\User' ) ) { */ public $target_id = null; + public $updating_process = false; + /** * User constructor. */ @@ -160,8 +162,30 @@ if ( ! class_exists( 'um\core\User' ) ) { add_action( 'update_user_meta', array( &$this, 'flush_um_count_users_transient_update' ), 10, 4 ); add_action( 'added_user_meta', array( &$this, 'flush_um_count_users_transient_add' ), 10, 4 ); add_action( 'delete_user_meta', array( &$this, 'flush_um_count_users_transient_delete' ), 10, 4 ); + + add_action( 'update_user_metadata', array( &$this, 'avoid_banned_keys' ), 10, 3 ); } + /** + * Low-level checking to avoid updating banned user metakeys while UM Forms submission. + * + * @param null|bool $check Whether to allow updating metadata for the given type. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. + * + * @return null|bool + */ + public function avoid_banned_keys( $check, $object_id, $meta_key ) { + if ( false === $this->updating_process ) { + return $check; + } + + if ( in_array( $meta_key, $this->banned_keys, true ) ) { + $check = false; + } + + return $check; + } /** * @param $meta_ids @@ -2104,57 +2128,53 @@ if ( ! class_exists( 'um\core\User' ) ) { um_deprecated_function( 'update_files', '2.1.0', '' ); } - /** * Update profile * * @param $changes */ - function update_profile( $changes ) { - - $args['ID'] = $this->id; + public function update_profile( $changes ) { + $this->updating_process = true; + $args['ID'] = $this->id; /** - * UM hook + * Filters the update profile changes data. * - * @type filter - * @title um_before_update_profile - * @description Change update profile changes data - * @input_vars - * [{"var":"$changes","type":"array","desc":"User Profile Changes"}, - * {"var":"$user_id","type":"int","desc":"User ID"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * Remove some_metakey from changes where user ID equals 12. + * function my_custom_um_prepare_user_results_array_meta( $changes, $user_id ) { + * if ( 12 === $user_id ) { + * unset( $changes['{some_metakey}']; + * } * return $changes; * } - * ?> + * add_filter( 'um_before_update_profile', 'my_custom_before_update_profile', 10, 2 ); */ $changes = apply_filters( 'um_before_update_profile', $changes, $args['ID'] ); foreach ( $changes as $key => $value ) { - if ( in_array( $key, $this->banned_keys ) ) { + if ( in_array( $key, $this->banned_keys, true ) ) { continue; } - if ( ! in_array( $key, $this->update_user_keys ) ) { + if ( ! in_array( $key, $this->update_user_keys, true ) ) { if ( $value === 0 ) { update_user_meta( $this->id, $key, '0' ); } else { update_user_meta( $this->id, $key, $value ); } } else { - $args[ $key ] = $changes[ $key ]; + $args[ $key ] = $value; } } - // update user if ( count( $args ) > 1 ) { //if isset roles argument validate role to properly for security reasons @@ -2162,14 +2182,14 @@ if ( ! class_exists( 'um\core\User' ) ) { global $wp_roles; $exclude_roles = array_diff( array_keys( $wp_roles->roles ), UM()->roles()->get_editable_user_roles() ); - if ( in_array( $args['role'], $exclude_roles ) ) { + if ( in_array( $args['role'], $exclude_roles, true ) ) { unset( $args['role'] ); } } wp_update_user( $args ); } - + $this->updating_process = false; }