Headline
CVE-2023-4718: n9m-font-awesome-4.php in font-awesome-4-menus/trunk – WordPress Plugin Repository
The Font Awesome 4 Menus plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the ‘fa’ and ‘fa-stack’ shortcodes in versions up to, and including, 4.7.0 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.
1<?php2/*3Plugin Name: Font Awesome 4 Menus4Plugin URI: https://www.newnine.com/plugins/font-awesome-4-menus5Description: Join the retina/responsive revolution by easily adding Font Awesome 4.7.0 icons to your WordPress menus and anywhere else on your site! No programming necessary.6Version: 4.7.07Author: New Nine Media8Author URI: https://www.newnine.com9License: GPLv2 or later10*/1112/*13 Copyright 2013-2016 NEW NINE MEDIA (tel : +1-800-288-9699)1415 This program is free software; you can redistribute it and/or modify16 it under the terms of the GNU General Public License, version 2, as 17 published by the Free Software Foundation.1819 This program is distributed in the hope that it will be useful,20 but WITHOUT ANY WARRANTY; without even the implied warranty of21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the22 GNU General Public License for more details.2324 You should have received a copy of the GNU General Public License25 along with this program; if not, write to the Free Software26 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA27*/2829class FontAwesomeFour {3031 public static $defaults = array(32 ‘maxcdn_location’ => 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css’,33 ‘spacing’ => 1,34 ‘stylesheet’ => 'local’,35 ‘version’ => '4.7.0’36 );3738 function __construct(){39 global $wp_version;4041 add_action( 'admin_enqueue_scripts’, array( $this, ‘admin_enqueue_scripts’ ) );42 add_action( 'admin_menu’, array( $this, ‘admin_menu’ ) );43 add_action( 'admin_notices’, array( $this, ‘admin_notices’ ) );44 add_action( 'wp_enqueue_scripts’, array( $this, ‘wp_enqueue_scripts’ ) );4546 add_filter( 'nav_menu_css_class’, array( $this, ‘nav_menu_css_class’ ) );47 add_filter( 'walker_nav_menu_start_el’, array( $this, ‘walker_nav_menu_start_el’ ), 10, 4 );4849 add_shortcode( 'fa’, array( $this, ‘shortcode_icon’ ) );50 add_shortcode( 'fa-stack’, array( $this, ‘shortcode_stack’ ) );51 }5253 function admin_enqueue_scripts( $hook ){54 if( ‘settings_page_n9m-font-awesome-4-menus’ == $hook ){55 wp_enqueue_style( 'n9m-admin-font-awesome-4’, plugins_url( 'css/font-awesome.min.css’, __FILE__ ), false, self::$defaults[ ‘version’ ] );56 }57 }5859 function admin_menu(){60 add_submenu_page( 'options-general.php’, 'Font Awesome 4 Menus’, 'Font Awesome’, 'edit_theme_options’, 'n9m-font-awesome-4-menus’, array( $this, ‘admin_menu_cb’ ) );61 }6263 function admin_menu_cb(){64 if( $_POST && check_admin_referer( ‘n9m-fa’ ) ){65 $settings = array();66 switch( $_POST[ ‘n9m_location’ ] ){67 case 'local’:68 case 'maxcdn’:69 case 'none’:70 $settings[ ‘stylesheet’ ] = $_POST[ ‘n9m_location’ ];71 break;72 case ‘other’:73 $settings[ ‘stylesheet’ ] = ‘other’;74 $settings[ ‘stylesheet_location’ ] = sanitize_text_field( $_POST[ ‘n9m_location-other-location’ ] );75 break;76 }77 if( isset( $_POST[ ‘n9m_text_spacing’ ] ) ){78 $settings[ ‘spacing’ ] = 1;79 } else {80 $settings[ ‘spacing’ ] = 0;81 }82 update_option( ‘n9m-font-awesome-4-menus’, $settings );83 print ‘<div class="updated"><p>Your settings have been saved!</p></div>’;84 }85 $settings = get_option( ‘n9m-font-awesome-4-menus’, self::$defaults );86 print ' <div class="wrap">87 <h2><i class="fa fa-thumbs-o-up"></i> ' . get_admin_page_title() . ‘</h2>88 <p>Thank you for using Font Awesome 4 Menus by <a href="https://www.newnine.com" target="_blank">New Nine</a>! To view available icons, <a href="http://fortawesome.github.io/Font-Awesome/icons/" target="_blank">click here to visit the Font Awesome website</a>.</p>89 <form action="’ . admin_url( ‘options-general.php?page=n9m-font-awesome-4-menus’ ) . ‘" method="post">90 <h3>Font Awesome Stylesheet</h3>91 <p>Select how you want Font Awesome 4’s stylesheet loaded on your site (if at all):</p>92 <table class="form-table">93 <tbody>94 <tr>95 <th scope="row">Load Font Awesome 4 From:</th>96 <td>97 <fieldset>98 <legend class="screen-reader-text"><span>Load Font Awesome 4 From</span></legend>99 <label for="n9m_location-local"><input type="radio" name="n9m_location" id="n9m_location-local" value="local"’ . ( ‘local’ == $settings[ ‘stylesheet’ ] ? ' checked’ : false ) . ‘> Local plugin folder (default)</label>100 <br />101 <label for="n9m_location-maxcdn"><input type="radio" name="n9m_location" id="n9m_location-maxcdn" value="maxcdn"’ . ( ‘maxcdn’ == $settings[ ‘stylesheet’ ] ? ' checked’ : false ) . ‘> Official Font Awesome CDN <span class="description">(<a href="https://www.bootstrapcdn.com/fontawesome/" target="_blank">Font Awesome CDN powered by MaxCDN</a>)</span></label>102 <br />103 <label for="n9m_location-other"><input type="radio" name="n9m_location" id="n9m_location-other" value="other"’ . ( ‘other’ == $settings[ ‘stylesheet’ ] ? ' checked’ : false ) . ‘> A custom location:</label> <input type="text" name="n9m_location-other-location" id="n9m_location-other-location" placeholder="Enter full url here" class="regular-text" value="’ . ( isset( $settings[ ‘stylesheet_location’ ] ) ? $settings[ ‘stylesheet_location’ ] : ‘’ ) . ‘">104 <br />105 <label for="n9m_location-none"><input type="radio" name="n9m_location" id="n9m_location-none" value="none"’ . ( ‘none’ == $settings[ ‘stylesheet’ ] ? ' checked’ : false ) . ‘> Don’t load Font Awesome 4’s stylesheet <span class="description">(use this if you load Font Awesome 4 elsewhere on your site)</span></label>106 </fieldset>107 </td>108 </tr>109 </tbody>110 </table>111 <h3>Icon Spacing</h3>112 <p>By default, Font Awesome 4 Menus adds a space before or after the icon in your menu. Uncheck the box below to remove this space and give you finer control over your custom styling.</p>113 <p><label for="n9m_text_spacing"><input type="checkbox" name="n9m_text_spacing" id="n9m_text_spacing" value="1"’ . ( 1 == $settings[ ‘spacing’ ] ? ' checked’ : false ) . ‘> Keep the space between my text and my icons <span class="description">(default is checked)</span></label>114 <p>’ . wp_nonce_field( ‘n9m-fa’ ) . '<button type="submit" class="button button-primary">Save Settings</button></p>115 </form>116 </div>’;117 }118119 function admin_notices(){120 global $current_user, $pagenow;121 if( isset( $_REQUEST[ ‘action’ ] ) && ‘kill-n9m-font-awesome-4-notice’ == $_REQUEST[ ‘action’ ] ){122 update_user_meta( $current_user->data->ID, 'n9m-font-awesome-4-notice-hide’, 1 );123 }124 $shownotice = get_user_meta( $current_user->data->ID, ‘n9m-font-awesome-4-notice-hide’, true );125 if( ‘plugins.php’ == $pagenow && !$shownotice ){126 print ' <div class="updated is-dismissible">127 <div style="float: right;"><a href="?action=kill-n9m-font-awesome-4-notice" style="color: #7ad03a; display: block; padding: 8px;">✘</a></div>128 <p>Thank you for installing Font Awesome Menus 4 by <a href="https://www.newnine.com">New Nine</a>! Want to see what else we’re up to? Subscribe below to our infrequent updates. You can unsubscribe at any time.</p>129 <form action="http://newnine.us2.list-manage.com/subscribe/post?u=067bab5a6984981f003cf003d&id=1b25a2aee6" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" target="_blank">130 <p><input type="text" name="FNAME" placeholder="First Name" value="’ . ( !empty( $current_user->first_name ) ? $current_user->first_name : ‘’ ) . ‘"> <input type="text" name="LNAME" placeholder="Last Name" value="’ . ( !empty( $current_user->last_name ) ? $current_user->last_name : ‘’ ) . ‘"> <input type="text" name="EMAIL" placeholder="Email address" required value="’ . $current_user->user_email . '"> <input type="hidden" id="group_1" name="group[14489][1]" value="1"> <input type="submit" name="subscribe" value="Join" class="button action"></p>131 </form>132 </div>’;133 }134 }135136 function nav_menu_css_class( $classes ){137 if( is_array( $classes ) ){138 $tmp_classes = preg_grep( '/^(fa)(-\S+)?$/i’, $classes );139 if( !empty( $tmp_classes ) ){140 $classes = array_values( array_diff( $classes, $tmp_classes ) );141 }142 }143 return $classes;144 }145146 public static function register_uninstall_hook(){147 if( current_user_can( ‘delete_plugins’ ) ){148 delete_option( ‘n9m-font-awesome-4-menus’ );149 $users_with_meta = get_users( array(150 ‘meta_key’ => 'n9m-font-awesome-4-notice-hide’,151 ‘meta_value’ => 1152 ) );153 foreach( $users_with_meta as $user_with_meta ){154 delete_user_meta( $user_with_meta->ID, ‘n9m-font-awesome-4-notice-hide’ );155 }156 }157 }158159 protected function replace_item( $item_output, $classes ){160 $settings = get_option( 'n9m-font-awesome-4-menus’, FontAwesomeFour::$defaults );161 $spacer = 1 == $settings[ ‘spacing’ ] ? ' ' : '’;162163 if( !in_array( 'fa’, $classes ) ){164 array_unshift( $classes, ‘fa’ );165 }166167 $before = true;168 if( in_array( 'fa-after’, $classes ) ){169 $classes = array_values( array_diff( $classes, array( ‘fa-after’ ) ) );170 $before = false;171 }172173 $icon = ‘<i class="’ . implode( ' ', $classes ) . '"></i>’;174175 preg_match( '/(<a.+>)(.+)(<\/a>)/i’, $item_output, $matches );176 if( 4 === count( $matches ) ){177 $item_output = $matches[1];178 if( $before ){179 $item_output .= $icon . ‘<span class="fontawesome-text">’ . $spacer . $matches[2] . '</span>’;180 } else {181 $item_output .= ‘<span class="fontawesome-text">’ . $matches[2] . $spacer . ‘</span>’ . $icon;182 }183 $item_output .= $matches[3];184 }185 return $item_output;186 }187 188 function shortcode_icon( $atts ){189 $a = shortcode_atts( array(190 ‘class’ => '’191 ), $atts );192 if( !empty( $a[ ‘class’ ] ) ){193 $class_array = explode( ' ', $a[ ‘class’ ] );194 if( !in_array( 'fa’, $class_array ) ){195 $class_array[] = 'fa’;196 }197 return ‘<i class="’ . implode( ' ', $class_array ) . '"></i>’;198 }199 }200 201 function shortcode_stack( $atts, $content = null ){202 $a = shortcode_atts( array(203 ‘class’ => '’204 ), $atts );205 $class_array = array();206 if( empty( $a[ ‘class’ ] ) ){207 $class_array = array( ‘fa-stack’ );208 } else {209 $class_array = explode( ' ', $a[ ‘class’ ] );210 if( !in_array( 'fa-stack’, $class_array ) ){211 $class_array[] = 'fa-stack’;212 }213 }214 return ‘<span class="’ . implode( ' ', $class_array ) . ‘">’ . do_shortcode( $content ) . '</span>’;215 }216217 function walker_nav_menu_start_el( $item_output, $item, $depth, $args ){218 if( is_array( $item->classes ) ){219 $classes = preg_grep( '/^(fa)(-\S+)?$/i’, $item->classes );220 if( !empty( $classes ) ){221 $item_output = $this->replace_item( $item_output, $classes );222 }223 }224 return $item_output;225 }226227 function wp_enqueue_scripts(){228 $settings = get_option( 'n9m-font-awesome-4-menus’, self::$defaults );229 switch( $settings[ ‘stylesheet’ ] ){230 case 'local’:231 wp_register_style( 'font-awesome-four’, plugins_url( 'css/font-awesome.min.css’, __FILE__ ), array(), self::$defaults[ ‘version’ ], ‘all’ );232 wp_enqueue_style( ‘font-awesome-four’ );233 break;234 case 'maxcdn’:235 wp_register_style( 'font-awesome-four’, self::$defaults[ ‘maxcdn_location’ ], array(), self::$defaults[ ‘version’ ], ‘all’ );236 wp_enqueue_style( ‘font-awesome-four’ );237 break;238 case 'none’:239 break;240 case 'other’:241 wp_register_style( 'font-awesome-four’, $settings[ ‘stylesheet_location’ ], array(), self::$defaults[ ‘version’ ], ‘all’ );242 wp_enqueue_style( ‘font-awesome-four’ );243 break;244 }245 }246247 public static function write_log( $log ){248 if( is_array( $log ) || is_object( $log ) ){249 error_log( print_r( $log, true ) );250 } else {251 error_log( $log );252 }253 }254 255}256$n9m_font_awesome_four = new FontAwesomeFour();257258register_uninstall_hook( __FILE__, array( 'FontAwesomeFour’, ‘register_uninstall_hook’ ) );