Headline
CVE-2023-2584: head_footer.php in pixelyoursite/trunk/modules/head_footer – WordPress Plugin Repository
The PixelYourSite plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in versions up to, and including, 9.3.6 (9.6.1 in the Pro version) due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level permissions and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.
1<?php23namespace PixelYourSite;45if ( ! defined( ‘ABSPATH’ ) ) {6 exit; // Exit if accessed directly.7}89class HeadFooter extends Settings {1011 private static $_instance;1213 private $is_mobile;1415 public static function instance() {1617 if ( is_null( self::$_instance ) ) {18 self::$_instance = new self();19 }2021 return self::$_instance;2223 }2425 public function __construct() {26 27 parent::__construct( ‘head_footer’ );28 29 $this->locateOptions(30 PYS_FREE_PATH . '/modules/head_footer/options_fields.json’,31 PYS_FREE_PATH . '/modules/head_footer/options_defaults.json’32 );33 34 add_action( 'pys_register_plugins’, function( $core ) {35 /** @var PYS $core */36 $core->registerPlugin( $this );37 } );38 39 if ( $this->getOption( ‘enabled’ ) ) {40 add_action( 'add_meta_boxes’, array( $this, ‘register_meta_box’ ) );41 add_action( 'save_post’, array( $this, ‘save_meta_box’ ) );42 }43 44 if ( $this->getOption( ‘enabled’ ) ) {45 add_action( 'template_redirect’, array( $this, ‘output_scripts’ ) );46 }47 48 }4950 /**51 * Register meta box for each public post type.52 */53 public function register_meta_box() {54 55 if ( current_user_can( ‘manage_pys’ ) ) {56 57 $screens = get_post_types( array( ‘public’ => true ) );58 59 foreach ( $screens as $screen ) {60 add_meta_box( 'pys-head-footer’, 'PixelYourSite Head & Footer Scripts’,61 array( $this, ‘render_meta_box’ ),62 $screen );63 }64 65 }6667 }6869 public function render_meta_box() {70 include 'views/html-meta-box.php’;71 }7273 public function save_meta_box( $post_id ) {7475 if ( defined( ‘DOING_AUTOSAVE’ ) && DOING_AUTOSAVE ) {76 return;77 }78 79 if ( ! current_user_can( ‘manage_pys’ ) ) {80 return;81 }8283 if ( ! isset( $_POST[‘pys_head_footer’] ) ) {84 // delete_post_meta( $post_id, ‘_pys_head_footer’ );85 return;86 }8788 $data = $_POST[‘pys_head_footer’];8990 $meta = array(91 ‘disable_global’ => isset( $data[‘disable_global’] ) ? true : false,92 ‘head_any’ => isset( $data[‘head_any’] ) ? trim( $data[‘head_any’] ) : '’,93 ‘head_desktop’ => isset( $data[‘head_desktop’] ) ? trim( $data[‘head_desktop’] ) : '’,94 ‘head_mobile’ => isset( $data[‘head_mobile’] ) ? trim( $data[‘head_mobile’] ) : '’,95 ‘footer_any’ => isset( $data[‘footer_any’] ) ? trim( $data[‘footer_any’] ) : '’,96 ‘footer_desktop’ => isset( $data[‘footer_desktop’] ) ? trim( $data[‘footer_desktop’] ) : '’,97 ‘footer_mobile’ => isset( $data[‘footer_mobile’] ) ? trim( $data[‘footer_mobile’] ) : '’,98 );99100 update_post_meta( $post_id, '_pys_head_footer’, $meta );101102 }103104 public function output_scripts() {105 global $post;106107 if ( is_admin() || defined( ‘DOING_AJAX’ ) || defined( ‘DOING_CRON’ ) ) {108 return;109 }110 111 $this->is_mobile = wp_is_mobile();112113 /**114 * WooCommerce Order Received page115 */116117 if ( isWooCommerceActive() && is_order_received_page() ) {118 add_action( 'wp_head’, array( $this, ‘output_head_woo_order_received’ ) );119 add_action( 'wp_footer’, array( $this, ‘output_footer_woo_order_received’ ) );120 }121122 $disabled_by_woo = isWooCommerceActive() && is_order_received_page() &&123 $this->getOption( ‘woo_order_received_disable_global’ );124125 if ( $disabled_by_woo ) {126 return;127 }128129 /**130 * Single Post131 */132133 if ( is_singular() && $post ) {134 $post_meta = get_post_meta( $post->ID, '_pys_head_footer’, true );135 } else {136 $post_meta = array();137 }138139 if ( ! empty( $post_meta ) ) {140 add_action( 'wp_head’, array( $this, ‘output_head_post’ ) );141 add_action( 'wp_footer’, array( $this, ‘output_footer_post’ ) );142 }143144 /**145 * Global146 */147148 $disabled_by_post = ! empty( $post_meta ) && isset($post_meta[‘disable_global’]) && $post_meta[‘disable_global’];149150 if ( ! $disabled_by_post ) {151 add_action( 'wp_head’, array( $this, ‘output_head_global’ ) );152 add_action( 'wp_footer’, array( $this, ‘output_footer_global’ ) );153 }154155 }156157 public function output_head_woo_order_received() {158159 $scripts_any = $this->getOption( ‘woo_order_received_head_any’ );160161 if ( $scripts_any ) {162 echo "\r\n{$scripts_any}\r\n";163 }164165 if ( $this->is_mobile ) {166 $scripts_by_device = $this->getOption( ‘woo_order_received_head_mobile’ );167 } else {168 $scripts_by_device = $this->getOption( ‘woo_order_received_head_desktop’ );169 }170171 if ( $scripts_by_device ) {172 echo "\r\n{$scripts_by_device}\r\n";173 }174175 }176177 public function output_footer_woo_order_received() {178179 $scripts_any = $this->getOption( ‘woo_order_received_footer_any’ );180181 if ( $scripts_any ) {182 echo "\r\n{$scripts_any}\r\n";183 }184185 if ( $this->is_mobile ) {186 $scripts_by_device = $this->getOption( ‘woo_order_received_footer_mobile’ );187 } else {188 $scripts_by_device = $this->getOption( ‘woo_order_received_footer_desktop’ );189 }190191 if ( $scripts_by_device ) {192 echo "\r\n{$scripts_by_device}\r\n";193 }194195 }196197 public function output_head_global() {198199 $scripts_any = $this->getOption( ‘head_any’ );200201 if ( $scripts_any ) {202 echo "\r\n{$scripts_any}\r\n";203 }204205 if ( $this->is_mobile ) {206 $scripts_by_device = $this->getOption( ‘head_mobile’ );207 } else {208 $scripts_by_device = $this->getOption( ‘head_desktop’ );209 }210211 if ( $scripts_by_device ) {212 echo "\r\n{$scripts_by_device}\r\n";213 }214215 }216217 public function output_footer_global() {218219 $scripts_any = $this->getOption( ‘footer_any’ );220221 if ( $scripts_any ) {222 echo "\r\n{$scripts_any}\r\n";223 }224225 if ( $this->is_mobile ) {226 $scripts_by_device = $this->getOption( ‘footer_mobile’ );227 } else {228 $scripts_by_device = $this->getOption( ‘footer_desktop’ );229 }230231 if ( $scripts_by_device ) {232 echo "\r\n{$scripts_by_device}\r\n";233 }234235 }236237 public function output_head_post() {238 global $post;239240 $post_meta = get_post_meta( $post->ID, '_pys_head_footer’, true );241242 $scripts_any = isset( $post_meta[‘head_any’] ) ? $post_meta[‘head_any’] : false;243244 if ( $scripts_any ) {245 echo "\r\n{$scripts_any}\r\n";246 }247248 if ( $this->is_mobile ) {249 $scripts_by_device = isset( $post_meta[‘head_mobile’] ) ? $post_meta[‘head_mobile’] : false;250 } else {251 $scripts_by_device = isset( $post_meta[‘head_desktop’] ) ? $post_meta[‘head_desktop’] : false;252 }253254 if ( $scripts_by_device ) {255 echo "\r\n{$scripts_by_device}\r\n";256 }257258 }259260 public function output_footer_post() {261 global $post;262263 $post_meta = get_post_meta( $post->ID, '_pys_head_footer’, true );264265 $scripts_any = isset( $post_meta[‘footer_any’] ) ? $post_meta[‘footer_any’] : false;266267 if ( $scripts_any ) {268 echo "\r\n{$scripts_any}\r\n";269 }270271 if ( $this->is_mobile ) {272 $scripts_by_device = isset( $post_meta[‘footer_mobile’] ) ? $post_meta[‘footer_mobile’] : false;273 } else {274 $scripts_by_device = isset( $post_meta[‘footer_desktop’] ) ? $post_meta[‘footer_desktop’] : false;275 }276277 if ( $scripts_by_device ) {278 echo "\r\n{$scripts_by_device}\r\n";279 }280281 }282283}284285/**286 * @return HeadFooter287 */288function HeadFooter() {289 return HeadFooter::instance();290}291292HeadFooter();