Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2023-5335: buzzsprout-podcasting.php in buzzsprout-podcasting/tags/1.8.3 – WordPress Plugin Repository

The Buzzsprout Podcasting plugin for WordPress is vulnerable to Stored Cross-Site Scripting via ‘buzzsprout’ shortcode in versions up to, and including, 1.8.3 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers with contributor-level and above permissions to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVE
#xss#web#js#java#wordpress#php#perl#auth#ssl

1<?php2/*3Plugin Name: Buzzsprout Podcasting4Plugin URI: http://www.buzzsprout.com/wordpress5Description: This plugin fetches content from a Buzzsprout feed URL, from which user can pick an episode and add it into the post6Version: 1.8.37Author: Buzzsprout8Author URI: http://www.buzzsprout.com9*/1011class Buzzsprout_Podcasting{1213 const PLUGIN_NAME = 'Buzzsprout Podcasting’;14 const PLUGIN_SLUG = 'buzzsprout-podcasting’;15 const PLUGIN_TEXT_DOMAIN = 'buzzsprout-podcasting-domain’;16 const PLUGIN_VERSION = 1.8;1718 /**19 * @desc Initializes the plugin20 *21 */22 public static function initialize(){23 add_filter( 'media_upload_tabs’, array( __CLASS__, ‘register_media_tab’ ) );24 add_action( 'media_upload_buzzsprout_podcasting’, array( __CLASS__, ‘add_media_tab’ ) );25 add_action( 'admin_menu’, array( __CLASS__, ‘add_options_page’ ) );26 add_action( 'admin_init’, array( __CLASS__, ‘register_settings’ ) );27 add_action( 'admin_enqueue_scripts’, array( __CLASS__, ‘enqueue_scripts’ ) );28 add_action( 'admin_print_styles-media-upload-popup’, array( __CLASS__, ‘enqueue_media_tab_style’ ) );29 add_action('admin_notices’, array( __CLASS__, ‘buzzsprout_admin_notice’ ) );30 add_shortcode('buzzsprout’, array( __CLASS__, ‘buzzsprout_shortcode_handler’ ) );31 }3233 /**34 * @desc Registers the Buzzsprout Podcasting media tab35 * @param array $tabs All media tabs36 * @return array All media tabs including the newly added Buzzsprout Podcasting37 */38 public static function register_media_tab($tabs) {39 $new_tab = array( ‘buzzsprout_podcasting’ => __( 'Buzzsprout Podcasting’, self::PLUGIN_TEXT_DOMAIN ) );40 return array_merge( $tabs, $new_tab );41 }4243 /**44 * @desc Adds the media tab45 * @return wp_iframe()46 */47 public static function add_media_tab(){48 return wp_iframe( array( __CLASS__, ‘media_tab_content’ ) );49 }5051 /**52 * @desc Enqueue scripts to be used throughout the admin pages53 * @return void54 */55 public static function enqueue_scripts(){56 wp_enqueue_style( 'buzzsprout-podcasting-admin’, plugins_url( '/css/admin.css’, __FILE__ ), false, self::PLUGIN_VERSION );57 wp_enqueue_script( 'buzzsprout-podcasting-admin’, plugins_url('/js/admin-onload.js’, __FILE__ ), array( 'jquery’, ‘media-upload’ ) );58 }5960 /**61 * @desc Enqueue styles and scripts to use for the media upload thickbox62 * @return void63 */64 public static function enqueue_media_tab_style(){65 wp_enqueue_style( 'buzzsprout-podcasting-admin’, plugins_url( '/css/admin.css’, __FILE__ ), false, self::PLUGIN_VERSION );66 wp_enqueue_script( 'buzzsprout-podcasting-box’, plugins_url('/js/box.js’, __FILE__ ), array( ‘jquery’ ) );67 }6869 /**70 * @desc Content for the Buzzsprout Podcasting media tab within the media uploader thickbox71 * @return mixed Media tab content72 */73 public static function media_tab_content(){74 media_upload_header();75 $buzzsprout_options = get_option( self::PLUGIN_SLUG ); ?>76 <div class="box">77 <div style="float:right;">78 <p style="margin-top: 0;"><strong>Enjoying the Buzzsprout Plugin?</strong><br>Your <a href="https://wordpress.org/support/view/plugin-reviews/buzzsprout-podcasting" target="_blank">ratings and reviews</a> are much appreciated!</p>79 </div>80 <?php if ( !$buzzsprout_options ): ?>81 <p class="major-info error"><?php printf( __( ‘You have not specified a valid Buzzsprout feed URL yet. Please use the form under %s %s to do so.’, self::PLUGIN_TEXT_DOMAIN ), __( self::PLUGIN_NAME ),’<a href="’ . admin_url( ‘options-general.php?page=buzzsprout-podcasting’ ) . ‘" target="_blank">’ . __( ‘Settings page’, self::PLUGIN_TEXT_DOMAIN ).’</a>’ ); ?></p>82 <?php elseif( !self::is_feed_valid( $buzzsprout_options[‘feed-uri’] ) ): error_log(self::is_feed_valid( $buzzsprout_options[‘feed-uri’] ) ); ?>83 <p class="major-info error"><?php printf(__('A valid Buzzsprout feed URL cannot be found. Please use the form under %s to update your settings.’, self::PLUGIN_TEXT_DOMAIN), '<a href="’.admin_url(‘options-general.php?page=buzzsprout-podcasting’).’">’.__(‘Settings’, self::PLUGIN_TEXT_DOMAIN).’</a>’); ?></p>84 <?php else:85 $rss = fetch_feed( $buzzsprout_options[‘feed-uri’].’?’.strtotime(“now”) );86 87 // MIME type can throw errors inside fetch_feed.88 // Use SimplePie class directly to force feed.89 if ( is_wp_error( $rss ) ) {90 $rss = new SimplePie();91 $rss->set_feed_url($buzzsprout_options[‘feed-uri’].’?’.strtotime(“now”));92 $rss->force_feed(true); // Force feed to fix MIME type errors93 $rss->init();94 $rss->handle_content_type();95 }96 97 $maxitems = $rss->get_item_quantity($buzzsprout_options[‘number-episodes’]);98 $items = $rss->get_items( 0, $maxitems ); ?>99 <h2><?php _e( 'Select an Episode’, self::PLUGIN_TEXT_DOMAIN ); ?></h2>100 <ul>101 <?php if ($maxitems == 0): ?>102 <li class="error"><?php _e( 'No feed items can be retrieved.’, self::PLUGIN_TEXT_DOMAIN ); ?></li>103 <?php else: ?>104 <?php foreach ( $items as $item ): // Loop through each feed item and display each item as a hyperlink. ?>105 <li>106 <a class="buzzp-item" href="#" title="<?php echo esc_attr( __('Click to add this episode into the post’, self::PLUGIN_TEXT_DOMAIN ) ); ?>" data-short-tag="<?php echo self::buzzsprout_item_create_short_tag($item->get_enclosure()->get_link(), $buzzsprout_options[‘include-flash’]); ?>"><?php echo $item->get_title(); ?></a>107 </li>108 <?php endforeach; ?>109 <?php endif; ?>110 </ul>111 <?php endif; ?>112 </div><?php113 }114115 /**116 * @desc Adds the Buzzsprout Podcasting Options menu item117 * @return void118 */119 public static function add_options_page(){120 add_options_page(self::PLUGIN_NAME, self::PLUGIN_NAME, 'manage_options’, self::PLUGIN_SLUG, array(__CLASS__, ‘options_page_content’));121 }122123 /**124 * @desc Registers the settings, settings section, and settings fields for the Buzzsprout Options page125 * @return void126 */127 public static function register_settings(){128 register_setting( self::PLUGIN_SLUG, self::PLUGIN_SLUG, array( __CLASS__, ‘buzzsprout_options_validate’ ) );129 add_settings_section( 'buzzsprout_settings’, __( 'Buzzsprout Settings’, self::PLUGIN_TEXT_DOMAIN ), array( __CLASS__, ‘buzzsprout_settings_section_cb’), self::PLUGIN_SLUG );130 add_settings_field( 'buzzsprout_feed_address’, __( 'Buzzsprout feed address (URL)', self::PLUGIN_TEXT_DOMAIN ), array( __CLASS__, ‘buzzsprout_feed_address_cb’ ), self::PLUGIN_SLUG, ‘buzzsprout_settings’ );131 add_settings_field( 'buzzsprout_include_flash’, __( 'Include audio player?’, self::PLUGIN_TEXT_DOMAIN ), array( __CLASS__, ‘buzzsprout_include_flash_cb’ ), self::PLUGIN_SLUG, ‘buzzsprout_settings’ );132 add_settings_field( 'buzzsprout_number_episodes’, __( ‘Number of Episodes to return’, self::PLUGIN_TEXT_DOMAIN ), array( __CLASS__, ‘buzzsprout_number_episodes_cb’ ), self::PLUGIN_SLUG, ‘buzzsprout_settings’ );133 }134135 /**136 * @desc Displays the Buzzsprout Podcasting Options page content137 * @return mixed Options page content138 */139 public static function options_page_content(){ ?>140 <div class="wrap buzzp">141 <div id="icon-options-buzzp" class="icon32"></div>142 <h2><?php _e( self::PLUGIN_NAME, self::PLUGIN_TEXT_DOMAIN )?></h2>143 <p><?php _e(“Buzzsprout is the only solution you need for publishing, hosting, promoting and tracking your podcast on the web. It eliminates the hassles and technical know-how required with self-managed podcast publishing. Whether you’re just starting out or have been podcasting for years, Buzzsprout is the easiest way to get your podcast online.", self::PLUGIN_TEXT_DOMAIN); ?></p>144 <p><?php printf(__('You can learn more about Buzzsprout and create your own FREE account at %s.’, self::PLUGIN_TEXT_DOMAIN ), '<a href="http://www.buzzsprout.com” target="_blank">http://www.buzzsprout.com</a>’); ?></p>145 <form action="options.php" method="post">146 <?php settings_fields(self::PLUGIN_SLUG); ?>147 <?php do_settings_sections(self::PLUGIN_SLUG); ?>148 <p class="submit">149 <input class="button-primary" name="submit" type="submit" value="<?php echo( esc_attr( __( 'Save Changes’, self::PLUGIN_TEXT_DOMAIN) ) ); ?>" />150 </p>151 </form>152153 <h3><?php _e('How the Buzzsprout Podcasting Plugin Works’, self::PLUGIN_TEXT_DOMAIN)?></h3>154155 <p class="how-it-works">156 <?php _e( 'The Buzzsprout Podcasting plugin makes embedding podcast episodes into your blog posts a breeze. Please see our <a href="https://www.buzzsprout.com/help/27" target="_blank"><strong>WP Plugin Help Section</strong></a> for instructions, screenshots, and videos.’, self::PLUGIN_TEXT_DOMAIN ); ?>157 </p>158 </div>159 <?php160 }161162 /**163 * @desc Validates the buzzsprout options settings164 * @param $input Array of the buzzsprout_podcasting_options165 * @return array Clean array of the buzzsprout podcasting options166 */167 public static function buzzsprout_options_validate($input){168 $new_input = array();169 $new_input[‘feed-uri’] = esc_url_raw(strip_tags( $input[‘feed-uri’] ) );170 $new_input[‘include-flash’] = ($input[‘include-flash’] == ‘on’) ? true : false;171 $new_input[‘number-episodes’] = strip_tags( $input[‘number-episodes’] );172 return $new_input;173 }174175 /**176 * @desc Adds a description to the Buzzsprout Settings section on the Buzzsprout Podcasting Options page177 * @return void178 */179 public static function buzzsprout_settings_section_cb(){180 return ‘’;181 }182183 /**184 * @desc Displays the feed address input for the Buzzsprout Podcasting Options page185 * @return void186 */187 public static function buzzsprout_feed_address_cb(){188 $buzzsprout_options = get_option(self::PLUGIN_SLUG);189 ?>190 <input style="width: 300px" type="text" name="<?php echo esc_attr( self::PLUGIN_SLUG.’[feed-uri]'); ?>" value="<?php echo esc_attr($buzzsprout_options[‘feed-uri’]); ?>" />191 <span class="guide">192 <?php printf( __(‘%s, then click on iTunes & Directories > RSS Feed.’, self::PLUGIN_TEXT_DOMAIN ), ‘<a href="http://www.buzzsprout.com/login" target="_blank">’.__(‘Login to your account’, self::PLUGIN_TEXT_DOMAIN).’</a>’); ?>193 </span><?php194 }195196 /**197 * @desc Displays the include flash input for the Buzzsprout Podcasting Options page198 * @return void199 */200 public static function buzzsprout_include_flash_cb(){201 $buzzsprout_options = get_option(self::PLUGIN_SLUG); ?>202 <input type="checkbox" name="<?php echo esc_attr( self::PLUGIN_SLUG.’[include-flash]'); ?>" <?php checked($buzzsprout_options[‘include-flash’]); ?> /> Yes203 <?php204 }205206 /**207 * @desc Displays the number episodes select box for the Buzzsprout Podcasting Options page208 * @return void209 */210 public static function buzzsprout_number_episodes_cb(){211 $buzzsprout_options = get_option(self::PLUGIN_SLUG); ?>212 <p>213 <select name="<?php echo esc_attr( self::PLUGIN_SLUG.’[number-episodes]'); ?>">214 <?php for ($i = 5; $i < 21; $i += 5):215 printf('<option value="%s"%s>%s</option>%s’, $i, selected($buzzsprout_options[‘number-episodes’], $i), $i, PHP_EOL);216 endfor;217 printf('<option value="%s"%s>%s</option>%s’, 9999, selected($buzzsprout_options[‘number-episodes’], 9999), __('All’, self::PLUGIN_TEXT_DOMAIN), PHP_EOL); ?>218 </select>219 <br class="clear" />220 </p><?php221 }222223 /**224 * @desc225 * @param string $url226 * @return bool Is valid or not227 */228 public static function is_feed_valid($url){229 if (!trim($url)) return false;230 return preg_match('|^http(s)?://(feeds\.)?buzzsprout\.com/[0-9]+\.rss$|i’, $url);231 }232233 /**234 * @desc Gets the subcription ID (from the RSS URL)235 *236 * @param mixed $feed_uri237 * @return mixed238 */239 public static function get_subscription_id($feed_uri = false){240241 // if a feed URI is not provided, try getting it from DB242 if (!$feed_uri){243 $buzzsprout_otions = get_option(self::PLUGIN_SLUG);244245 if(!$buzzsprout_otions)246 return false;247248 $feed_uri = $buzzsprout_otions[‘feed-uri’];249 }250251 if (!preg_match_all('|^https?://(feeds\.)?buzzsprout\.com/([0-9]+)\.rss$|i’, $feed_uri, $matches)) return false;252 return isset($matches[2][0]) ? $matches[2][0] : false;253 }254255 /**256 * @desc Handles the [buzzsprout] shortcode257 *258 * @param mixed $atts259 * @return The parsed HTML260 */261 public static function buzzsprout_shortcode_handler($atts){262 extract(shortcode_atts(array(263 ‘episode’ => 0,264 ‘player’ => 'true’,265 ), $atts));266267 // as player=true is preferred, we only disable player if the value is exclusively 'false’268 $parsed_html = sprintf(269 '<div id="buzzsprout-player-%s"></div>270 <script src="https://www.buzzsprout.com/%s/%s.js?container_id=buzzsprout-player-%s&%s" type="text/javascript" charset="utf-8"></script>271 ', $episode, self::get_subscription_id(), $episode, $episode, $player != ‘false’ ? ‘player=small’ : ‘’272 );273274 return $parsed_html;275 }276277 /**278 * Create a short tag to add into the post279 *280 * @param string Link of the buzz media file281 * @param mixed Whether player should be enabled282 */283 public static function buzzsprout_item_create_short_tag($buzz_item_link, $player){284 // http://www.buzzsprout.com/96/1917-ep-9-rams-vs-titans.mp3285 if (!preg_match_all(‘|(buzzsprout\.com)/[0-9]+/([0-9]+).*|i’, $buzz_item_link, $matches)) return false;286287 if (!isset($matches[2][0])) return false;288289 $tag = sprintf("[buzzsprout episode=’%s’ player=’%s’]", trim($matches[2][0]), $player ? ‘true’ : ‘false’);290 return $tag;291 }292293 /**294 * @desc Check if the feed provided is valid and if so, the Settings updated message will be displayed, if not, the Invalid Buzzsprout Feed URL error message will be displayed.295 *296 */297 public static function buzzsprout_admin_notice(){298 global $pagenow;299 if ($pagenow == ‘options-general.php’ && $_GET[‘page’] == self::PLUGIN_SLUG) {300 if ( (isset($_GET[‘updated’]) && $_GET[‘updated’] == ‘true’) || (isset($_GET[‘settings-updated’]) && $_GET[‘settings-updated’] == ‘true’) ) {301302 $errors = get_settings_errors();303304 $buzzsprout_options = get_option( self::PLUGIN_SLUG );305 if(!self::is_feed_valid($buzzsprout_options[‘feed-uri’])){306 $buzzsprout_options[‘feed-uri’] = '’;307 update_option(self::PLUGIN_SLUG, $buzzsprout_options);308 $error_message = __(‘Invalid Buzzsprout Feed URL’);309 add_settings_error('general’, 'settings_updated’, $error_message, ‘error’);310 } else {311 $original_message = $errors[0][‘message’];312 add_settings_error('general’, 'settings_updated’, $original_message, ‘updated’);313 }314 }315 }316 }317}318add_action('init’, array('Buzzsprout_Podcasting’, ‘initialize’));

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907