exists( $file ) ) { $wp_filesystem->put_contents( $file, "put_contents( $file, "header(\$_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden' );\n" ); $wp_filesystem->put_contents( $file, "die( '403 Forbidden' );\n" ); } } } /** * Method remove_wp_version() * * Remove the WordPress version (WordPress Generator). * * @param bool $force Force action if true, don't force if false. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. */ public static function remove_wp_version( $force = false ) { if ( $force || self::get_security_option( 'wp_version' ) ) { remove_action( 'wp_head', 'wp_generator' ); remove_filter( 'wp_head', 'wp_generator' ); } } /** * Method remove_rsd() * * Remove the Really Simple Discovery meta tag. * * @param bool $force Force action if true, don't force if false. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. */ public static function remove_rsd( $force = false ) { if ( $force || self::get_security_option( 'rsd' ) ) { remove_action( 'wp_head', 'rsd_link' ); } } /** * Method remove_wlw() * * Remove the Windows Live Writer meta tag. * * @param bool $force Force action if true, don't force if false. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. */ public static function remove_wlw( $force = false ) { if ( $force || self::get_security_option( 'wlw' ) ) { remove_action( 'wp_head', 'wlwmanifest_link' ); } } /** * Method remove_php_reporting() * * Disable the PHP error reporting. * * @param bool $force Force action if true, don't force if false. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. */ public static function remove_php_reporting( $force = false ) { if ( $force || self::get_security_option( 'php_reporting' ) ) { error_reporting( 0 ); //phpcs:ignore -- required to achieve desired results, pull request solutions appreciated. ini_set( 'display_errors', 'off' ); //phpcs:ignore -- required to achieve desired results, pull request solutions appreciated. ini_set( 'display_startup_errors', 0 ); //phpcs:ignore -- required to achieve desired results, pull request solutions appreciated. } } /** * Method remove_database_reporting() * * Disable the database error reporting. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. */ public static function remove_database_reporting() { global $wpdb; $wpdb->hide_errors(); $wpdb->suppress_errors(); } /** * Method remove_registered_versions() * * Remove the scripts and stylesheets registered versions. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. */ public static function remove_registered_versions() { if ( self::get_security_option( 'registered_versions' ) ) { global $wp_styles; if ( $wp_styles instanceof WP_Styles ) { foreach ( $wp_styles->registered as $handle => $style ) { $wp_styles->registered[ $handle ]->ver = null; } } global $wp_scripts; if ( $wp_scripts instanceof WP_Scripts ) { foreach ( $wp_scripts->registered as $handle => $script ) { $wp_scripts->registered[ $handle ]->ver = null; } } } } /** * Method remove_script_versions() * * Remove scripts versions. * * @param string $src Script or stylesheet location path. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. * * @return string $src Script or stylesheet striped location path. */ public static function remove_script_versions( $src ) { if ( self::get_security_option( 'scripts_version' ) ) { if ( strpos( $src, '?ver=' ) ) { $src = remove_query_arg( 'ver', $src ); } return $src; } return $src; } /** * Method remove_generator_version() * * Remove the WordPress Generator version. * * @param bool $force Force action if true, don't force if false. * * @uses MainWP_Security::custom_the_generator() Set custom generator. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. */ public static function remove_generator_version( $force = false ) { if ( $force || self::get_security_option( 'generator_version' ) ) { $types = array( 'html', 'xhtml', 'atom', 'rss2', 'rdf', 'comment', 'export' ); foreach ( $types as $type ) { add_filter( 'get_the_generator_' . $type, array( 'MainWP_Security', 'custom_the_generator' ), 10, 2 ); } } } /** * Method custom_the_generator() * * Set custom generator. * * @param string $generator Generator to process. * @param array $type Array containing the generator types. * * @used-by MainWP_Security::remove_generator_version() Remove the WordPress Generator version. * * @return string Return empty string. */ public static function custom_the_generator( $generator, $type = '' ) { return ''; } /** * Method remove_theme_versions() * * Remove themes versions. * * @param string $src Theme stylesheet location path. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. * * @return string $src Theme stylesheet striped location path. */ public static function remove_theme_versions( $src ) { if ( self::get_security_option( 'styles_version' ) ) { if ( strpos( $src, '?ver=' ) ) { $src = remove_query_arg( 'ver', $src ); } return $src; } return $src; } /** * Method remove_readme() * * Remove the readme.html file. * * @param bool $force Force action if true, don't force if false. * * @used-by MainWP_Security::fix_all() Fire off functions to fix detected security issues. * * @return bool true Return true to skip the process if child site is on WP Engine host. */ public static function remove_readme( $force = false ) { // to prevent remove readme.html file on WP Engine hosting. if ( MainWP_Helper::is_wp_engine() ) { return true; } MainWP_Helper::get_wp_filesystem(); global $wp_filesystem; if ( $force || self::get_security_option( 'readme' ) ) { if ( $wp_filesystem->exists( ABSPATH . 'readme.html' ) ) { if ( ! unlink( ABSPATH . 'readme.html' ) ) { $wp_filesystem->delete( ABSPATH . 'readme.html' ); if ( $wp_filesystem->exists( ABSPATH . 'readme.html' ) ) { // prevent repeat delete. self::update_security_option( 'readme', false ); } } } } } /** * Method prevent_listing_ok() * * Check if the directory listing is prevented. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false If directory listing prevented, return true, if not, return false. */ public static function prevent_listing_ok() { global $wp_filesystem; MainWP_Helper::get_wp_filesystem(); self::init_listing_directories(); foreach ( self::$listingDirectories as $directory ) { $file = $directory . DIRECTORY_SEPARATOR . 'index.php'; if ( ! $wp_filesystem->exists( $file ) ) { return false; } } return true; } /** * Method remove_wp_version_ok() * * Check if the WordPress version has been removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false If WordPress version removed, return true, if not return false. */ public static function remove_wp_version_ok() { return ! ( has_action( 'wp_head', 'wp_generator' ) || has_filter( 'wp_head', 'wp_generator' ) ); } /** * Method remove_rsd_ok() * * Check if the Really Simple Discovery meta tag has been removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false If the Really Simple Discovery meta tag has been removed, return true, if not return false. */ public static function remove_rsd_ok() { return ( ! has_action( 'wp_head', 'rsd_link' ) ); } /** * Method remove_wlw_ok() * * Check if the Windows Live Writer meta tag has been removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false If the Windows Live Writer meta tag has been removed, return true, if not return false. */ public static function remove_wlw_ok() { return ( ! has_action( 'wp_head', 'wlwmanifest_link' ) ); } /** * Method remove_database_reporting_ok() * * Check if the database error reporting has been disabled. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false If the database error reporting has been disabled, return true, if not, return false. */ public static function remove_database_reporting_ok() { global $wpdb; return ( false === $wpdb->show_errors ); } /** * Method remove_php_reporting_ok() * * Check if the PHP error reporting has been disabled. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false If the PHP error reporting has been disabled, return true, if not, return false. */ public static function remove_php_reporting_ok() { return ! ( ( ( 0 != ini_get( 'display_errors' ) ) && ( 'off' != ini_get( 'display_errors' ) ) ) || ( ( 0 != ini_get( 'display_startup_errors' ) ) && ( 'off' != ini_get( 'display_startup_errors' ) ) ) ); } /** * Method remove_scripts_version_ok() * * Check if scripts versions are removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false Return true if versions have been removed, false if not. */ public static function remove_scripts_version_ok() { return self::get_security_option( 'scripts_version' ); } /** * Method remove_styles_version_ok() * * Check if stylesheets versions are removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false Return true if versions have been removed, false if not. */ public static function remove_styles_version_ok() { return self::get_security_option( 'styles_version' ); } /** * Method remove_generator_version_ok() * * Check if the WordPress Generator version has been removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false Return true if registered versions have been removed, false if not. */ public static function remove_generator_version_ok() { return self::get_security_option( 'generator_version' ); } /** * Method remove_registered_versions_ok() * * Check if the scripts and stylesheets registered versions are removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false Return true if registered versions have been removed, false if not. */ public static function remove_registered_versions_ok() { return self::get_security_option( 'registered_versions' ); } /** * Method admin_user_ok() * * Check if any of administrator accounts has 'admin' as username. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true Return true no 'admin' username detected, fale if not. */ public static function admin_user_ok() { $user = get_user_by( 'login', 'admin' ); if ( ! $user ) { return true; } if ( 10 !== $user->wp_user_level && ( ! isset( $user->user_level ) || 10 !== $user->user_level ) && ! user_can( $user, 'level_10' ) ) { return true; } return false; } /** * Method remove_readme_ok() * * Check if the readme.html file has been removed. * * @used-by MainWP_Security::get_stats_security() Calculate total number of detected secutiry issues. * * @return bool true|false Return true if the readme.html file has been removed, false if not. */ public static function remove_readme_ok() { return ! file_exists( ABSPATH . 'readme.html' ); } /** * Method get_stats_security() * * Calculate total number of detected secutiry issues. * * @uses MainWP_Security::prevent_listing_ok() Check if the directory listing is prevented. * @uses MainWP_Security::remove_wp_version_ok() Check if the WordPress version has been removed. * @uses MainWP_Security::remove_rsd_ok() Check if the Really Simple Discovery meta tag has been removed. * @uses MainWP_Security::remove_wlw_ok() Check if the Windows Live Writer meta tag has been removed. * @uses MainWP_Security::remove_database_reporting_ok() Check if the database error reporting has been disabled. * @uses MainWP_Security::remove_php_reporting_ok() Check if the PHP error reporting has been disabled. * @uses MainWP_Security::remove_scripts_version_ok() Check if scripts versions are removed. * @uses MainWP_Security::remove_styles_version_ok() Check if stylesheets versions are removed. * @uses MainWP_Security::remove_generator_version_ok() Check if the WordPress Generator version has been removed. * @uses MainWP_Security::remove_registered_versions_ok() Check if the scripts and stylesheets registered versions are removed. * @uses MainWP_Security::admin_user_ok() Check if any of administrator accounts has 'admin' as username. * @uses MainWP_Security::remove_readme_ok() Check if the readme.html file has been removed. * * @return int $total_issues Total number of detected security issues. */ public static function get_stats_security() { $total_issues = 0; if ( ! self::prevent_listing_ok() ) { $total_issues ++; } if ( ! self::remove_wp_version_ok() ) { $total_issues ++; } if ( ! self::remove_rsd_ok() ) { $total_issues ++; } if ( ! self::remove_wlw_ok() ) { $total_issues ++; } if ( ! self::remove_database_reporting_ok() ) { $total_issues ++; } if ( ! self::remove_php_reporting_ok() ) { $total_issues ++; } if ( ! self::remove_scripts_version_ok() || ! self::remove_styles_version_ok() || ! self::remove_generator_version_ok() ) { $total_issues ++; } if ( ! self::remove_registered_versions_ok() ) { $total_issues ++; } if ( ! self::admin_user_ok() ) { $total_issues ++; } if ( ! self::remove_readme_ok() ) { $total_issues ++; } return $total_issues; } /** * Method get_security_option() * * Get security check settings. * * @param string $option Security check option. * * @return array Security settings. */ public static function get_security_option( $option ) { $security = get_option( 'mainwp_security' ); return ! empty( $security ) && isset( $security[ $option ] ) && ( true === $security[ $option ] ); } /** * Method update_security_option() * * Update the security issues feature settings. * * @param string $key Security option key. * @param string $value Security option value. */ public static function update_security_option( $key, $value ) { $security = get_option( 'mainwp_security' ); if ( ! empty( $key ) ) { $security[ $key ] = $value; } MainWP_Helper::update_option( 'mainwp_security', $security, 'yes' ); } }