Project: Wordpress Plugin Portfolio X 2.3.0

Vulnerability: #9223978 (2018-11-16 16:19:13)

Warning

There are many false positives, or unexploitable vulnerabilities. Please create working "PoC" exploit before reporting anything to vendor!

Details:

Sink @FUNCTION::add_metadata
Risk _POST
/portfolio-x/inc/cmb2/includes/CMB2_hookup.php:522 (show/hide source)
502  	 * @return null
503  	 */
504  	public function save_comment( $comment_id ) {
505  
506  		$can_edit = current_user_can( 'moderate_comments', $comment_id );
507  
508  		if ( $this->can_save( get_comment_type( $comment_id ) ) && $can_edit ) {
509  			$this->cmb->save_fields( $comment_id, 'comment', $_POST );
510  		}
511  	}
512  
513  	/**
514  	 * Save data from user fields
515  	 * @since  1.0.x
516  	 * @param  int   $user_id  User ID
517  	 * @return null
518  	 */
519  	public function save_user( $user_id ) {
520  		// check permissions
521  		if ( $this->can_save( 'user' ) ) {
522 $this->cmb->save_fields( $user_id, 'user', $_POST );
523 } 524 }
Threat level 1

Callstack:

CMB2_Field::update_data /portfolio-x/inc/cmb2/includes/CMB2_Field.php:340 (show/hide source)
320  		 * The dynamic portion of the hook, $a['field_id'], refers to the current
321  		 * field id paramater. Returning a non-null value
322  		 * will effectively short-circuit the function.
323  		 *
324  		 * @since 2.0.0
325  		 */
326  		$override = apply_filters( "cmb2_override_{$a['field_id']}_meta_save", $override, $a, $this->args(), $this );
327  
328  		// If override, return that
329  		if ( null !== $override ) {
330  			return $override;
331  		}
332  
333  		// Options page handling (or temp data store)
334  		if ( 'options-page' === $a['type'] || empty( $a['id'] ) ) {
335  			return cmb2_options( $a['id'] )->update( $a['field_id'], $a['value'], false, $a['single'] );
336  		}
337  
338  		// Add metadata if not single
339  		if ( ! $a['single'] ) {
340 return add_metadata( $a['type'], $a['id'], $a['field_id'], $a['value'], false );
341 } 342
CMB2_Field::save_field /portfolio-x/inc/cmb2/includes/CMB2_Field.php:531 (show/hide source)
511  			// Nothing to see here.
512  			$action = 'disabled';
513  
514  		} elseif ( $this->args( 'multiple' ) && ! $this->args( 'repeatable' ) && ! $this->group ) {
515  
516  			$this->remove_data();
517  			$count = 0;
518  
519  			if ( ! empty( $new_value ) ) {
520  				foreach ( $new_value as $add_new ) {
521  					if ( $this->update_data( $add_new, false ) ) {
522  						$count++;
523  					}
524  				}
525  			}
526  
527  			$updated = $count ? $count : false;
528  			$action  = 'repeatable';
529  
530  		} elseif ( ! CMB2_Utils::isempty( $new_value ) && $new_value !== $this->get_data() ) {
531 $updated = $this->update_data( $new_value );
532 $action = 'updated'; 533 } elseif ( CMB2_Utils::isempty( $new_value ) ) {
CMB2_Field::save_field_from_data /portfolio-x/inc/cmb2/includes/CMB2_Field.php:494 (show/hide source)
474  			return $override_value;
475  		}
476  
477  		// Sanitization via 'CMB2_Sanitize'
478  		return $sanitizer->{$this->type()}();
479  	}
480  
481  	/**
482  	 * Process $_POST data to save this field's value
483  	 * @since  2.0.3
484  	 * @param  array $data_to_save $_POST data to check
485  	 * @return array|int|bool                Result of save, false on failure
486  	 */
487  	public function save_field_from_data( array $data_to_save ) {
488  		$this->data_to_save = $data_to_save;
489  
490  		$meta_value = isset( $this->data_to_save[ $this->id( true ) ] )
491  			? $this->data_to_save[ $this->id( true ) ]
492  			: null;
493  
494 return $this->save_field( $meta_value );
495 } 496
CMB2::process_field /portfolio-x/inc/cmb2/includes/CMB2.php:602 (show/hide source)
582  	 */
583  	public function process_field( $field_args ) {
584  
585  		switch ( $field_args['type'] ) {
586  
587  			case 'group':
588  				if ( $this->save_group( $field_args ) ) {
589  					$this->updated[] = $field_args['id'];
590  				}
591  
592  				break;
593  
594  			case 'title':
595  				// Don't process title fields
596  				break;
597  
598  			default:
599  
600  				$field = $this->get_new_field( $field_args );
601  
602 if ( $field->save_field_from_data( $this->data_to_save ) ) {
603 $this->updated[] = $field->id(); 604 }
CMB2::process_fields /portfolio-x/inc/cmb2/includes/CMB2.php:574 (show/hide source)
554  		}
555  
556  		$this->after_save();
557  	}
558  
559  	/**
560  	 * Process and save form fields
561  	 * @since  2.0.0
562  	 */
563  	public function process_fields() {
564  
565  		$this->pre_process();
566  
567  		// Remove the show_on properties so saving works
568  		$this->prop( 'show_on', array() );
569  
570  		// save field ids of those that are updated
571  		$this->updated = array();
572  
573  		foreach ( $this->prop( 'fields' ) as $field_args ) {
574 $this->process_field( $field_args );
575 } 576 }
CMB2::save_fields /portfolio-x/inc/cmb2/includes/CMB2.php:549 (show/hide source)
529  		// Reset the object id
530  		$this->object_id( $stored_id );
531  
532  		return $sanitized_values;
533  	}
534  
535  	/**
536  	 * Loops through and saves field data
537  	 * @since  1.0.0
538  	 * @param  int    $object_id    Object ID
539  	 * @param  string $object_type  Type of object being saved. (e.g., post, user, or comment)
540  	 * @param  array  $data_to_save Array of key => value data for saving. Likely $_POST data.
541  	 */
542  	public function save_fields( $object_id = 0, $object_type = '', $data_to_save = array() ) {
543  
544  		// Fall-back to $_POST data
545  		$this->data_to_save = ! empty( $data_to_save ) ? $data_to_save : $_POST;
546  		$object_id = $this->object_id( $object_id );
547  		$object_type = $this->object_type( $object_type );
548  
549 $this->process_fields();
550 551 // If options page, save the updated options
@FUNCTION::cmb2_print_metabox_form /portfolio-x/inc/cmb2/includes/helper-functions.php:307 (show/hide source)
287  		'form_format' => '<form class="cmb-form" method="post" id="%1$s" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" name="object_id" value="%2$s">%3$s<input type="submit" name="submit-cmb" value="%4$s" class="button-primary"></form>',
288  		'save_button' => esc_html__( 'Save', 'cmb2' ),
289  		'object_type' => $cmb->mb_object_type(),
290  		'cmb_styles'  => $cmb->prop( 'cmb_styles' ),
291  		'enqueue_js'  => $cmb->prop( 'enqueue_js' ),
292  	) );
293  
294  	// Set object type explicitly (rather than trying to guess from context)
295  	$cmb->object_type( $args['object_type'] );
296  
297  	// Save the metabox if it's been submitted
298  	// check permissions
299  	// @todo more hardening?
300  	if (
301  		$cmb->prop( 'save_fields' )
302  		// check nonce
303  		&& isset( $_POST['submit-cmb'], $_POST['object_id'], $_POST[ $cmb->nonce() ] )
304  		&& wp_verify_nonce( $_POST[ $cmb->nonce() ], $cmb->nonce() )
305  		&& $object_id && $_POST['object_id'] == $object_id
306  	) {
307 $cmb->save_fields( $object_id, $cmb->object_type(), $_POST );
308 } 309
@FUNCTION::cmb2_get_metabox_form /portfolio-x/inc/cmb2/includes/helper-functions.php:262 (show/hide source)
242  function cmb2_get_metabox_sanitized_values( $meta_box, array $data_to_sanitize ) {
243  	$cmb = cmb2_get_metabox( $meta_box );
244  	return $cmb ? $cmb->get_sanitized_values( $data_to_sanitize ) : false;
245  }
246  
247  /**
248   * Retrieve a metabox form
249   * @since  2.0.0
250   * @param  mixed   $meta_box  Metabox config array or Metabox ID
251   * @param  int     $object_id Object ID
252   * @param  array   $args      Optional arguments array
253   * @return string             CMB2 html form markup
254   */
255  function cmb2_get_metabox_form( $meta_box, $object_id = 0, $args = array() ) {
256  
257  	$object_id = $object_id ? $object_id : get_the_ID();
258  	$cmb       = cmb2_get_metabox( $meta_box, $object_id );
259  
260  	ob_start();
261  	// Get cmb form
262 cmb2_print_metabox_form( $cmb, $object_id, $args );
263 $form = ob_get_contents(); 264 ob_end_clean();
@FUNCTION::cmb2_metabox_form /portfolio-x/inc/cmb2/includes/helper-functions.php:344 (show/hide source)
324  	printf( $format_parts[0], $cmb->cmb_id, $object_id );
325  	$cmb->show_form();
326  
327  	if ( isset( $format_parts[1] ) && $format_parts[1] ) {
328  		printf( str_ireplace( '%4$s', '%1$s', $format_parts[1] ), $args['save_button'] );
329  	}
330  
331  }
332  
333  /**
334   * Display a metabox form (or optionally return it) & save it on submission
335   * @since  1.0.0
336   * @param  mixed   $meta_box  Metabox config array or Metabox ID
337   * @param  int     $object_id Object ID
338   * @param  array   $args      Optional arguments array
339   */
340  function cmb2_metabox_form( $meta_box, $object_id = 0, $args = array() ) {
341  	if ( ! isset( $args['echo'] ) || $args['echo'] ) {
342  		cmb2_print_metabox_form( $meta_box, $object_id, $args );
343  	} else {
344 return cmb2_get_metabox_form( $meta_box, $object_id, $args );
345 } 346 }