Custom dropdown callback functions security enhancements:

- avoid using different letter case for bypass the blacklist e.g. phpInfo
- avoid using root namespace for bypass the blacklist e.g. \phpinfo
This commit is contained in:
Nikita Sinelnikov
2022-11-09 03:17:23 +02:00
parent 096a1caf27
commit 2004aa7dde
6 changed files with 31 additions and 12 deletions
+1 -1
View File
@@ -1220,7 +1220,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Builder' ) ) {
$arr_options['function_exists'] = function_exists( $um_callback_func );
}
if ( in_array( $um_callback_func, UM()->fields()->dropdown_options_source_blacklist(), true ) ) {
if ( UM()->fields()->is_source_blacklisted( $um_callback_func ) ) {
wp_send_json_error( __( 'This is not possible for security reasons. Don\'t use internal PHP functions.', 'ultimate-member' ) );
}
+26 -7
View File
@@ -112,7 +112,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
$output = null;
foreach ( $fields as $key => $data ) {
$output .= UM()->fields()->edit_field( $key, $data );
$output .= $this->edit_field( $key, $data );
}
echo $output;
@@ -147,7 +147,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
if ( array_key_exists( 'custom_dropdown_options_source', $args ) ) {
if ( function_exists( wp_unslash( $args['custom_dropdown_options_source'] ) ) ) {
if ( ! in_array( $args['custom_dropdown_options_source'], UM()->fields()->dropdown_options_source_blacklist(), true ) ) {
if ( ! $this->is_source_blacklisted( $args['custom_dropdown_options_source'] ) ) {
$allowed_callbacks = UM()->options()->get( 'allowed_choice_callbacks' );
if ( ! empty( $allowed_callbacks ) ) {
$allowed_callbacks = array_map( 'rtrim', explode( "\n", $allowed_callbacks ) );
@@ -204,7 +204,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
if ( array_key_exists( 'custom_dropdown_options_source', $args ) ) {
if ( function_exists( wp_unslash( $args['custom_dropdown_options_source'] ) ) ) {
if ( ! in_array( $args['custom_dropdown_options_source'], UM()->fields()->dropdown_options_source_blacklist(), true ) ) {
if ( ! $this->is_source_blacklisted( $args['custom_dropdown_options_source'] ) ) {
$allowed_callbacks = UM()->options()->get( 'allowed_choice_callbacks' );
if ( ! empty( $allowed_callbacks ) ) {
$allowed_callbacks = array_map( 'rtrim', explode( "\n", $allowed_callbacks ) );
@@ -1309,6 +1309,25 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
return $blacklist;
}
/**
* Is the dropdown source callback function blacklisted?
*
* @param string $source Function name
*
* @return bool
*/
public function is_source_blacklisted( $source ) {
// avoid using different letter case for bypass the blacklist e.g. phpInfo
// avoid using root namespace for bypass the blacklist e.g. \phpinfo
$source = trim( strtolower( $source ), '\\' );
if ( in_array( $source, $this->dropdown_options_source_blacklist(), true ) ) {
return true;
}
return false;
}
/**
* Gets selected option value from a callback function
*
@@ -1322,7 +1341,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
if ( in_array( $type, array( 'select', 'multiselect' ) ) && ! empty( $data['custom_dropdown_options_source'] ) ) {
if ( in_array( $data['custom_dropdown_options_source'], $this->dropdown_options_source_blacklist(), true ) ) {
if ( $this->is_source_blacklisted( $data['custom_dropdown_options_source'] ) ) {
return $value;
}
@@ -1393,7 +1412,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
if ( in_array( $type, array( 'select', 'multiselect' ) ) && ! empty( $data['custom_dropdown_options_source'] ) ) {
if ( in_array( $data['custom_dropdown_options_source'], $this->dropdown_options_source_blacklist(), true ) ) {
if ( $this->is_source_blacklisted( $data['custom_dropdown_options_source'] ) ) {
return $arr_options;
}
@@ -3062,7 +3081,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
if ( ! empty( $data['custom_dropdown_options_source'] ) && $has_parent_option && function_exists( $data['custom_dropdown_options_source'] ) &&
um_user( $data['parent_dropdown_relationship'] )
) {
if ( ! in_array( $data['custom_dropdown_options_source'], $this->dropdown_options_source_blacklist(), true ) ) {
if ( ! $this->is_source_blacklisted( $data['custom_dropdown_options_source'] ) ) {
$options = call_user_func( $data['custom_dropdown_options_source'], $data['parent_dropdown_relationship'] );
}
@@ -3082,7 +3101,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
if ( $has_parent_option ) {
if ( ! empty( $data['custom_dropdown_options_source'] ) && $has_parent_option &&
function_exists( $data['custom_dropdown_options_source'] ) && isset( UM()->form()->post_form[ $form_key ] ) ) {
if ( ! in_array( $data['custom_dropdown_options_source'], $this->dropdown_options_source_blacklist(), true ) ) {
if ( ! $this->is_source_blacklisted( $data['custom_dropdown_options_source'] ) ) {
$options = call_user_func( $data['custom_dropdown_options_source'], $data['parent_dropdown_relationship'] );
}
}
+1 -1
View File
@@ -148,7 +148,7 @@ if ( ! class_exists( 'um\core\Form' ) ) {
wp_send_json( $arr_options );
}
if ( in_array( $ajax_source_func, UM()->fields()->dropdown_options_source_blacklist(), true ) ) {
if ( UM()->fields()->is_source_blacklisted( $ajax_source_func ) ) {
$arr_options['status'] = 'error';
$arr_options['message'] = __( 'This is not possible for security reasons.', 'ultimate-member' );
+1 -1
View File
@@ -95,7 +95,7 @@ if ( ! class_exists( 'um\core\Validation' ) ) {
isset( $fields[ $key ]['custom_dropdown_options_source'] ) &&
! empty( $fields[ $key ]['custom_dropdown_options_source'] ) &&
function_exists( $fields[ $key ]['custom_dropdown_options_source'] ) ) {
if ( ! in_array( $fields[ $key ]['custom_dropdown_options_source'], UM()->fields()->dropdown_options_source_blacklist(), true ) ) {
if ( ! UM()->fields()->is_source_blacklisted( $fields[ $key ]['custom_dropdown_options_source'] ) ) {
$arr_options = call_user_func( $fields[ $key ]['custom_dropdown_options_source'] );
$fields[ $key ]['options'] = array_keys( $arr_options );
}
+1 -1
View File
@@ -295,7 +295,7 @@ function um_user_edit_profile( $args ) {
$options = array();
if ( ! empty( $array['custom_dropdown_options_source'] ) && function_exists( $array['custom_dropdown_options_source'] ) && ! $has_custom_source ) {
if ( ! in_array( $array['custom_dropdown_options_source'], UM()->fields()->dropdown_options_source_blacklist(), true ) ) {
if ( ! UM()->fields()->is_source_blacklisted( $array['custom_dropdown_options_source'] ) ) {
$callback_result = call_user_func( $array['custom_dropdown_options_source'], $array['options'] );
if ( is_array( $callback_result ) ) {
$options = array_keys( $callback_result );
+1 -1
View File
@@ -694,7 +694,7 @@ add_filter( 'um_field_non_utf8_value', 'um_field_non_utf8_value' );
*/
function um_select_dropdown_dynamic_callback_options( $options, $data ) {
if ( ! empty( $data['custom_dropdown_options_source'] ) && function_exists( $data['custom_dropdown_options_source'] ) ) {
if ( in_array( $data['custom_dropdown_options_source'], UM()->fields()->dropdown_options_source_blacklist(), true ) ) {
if ( UM()->fields()->is_source_blacklisted( $data['custom_dropdown_options_source'] ) ) {
return $options;
}
$options = call_user_func( $data['custom_dropdown_options_source'] );