PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /home/trave494/craftsperks.online/wp-content/plugins/wordfence/lib/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : /home/trave494/craftsperks.online/wp-content/plugins/wordfence/lib/wfConfig.php |
<?php class wfConfig { const AUTOLOAD = 'yes'; const DONT_AUTOLOAD = 'no'; public static $diskCache = array(); private static $diskCacheDisabled = false; //enables if we detect a write fail so we don't keep calling stat() private static $cacheDisableCheckDone = false; private static $table = false; private static $tableExists = true; private static $cache = array(); private static $DB = false; private static $tmpFileHeader = "<?php\n/* Wordfence temporary file security header */\necho \"Nothing to see here!\\n\"; exit(0);\n?>"; private static $tmpDirCache = false; public static $defaultConfig = array( //All exportable boolean options "checkboxes" => array( "alertOn_critical" => array('value' => true, 'autoload' => self::AUTOLOAD), "alertOn_update" => array('value' => false, 'autoload' => self::AUTOLOAD), "alertOn_warnings" => array('value' => true, 'autoload' => self::AUTOLOAD), "alertOn_throttle" => array('value' => false, 'autoload' => self::AUTOLOAD), "alertOn_block" => array('value' => true, 'autoload' => self::AUTOLOAD), "alertOn_loginLockout" => array('value' => true, 'autoload' => self::AUTOLOAD), "alertOn_lostPasswdForm" => array('value' => true, 'autoload' => self::AUTOLOAD), "alertOn_adminLogin" => array('value' => true, 'autoload' => self::AUTOLOAD), "alertOn_firstAdminLoginOnly" => array('value' => false, 'autoload' => self::AUTOLOAD), "alertOn_nonAdminLogin" => array('value' => false, 'autoload' => self::AUTOLOAD), "alertOn_firstNonAdminLoginOnly" => array('value' => false, 'autoload' => self::AUTOLOAD), "alertOn_wordfenceDeactivated" => array('value' => true, 'autoload' => self::AUTOLOAD), "liveTrafficEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD), "advancedCommentScanning" => array('value' => false, 'autoload' => self::AUTOLOAD), "checkSpamIP" => array('value' => false, 'autoload' => self::AUTOLOAD), "spamvertizeCheck" => array('value' => false, 'autoload' => self::AUTOLOAD), "liveTraf_ignorePublishers" => array('value' => true, 'autoload' => self::AUTOLOAD), //"perfLoggingEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD), "scheduledScansEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD), "lowResourceScansEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD), "scansEnabled_checkGSB" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_checkHowGetIPs" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_core" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_themes" => array('value' => false, 'autoload' => self::AUTOLOAD), "scansEnabled_plugins" => array('value' => false, 'autoload' => self::AUTOLOAD), "scansEnabled_coreUnknown" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_malware" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_fileContents" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_fileContentsGSB" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_checkReadableConfig" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_suspectedFiles" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_posts" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_comments" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_suspiciousOptions" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_passwds" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_diskSpace" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_options" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_wpscan_fullPathDisclosure" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_wpscan_directoryListingEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_dns" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_scanImages" => array('value' => false, 'autoload' => self::AUTOLOAD), "scansEnabled_highSense" => array('value' => false, 'autoload' => self::AUTOLOAD), "scansEnabled_oldVersions" => array('value' => true, 'autoload' => self::AUTOLOAD), "scansEnabled_suspiciousAdminUsers" => array('value' => true, 'autoload' => self::AUTOLOAD), "liveActivityPauseEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD), "firewallEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD), "blockFakeBots" => array('value' => false, 'autoload' => self::AUTOLOAD), "autoBlockScanners" => array('value' => true, 'autoload' => self::AUTOLOAD), "loginSecurityEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD), "loginSec_lockInvalidUsers" => array('value' => false, 'autoload' => self::AUTOLOAD), "loginSec_maskLoginErrors" => array('value' => true, 'autoload' => self::AUTOLOAD), "loginSec_blockAdminReg" => array('value' => true, 'autoload' => self::AUTOLOAD), "loginSec_disableAuthorScan" => array('value' => true, 'autoload' => self::AUTOLOAD), "loginSec_disableOEmbedAuthor" => array('value' => false, 'autoload' => self::AUTOLOAD), "notification_updatesNeeded" => array('value' => true, 'autoload' => self::AUTOLOAD), "notification_securityAlerts" => array('value' => true, 'autoload' => self::AUTOLOAD), "notification_promotions" => array('value' => true, 'autoload' => self::AUTOLOAD), "notification_blogHighlights" => array('value' => true, 'autoload' => self::AUTOLOAD), "notification_productUpdates" => array('value' => true, 'autoload' => self::AUTOLOAD), "notification_scanStatus" => array('value' => true, 'autoload' => self::AUTOLOAD), "other_hideWPVersion" => array('value' => false, 'autoload' => self::AUTOLOAD), "other_noAnonMemberComments" => array('value' => true, 'autoload' => self::AUTOLOAD), "other_blockBadPOST" => array('value' => false, 'autoload' => self::AUTOLOAD), "other_scanComments" => array('value' => true, 'autoload' => self::AUTOLOAD), "other_pwStrengthOnUpdate" => array('value' => true, 'autoload' => self::AUTOLOAD), "other_WFNet" => array('value' => true, 'autoload' => self::AUTOLOAD), "other_scanOutside" => array('value' => false, 'autoload' => self::AUTOLOAD), "other_bypassLitespeedNoabort" => array('value' => false, 'autoload' => self::AUTOLOAD), "deleteTablesOnDeact" => array('value' => false, 'autoload' => self::AUTOLOAD), "autoUpdate" => array('value' => false, 'autoload' => self::AUTOLOAD), "disableCookies" => array('value' => false, 'autoload' => self::AUTOLOAD), "startScansRemotely" => array('value' => false, 'autoload' => self::AUTOLOAD), "disableConfigCaching" => array('value' => false, 'autoload' => self::AUTOLOAD), "addCacheComment" => array('value' => false, 'autoload' => self::AUTOLOAD), "disableCodeExecutionUploads" => array('value' => false, 'autoload' => self::AUTOLOAD), "allowHTTPSCaching" => array('value' => false, 'autoload' => self::AUTOLOAD), "debugOn" => array('value' => false, 'autoload' => self::AUTOLOAD), 'email_summary_enabled' => array('value' => true, 'autoload' => self::AUTOLOAD), 'email_summary_dashboard_widget_enabled' => array('value' => true, 'autoload' => self::AUTOLOAD), 'ssl_verify' => array('value' => true, 'autoload' => self::AUTOLOAD), 'ajaxWatcherDisabled_front' => array('value' => false, 'autoload' => self::AUTOLOAD), 'ajaxWatcherDisabled_admin' => array('value' => false, 'autoload' => self::AUTOLOAD), 'wafAlertOnAttacks' => array('value' => true, 'autoload' => self::AUTOLOAD), 'disableWAFIPBlocking' => array('value' => false, 'autoload' => self::AUTOLOAD), 'showAdminBarMenu' => array('value' => true, 'autoload' => self::AUTOLOAD), ), //All exportable variable type options "otherParams" => array( "scan_include_extra" => array('value' => "", 'autoload' => self::AUTOLOAD), "alertEmails" => array('value' => "", 'autoload' => self::AUTOLOAD), "liveTraf_ignoreUsers" => array('value' => "", 'autoload' => self::AUTOLOAD), "liveTraf_ignoreIPs" => array('value' => "", 'autoload' => self::AUTOLOAD), "liveTraf_ignoreUA" => array('value' => "", 'autoload' => self::AUTOLOAD), "apiKey" => array('value' => "", 'autoload' => self::AUTOLOAD), "maxMem" => array('value' => '256', 'autoload' => self::AUTOLOAD), 'scan_exclude' => array('value' => '', 'autoload' => self::AUTOLOAD), 'scan_maxIssues' => array('value' => 1000, 'autoload' => self::AUTOLOAD), 'scan_maxDuration' => array('value' => '', 'autoload' => self::AUTOLOAD), 'whitelisted' => array('value' => '', 'autoload' => self::AUTOLOAD), 'bannedURLs' => array('value' => '', 'autoload' => self::AUTOLOAD), 'maxExecutionTime' => array('value' => '', 'autoload' => self::AUTOLOAD), 'howGetIPs' => array('value' => '', 'autoload' => self::AUTOLOAD), 'actUpdateInterval' => array('value' => '', 'autoload' => self::AUTOLOAD), 'alert_maxHourly' => array('value' => 0, 'autoload' => self::AUTOLOAD), 'loginSec_userBlacklist' => array('value' => '', 'autoload' => self::AUTOLOAD), 'liveTraf_maxRows' => array('value' => 2000, 'autoload' => self::AUTOLOAD), "neverBlockBG" => array('value' => "neverBlockVerified", 'autoload' => self::AUTOLOAD), "loginSec_countFailMins" => array('value' => "240", 'autoload' => self::AUTOLOAD), "loginSec_lockoutMins" => array('value' => "240", 'autoload' => self::AUTOLOAD), 'loginSec_strongPasswds' => array('value' => 'pubs', 'autoload' => self::AUTOLOAD), 'loginSec_maxFailures' => array('value' => "20", 'autoload' => self::AUTOLOAD), 'loginSec_maxForgotPasswd' => array('value' => "20", 'autoload' => self::AUTOLOAD), 'maxGlobalRequests' => array('value' => "DISABLED", 'autoload' => self::AUTOLOAD), 'maxGlobalRequests_action' => array('value' => "throttle", 'autoload' => self::AUTOLOAD), 'maxRequestsCrawlers' => array('value' => "DISABLED", 'autoload' => self::AUTOLOAD), 'maxRequestsCrawlers_action' => array('value' => "throttle", 'autoload' => self::AUTOLOAD), 'maxRequestsHumans' => array('value' => "DISABLED", 'autoload' => self::AUTOLOAD), 'maxRequestsHumans_action' => array('value' => "throttle", 'autoload' => self::AUTOLOAD), 'max404Crawlers' => array('value' => "DISABLED", 'autoload' => self::AUTOLOAD), 'max404Crawlers_action' => array('value' => "throttle", 'autoload' => self::AUTOLOAD), 'max404Humans' => array('value' => "DISABLED", 'autoload' => self::AUTOLOAD), 'max404Humans_action' => array('value' => "throttle", 'autoload' => self::AUTOLOAD), 'maxScanHits' => array('value' => "DISABLED", 'autoload' => self::AUTOLOAD), 'maxScanHits_action' => array('value' => "throttle", 'autoload' => self::AUTOLOAD), 'blockedTime' => array('value' => "300", 'autoload' => self::AUTOLOAD), 'email_summary_interval' => array('value' => 'weekly', 'autoload' => self::AUTOLOAD), 'email_summary_excluded_directories' => array('value' => 'wp-content/cache,wp-content/wflogs', 'autoload' => self::AUTOLOAD), 'allowed404s' => array('value' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png\n/browserconfig.xml", 'autoload' => self::AUTOLOAD), 'wafAlertWhitelist' => array('value' => '', 'autoload' => self::AUTOLOAD), 'wafAlertInterval' => array('value' => 600, 'autoload' => self::AUTOLOAD), 'wafAlertThreshold' => array('value' => 100, 'autoload' => self::AUTOLOAD), 'howGetIPs_trusted_proxies' => array('value' => '', 'autoload' => self::AUTOLOAD), ), //Set as default only, not included automatically in the settings import/export or options page saving 'defaultsOnly' => array( 'cbl_loggedInBlocked' => array('value' => false, 'autoload' => self::AUTOLOAD), 'cbl_loginFormBlocked' => array('value' => false, 'autoload' => self::AUTOLOAD), 'cbl_restOfSiteBlocked' => array('value' => true, 'autoload' => self::AUTOLOAD), 'isPaid' => array('value' => false, 'autoload' => self::AUTOLOAD), 'hasKeyConflict' => array('value' => false, 'autoload' => self::AUTOLOAD), 'betaThreatDefenseFeed' => array('value' => false, 'autoload' => self::AUTOLOAD), 'cbl_action' => array('value' => 'block', 'autoload' => self::AUTOLOAD), 'cbl_redirURL' => array('value' => '', 'autoload' => self::AUTOLOAD), 'cbl_bypassRedirURL' => array('value' => '', 'autoload' => self::AUTOLOAD), 'cbl_bypassRedirDest' => array('value' => '', 'autoload' => self::AUTOLOAD), 'cbl_bypassViewURL' => array('value' => '', 'autoload' => self::AUTOLOAD), 'cbl_countries' => array('value' => '', 'autoload' => self::AUTOLOAD), 'timeoffset_wf_updated' => array('value' => 0, 'autoload' => self::AUTOLOAD), 'cacheType' => array('value' => 'disabled', 'autoload' => self::AUTOLOAD), 'detectProxyRecommendation' => array('value' => '', 'autoload' => self::DONT_AUTOLOAD), 'loginSec_enableSeparateTwoFactor' => array('value' => false, 'autoload' => self::AUTOLOAD), ), ); public static $serializedOptions = array('lastAdminLogin', 'scanSched', 'emailedIssuesList', 'wf_summaryItems', 'adminUserList', 'twoFactorUsers', 'alertFreqTrack', 'wfStatusStartMsgs', 'vulnerabilities_plugin', 'vulnerabilities_theme', 'dashboardData', 'malwarePrefixes', 'noc1ScanSchedule', 'allScansScheduled'); public static function setDefaults() { foreach (self::$defaultConfig['checkboxes'] as $key => $config) { $val = $config['value']; $autoload = $config['autoload']; if (self::get($key) === false) { self::set($key, $val ? '1' : '0', $autoload); } } foreach (self::$defaultConfig['otherParams'] as $key => $config) { $val = $config['value']; $autoload = $config['autoload']; if (self::get($key) === false) { self::set($key, $val, $autoload); } } foreach (self::$defaultConfig['defaultsOnly'] as $key => $config) { $val = $config['value']; $autoload = $config['autoload']; if (self::get($key) === false) { if ($val === false) { self::set($key, '0', $autoload); } else if ($val === true) { self::set($key, '1', $autoload); } else { self::set($key, $val, $autoload); } } } self::set('encKey', substr(wfUtils::bigRandomHex(), 0, 16)); if (self::get('maxMem', false) === false) { self::set('maxMem', '256'); } if (self::get('other_scanOutside', false) === false) { self::set('other_scanOutside', 0); } if (self::get('email_summary_enabled')) { wfActivityReport::scheduleCronJob(); } else { wfActivityReport::disableCronJob(); } } public static function loadAllOptions() { global $wpdb; $options = wp_cache_get('alloptions', 'wordfence'); if (!$options) { $table = self::table(); self::updateTableExists(); $suppress = $wpdb->suppress_errors(); if (!($rawOptions = $wpdb->get_results("SELECT name, val FROM {$table} WHERE autoload = 'yes'"))) { $rawOptions = $wpdb->get_results("SELECT name, val FROM {$table}"); } $wpdb->suppress_errors($suppress); $options = array(); foreach ((array) $rawOptions as $o) { if (in_array($o->name, self::$serializedOptions)) { $val = maybe_unserialize($o->val); if ($val) { $options[$o->name] = $val; } } else { $options[$o->name] = $o->val; } } wp_cache_add_non_persistent_groups('wordfence'); wp_cache_add('alloptions', $options, 'wordfence'); } return $options; } public static function updateTableExists() { global $wpdb; self::$tableExists = $wpdb->get_col($wpdb->prepare(<<<SQL SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=%s SQL , self::table())); } private static function updateCachedOption($name, $val) { $options = self::loadAllOptions(); $options[$name] = $val; wp_cache_set('alloptions', $options, 'wordfence'); } private static function removeCachedOption($name) { $options = self::loadAllOptions(); if (isset($options[$name])) { unset($options[$name]); wp_cache_set('alloptions', $options, 'wordfence'); } } private static function getCachedOption($name) { $options = self::loadAllOptions(); if (isset($options[$name])) { return $options[$name]; } $table = self::table(); $val = self::getDB()->querySingle("SELECT val FROM {$table} WHERE name='%s'", $name); if ($val !== null) { $options[$name] = $val; wp_cache_set('alloptions', $options, 'wordfence'); } return $val; } private static function hasCachedOption($name) { $options = self::loadAllOptions(); return isset($options[$name]); } public static function getExportableOptionsKeys(){ $ret = array(); foreach(self::$defaultConfig['checkboxes'] as $key => $val){ $ret[] = $key; } foreach(self::$defaultConfig['otherParams'] as $key => $val){ if($key != 'apiKey'){ $ret[] = $key; } } foreach(array('cbl_action', 'cbl_countries', 'cbl_redirURL', 'cbl_loggedInBlocked', 'cbl_loginFormBlocked', 'cbl_restOfSiteBlocked', 'cbl_bypassRedirURL', 'cbl_bypassRedirDest', 'cbl_bypassViewURL') as $key){ $ret[] = $key; } return $ret; } public static function parseOptions($excludeOmitted = false) { $ret = array(); foreach (self::$defaultConfig['checkboxes'] as $key => $val) { //value is not used. We just need the keys for validation if ($excludeOmitted && isset($_POST[$key])) { $ret[$key] = (int) $_POST[$key]; } else if (!$excludeOmitted || isset($_POST[$key])) { $ret[$key] = isset($_POST[$key]) ? '1' : '0'; } } foreach (self::$defaultConfig['otherParams'] as $key => $val) { if (!$excludeOmitted || isset($_POST[$key])) { if (isset($_POST[$key])) { $ret[$key] = stripslashes($_POST[$key]); } else { error_log("Missing options param \"$key\" when parsing parameters."); } } } /* for debugging only: foreach($_POST as $key => $val){ if($key != 'action' && $key != 'nonce' && (! array_key_exists($key, self::$checkboxes)) && (! array_key_exists($key, self::$otherParams)) ){ error_log("Unrecognized option: $key"); } } */ return $ret; } public static function setArray($arr){ foreach($arr as $key => $val){ self::set($key, $val); } } public static function getHTML($key){ return esc_html(self::get($key)); } public static function inc($key){ $val = self::get($key, false); if(! $val){ $val = 0; } self::set($key, $val + 1); return $val + 1; } public static function atomicInc($key) { if (!self::$tableExists) { return false; } global $wpdb; $old_suppress_errors = $wpdb->suppress_errors(true); $table = self::table(); $rowExists = false; do { if (!$rowExists && $wpdb->query($wpdb->prepare("INSERT INTO {$table} (name, val, autoload) values (%s, %s, %s)", $key, 1, self::DONT_AUTOLOAD))) { $val = 1; $successful = true; } else { $rowExists = true; $val = self::get($key, 1); if ($wpdb->query($wpdb->prepare("UPDATE {$table} SET val = %s WHERE name = %s AND val = %s", $val + 1, $key, $val))) { $val++; $successful = true; } } } while (!$successful); $wpdb->suppress_errors($old_suppress_errors); return $val; } public static function set($key, $val, $autoload = self::AUTOLOAD) { global $wpdb; if (is_array($val)) { $msg = "wfConfig::set() got an array as second param with key: $key and value: " . var_export($val, true); wordfence::status(1, 'error', $msg); return; } if (($key == 'apiKey' || $key == 'isPaid' || $key == 'other_WFNet') && wfWAF::getInstance() && !WFWAF_SUBDIRECTORY_INSTALL) { if ($key == 'isPaid' || $key == 'other_WFNet') { $val = !!$val; } try { wfWAF::getInstance()->getStorageEngine()->setConfig($key, $val); } catch (wfWAFStorageFileException $e) { error_log($e->getMessage()); } } if (!self::$tableExists) { return; } $table = self::table(); if ($wpdb->query($wpdb->prepare("INSERT INTO {$table} (name, val, autoload) values (%s, %s, %s) ON DUPLICATE KEY UPDATE val = %s, autoload = %s", $key, $val, $autoload, $val, $autoload)) !== false && $autoload != self::DONT_AUTOLOAD) { self::updateCachedOption($key, $val); } if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController') && (substr($key, 0, 4) == 'cbl_' || $key == 'blockedTime' || $key == 'disableWAFIPBlocking')) { wfWAFIPBlocksController::synchronizeConfigSettings(); } } public static function get($key, $default = false, $allowCached = true) { global $wpdb; if ($allowCached && self::hasCachedOption($key)) { return self::getCachedOption($key); } if (!self::$tableExists) { return $default; } $table = self::table(); if (!($option = $wpdb->get_row($wpdb->prepare("SELECT name, val, autoload FROM {$table} WHERE name = %s", $key)))) { return $default; } if ($option->autoload != self::DONT_AUTOLOAD) { self::updateCachedOption($key, $option->val); } return $option->val; } private static function canCompressValue() { if (!function_exists('gzencode') || !function_exists('gzdecode')) { return false; } $disabled = explode(',', ini_get('disable_functions')); if (in_array('gzencode', $disabled) || in_array('gzdecode', $disabled)) { return false; } return true; } private static function isCompressedValue($data) { //Based on http://www.ietf.org/rfc/rfc1952.txt if (strlen($data) < 2) { return false; } $magicBytes = substr($data, 0, 2); if ($magicBytes !== (chr(0x1f) . chr(0x8b))) { return false; } //Small chance of false positives here -- can check the header CRC if it turns out it's needed return true; } private static function ser_chunked_key($key) { return 'wordfence_chunked_' . $key . '_'; } public static function get_ser($key, $default = false, $cache = true) { if (self::hasCachedOption($key)) { return self::getCachedOption($key); } if (!self::$tableExists) { return $default; } //Check for a chunked value first $chunkedValueKey = self::ser_chunked_key($key); $header = self::getDB()->querySingle("select val from " . self::table() . " where name=%s", $chunkedValueKey . 'header'); if ($header) { $header = unserialize($header); $count = $header['count']; $path = tempnam(sys_get_temp_dir(), $key); //Writing to a file like this saves some of PHP's in-memory copying when just appending each chunk to a string $fh = fopen($path, 'r+'); $length = 0; for ($i = 0; $i < $count; $i++) { $chunk = self::getDB()->querySingle("select val from " . self::table() . " where name=%s", $chunkedValueKey . $i); self::getDB()->flush(); //clear cache if (!$chunk) { wordfence::status(2, 'error', "Error reassembling value for {$key}"); return $default; } fwrite($fh, $chunk); $length += strlen($chunk); unset($chunk); } fseek($fh, 0); $serialized = fread($fh, $length); fclose($fh); unlink($path); if (self::canCompressValue() && self::isCompressedValue($serialized)) { $inflated = @gzdecode($serialized); if ($inflated !== false) { unset($serialized); if ($cache) { self::updateCachedOption($key, unserialize($inflated)); return self::getCachedOption($key); } return unserialize($inflated); } } if ($cache) { self::updateCachedOption($key, unserialize($serialized)); return self::getCachedOption($key); } return unserialize($serialized); } else { $serialized = self::getDB()->querySingle("select val from " . self::table() . " where name=%s", $key); self::getDB()->flush(); //clear cache if ($serialized) { if (self::canCompressValue() && self::isCompressedValue($serialized)) { $inflated = @gzdecode($serialized); if ($inflated !== false) { unset($serialized); return unserialize($inflated); } } if ($cache) { self::updateCachedOption($key, unserialize($serialized)); return self::getCachedOption($key); } return unserialize($serialized); } } return $default; } public static function set_ser($key, $val, $allowCompression = false, $autoload = self::AUTOLOAD) { /* * Because of the small default value for `max_allowed_packet` and `max_long_data_size`, we're stuck splitting * large values into multiple chunks. To minimize memory use, the MySQLi driver is used directly when possible. */ global $wpdb; $dbh = $wpdb->dbh; $useMySQLi = (is_object($dbh) && $wpdb->use_mysqli); if (!self::$tableExists) { return; } self::delete_ser_chunked($key); //Ensure any old values for a chunked value are deleted first if (self::canCompressValue() && $allowCompression) { $data = gzencode(serialize($val)); } else { $data = serialize($val); } if (!$useMySQLi) { $data = bin2hex($data); } $dataLength = strlen($data); $maxAllowedPacketBytes = self::getDB()->getMaxAllowedPacketBytes(); $chunkSize = intval((($maxAllowedPacketBytes < 1024 /* MySQL minimum, probably failure to fetch it */ ? 1024 * 1024 /* MySQL default */ : $maxAllowedPacketBytes) - 50) / 1.2); //Based on max_allowed_packet + 20% for escaping and SQL $chunkSize = $chunkSize - ($chunkSize % 2); //Ensure it's even $chunkedValueKey = self::ser_chunked_key($key); if ($dataLength > $chunkSize) { $chunks = 0; while (($chunks * $chunkSize) < $dataLength) { $dataChunk = substr($data, $chunks * $chunkSize, $chunkSize); if ($useMySQLi) { $chunkKey = $chunkedValueKey . $chunks; $stmt = $dbh->prepare("INSERT IGNORE INTO " . self::table() . " (name, val, autoload) VALUES (?, ?, 'no')"); if ($stmt === false) { wordfence::status(2, 'error', "Error writing value chunk for {$key} (MySQLi error: [{$dbh->errno}] {$dbh->error})"); return false; } $null = NULL; $stmt->bind_param("sb", $chunkKey, $null); if (!$stmt->send_long_data(1, $dataChunk)) { wordfence::status(2, 'error', "Error writing value chunk for {$key} (MySQLi error: [{$dbh->errno}] {$dbh->error})"); return false; } if (!$stmt->execute()) { wordfence::status(2, 'error', "Error finishing writing value for {$key} (MySQLi error: [{$dbh->errno}] {$dbh->error})"); return false; } } else { if (!self::getDB()->queryWrite(sprintf("insert ignore into " . self::table() . " (name, val, autoload) values (%%s, X'%s', 'no')", $dataChunk), $chunkedValueKey . $chunks)) { $errno = mysql_errno($wpdb->dbh); wordfence::status(2, 'error', "Error writing value chunk for {$key} (MySQL error: [$errno] {$wpdb->last_error})"); return false; } } $chunks++; } if (!self::getDB()->queryWrite(sprintf("insert ignore into " . self::table() . " (name, val, autoload) values (%%s, X'%s', 'no')", bin2hex(serialize(array('count' => $chunks)))), $chunkedValueKey . 'header')) { wordfence::status(2, 'error', "Error writing value header for {$key}"); return false; } } else { $exists = self::getDB()->querySingle("select name from " . self::table() . " where name='%s'", $key); if ($useMySQLi) { if ($exists) { $stmt = $dbh->prepare("UPDATE " . self::table() . " SET val=? WHERE name=?"); if ($stmt === false) { wordfence::status(2, 'error', "Error writing value for {$key} (MySQLi error: [{$dbh->errno}] {$dbh->error})"); return false; } $null = NULL; $stmt->bind_param("bs", $null, $key); } else { $stmt = $dbh->prepare("INSERT IGNORE INTO " . self::table() . " (val, name, autoload) VALUES (?, ?, ?)"); if ($stmt === false) { wordfence::status(2, 'error', "Error writing value for {$key} (MySQLi error: [{$dbh->errno}] {$dbh->error})"); return false; } $null = NULL; $stmt->bind_param("bss", $null, $key, $autoload); } if (!$stmt->send_long_data(0, $data)) { wordfence::status(2, 'error', "Error writing value for {$key} (MySQLi error: [{$dbh->errno}] {$dbh->error})"); return false; } if (!$stmt->execute()) { wordfence::status(2, 'error', "Error finishing writing value for {$key} (MySQLi error: [{$dbh->errno}] {$dbh->error})"); return false; } } else { if ($exists) { self::getDB()->queryWrite(sprintf("update " . self::table() . " set val=X'%s' where name=%%s", $data), $key); } else { self::getDB()->queryWrite(sprintf("insert ignore into " . self::table() . " (name, val, autoload) values (%%s, X'%s', %%s)", $data), $key, $autoload); } } } self::getDB()->flush(); if ($autoload != self::DONT_AUTOLOAD) { self::updateCachedOption($key, $val); } return true; } private static function delete_ser_chunked($key) { if (!self::$tableExists) { return; } self::removeCachedOption($key); $chunkedValueKey = self::ser_chunked_key($key); $header = self::getDB()->querySingle("select val from " . self::table() . " where name=%s", $chunkedValueKey . 'header'); if (!$header) { return; } $header = unserialize($header); $count = $header['count']; for ($i = 0; $i < $count; $i++) { self::getDB()->queryWrite("delete from " . self::table() . " where name='%s'", $chunkedValueKey . $i); } self::getDB()->queryWrite("delete from " . self::table() . " where name='%s'", $chunkedValueKey . 'header'); } public static function f($key){ echo esc_attr(self::get($key)); } public static function p() { return self::get('isPaid'); } public static function cbp($key){ if(self::get('isPaid') && self::get($key)){ echo ' checked '; } } public static function cb($key){ if(self::get($key)){ echo ' checked '; } } public static function sel($key, $val, $isDefault = false){ if((! self::get($key)) && $isDefault){ echo ' selected '; } if(self::get($key) == $val){ echo ' selected '; } } private static function getDB(){ if(! self::$DB){ self::$DB = new wfDB(); } return self::$DB; } private static function table(){ if(! self::$table){ global $wpdb; self::$table = $wpdb->base_prefix . 'wfConfig'; } return self::$table; } public static function haveAlertEmails(){ $emails = self::getAlertEmails(); return sizeof($emails) > 0 ? true : false; } public static function getAlertEmails(){ $dat = explode(',', self::get('alertEmails')); $emails = array(); foreach($dat as $email){ if(preg_match('/\@/', $email)){ $emails[] = trim($email); } } return $emails; } public static function getAlertLevel(){ if(self::get('alertOn_warnings')){ return 2; } else if(self::get('alertOn_critical')){ return 1; } else { return 0; } } public static function liveTrafficEnabled(&$overriden = null){ $enabled = self::get('liveTrafficEnabled'); if (WORDFENCE_DISABLE_LIVE_TRAFFIC || function_exists('wpe_site')) { $enabled = false; if ($overriden !== null) { $overriden = true; } } return $enabled; } public static function enableAutoUpdate(){ wfConfig::set('autoUpdate', '1'); wp_clear_scheduled_hook('wordfence_daily_autoUpdate'); if (is_main_site()) { wp_schedule_event(time(), 'daily', 'wordfence_daily_autoUpdate'); } } public static function disableAutoUpdate(){ wfConfig::set('autoUpdate', '0'); wp_clear_scheduled_hook('wordfence_daily_autoUpdate'); } public static function createLock($name, $timeout = null) { //Polyfill since WP's built-in version wasn't added until 4.5 global $wpdb; $oldBlogID = $wpdb->set_blog_id(0); if (function_exists('WP_Upgrader::create_lock')) { $result = WP_Upgrader::create_lock($name, $timeout); $wpdb->set_blog_id($oldBlogID); return $result; } if (!$timeout) { $timeout = 3600; } $lock_option = $name . '.lock'; $lock_result = $wpdb->query($wpdb->prepare("INSERT IGNORE INTO `{$wpdb->options}` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, 'no') /* LOCK */", $lock_option, time())); if (!$lock_result) { $lock_result = get_option($lock_option); if (!$lock_result) { $wpdb->set_blog_id($oldBlogID); return false; } if ($lock_result > (time() - $timeout)) { $wpdb->set_blog_id($oldBlogID); return false; } self::releaseLock($name); $wpdb->set_blog_id($oldBlogID); return self::createLock($name, $timeout); } update_option($lock_option, time()); $wpdb->set_blog_id($oldBlogID); return true; } public static function releaseLock($name) { global $wpdb; $oldBlogID = $wpdb->set_blog_id(0); if (function_exists('WP_Upgrader::release_lock')) { $result = WP_Upgrader::release_lock($name); } else { $result = delete_option($name . '.lock'); } $wpdb->set_blog_id($oldBlogID); return $result; } public static function autoUpdate(){ try { if (!wfConfig::get('other_bypassLitespeedNoabort', false) && getenv('noabort') != '1' && stristr($_SERVER['SERVER_SOFTWARE'], 'litespeed') !== false) { $lastEmail = self::get('lastLiteSpdEmail', false); if( (! $lastEmail) || (time() - (int)$lastEmail > (86400 * 30))){ self::set('lastLiteSpdEmail', time()); wordfence::alert("Wordfence Upgrade not run. Please modify your .htaccess", "To preserve the integrity of your website we are not running Wordfence auto-update.\n" . "You are running the LiteSpeed web server which has been known to cause a problem with Wordfence auto-update.\n" . "Please go to your website now and make a minor change to your .htaccess to fix this.\n" . "You can find out how to make this change at:\n" . "https://docs.wordfence.com/en/LiteSpeed_aborts_Wordfence_scans_and_updates._How_do_I_prevent_that%3F\n" . "\nAlternatively you can disable auto-update on your website to stop receiving this message and upgrade Wordfence manually.\n", '127.0.0.1' ); } return; } require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'); require_once(ABSPATH . 'wp-admin/includes/misc.php'); /* We were creating show_message here so that WP did not write to STDOUT. This had the strange effect of throwing an error about redeclaring show_message function, but only when a crawler hit the site and triggered the cron job. Not a human. So we're now just require'ing misc.php which does generate output, but that's OK because it is a loopback cron request. if(! function_exists('show_message')){ function show_message($msg = 'null'){} } */ if(! defined('FS_METHOD')){ define('FS_METHOD', 'direct'); //May be defined already and might not be 'direct' so this could cause problems. But we were getting reports of a warning that this is already defined, so this check added. } require_once(ABSPATH . 'wp-includes/update.php'); require_once(ABSPATH . 'wp-admin/includes/file.php'); if (!self::createLock('wfAutoUpdate')) { return; } wp_update_plugins(); ob_start(); $upgrader = new Plugin_Upgrader(); $upret = $upgrader->upgrade(WORDFENCE_BASENAME); if($upret){ $cont = file_get_contents(WORDFENCE_FCPATH); if(wfConfig::get('alertOn_update') == '1' && preg_match('/Version: (\d+\.\d+\.\d+)/', $cont, $matches) ){ wordfence::alert("Wordfence Upgraded to version " . $matches[1], "Your Wordfence installation has been upgraded to version " . $matches[1], '127.0.0.1'); } } $output = @ob_get_contents(); @ob_end_clean(); } catch(Exception $e){} self::releaseLock('wfAutoUpdate'); } /** * .htaccess file contents to disable all script execution in a given directory. */ private static $_disable_scripts_htaccess = '# BEGIN Wordfence code execution protection <IfModule mod_php5.c> php_flag engine 0 </IfModule> <IfModule mod_php7.c> php_flag engine 0 </IfModule> AddHandler cgi-script .php .phtml .php3 .pl .py .jsp .asp .htm .shtml .sh .cgi Options -ExecCGI # END Wordfence code execution protection '; private static $_disable_scripts_regex = '/# BEGIN Wordfence code execution protection.+?# END Wordfence code execution protection/s'; private static function _uploadsHtaccessFilePath() { $upload_dir = wp_upload_dir(); return $upload_dir['basedir'] . '/.htaccess'; } /** * Add/Merge .htaccess file in the uploads directory to prevent code execution. * * @return bool * @throws wfConfigException */ public static function disableCodeExecutionForUploads() { $uploads_htaccess_file_path = self::_uploadsHtaccessFilePath(); $uploads_htaccess_has_content = false; if (file_exists($uploads_htaccess_file_path)) { $htaccess_contents = file_get_contents($uploads_htaccess_file_path); // htaccess exists and contains our htaccess code to disable script execution, nothing more to do if (strpos($htaccess_contents, self::$_disable_scripts_htaccess) !== false) { return true; } $uploads_htaccess_has_content = strlen(trim($htaccess_contents)) > 0; } if (@file_put_contents($uploads_htaccess_file_path, ($uploads_htaccess_has_content ? "\n\n" : "") . self::$_disable_scripts_htaccess, FILE_APPEND | LOCK_EX) === false) { throw new wfConfigException("Unable to save the .htaccess file needed to disable script execution in the uploads directory. Please check your permissions on that directory."); } self::set('disableCodeExecutionUploadsPHP7Migrated', true); return true; } public static function migrateCodeExecutionForUploadsPHP7() { if (self::get('disableCodeExecutionUploads')) { if (!self::get('disableCodeExecutionUploadsPHP7Migrated')) { $uploads_htaccess_file_path = self::_uploadsHtaccessFilePath(); if (file_exists($uploads_htaccess_file_path)) { $htaccess_contents = file_get_contents($uploads_htaccess_file_path); if (preg_match(self::$_disable_scripts_regex, $htaccess_contents)) { $htaccess_contents = preg_replace(self::$_disable_scripts_regex, self::$_disable_scripts_htaccess, $htaccess_contents); @file_put_contents($uploads_htaccess_file_path, $htaccess_contents); self::set('disableCodeExecutionUploadsPHP7Migrated', true); } } } } } /** * Remove script execution protections for our the .htaccess file in the uploads directory. * * @return bool * @throws wfConfigException */ public static function removeCodeExecutionProtectionForUploads() { $uploads_htaccess_file_path = self::_uploadsHtaccessFilePath(); if (file_exists($uploads_htaccess_file_path)) { $htaccess_contents = file_get_contents($uploads_htaccess_file_path); // Check that it is in the file if (preg_match(self::$_disable_scripts_regex, $htaccess_contents)) { $htaccess_contents = preg_replace(self::$_disable_scripts_regex, '', $htaccess_contents); $error_message = "Unable to remove code execution protections applied to the .htaccess file in the uploads directory. Please check your permissions on that file."; if (strlen(trim($htaccess_contents)) === 0) { // empty file, remove it if (!@unlink($uploads_htaccess_file_path)) { throw new wfConfigException($error_message); } } elseif (@file_put_contents($uploads_htaccess_file_path, $htaccess_contents, LOCK_EX) === false) { throw new wfConfigException($error_message); } } } return true; } } class wfConfigException extends Exception {} ?>