Developers: If you prefer to edit all Wordfence options on one page, you can enable the "All Options" page here:
', 'wfplugin_devalloptions'); wfConfig::set('generateAllOptionsNotification', 1); }*/ //7.1.9 if (wfConfig::get('loginSec_maxFailures') == 1) { wfConfig::set('loginSec_maxFailures', 2); } $blocksTable = wfBlock::blocksTable(); $patternBlocks = wfBlock::patternBlocks(); foreach ($patternBlocks as $b) { if (!empty($b->ipRange) && preg_match('/^\d+\-\d+$/', $b->ipRange)) { //Old-style range block using long2ip $ipRange = new wfUserIPRange($b->ipRange); $ipRange = $ipRange->getIPString(); $parameters = $b->parameters; $parameters['ipRange'] = $ipRange; $wpdb->query($wpdb->prepare("UPDATE `{$blocksTable}` SET `parameters` = %s WHERE `id` = %d", json_encode($parameters), $b->id)); } } wfConfig::set('needsGeoIPSync', true, wfConfig::DONT_AUTOLOAD); // Set the default scan options based on scan type. if (!wfConfig::get('config720Migration', false)) { // Replace critical/warning checkboxes with setting based on numeric severity value. if (wfConfig::hasCachedOption('alertOn_critical') && wfConfig::hasCachedOption('alertOn_warnings')) { $alertOnCritical = wfConfig::get('alertOn_critical'); $alertOnWarnings = wfConfig::get('alertOn_warnings'); wfConfig::set('alertOn_scanIssues', $alertOnCritical || $alertOnWarnings); if ($alertOnCritical && ! $alertOnWarnings) { wfConfig::set('alertOn_severityLevel', wfIssues::SEVERITY_HIGH); } else { wfConfig::set('alertOn_severityLevel', wfIssues::SEVERITY_LOW); } } // Update severity for existing issues where they are still using the old severity values. foreach (wfIssues::$issueSeverities as $issueType => $severity) { $wpdb->query($wpdb->prepare("UPDATE $issuesTable SET severity = %d WHERE `type` = %s AND severity in (0,1,2) ", $severity, $issueType)); } $syncedOptions = array(); switch (wfConfig::get('scanType')) { case wfScanner::SCAN_TYPE_LIMITED: $syncedOptions = wfScanner::limitedScanTypeOptions(); break; case wfScanner::SCAN_TYPE_STANDARD: $syncedOptions = wfScanner::standardScanTypeOptions(); break; case wfScanner::SCAN_TYPE_HIGH_SENSITIVITY: $syncedOptions = wfScanner::highSensitivityScanTypeOptions(); break; } if ($syncedOptions) { foreach ($syncedOptions as $key => $value) { if (is_bool($value)) { wfConfig::set($key, $value ? 1 : 0); } } } wfConfig::set('config720Migration', true); } //7.2.3 if (wfConfig::get('waf_status') === false) { $firewall = new wfFirewall(); $firewall->syncStatus(true); } //7.3.1 //---- drop long deprecated tables $tables = array('wfBadLeechers', 'wfBlockedCommentLog', 'wfBlocks', 'wfBlocksAdv', 'wfLeechers', 'wfLockedOut', 'wfNet404s', 'wfScanners', 'wfThrottleLog', 'wfVulnScanners'); foreach ($tables as $t) { $schema->drop($t); } //---- enable legacy 2fa if applicable if (wfConfig::get('isPaid') && (wfCredentialsController::hasOld2FARecords() || version_compare(phpversion(), '5.3', '<'))) { wfConfig::set(wfCredentialsController::ALLOW_LEGACY_2FA_OPTION, true); } //Check the How does Wordfence get IPs setting wfUtils::requestDetectProxyCallback(); //Install new schedule. If schedule config is blank it will install the default 'auto' schedule. wfScanner::shared()->scheduleScans(); //Check our minimum versions and generate the necessary warnings if (!wp_next_scheduled('wordfence_version_check')) { wp_schedule_single_event(time(), 'wordfence_version_check'); } //Must be the final line } public static function _refreshVulnerabilityCache($upgrader = null, $hook_extra = null) { if($hook_extra ===null || in_array($hook_extra['type'], array('plugin', 'theme'))){ $update_check = new wfUpdateCheck(); $update_check->checkAllVulnerabilities(); } } private static function doEarlyAccessLogging(){ $wfLog = self::getLog(); if($wfLog->logHitOK()){ $request = $wfLog->getCurrentRequest(); if(is_404()){ if ($request) { $request->statusCode = 404; } $wfLog->logLeechAndBlock('404'); } else { $wfLog->logLeechAndBlock('hit'); } } } public static function initProtection(){ //Basic protection during WAF learning period // Infinite WP Client - Authentication Bypass < 1.9.4.5 // https://wpvulndb.com/vulnerabilities/10011 $iwpRule = new wfWAFRule(wfWAF::getInstance(), 0x80000000, null, 'auth-bypass', 100, 'Infinite WP Client - Authentication Bypass < 1.9.4.5', 0, 'block', null); wfWAF::getInstance()->setRules(wfWAF::getInstance()->getRules() + array(0x80000000 => $iwpRule)); if (strrpos(wfWAF::getInstance()->getRequest()->getRawBody(), '_IWP_JSON_PREFIX_') !== false) { $iwpRequestDataArray = explode('_IWP_JSON_PREFIX_', wfWAF::getInstance()->getRequest()->getRawBody()); $iwpRequest = json_decode(trim(base64_decode($iwpRequestDataArray[1])), true); if (is_array($iwpRequest)) { if (array_key_exists('iwp_action', $iwpRequest) && ($iwpRequest['iwp_action'] === 'add_site' || $iwpRequest['iwp_action'] === 'readd_site') ) { require_once ABSPATH . '/wp-admin/includes/plugin.php'; if (is_plugin_active('iwp-client/init.php')) { $iwpPluginData = get_plugin_data(WP_PLUGIN_DIR . '/iwp-client/init.php'); if (version_compare('1.9.4.5', $iwpPluginData['Version'], '>')) { remove_action('setup_theme', 'iwp_mmb_set_request'); } } if ((is_multisite() ? get_site_option('iwp_client_action_message_id') : get_option('iwp_client_action_message_id')) && (is_multisite() ? get_site_option('iwp_client_public_key') : get_option('iwp_client_public_key')) ) { wfWAF::getInstance()->getStorageEngine()->logAttack(array($iwpRule), 'request.rawBody', wfWAF::getInstance()->getRequest()->getRawBody(), wfWAF::getInstance()->getRequest(), wfWAF::getInstance()->getRequest()->getMetadata() ); } } } } } public static function install_actions(){ register_activation_hook(WORDFENCE_FCPATH, 'wordfence::installPlugin'); register_deactivation_hook(WORDFENCE_FCPATH, 'wordfence::uninstallPlugin'); $versionInOptions = ((is_multisite() && function_exists('get_network_option')) ? get_network_option(null, 'wordfence_version', false) : get_option('wordfence_version', false)); if( (! $versionInOptions) || version_compare(WORDFENCE_VERSION, $versionInOptions, '>')){ //Either there is no version in options or the version in options is greater and we need to run the upgrade self::runInstall(); } self::getLog()->initLogRequest(); //Fix wp_mail bug when $_SERVER['SERVER_NAME'] is undefined add_filter('wp_mail_from', 'wordfence::fixWPMailFromAddress'); //These access wfConfig::get('apiKey') and will fail if runInstall hasn't executed. if(defined('MULTISITE') && MULTISITE === true){ global $blog_id; if($blog_id == 1 && get_option('wordfenceActivated') != 1){ return; } //Because the plugin is active once installed, even before it's network activated, for site 1 (WordPress team, why?!) } //User may be logged in or not, so register both handlers add_action('wp_ajax_nopriv_wordfence_lh', 'wordfence::ajax_lh_callback'); add_action('wp_ajax_nopriv_wordfence_doScan', 'wordfence::ajax_doScan_callback'); add_action('wp_ajax_nopriv_wordfence_testAjax', 'wordfence::ajax_testAjax_callback'); if(wfUtils::hasLoginCookie()){ //may be logged in. Fast way to check. These aren't secure functions, this is just a perf optimization, along with every other use of hasLoginCookie() add_action('wp_ajax_wordfence_lh', 'wordfence::ajax_lh_callback'); add_action('wp_ajax_wordfence_doScan', 'wordfence::ajax_doScan_callback'); add_action('wp_ajax_wordfence_testAjax', 'wordfence::ajax_testAjax_callback'); if (is_multisite()) { add_action('wp_network_dashboard_setup', 'wordfence::addDashboardWidget'); } else { add_action('wp_dashboard_setup', 'wordfence::addDashboardWidget'); } } add_action('wp_ajax_wordfence_wafStatus', 'wordfence::ajax_wafStatus_callback'); add_action('wp_ajax_nopriv_wordfence_wafStatus', 'wordfence::ajax_wafStatus_callback'); add_action('wp_ajax_nopriv_wordfence_remoteVerifySwitchTo2FANew', 'wordfence::ajax_remoteVerifySwitchTo2FANew_callback'); add_action('wordfence_start_scheduled_scan', 'wordfence::wordfenceStartScheduledScan'); add_action('wordfence_daily_cron', 'wordfence::dailyCron'); add_action('wordfence_daily_autoUpdate', 'wfConfig::autoUpdate'); add_action('wordfence_hourly_cron', 'wordfence::hourlyCron'); add_action('wordfence_version_check', array(wfVersionCheckController::shared(), 'checkVersionsAndWarn')); add_action('plugins_loaded', 'wordfence::veryFirstAction'); add_action('init', 'wordfence::initAction'); //add_action('admin_bar_menu', 'wordfence::admin_bar_menu', 99); add_action('template_redirect', 'wordfence::templateRedir', 1001); add_action('shutdown', 'wordfence::shutdownAction'); if (!wfConfig::get('ajaxWatcherDisabled_front')) { add_action('wp_enqueue_scripts', 'wordfence::enqueueAJAXWatcher'); } if (!wfConfig::get('ajaxWatcherDisabled_admin')) { add_action('admin_enqueue_scripts', 'wordfence::enqueueAJAXWatcher'); } //add_action('wp_enqueue_scripts', 'wordfence::enqueueDashboard'); add_action('admin_enqueue_scripts', 'wordfence::enqueueDashboard'); if(version_compare(PHP_VERSION, '5.4.0') >= 0){ add_action('wp_authenticate','wordfence::authActionNew', 1, 2); } else { add_action('wp_authenticate','wordfence::authActionOld', 1, 2); } add_filter('authenticate', 'wordfence::authenticateFilter', 99, 3); $lockout = wfBlock::lockoutForIP(wfUtils::getIP()); if ($lockout !== false) { add_filter('xmlrpc_enabled', '__return_false'); } add_action('login_init','wordfence::loginInitAction'); add_action('wp_login','wordfence::loginAction'); add_action('wp_logout','wordfence::logoutAction'); add_action('lostpassword_post', 'wordfence::lostPasswordPost', 1, 2); $allowSeparatePrompt = ini_get('output_buffering') > 0; if (wfConfig::get('loginSec_enableSeparateTwoFactor') && $allowSeparatePrompt) { add_action('login_form', 'wordfence::showTwoFactorField'); } if(wfUtils::hasLoginCookie()){ add_action('user_profile_update_errors', 'wordfence::validateProfileUpdate', 0, 3 ); add_action('profile_update', 'wordfence::profileUpdateAction', 99, 2); } add_action('validate_password_reset', 'wordfence::validatePassword', 10, 2); // Add actions for the email summary add_action('wordfence_email_activity_report', array('wfActivityReport', 'executeCronJob')); //For debugging //add_filter( 'cron_schedules', 'wordfence::cronAddSchedules' ); add_filter('wp_redirect', 'wordfence::wpRedirectFilter', 99, 2); add_filter('wp_redirect_status', 'wordfence::wpRedirectStatusFilter', 99, 2); //html|xhtml|atom|rss2|rdf|comment|export if(wfConfig::get('other_hideWPVersion')){ add_filter('style_loader_src', 'wordfence::replaceVersion'); add_filter('script_loader_src', 'wordfence::replaceVersion'); add_action('upgrader_process_complete', 'wordfence::hideReadme'); } add_filter('get_the_generator_html', 'wordfence::genFilter', 99, 2); add_filter('get_the_generator_xhtml', 'wordfence::genFilter', 99, 2); add_filter('get_the_generator_atom', 'wordfence::genFilter', 99, 2); add_filter('get_the_generator_rss2', 'wordfence::genFilter', 99, 2); add_filter('get_the_generator_rdf', 'wordfence::genFilter', 99, 2); add_filter('get_the_generator_comment', 'wordfence::genFilter', 99, 2); add_filter('get_the_generator_export', 'wordfence::genFilter', 99, 2); add_filter('registration_errors', 'wordfence::registrationFilter', 99, 3); add_filter('woocommerce_new_customer_data', 'wordfence::wooRegistrationFilter', 99, 1); if (wfConfig::get('loginSec_disableAuthorScan')) { add_filter('oembed_response_data', 'wordfence::oembedAuthorFilter', 99, 4); add_filter('rest_request_before_callbacks', 'wordfence::jsonAPIAuthorFilter', 99, 3); add_filter('rest_post_dispatch', 'wordfence::jsonAPIAdjustHeaders', 99, 3); add_filter('wp_sitemaps_users_pre_url_list', '__return_false', 99, 0); add_filter('wp_sitemaps_add_provider', 'wordfence::wpSitemapUserProviderFilter', 99, 2); } if (wfConfig::get('loginSec_disableApplicationPasswords')) { add_filter('wp_is_application_passwords_available', '__return_false'); // Override the wp_die handler to let the user know app passwords were disabled by the Wordfence option. if (!empty($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] === ABSPATH . 'wp-admin/authorize-application.php') { add_filter('wp_die_handler', function ($handler = null) { return function ($message, $title, $args) { if ($message === 'Application passwords are not available.') { $message = __('Application passwords have been disabled by Wordfence.', 'wordfence'); } _default_wp_die_handler($message, $title, $args); }; }, 10, 1); } } add_filter('rest_dispatch_request', 'wordfence::_filterCentralFromLiveTraffic', 99, 4); // Change GoDaddy's limit login mu-plugin since it can interfere with the two factor auth message. if (self::hasGDLimitLoginsMUPlugin()) { add_action('login_errors', array('wordfence', 'fixGDLimitLoginsErrors'), 11); } add_action('upgrader_process_complete', 'wordfence::_refreshVulnerabilityCache', 10, 2); add_action('upgrader_process_complete', 'wfUpdateCheck::syncAllVersionInfo'); add_action('upgrader_process_complete', 'wordfence::_scheduleRefreshUpdateNotification', 99, 2); add_action('automatic_updates_complete', 'wordfence::_scheduleRefreshUpdateNotification', 99, 0); add_action('wordfence_refreshUpdateNotification', 'wordfence::_refreshUpdateNotification', 99, 0); add_action('wordfence_completeCoreUpdateNotification', 'wordfence::_completeCoreUpdateNotification', 99, 0); add_action('wfls_xml_rpc_blocked', 'wordfence::checkSecurityNetwork'); add_action('wfls_registration_blocked', 'wordfence::checkSecurityNetwork'); add_action('wfls_activation_page_header', 'wordfence::_outputLoginSecurityInstallation'); add_action('wfls_activation_page_footer', 'wordfence::_outputLoginSecurityTour'); add_action('wfls_settings_set', 'wordfence::queueCentralConfigurationSync'); if(is_admin()){ add_action('admin_init', 'wordfence::admin_init'); add_action('admin_head', 'wordfence::_retargetWordfenceSubmenuCallout'); if(is_multisite()){ if(wfUtils::isAdminPageMU()){ add_action('network_admin_menu', 'wordfence::admin_menus', 10); add_action('network_admin_menu', 'wordfence::admin_menus_20', 20); add_action('network_admin_menu', 'wordfence::admin_menus_30', 30); add_action('network_admin_menu', 'wordfence::admin_menus_40', 40); add_action('network_admin_menu', 'wordfence::admin_menus_50', 50); add_action('network_admin_menu', 'wordfence::admin_menus_60', 60); add_action('network_admin_menu', 'wordfence::admin_menus_70', 70); add_action('network_admin_menu', 'wordfence::admin_menus_80', 80); add_action('network_admin_menu', 'wordfence::admin_menus_90', 90); } //else don't show menu } else { add_action('admin_menu', 'wordfence::admin_menus', 10); add_action('admin_menu', 'wordfence::admin_menus_20', 20); add_action('admin_menu', 'wordfence::admin_menus_30', 30); add_action('admin_menu', 'wordfence::admin_menus_40', 40); add_action('admin_menu', 'wordfence::admin_menus_50', 50); add_action('admin_menu', 'wordfence::admin_menus_60', 60); add_action('admin_menu', 'wordfence::admin_menus_70', 70); add_action('admin_menu', 'wordfence::admin_menus_80', 80); add_action('admin_menu', 'wordfence::admin_menus_90', 90); } add_filter('plugin_action_links_' . plugin_basename(realpath(dirname(__FILE__) . '/../wordfence.php')), 'wordfence::_pluginPageActionLinks'); } add_action('request', 'wordfence::preventAuthorNScans'); add_action('password_reset', 'wordfence::actionPasswordReset'); $adminUsers = new wfAdminUserMonitor(); if ($adminUsers->isEnabled()) { add_action('set_user_role', array($adminUsers, 'updateToUserRole'), 10, 3); add_action('grant_super_admin', array($adminUsers, 'grantSuperAdmin'), 10, 1); add_action('revoke_super_admin', array($adminUsers, 'revokeSuperAdmin'), 10, 1); } else if (wfConfig::get_ser('adminUserList', false)) { // reset this in the event it's disabled or the network is too large wfConfig::set_ser('adminUserList', false); } if (wfConfig::liveTrafficEnabled()) { add_action('wp_head', 'wordfence::wfLogHumanHeader'); add_action('login_head', 'wordfence::wfLogHumanHeader'); } add_action('wordfence_processAttackData', 'wordfence::processAttackData'); if (!empty($_GET['wordfence_syncAttackData']) && get_site_option('wordfence_syncingAttackData') <= time() - 60 && get_site_option('wordfence_lastSyncAttackData', 0) < time() - 8) { @ignore_user_abort(true); update_site_option('wordfence_syncingAttackData', time()); header('Content-Type: text/javascript'); define('WORDFENCE_SYNCING_ATTACK_DATA', true); add_action('init', 'wordfence::syncAttackData', 10, 0); add_filter('woocommerce_unforce_ssl_checkout', '__return_false'); } add_action('wordfence_batchReportBlockedAttempts', 'wordfence::wfsnBatchReportBlockedAttempts'); add_action('wordfence_batchReportFailedAttempts', 'wordfence::wfsnBatchReportFailedAttempts'); if (wfConfig::get('other_hideWPVersion')) { add_filter('update_feedback', 'wordfence::restoreReadmeForUpgrade'); } add_action('rest_api_init', 'wordfence::initRestAPI'); if (wfCentral::isConnected()) { add_action('wordfence_security_event', 'wfCentral::sendSecurityEvent', 10, 3); } else { add_action('wordfence_security_event', 'wfCentral::sendAlertCallback', 10, 3); } if (!wfConfig::get('wordfenceI18n', true)) { add_filter('gettext', function ($translation, $text, $domain) { if ($domain === 'wordfence') { return $text; } return $translation; }, 10, 3); } } public static function _pluginPageActionLinks($links) { if (!wfConfig::get('isPaid')) { $links = array_merge(array('aWordfencePluginCallout' => '' . esc_html__('Upgrade To Premium', 'wordfence') . ' (' . esc_html__('opens in new tab', 'wordfence') . ')'), $links); } return $links; } public static function _outputLoginSecurityInstallation() { if (WORDFENCE_LS_FROM_CORE && wfOnboardingController::shouldShowAttempt3()) { echo wfView::create('onboarding/banner')->render(); } } public static function _outputLoginSecurityTour() { if (WORDFENCE_LS_FROM_CORE) { echo wfView::create('tours/login-security', array())->render(); } } public static function fixWPMailFromAddress($from_email) { if ($from_email == 'wordpress@') { //$_SERVER['SERVER_NAME'] is undefined so we get an incomplete email address wordfence::status(4, 'info', __("wp_mail from address is incomplete, attempting to fix", 'wordfence')); $urls = array(get_site_url(), get_home_url()); foreach ($urls as $u) { if (!empty($u)) { $u = preg_replace('#^[^/]*//+([^/]+).*$#', '\1', $u); if (substr($u, 0, 4) == 'www.') { $u = substr($u, 4); } if (!empty($u)) { wordfence::status(4, 'info', sprintf(/* translators: Email address. */ __("Fixing wp_mail from address: %s", 'wordfence'), $from_email . $u)); return $from_email . $u; } } } //Can't fix it, return it as it was } return $from_email; } public static function wpRedirectFilter($location, $status) { self::getLog()->initLogRequest(); self::getLog()->getCurrentRequest()->statusCode = $status; return $location; } public static function wpRedirectStatusFilter($status, $location) { self::getLog()->initLogRequest(); self::getLog()->getCurrentRequest()->statusCode = $status; self::getLog()->logHit(); return $status; } public static function enqueueAJAXWatcher() { $wafDisabled = !WFWAF_ENABLED || (class_exists('wfWAFConfig') && wfWAFConfig::isDisabled()); if (wfUtils::isAdmin() && !$wafDisabled) { wp_enqueue_style('wordfenceAJAXcss', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/wordfenceBox.css'), '', WORDFENCE_VERSION); wp_enqueue_script('wfi18njs', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/wfi18n.js'), array(), WORDFENCE_VERSION); wp_enqueue_script('wordfenceAJAXjs', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/admin.ajaxWatcher.js'), array('jquery'), WORDFENCE_VERSION); wp_localize_script('wordfenceAJAXjs', 'WFAJAXWatcherVars', array( 'nonce' => wp_create_nonce('wf-waf-error-page'), )); self::setupI18nJSStrings(); } } public static function enqueueDashboard() { if (wfUtils::isAdmin()) { wp_enqueue_style('wf-adminbar', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/wf-adminbar.css'), '', WORDFENCE_VERSION); wp_enqueue_script('wordfenceDashboardjs', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/wfdashboard.js'), array('jquery'), WORDFENCE_VERSION); if (wfConfig::get('showAdminBarMenu')) { wp_enqueue_script('wordfencePopoverjs', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/wfpopover.js'), array('jquery'), WORDFENCE_VERSION); wp_localize_script('wordfenceDashboardjs', 'WFDashVars', array( 'ajaxURL' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('wp-ajax'), )); } } } public static function ajax_testAjax_callback(){ die("WFSCANTESTOK"); } public static function ajax_doScan_callback(){ @ignore_user_abort(true); self::$wordfence_wp_version = false; if (!defined('DONOTCACHEDB')) { define('DONOTCACHEDB', true); } //This is messy, but not sure of a better way to do this without guaranteeing we get $wp_version require(ABSPATH . 'wp-includes/version.php'); /** @var string $wp_version */ self::$wordfence_wp_version = $wp_version; require_once(dirname(__FILE__) . '/wfScan.php'); wfScan::wfScanMain(); } //END doScan public static function ajax_lh_callback(){ self::getLog()->canLogHit = false; $UA = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; $isCrawler = empty($UA); if ($UA) { if (wfCrawl::isCrawler($UA) || wfCrawl::isGoogleCrawler()) { $isCrawler = true; } } @ob_end_clean(); if(! headers_sent()){ header('Content-type: text/javascript'); header("Connection: close"); header("Content-Length: 0"); header("X-Robots-Tag: noindex"); if (!$isCrawler) { wfLog::cacheHumanRequester(wfUtils::getIP(), $UA); } } flush(); if(! $isCrawler){ $hid = $_GET['hid']; $hid = wfUtils::decrypt($hid); if(! preg_match('/^\d+$/', $hid)){ exit(); } $db = new wfDB(); $table_wfHits = wfDB::networkTable('wfHits'); $db->queryWrite("update {$table_wfHits} set jsRun=1 where id=%d", $hid); } die(""); } public static function ajaxReceiver(){ if(! wfUtils::isAdmin()){ wfUtils::send_json(array('errorMsg' => __("You appear to have logged out or you are not an admin. Please sign-out and sign-in again.", 'wordfence'))); } $func = (isset($_POST['action']) && $_POST['action']) ? $_POST['action'] : $_GET['action']; $nonce = (isset($_POST['nonce']) && $_POST['nonce']) ? $_POST['nonce'] : $_GET['nonce']; if(! wp_verify_nonce($nonce, 'wp-ajax')){ wfUtils::send_json(array('errorMsg' => __("Your browser sent an invalid security token to Wordfence. Please try reloading this page or signing out and in again.", 'wordfence'), 'tokenInvalid' => 1)); } //func is e.g. wordfence_ticker so need to munge it $func = str_replace('wordfence_', '', $func); $returnArr = call_user_func('wordfence::ajax_' . $func . '_callback'); if($returnArr === false){ $returnArr = array('errorMsg' => __("Wordfence encountered an internal error executing that request.", 'wordfence')); } if(! is_array($returnArr)){ error_log("Function " . wp_kses($func, array()) . " did not return an array and did not generate an error."); $returnArr = array(); } if(isset($returnArr['nonce'])){ error_log("Wordfence ajax function return an array with 'nonce' already set. This could be a bug."); } $returnArr['nonce'] = wp_create_nonce('wp-ajax'); wfUtils::send_json($returnArr); } public static function ajax_remoteVerifySwitchTo2FANew_callback() { $payload = wfUtils::decodeJWT(wfConfig::get('new2FAMigrationNonce')); if (empty($payload)) { wfUtils::send_json(new stdClass()); //Ensures an object response } $package = wfCrypt::noc1_encrypt($payload); wfUtils::send_json($package); } public static function ajax_switchTo2FANew_callback() { $migrate = (isset($_POST['migrate']) && wfUtils::truthyToBoolean($_POST['migrate'])); $twoFactorUsers = wfConfig::get_ser('twoFactorUsers', array()); if ($migrate && is_array($twoFactorUsers) && !empty($twoFactorUsers)) { $smsActive = array(); $authenticatorActive = array(); foreach ($twoFactorUsers as &$t) { if ($t[3] == 'activated') { $user = new WP_User($t[0]); if ($user instanceof WP_User && $user->exists()) { if ((!isset($t[5]) || $t[5] != 'authenticator')) { $smsActive[] = $user->user_login; } else { $authenticatorActive[] = $t[6]; } } } } if (!empty($smsActive)) { return array('ok' => 0, 'smsActive' => $smsActive); } $total = 0; $imported = 0; $nonce = bin2hex(wfWAFUtils::random_bytes(32)); wfConfig::set('new2FAMigrationNonce', wfUtils::generateJWT(array('nonce' => $nonce), 90)); $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion()); try { $response = $api->call('twoFactorTOTP_migrate', array(), array('migrateids' => json_encode($authenticatorActive), 'nonce' => $nonce, 'verifyurl' => add_query_arg(array('action' => 'wordfence_remoteVerifySwitchTo2FANew'), admin_url('admin-ajax.php')))); /* * A successful response will be in the format * { * "ok": 1, * "records": { * "skipped": { *%s
", esc_html__('Please wait 3 minutes and try again', 'wordfence'), esc_html__('You have used this form too much. Please wait 3 minutes and try again.', 'wordfence') ); exit(); } if(! $numTries){ $numTries = 1; } else { $numTries = $numTries + 1; } set_transient('wordfenceUnlockTries', $numTries, 180); $email = trim(@$_POST['email']); global $wpdb; $ws = $wpdb->get_results($wpdb->prepare("SELECT ID, user_login FROM $wpdb->users WHERE user_email = %s", $email)); $found = false; foreach($ws as $user){ $userDat = get_userdata($user->ID); if(wfUtils::isAdmin($userDat)){ if($email == $userDat->user_email){ $found = true; break; } } } if(! $found){ foreach(wfConfig::getAlertEmails() as $alertEmail){ if($alertEmail == $email){ $found = true; break; } } } if($found){ $key = wfUtils::bigRandomHex(); $IP = wfUtils::getIP(); set_transient('wfunlock_' . $key, $IP, 1800); $content = wfUtils::tmpl('email_unlockRequest.php', array( 'siteName' => get_bloginfo('name', 'raw'), 'siteURL' => wfUtils::getSiteBaseURL(), 'unlockHref' => wfUtils::getSiteBaseURL() . '?_wfsf=unlockAccess&key=' . $key, 'key' => $key, 'IP' => $IP )); wp_mail($email, __("Unlock email requested", 'wordfence'), $content, "Content-Type: text/html"); } echo "" . esc_html(sprintf(/* translators: Email address. */ __("We received a request to email \"%s\" instructions to unlock their access. If that is the email address of a site administrator or someone on the Wordfence alert list, they have been emailed instructions on how to regain access to this system. The instructions we sent will expire 30 minutes from now.", 'wordfence'), wp_kses($email, array()))) . "
"; exit(); } else if($wfFunc == 'unlockAccess'){ if (!preg_match('/^(?:(?:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9](?::|$)){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))$/i', get_transient('wfunlock_' . $_GET['key']))) { _e("Invalid key provided for authentication.", 'wordfence'); exit(); } if($_GET['func'] == 'unlockMyIP'){ wfBlock::unblockIP(wfUtils::getIP()); if (class_exists('wfWAFIPBlocksController')) { wfWAFIPBlocksController::setNeedsSynchronizeConfigSettings(); } self::clearLockoutCounters(wfUtils::getIP()); header('Location: ' . wp_login_url()); exit(); } else if($_GET['func'] == 'unlockAllIPs'){ wordfence::status(1, 'info', __("Request received via unlock email link to unblock all IPs.", 'wordfence')); wfBlock::removeAllIPBlocks(); if (class_exists('wfWAFIPBlocksController')) { wfWAFIPBlocksController::setNeedsSynchronizeConfigSettings(); } self::clearLockoutCounters(wfUtils::getIP()); header('Location: ' . wp_login_url()); exit(); } else if($_GET['func'] == 'disableRules'){ wfConfig::set('firewallEnabled', 0); wfConfig::set('loginSecurityEnabled', 0); wordfence::status(1, 'info', __("Request received via unlock email link to unblock all IPs via disabling firewall rules.", 'wordfence')); wfBlock::removeAllIPBlocks(); wfBlock::removeAllCountryBlocks(); if (class_exists('wfWAFIPBlocksController')) { wfWAFIPBlocksController::setNeedsSynchronizeConfigSettings(); } self::clearLockoutCounters(wfUtils::getIP()); header('Location: ' . wp_login_url()); exit(); } else { _e("Invalid function specified. Please check the link we emailed you and make sure it was not cut-off by your email reader.", 'wordfence'); exit(); } } else if ($wfFunc == 'detectProxy') { wfUtils::doNotCache(); if (wfUtils::processDetectProxyCallback()) { self::getLog()->getCurrentRequest()->action = 'scan:detectproxy'; //Exempt a valid callback from live traffic echo wfConfig::get('detectProxyRecommendation', '-'); } else { echo '0'; } exit(); } else if ($wfFunc == 'removeAlertEmail') { wfUtils::doNotCache(); $payloadStatus = false; $jwt = (isset($_GET['jwt']) && is_string($_GET['jwt'])) ? $_GET['jwt'] : ''; if (!empty($jwt)) { $payload = wfUtils::decodeJWT($jwt); if ($payload && isset($payload['email'])) { $payloadStatus = true; } } if (isset($_POST['resend'])) { $email = trim(@$_POST['email']); $found = false; $alertEmails = wfConfig::getAlertEmails(); foreach ($alertEmails as $e) { if ($e == $email) { $found = true; break; } } if ($found) { $content = wfUtils::tmpl('email_unsubscribeRequest.php', array( 'siteName' => get_bloginfo('name', 'raw'), 'siteURL' => wfUtils::getSiteBaseURL(), 'IP' => wfUtils::getIP(), 'jwt' => wfUtils::generateJWT(array('email' => $email)), )); wp_mail($email, __("Unsubscribe Requested", 'wordfence'), $content, "Content-Type: text/html"); } echo wfView::create('common/unsubscribe', array( 'state' => 'resent', ))->render(); exit(); } else if (!$payloadStatus) { echo wfView::create('common/unsubscribe', array( 'state' => 'bad', ))->render(); exit(); } else if (isset($_POST['confirm'])) { $confirm = wfUtils::truthyToBoolean($_POST['confirm']); if ($confirm) { $found = false; $alertEmails = wfConfig::getAlertEmails(); $updatedAlertEmails = array(); foreach ($alertEmails as $alertEmail) { if ($alertEmail == $payload['email']) { $found = true; } else { $updatedAlertEmails[] = $alertEmail; } } if ($found) { wfConfig::set('alertEmails', implode(',', $updatedAlertEmails)); } echo wfView::create('common/unsubscribe', array( 'jwt' => $_GET['jwt'], 'email' => $payload['email'], 'state' => 'unsubscribed', ))->render(); exit(); } } echo wfView::create('common/unsubscribe', array( 'jwt' => $_GET['jwt'], 'email' => $payload['email'], 'state' => 'prompt', ))->render(); exit(); } else if ($wfFunc == 'installLicense') { if (wfUtils::isAdmin()) { wfUtils::doNotCache(); if (isset($_POST['license'])) { $nonceValid = wp_verify_nonce(@$_POST['nonce'], 'wf-form'); if (!$nonceValid) { die(__('Sorry but your browser sent an invalid security token when trying to use this form.', 'wordfence')); } $changes = array('apiKey' => $_POST['license']); $errors = wfConfig::validate($changes); if ($errors !== true) { $error = __('An error occurred while saving the license.', 'wordfence'); if (count($errors) == 1) { $error = sprintf(/* translators: Error message. */ __('An error occurred while saving the license: %s', 'wordfence'), $errors[0]['error']); } echo wfView::create('common/license', array( 'state' => 'bad', 'error' => $error, ))->render(); exit(); } try { wfConfig::save(wfConfig::clean($changes)); echo wfView::create('common/license', array( 'state' => 'installed', ))->render(); exit(); } catch (Exception $e) { echo wfView::create('common/license', array( 'state' => 'bad', 'error' => sprintf(/* translators: Error message. */ __('An error occurred while saving the license: %s', 'wordfence'), $e->getMessage()), ))->render(); exit(); } } echo wfView::create('common/license', array( 'state' => 'prompt', ))->render(); exit(); } } if (is_main_site() && wfUtils::isAdmin()) { if (wp_next_scheduled('wordfence_daily_cron') === false) { wp_schedule_event(time() + 600, 'daily', 'wordfence_daily_cron'); wordfence::status(2, 'info', __("Rescheduled missing daily cron", 'wordfence')); } if (wp_next_scheduled('wordfence_hourly_cron') === false) { wp_schedule_event(time() + 600, 'hourly', 'wordfence_hourly_cron'); wordfence::status(2, 'info', __("Rescheduled missing hourly cron", 'wordfence')); } } // Sync the WAF data with the database. $updateCountries = false; if (!WFWAF_SUBDIRECTORY_INSTALL && $waf = wfWAF::getInstance()) { $homeurl = wfUtils::wpHomeURL(); $siteurl = wfUtils::wpSiteURL(); //Sync the GeoIP database if needed $destination = WFWAF_LOG_PATH . '/GeoLite2-Country.mmdb'; if (!file_exists($destination) || wfConfig::get('needsGeoIPSync')) { $allowSync = false; if (wfConfig::createLock('wfSyncGeoIP')) { $status = get_transient('wfSyncGeoIPActive'); if (!$status) { $allowSync = true; set_transient('wfSyncGeoIPActive', true, 3600); } wfConfig::releaseLock('wfSyncGeoIP'); } if ($allowSync) { if (version_compare(phpversion(), '5.4.0', '>=')) { if (!class_exists('wfGeoIP2')) { require_once(dirname(__FILE__) . '/../models/common/wfGeoIP2.php'); } try { $wflogsGeoIP = @wfGeoIP2::shared(wfGeoIP2::DB_WFLOGS); $bundledGeoIP = @wfGeoIP2::shared(wfGeoIP2::DB_BUNDLED); if ($wflogsGeoIP === false || $wflogsGeoIP->version() != $bundledGeoIP->version()) { $source = dirname(__FILE__) . '/GeoLite2-Country.mmdb'; if (copy($source, $destination)) { $shash = ''; $dhash = ''; $sp = @fopen($source, "rb"); if ($sp) { $scontext = hash_init('sha256'); while (!feof($sp)) { $data = fread($sp, 65536); if ($data === false) { $scontext = false; break; } hash_update($scontext, $data); } fclose($sp); if ($scontext !== false) { $shash = hash_final($scontext, false); } } $dp = @fopen($destination, "rb"); if ($dp) { $dcontext = hash_init('sha256'); while (!feof($dp)) { $data = fread($dp, 65536); if ($data === false) { $dcontext = false; break; } hash_update($dcontext, $data); } fclose($dp); if ($scontext !== false) { $dhash = hash_final($dcontext, false); } } if (hash_equals($shash, $dhash)) { $updateCountries = true; wfConfig::remove('needsGeoIPSync'); delete_transient('wfSyncGeoIPActive'); } } } else { wfConfig::remove('needsGeoIPSync'); delete_transient('wfSyncGeoIPActive'); } } catch (Exception $e) { //Ignore } } } } if (!$updateCountries && version_compare(phpversion(), '5.4.0', '>=')) { $previousVersionHash = wfConfig::get('geoIPVersionHash', ''); $geoIPVersion = wfUtils::geoIPVersion(); if (is_array($geoIPVersion)) { $geoIPVersion = implode(',', $geoIPVersion); } $geoIPVersionHash = hash('sha256', $geoIPVersion); $updateCountries = ($geoIPVersion !== null && $previousVersionHash != $geoIPVersionHash); } if ($updateCountries) { // Fix the data in the country column $intervalSQL = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day)) / 86400)'; switch (wfConfig::get('email_summary_interval', 'weekly')) { case 'daily': $intervalSQL = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 day)) / 86400)'; break; case 'monthly': $intervalSQL = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month)) / 86400)'; break; } $table_wfBlockedIPLog = wfDB::networkTable('wfBlockedIPLog'); $ip_results = $wpdb->get_results("SELECT DISTINCT countryCode, IP FROM `{$table_wfBlockedIPLog}` WHERE unixday >= {$intervalSQL} GROUP BY IP ORDER BY unixday DESC LIMIT 500"); if ($ip_results) { foreach ($ip_results as $ip_row) { $country = wfUtils::IP2Country(wfUtils::inet_ntop($ip_row->IP)); if ($country != $ip_row->countryCode) { $wpdb->query($wpdb->prepare("UPDATE `{$table_wfBlockedIPLog}` SET countryCode = %s WHERE IP = %s", $country, $ip_row->IP)); } } } $geoIPVersion = wfUtils::geoIPVersion(); if (is_array($geoIPVersion)) { $geoIPVersion = implode(',', $geoIPVersion); } $geoIPVersionHash = hash('sha256', $geoIPVersion); wfConfig::set('geoIPVersionHash', $geoIPVersionHash); } try { $sapi = @php_sapi_name(); if ($sapi != "cli") { $lastPermissionsTemplateCheck = wfConfig::getInt('lastPermissionsTemplateCheck', 0); if (defined('WFWAF_LOG_PATH') && ($lastPermissionsTemplateCheck + 43200) < time()) { //Run no more frequently than every 12 hours $timestamp = preg_replace('/[^0-9]/', '', microtime(false)); //We avoid using tmpfile since it can potentially create one with different permissions than the defaults $tmpTemplate = rtrim(WFWAF_LOG_PATH, '/') . "/template.{$timestamp}.tmp"; $template = rtrim(WFWAF_LOG_PATH, '/') . '/template.php'; @unlink($tmpTemplate); @file_put_contents($tmpTemplate, "\n"); $tmpStat = @stat($tmpTemplate); if ($tmpStat !== false) { $mode = $tmpStat[2] & 0777; $updatedMode = 0600; if (($mode & 0020) == 0020) { //Group writable $updatedMode = $updatedMode | 0060; } if (defined('WFWAF_LOG_FILE_MODE')) { $updatedMode = WFWAF_LOG_FILE_MODE; } $stat = @stat($template); if ($stat === false || ($stat[2] & 0777) != $updatedMode) { @chmod($tmpTemplate, $updatedMode); @unlink($template); @rename($tmpTemplate, $template); } @unlink($tmpTemplate); } else { @unlink($tmpTemplate); } wfConfig::set('lastPermissionsTemplateCheck', time()); @chmod(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755)); wfWAFWordPress::writeHtaccess(); $contents = self::_wflogsContents(); if ($contents) { $validFiles = wfWAF::getInstance()->fileList(); foreach ($validFiles as &$vf) { $vf = basename($vf); } $validFiles = array_filter($validFiles); $previousWflogsFileList = wfConfig::getJSON('previousWflogsFileList', array()); $wflogs = realpath(WFWAF_LOG_PATH); $filesRemoved = array(); foreach ($contents as $f) { if (!in_array($f, $validFiles) && in_array($f, $previousWflogsFileList)) { $fullPath = $f; $removed = self::_recursivelyRemoveWflogs($f); $filesRemoved = array_merge($filesRemoved, $removed); } } $contents = self::_wflogsContents(); wfConfig::setJSON('previousWflogsFileList', $contents); if (!empty($filesRemoved)) { $removalHistory = wfConfig::getJSON('diagnosticsWflogsRemovalHistory', array()); $removalHistory = array_slice($removalHistory, 0, 4); array_unshift($removalHistory, array(time(), $filesRemoved)); wfConfig::setJSON('diagnosticsWflogsRemovalHistory', $removalHistory); } } } } } catch (Exception $e) { //Ignore } try { $configDefaults = array( 'apiKey' => wfConfig::get('apiKey'), 'isPaid' => !!wfConfig::get('isPaid'), 'siteURL' => $siteurl, 'homeURL' => $homeurl, 'whitelistedIPs' => (string) wfConfig::get('whitelisted'), 'whitelistedServiceIPs' => @json_encode(wfUtils::whitelistedServiceIPs()), 'howGetIPs' => (string) wfConfig::get('howGetIPs'), 'howGetIPs_trusted_proxies' => wfConfig::get('howGetIPs_trusted_proxies', ''), 'detectProxyRecommendation' => (string) wfConfig::get('detectProxyRecommendation'), 'other_WFNet' => !!wfConfig::get('other_WFNet', true), 'pluginABSPATH' => ABSPATH, 'serverIPs' => json_encode(wfUtils::serverIPs()), 'blockCustomText' => wpautop(wp_strip_all_tags(wfConfig::get('blockCustomText', ''))), 'betaThreatDefenseFeed' => !!wfConfig::get('betaThreatDefenseFeed'), 'disableWAFIPBlocking' => wfConfig::get('disableWAFIPBlocking'), 'wordpressVersion' => wfConfig::get('wordpressVersion'), 'wordpressPluginVersions' => wfConfig::get_ser('wordpressPluginVersions'), 'wordpressThemeVersions' => wfConfig::get_ser('wordpressThemeVersions'), 'WPLANG' => get_site_option('WPLANG'), ); if (wfUtils::isAdmin()) { $errorNonceKey = 'errorNonce_' . get_current_user_id(); $configDefaults[$errorNonceKey] = wp_create_nonce('wf-waf-error-page'); //Used by the AJAX watcher script } foreach ($configDefaults as $key => $value) { $waf->getStorageEngine()->setConfig($key, $value, 'synced'); } if (wfConfig::get('timeoffset_wf') !== false) { $waf->getStorageEngine()->setConfig('timeoffset_wf', wfConfig::get('timeoffset_wf'), 'synced'); } else { $waf->getStorageEngine()->unsetConfig('timeoffset_wf', 'synced'); } if (class_exists('wfWAFIPBlocksController')) { wfWAFIPBlocksController::setNeedsSynchronizeConfigSettings(); } if (wfUtils::isAdmin()) { if ($waf->getStorageEngine()->getConfig('wafStatus', '') == 'learning-mode') { if ($waf->getStorageEngine()->getConfig('learningModeGracePeriodEnabled', false)) { if ($waf->getStorageEngine()->getConfig('learningModeGracePeriod', 0) <= time()) { // Reached the end of the grace period, activate the WAF. $waf->getStorageEngine()->setConfig('wafStatus', 'enabled'); $waf->getStorageEngine()->setConfig('learningModeGracePeriodEnabled', 0); $waf->getStorageEngine()->unsetConfig('learningModeGracePeriod'); $firewall = new wfFirewall(); $firewall->syncStatus(true); } } } } if (empty($_GET['wordfence_syncAttackData'])) { $table_wfHits = wfDB::networkTable('wfHits'); if ($waf->getStorageEngine() instanceof wfWAFStorageMySQL) { $lastAttackMicroseconds = floatval($waf->getStorageEngine()->getConfig('lastAttackDataTruncateTime')); } else { $lastAttackMicroseconds = $wpdb->get_var("SELECT MAX(attackLogTime) FROM {$table_wfHits}"); } if (get_site_option('wordfence_lastSyncAttackData', 0) < time() - 8) { if ($waf->getStorageEngine()->hasNewerAttackData($lastAttackMicroseconds)) { if (get_site_option('wordfence_syncingAttackData') <= time() - 60) { // Could be the request to itself is not completing, add ajax to the head as a workaround $attempts = get_site_option('wordfence_syncAttackDataAttempts', 0); if ($attempts > 10) { add_action('wp_head', 'wordfence::addSyncAttackDataAjax'); add_action('login_head', 'wordfence::addSyncAttackDataAjax'); add_action('admin_head', 'wordfence::addSyncAttackDataAjax'); } else { update_site_option('wordfence_syncAttackDataAttempts', ++$attempts); wp_remote_post(add_query_arg('wordfence_syncAttackData', microtime(true), home_url('/')), array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters('https_local_ssl_verify', false) )); } } } } } if ($waf instanceof wfWAFWordPress && ($learningModeAttackException = $waf->getLearningModeAttackException())) { $log = self::getLog(); $log->initLogRequest(); $request = $log->getCurrentRequest(); $request->action = 'learned:waf'; $request->attackLogTime = microtime(true); $ruleIDs = array(); /** @var wfWAFRule $failedRule */ foreach ($learningModeAttackException->getFailedRules() as $failedRule) { $ruleIDs[] = $failedRule->getRuleID(); } $actionData = array( 'learningMode' => 1, 'failedRules' => $ruleIDs, 'paramKey' => $learningModeAttackException->getParamKey(), 'paramValue' => $learningModeAttackException->getParamValue(), ); if ($ruleIDs && $ruleIDs[0]) { $rule = $waf->getRule($ruleIDs[0]); if ($rule) { $request->actionDescription = $rule->getDescription(); $actionData['category'] = $rule->getCategory(); $actionData['ssl'] = $waf->getRequest()->getProtocol() === 'https'; $actionData['fullRequest'] = base64_encode($waf->getRequest()); } } $request->actionData = wfRequestModel::serializeActionData($actionData); register_shutdown_function(array($request, 'save')); self::scheduleSendAttackData(); } } catch (wfWAFStorageFileException $e) { // We don't have anywhere to write files in this scenario. } catch (wfWAFStorageEngineMySQLiException $e) { // Ignore and continue } } if(wfConfig::get('firewallEnabled')){ $wfLog = self::getLog(); $wfLog->firewallBadIPs(); $IP = wfUtils::getIP(); if (wfBlock::isWhitelisted($IP)) { return; } if (wfConfig::get('neverBlockBG') == 'neverBlockUA' && wfCrawl::isGoogleCrawler()) { return; } if (wfConfig::get('neverBlockBG') == 'neverBlockVerified' && wfCrawl::isVerifiedGoogleCrawler()) { return; } if (wfConfig::get('bannedURLs', false)) { $URLs = explode("\n", wfUtils::cleanupOneEntryPerLine(wfConfig::get('bannedURLs'))); foreach ($URLs as $URL) { if (preg_match(wfUtils::patternToRegex($URL, ''), $_SERVER['REQUEST_URI'])) { $reason = __('Accessed a banned URL', 'wordfence'); wfBlock::createIP($reason, $IP, wfBlock::blockDuration(), time(), time(), 1, wfBlock::TYPE_IP_AUTOMATIC_TEMPORARY); wfActivityReport::logBlockedIP($IP, null, 'bannedurl'); $wfLog->tagRequestForBlock($reason); $wfLog->do503(3600, __("Accessed a banned URL", 'wordfence')); //exits } } } if (wfConfig::get('other_blockBadPOST') == '1' && $_SERVER['REQUEST_METHOD'] == 'POST' && empty($_SERVER['HTTP_USER_AGENT']) && empty($_SERVER['HTTP_REFERER'])) { $reason = __('POST received with blank user-agent and referer', 'wordfence'); wfBlock::createIP($reason, $IP, wfBlock::blockDuration(), time(), time(), 1, wfBlock::TYPE_IP_AUTOMATIC_TEMPORARY); wfActivityReport::logBlockedIP($IP, null, 'badpost'); $wfLog->tagRequestForBlock($reason); $wfLog->do503(3600, __("POST received with blank user-agent and referer", 'wordfence')); //exits } } } private static function _wflogsContents() { $dir = opendir(WFWAF_LOG_PATH); if ($dir) { $contents = array(); while ($path = readdir($dir)) { if ($path == '.' || $path == '..') { continue; } $contents[] = $path; } closedir($dir); return $contents; } return false; } /** * Removes a path within wflogs, recursing as necessary. * * @param string $file * @param array $processedDirs * @return array The list of removed files/folders. */ private static function _recursivelyRemoveWflogs($file, $processedDirs = array()) { if (preg_match('~(?:^|/|\\\\)\.\.(?:/|\\\\|$)~', $file)) { return array(); } if (stripos(WFWAF_LOG_PATH, 'wflogs') === false) { //Sanity check -- if not in a wflogs folder, user will have to do removal manually return array(); } $path = rtrim(WFWAF_LOG_PATH, '/') . '/' . $file; if (is_link($path)) { if (@unlink($path)) { return array($file); } return array(); } if (is_dir($path)) { $real = realpath($file); if (in_array($real, $processedDirs)) { return array(); } $processedDirs[] = $real; $count = 0; $dir = opendir($path); if ($dir) { $contents = array(); while ($sub = readdir($dir)) { if ($sub == '.' || $sub == '..') { continue; } $contents[] = $sub; } closedir($dir); $filesRemoved = array(); foreach ($contents as $f) { $removed = self::_recursivelyRemoveWflogs($file . '/' . $f, $processedDirs); $filesRemoved = array($filesRemoved, $removed); } } if (@rmdir($path)) { $filesRemoved[] = $file; } return $filesRemoved; } if (@unlink($path)) { return array($file); } return array(); } public static function loginAction($username){ if(sizeof($_POST) < 1){ return; } //only execute if login form is posted if(! $username){ return; } wfConfig::inc('totalLogins'); $user = get_user_by('login', $username); $userID = $user ? $user->ID : 0; self::getLog()->logLogin('loginOK', 0, $username); if(wfUtils::isAdmin($user)){ wfConfig::set_ser('lastAdminLogin', array( 'userID' => $userID, 'username' => $username, 'firstName' => $user->first_name, 'lastName' => $user->last_name, 'time' => wfUtils::localHumanDateShort(), 'IP' => wfUtils::getIP() )); } $salt = wp_salt('logged_in'); //TODO: Drop support for legacy cookie after 1 year $legacyCookieName = 'wf_loginalerted_' . hash_hmac('sha256', wfUtils::getIP() . '|' . $user->ID, $salt); $cookieName = 'wf_loginalerted_' . hash_hmac('sha256', $user->ID, $salt); $cookieValue = hash_hmac('sha256', $user->user_login, $salt); $newDevice = !(isset($_COOKIE[$legacyCookieName]) && hash_equals($cookieValue, $_COOKIE[$legacyCookieName])); //Check legacy cookie if($newDevice){ $newDevice = !(isset($_COOKIE[$cookieName]) && hash_equals($cookieValue, $_COOKIE[$cookieName])); } else{ $_COOKIE[$cookieName]=$cookieValue; } if(wfUtils::isAdmin($userID)){ $securityEvent = 'adminLogin'; $alertCallback = array(new wfAdminLoginAlert($cookieName, $cookieValue, $username, wfUtils::getIP()), 'send'); } else { $securityEvent = 'nonAdminLogin'; $alertCallback = array(new wfNonAdminLoginAlert($cookieName, $cookieValue, $username, wfUtils::getIP()), 'send'); } if($newDevice) $securityEvent.='NewLocation'; do_action('wordfence_security_event', $securityEvent, array( 'username' => $username, 'ip' => wfUtils::getIP(), ), $alertCallback); if (wfConfig::get(wfUtils::isAdmin($userID)?'alertOn_firstAdminLoginOnly':'alertOn_firstNonAdminLoginOnly')) { //Purge legacy cookie if still present if(array_key_exists($legacyCookieName, $_COOKIE)) wfUtils::setcookie($legacyCookieName, '', 1, '/', null, wfUtils::isFullSSL(), true); wfUtils::setcookie($cookieName, $cookieValue, time() + (86400 * 365), '/', null, wfUtils::isFullSSL(), true); } } public static function registrationFilter($errors, $sanitizedLogin, $userEmail) { if (wfConfig::get('loginSec_blockAdminReg') && $sanitizedLogin == 'admin') { $errors->add('user_login_error', __('ERROR: You can\'t register using that username', 'wordfence')); } return $errors; } public static function wooRegistrationFilter($wooCustomerData) { /* $wooCustomerData matches: array( 'user_login' => $username, 'user_pass' => $password, 'user_email' => $email, 'role' => 'customer', ) */ if (wfConfig::get('loginSec_blockAdminReg') && is_array($wooCustomerData) && isset($wooCustomerData['user_login']) && isset($wooCustomerData['user_email']) && preg_match('/^admin\d*$/i', $wooCustomerData['user_login'])) { //Converts a username of `admin` generated from something like `admin@example.com` to `adminexample` $emailComponents = explode('@', $wooCustomerData['user_email']); if (strpos(wfUtils::array_last($emailComponents), '.') === false) { //e.g., admin@localhost $wooCustomerData['user_login'] .= wfUtils::array_last($emailComponents); } else { //e.g., admin@example.com $hostComponents = explode('.', wfUtils::array_last($emailComponents)); array_pop($hostComponents); $wooCustomerData['user_login'] .= wfUtils::array_last($hostComponents); } //If it's still `admin` at this point, it will fall through and get blocked by wordfence::blacklistedUsernames } return $wooCustomerData; } public static function oembedAuthorFilter($data, $post, $width, $height) { unset($data['author_name']); unset($data['author_url']); return $data; } public static function jsonAPIAuthorFilter($response, $handler, $request) { $route = $request->get_route(); if (!current_user_can('edit_others_posts')) { $urlBase = wfWP_REST_Users_Controller::wfGetURLBase(); if (preg_match('~' . preg_quote($urlBase, '~') . '/*$~i', $route)) { $error = new WP_Error('rest_user_cannot_view', __('Sorry, you are not allowed to list users.', 'wordfence'), array('status' => rest_authorization_required_code())); $response = rest_ensure_response($error); if (!defined('WORDFENCE_REST_API_SUPPRESSED')) { define('WORDFENCE_REST_API_SUPPRESSED', true); } } else if (preg_match('~' . preg_quote($urlBase, '~') . '/+(\d+)/*$~i', $route, $matches)) { $id = (int) $matches[1]; if (get_current_user_id() !== $id) { $error = new WP_Error('rest_user_invalid_id', __('Invalid user ID.', 'wordfence'), array('status' => 404)); $response = rest_ensure_response($error); if (!defined('WORDFENCE_REST_API_SUPPRESSED')) { define('WORDFENCE_REST_API_SUPPRESSED', true); } } } } return $response; } public static function jsonAPIAdjustHeaders($response, $server, $request) { if (defined('WORDFENCE_REST_API_SUPPRESSED')) { $response->header('Allow', 'GET'); } return $response; } public static function wpSitemapUserProviderFilter($provider, $name) { if ($name === 'users') { return false; } return $provider; } public static function _filterCentralFromLiveTraffic($dispatch_result, $request, $route, $handler) { if (preg_match('~^/wordfence/v\d+/~i', $route)) { self::getLog()->canLogHit = false; } return $dispatch_result; } public static function showTwoFactorField() { $existingContents = ob_get_contents(); if (!preg_match('/wftwofactornonce:([0-9]+)\/(.+?)\s/', $existingContents, $matches)) { return; } $userID = intval($matches[1]); $twoFactorNonce = preg_replace('/[^a-f0-9]/i', '', $matches[2]); if (!self::verifyTwoFactorIntermediateValues($userID, $twoFactorNonce)) { return; } //Strip out the username and password fields $formPosition = strrpos($existingContents, '