Merged in feature/MAW-855-import-code-into-aws (pull request #2)

code import from pantheon

* code import from pantheon
This commit is contained in:
Tony Volpe
2023-12-04 23:08:14 +00:00
parent 8c9b1312bc
commit 8f4b5efda6
4766 changed files with 185592 additions and 239967 deletions

View File

@@ -237,6 +237,7 @@ echo wfView::create('scanner/site-cleaning-high-sense')->render();
echo wfView::create('scanner/site-cleaning-beta-sigs')->render();
echo wfView::create('scanner/no-issues')->render();
echo wfView::create('scanner/issue-wfUpgrade')->render();
echo wfView::create('scanner/issue-wfUpgradeError')->render();
echo wfView::create('scanner/issue-wfPluginUpgrade')->render();
echo wfView::create('scanner/issue-wfThemeUpgrade')->render();
echo wfView::create('scanner/issue-wfPluginRemoved')->render();

View File

@@ -113,14 +113,14 @@ if (!isset($sendingDiagnosticEmail)) {
))) ?></td>
<td>
<?php if ($infoOnly): ?>
<div class="wf-result-info"><?php echo nl2br(esc_html($result['message'])); ?></div>
<div class="wf-result-info"><?php echo (is_array($result['message']) && isset($result['message']['escaped']) ? $result['message']['escaped'] : nl2br(esc_html($result['message']))); ?></div>
<?php elseif ($result['test']): ?>
<div class="wf-result-success"><?php echo nl2br(esc_html($result['message'])); ?></div>
<div class="wf-result-success"><?php echo (is_array($result['message']) && isset($result['message']['escaped']) ? $result['message']['escaped'] : nl2br(esc_html($result['message']))); ?></div>
<?php else: ?>
<div class="wf-result-error"><?php echo nl2br(esc_html($result['message'])); ?></div>
<div class="wf-result-error"><?php echo (is_array($result['message']) && isset($result['message']['escaped']) ? $result['message']['escaped'] : nl2br(esc_html($result['message']))); ?></div>
<?php endif ?>
<?php if (isset($result['detail']) && !empty($result['detail'])): ?>
<p><strong><?php esc_html_e('Additional Detail', 'wordfence'); ?></strong><br><?php echo nl2br(esc_html($result['detail'])); ?></p>
<p><strong><?php esc_html_e('Additional Detail', 'wordfence'); ?></strong><br><?php echo (is_array($result['detail']) && isset($result['detail']['escaped']) ? $result['detail']['escaped'] : nl2br(esc_html($result['detail']))); ?></p>
<?php endif; ?>
</td>
</tr>
@@ -156,15 +156,15 @@ if (!isset($sendingDiagnosticEmail)) {
))) ?></div>
<div class="wf-right">
<?php if ($infoOnly): ?>
<div class="wf-result-info"><?php echo nl2br(esc_html($result['message'])); ?></div>
<div class="wf-result-info"><?php echo (is_array($result['message']) && isset($result['message']['escaped']) ? $result['message']['escaped'] : nl2br(esc_html($result['message']))); ?></div>
<?php elseif ($result['test']): ?>
<div class="wf-result-success"><?php echo nl2br(esc_html($result['message'])); ?></div>
<div class="wf-result-success"><?php echo (is_array($result['message']) && isset($result['message']['escaped']) ? $result['message']['escaped'] : nl2br(esc_html($result['message']))); ?></div>
<?php else: ?>
<div class="wf-result-error"><?php echo nl2br(esc_html($result['message'])); ?></div>
<div class="wf-result-error"><?php echo (is_array($result['message']) && isset($result['message']['escaped']) ? $result['message']['escaped'] : nl2br(esc_html($result['message']))); ?></div>
<?php endif ?>
<?php if (isset($result['detail']) && !empty($result['detail'])): ?>
<p><a href="#" onclick="jQuery('#wf-diagnostics-detail-<?php echo esc_attr($key); ?>').show(); jQuery(this).hide(); return false;" role="button"><?php esc_html_e('View Additional Detail', 'wordfence'); ?></a></p>
<pre class="wf-pre wf-split-word" id="wf-diagnostics-detail-<?php echo esc_attr($key); ?>" style="max-width: 600px; display: none;"><?php echo esc_html($result['detail']); ?></pre>
<pre class="wf-pre wf-split-word" id="wf-diagnostics-detail-<?php echo esc_attr($key); ?>" style="max-width: 600px; display: none;"><?php echo (is_array($result['detail']) && isset($result['detail']['escaped']) ? $result['detail']['escaped'] : nl2br(esc_html($result['detail']))); ?></pre>
<?php endif; ?>
</div>
</li>

View File

@@ -37,6 +37,17 @@ class wfCentralAPIRequest {
$this->body = $body;
$this->args = $args;
}
/**
* Handles an internal error when making a Central API request (e.g., a second sodium_compat library with an
* incompatible interface loading instead or in addition to ours).
*
* @param Exception|Throwable $e
*/
public static function handleInternalCentralAPIError($e) {
error_log('Wordfence encountered an internal Central API error: ' . $e->getMessage());
error_log('Wordfence stack trace: ' . $e->getTraceAsString());
}
public function execute() {
$args = array(
@@ -259,7 +270,7 @@ class wfCentralAuthenticatedAPIRequest extends wfCentralAPIRequest {
continue;
}
}
if (empty($token)) {
if (empty($token)) {
if (isset($e)) {
throw $e;
} else {
@@ -406,9 +417,16 @@ class wfCentral {
try {
$response = $request->execute();
return $response;
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
error_log($e);
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
return false;
}
@@ -437,9 +455,16 @@ class wfCentral {
try {
$response = $request->execute();
return $response;
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
error_log($e);
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
return false;
}
@@ -459,9 +484,16 @@ class wfCentral {
try {
$response = $request->execute();
return $response;
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
error_log($e);
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
return false;
}
@@ -484,9 +516,16 @@ class wfCentral {
try {
$response = $request->execute();
return $response;
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
error_log($e);
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
return false;
}
@@ -501,9 +540,13 @@ class wfCentral {
try {
$request->execute();
} catch (Exception $e) {
}
catch (Exception $e) {
// We can safely ignore an error here for now.
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
}
protected static $syncConfig = true;
@@ -540,9 +583,16 @@ class wfCentral {
try {
$response = $request->execute();
return $response;
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
error_log($e);
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
return false;
}
@@ -598,6 +648,14 @@ class wfCentral {
}
return false;
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
return false;
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
return false;
}
}
else {
$wfdb = new wfDB();

View File

@@ -699,7 +699,7 @@ class wfConfig {
global $wpdb;
$dbh = $wpdb->dbh;
$useMySQLi = (is_object($dbh) && $wpdb->use_mysqli && wfConfig::get('allowMySQLi', true) && WORDFENCE_ALLOW_DIRECT_MYSQLI);
$useMySQLi = wfUtils::useMySQLi();
if (!self::$tableExists) {
return;

View File

@@ -671,16 +671,21 @@ class wfDiagnostic
$message = __('wp_remote_post() test back to this server failed! Response was: ', 'wordfence') . $result->get_error_message();
}
else {
$message = __('wp_remote_post() test back to this server failed! Response was: ', 'wordfence') . $result['response']['code'] . " " . $result['response']['message'] . "\n";
$message .= __('This additional info may help you diagnose the issue. The response headers we received were:', 'wordfence') . "\n";
$message = __('wp_remote_post() test back to this server failed! Response was: ', 'wordfence') . '<br>' . $result['response']['code'] . " " . $result['response']['message'] . '<br><br>';
if ($this->_detectBlockedByCloudflare($result)) {
$message .= __('Cloudflare appears to be blocking your site from connecting to itself.', 'wordfence') . '<br>' . sprintf(' <a href="%s" target="_blank" rel="noopener noreferrer">', wfSupportController::esc_supportURL(wfSupportController::ITEM_DIAGNOSTICS_CLOUDFLARE_BLOCK)) . __('Get help with Cloudflare compatibility', 'wordfence') . '</a><br><br>';
}
$message .= __('This additional info may help you diagnose the issue. The response headers we received were:', 'wordfence') . '<br><br>';
if (isset($result['http_response']) && is_object($result['http_response']) && method_exists($result['http_response'], 'get_response_object') && is_object($result['http_response']->get_response_object()) && property_exists($result['http_response']->get_response_object(), 'raw')) {
$detail = str_replace("\r\n", "\n", $result['http_response']->get_response_object()->raw);
}
}
$message = wp_kses($message, array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()), 'em' => array(), 'code' => array(), 'br' => array()));
return array(
'test' => false,
'message' => $message,
'message' => array('escaped' => $message),
'detail' => $detail,
);
}
@@ -698,11 +703,14 @@ class wfDiagnostic
$handle = $interceptor->getHandle();
$errorNumber = curl_errno($handle);
if ($errorNumber === 6 /* COULDNT_RESOLVE_HOST */) {
$detail = sprintf(/* translators: error message from failed request */ __('This likely indicates that the server either does not support IPv6 or does not have an IPv6 address assigned or associated with the domain. Original error message: %s', 'wordfence'), is_array($result['message']) ? $result['message']['escaped'] : $result['message']);
$detail = wp_kses($detail, array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()), 'em' => array(), 'code' => array(), 'br' => array()));
return array(
'test' => false,
'infoOnly' => true,
'message' => __('IPv6 DNS resolution failed', 'wordfence'),
'detail' => sprintf(/* translators: error message from failed request */ __('This likely indicates that the server either does not support IPv6 or does not have an IPv6 address assigned or associated with the domain. Original error message: %s', 'wordfence'), $result['message'])
'detail' => array('escaped' => $detail),
);
}
}
@@ -721,6 +729,34 @@ class wfDiagnostic
);
}
/**
* Looks for markers in $result that indicate it was challenged/blocked by Cloudflare.
*
* @param $result
* @return bool
*/
private function _detectBlockedByCloudflare($result) {
$headers = $result['headers'];
if (isset($headers['cf-mitigated']) && strtolower($headers['cf-mitigated']) == 'challenge' /* managed challenge */) { //$headers is an instance of Requests_Utility_CaseInsensitiveDictionary
return true;
}
$body = $result['body'];
$search = array(
'/cdn-cgi/styles/challenges.css', //managed challenge
'/cdn-cgi/challenge-platform', //managed challenge
'/cdn-cgi/styles/cf.errors.css', //block
'cf-error-details', //block
'Cloudflare Ray ID', //block
);
foreach ($search as $s) {
if (stripos($body, $s) !== false) {
return true;
}
}
return false;
}
public function serverIP() {
$serverIPs = wfUtils::serverIPs();
return array(

View File

@@ -78,13 +78,14 @@ class wfIssues {
'wfPluginRemoved' => wfIssues::SEVERITY_CRITICAL,
'wfPluginUpgrade' => wfIssues::SEVERITY_MEDIUM,
'wfThemeUpgrade' => wfIssues::SEVERITY_MEDIUM,
'wfUpgradeError' => wfIssues::SEVERITY_MEDIUM,
'wfUpgrade' => wfIssues::SEVERITY_HIGH,
'wpscan_directoryList' => wfIssues::SEVERITY_HIGH,
'wpscan_fullPathDiscl' => wfIssues::SEVERITY_HIGH,
);
public static function validIssueTypes() {
return array('checkHowGetIPs', 'checkSpamIP', 'commentBadURL', 'configReadable', 'coreUnknown', 'database', 'diskSpace', 'wafStatus', 'easyPassword', 'file', 'geoipSupport', 'knownfile', 'optionBadURL', 'postBadTitle', 'postBadURL', 'publiclyAccessible', 'spamvertizeCheck', 'suspiciousAdminUsers', 'timelimit', 'wfPluginAbandoned', 'wfPluginRemoved', 'wfPluginUpgrade', 'wfPluginVulnerable', 'wfThemeUpgrade', 'wfUpgrade', 'wpscan_directoryList', 'wpscan_fullPathDiscl', 'skippedPaths');
return array('checkHowGetIPs', 'checkSpamIP', 'commentBadURL', 'configReadable', 'coreUnknown', 'database', 'diskSpace', 'wafStatus', 'easyPassword', 'file', 'geoipSupport', 'knownfile', 'optionBadURL', 'postBadTitle', 'postBadURL', 'publiclyAccessible', 'spamvertizeCheck', 'suspiciousAdminUsers', 'timelimit', 'wfPluginAbandoned', 'wfPluginRemoved', 'wfPluginUpgrade', 'wfPluginVulnerable', 'wfThemeUpgrade', 'wfUpgradeError', 'wfUpgrade', 'wpscan_directoryList', 'wpscan_fullPathDiscl', 'skippedPaths');
}
public static function statusPrep(){
@@ -530,13 +531,13 @@ class wfIssues {
}
public function deleteAllUpdateIssues() {
$issues = $this->getDB()->querySelect("SELECT id, status, ignoreP, ignoreC FROM {$this->issuesTable} WHERE status = 'new' AND (type = 'wfUpgrade' OR type = 'wfPluginUpgrade' OR type = 'wfThemeUpgrade')");
$issues = $this->getDB()->querySelect("SELECT id, status, ignoreP, ignoreC FROM {$this->issuesTable} WHERE status = 'new' AND (type = 'wfUpgrade' OR type = 'wfUpgradeError' OR type = 'wfPluginUpgrade' OR type = 'wfThemeUpgrade')");
$this->clearEmailedStatus($issues);
$this->getDB()->queryWrite("DELETE FROM {$this->issuesTable} WHERE status = 'new' AND (type = 'wfUpgrade' OR type = 'wfPluginUpgrade' OR type = 'wfThemeUpgrade')");
$this->getDB()->queryWrite("DELETE FROM {$this->issuesTable} WHERE status = 'new' AND (type = 'wfUpgrade' OR type = 'wfUpgradeError' OR type = 'wfPluginUpgrade' OR type = 'wfThemeUpgrade')");
if (wfCentral::isConnected()) {
wfCentral::deleteIssueTypes(array('wfUpgrade', 'wfPluginUpgrade', 'wfThemeUpgrade'));
wfCentral::deleteIssueTypes(array('wfUpgrade', 'wfUpgradeError', 'wfPluginUpgrade', 'wfThemeUpgrade'));
}
}

View File

@@ -1625,7 +1625,7 @@ class wfScanEngine {
$counter = 0;
$query = "select ID from " . $wpdb->users;
$dbh = $wpdb->dbh;
$useMySQLi = (is_object($dbh) && $wpdb->use_mysqli && wfConfig::get('allowMySQLi', true) && WORDFENCE_ALLOW_DIRECT_MYSQLI);
$useMySQLi = wfUtils::useMySQLi();
if ($useMySQLi) { //If direct-access MySQLi is available, we use it to minimize the memory footprint instead of letting it fetch everything into an array first
$result = $dbh->query($query);
if (!is_object($result)) {
@@ -1889,36 +1889,50 @@ class wfScanEngine {
foreach ($this->pluginRepoStatus as $slug => $status) {
if ($status === false) {
$result = plugins_api('plugin_information', array(
'slug' => $slug,
'fields' => array(
'short_description' => false,
'description' => false,
'sections' => false,
'tested' => true,
'requires' => true,
'rating' => false,
'ratings' => false,
'downloaded' => false,
'downloadlink' => false,
'last_updated' => true,
'added' => false,
'tags' => false,
'compatibility' => true,
'homepage' => true,
'versions' => false,
'donate_link' => false,
'reviews' => false,
'banners' => false,
'icons' => false,
'active_installs' => false,
'group' => false,
'contributors' => false,
),
));
unset($result->versions);
unset($result->screenshots);
$this->pluginRepoStatus[$slug] = $result;
try {
$result = plugins_api('plugin_information', array(
'slug' => $slug,
'fields' => array(
'short_description' => false,
'description' => false,
'sections' => false,
'tested' => true,
'requires' => true,
'rating' => false,
'ratings' => false,
'downloaded' => false,
'downloadlink' => false,
'last_updated' => true,
'added' => false,
'tags' => false,
'compatibility' => true,
'homepage' => true,
'versions' => false,
'donate_link' => false,
'reviews' => false,
'banners' => false,
'icons' => false,
'active_installs' => false,
'group' => false,
'contributors' => false,
),
));
unset($result->versions);
unset($result->screenshots);
$this->pluginRepoStatus[$slug] = $result;
}
catch (Exception $e) {
error_log(sprintf('Caught exception while attempting to refresh update status for slug %s: %s', $slug, $e->getMessage()));
$this->pluginRepoStatus[$slug] = false;
wfConfig::set(wfUpdateCheck::LAST_UPDATE_CHECK_ERROR_KEY, sprintf('%s [%s]', $e->getMessage(), $slug), false);
wfConfig::set(wfUpdateCheck::LAST_UPDATE_CHECK_ERROR_SLUG_KEY, $slug, false);
}
catch (Throwable $t) {
error_log(sprintf('Caught error while attempting to refresh update status for slug %s: %s', $slug, $t->getMessage()));
$this->pluginRepoStatus[$slug] = false;
wfConfig::set(wfUpdateCheck::LAST_UPDATE_CHECK_ERROR_KEY, sprintf('%s [%s]', $t->getMessage(), $slug), false);
wfConfig::set(wfUpdateCheck::LAST_UPDATE_CHECK_ERROR_SLUG_KEY, $slug, false);
}
$this->forkIfNeeded();
}
@@ -1929,7 +1943,39 @@ class wfScanEngine {
$haveIssues = wfIssues::STATUS_SECURE;
if (!$this->isFullScan()) {
$this->deleteNewIssues(array('wfUpgrade', 'wfPluginUpgrade', 'wfThemeUpgrade'));
$this->deleteNewIssues(array('wfUpgradeError', 'wfUpgrade', 'wfPluginUpgrade', 'wfThemeUpgrade'));
}
if ($lastError = wfConfig::get(wfUpdateCheck::LAST_UPDATE_CHECK_ERROR_KEY)) {
$lastSlug = wfConfig::get(wfUpdateCheck::LAST_UPDATE_CHECK_ERROR_SLUG_KEY);
$longMsg = sprintf(/* translators: error message. */ __("The update check performed during the scan encountered an error: %s", 'wordfence'), esc_html($lastError));
if ($lastSlug === false) {
$longMsg .= ' ' . __('Wordfence cannot detect if the installed plugins and themes are up to date. This might be caused by a PHP compatibility issue in one or more plugins/themes.', 'wordfence');
}
else {
$longMsg .= ' ' . __('Wordfence cannot detect if this plugin/theme is up to date. This might be caused by a PHP compatibility issue in the plugin.', 'wordfence');
}
$longMsg .= ' ' . sprintf(
/* translators: Support URL. */
__('<a href="%s" target="_blank" rel="noopener noreferrer">Get more information.<span class="screen-reader-text"> (' . esc_html__('opens in new tab', 'wordfence') . ')</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_SCAN_RESULT_UPDATE_CHECK_FAILED));
$ignoreKey = ($lastSlug === false ? 'wfUpgradeErrorGeneral' : sprintf('wfUpgradeError-%s', $lastSlug));
$added = $this->addIssue(
'wfUpgradeError',
wfIssues::SEVERITY_MEDIUM,
$ignoreKey,
$ignoreKey,
($lastSlug === false ? __("Update Check Encountered Error", 'wordfence') : sprintf(/* translators: plugin/theme slug. */ __("Update Check Encountered Error on '%s'", 'wordfence'), esc_html($lastSlug))),
$longMsg,
array()
);
if ($added == wfIssues::ISSUE_ADDED || $added == wfIssues::ISSUE_UPDATED) {
$haveIssues = wfIssues::STATUS_PROBLEM;
}
else if ($haveIssues != wfIssues::STATUS_PROBLEM && ($added == wfIssues::ISSUE_IGNOREP || $added == wfIssues::ISSUE_IGNOREC)) {
$haveIssues = wfIssues::STATUS_IGNORED;
}
}
// WordPress core updates needed
@@ -2029,8 +2075,12 @@ class wfScanEngine {
$statusArray['version'] = null;
wordfence::status(3, 'error', "Unable to determine version for plugin $slug");
}
$lastUpdateTimestamp = strtotime($statusArray['last_updated']);
if ($lastUpdateTimestamp > 0 && (time() - $lastUpdateTimestamp) > 63072000 /* ~2 years */) {
if (array_key_exists('last_updated', $statusArray) &&
is_string($statusArray['last_updated']) &&
($lastUpdateTimestamp = strtotime($statusArray['last_updated'])) &&
(time() - $lastUpdateTimestamp) > 63072000 /* ~2 years */) {
$statusArray['dateUpdated'] = wfUtils::formatLocalTime(get_option('date_format'), $lastUpdateTimestamp);
$severity = wfIssues::SEVERITY_MEDIUM;
$statusArray['abandoned'] = true;
@@ -2433,7 +2483,6 @@ class wfScanEngine {
wfConfig::set('wfKillRequested', 0, wfConfig::DONT_AUTOLOAD);
wordfence::status(4, 'info', __("Entering start scan routine", 'wordfence'));
if (wfScanner::shared()->isRunning()) {
wfUtils::getScanFileError();
return __("A scan is already running. Use the stop scan button if you would like to terminate the current scan.", 'wordfence');
}
wfConfig::set('currentCronKey', ''); //Ensure the cron key is cleared

View File

@@ -73,8 +73,8 @@ class wfScanMonitor {
if ($lastAttempt === null || $now - $lastAttempt < self::SCAN_START_TIMEOUT)
return;
$lastSuccess = wfConfig::get(self::CONFIG_LAST_SUCCESS);
self::setRemainingResumeAttempts(--$remainingAttempts);
if ($lastSuccess === null || $lastAttempt > $lastSuccess) {
self::setRemainingResumeAttempts(--$remainingAttempts);
wordfence::status(2, 'info', sprintf(__('Attempting to resume scan stage (%d attempt(s) remaining)...', 'wordfence'), $remainingAttempts));
self::resumeScan();
}

View File

@@ -149,6 +149,7 @@ class wfSupportController {
const ITEM_SCAN_RESULT_PUBLIC_CONFIG = 'scan-result-public-config';
const ITEM_SCAN_RESULT_PLUGIN_ABANDONED = 'scan-result-plugin-abandoned';
const ITEM_SCAN_RESULT_PLUGIN_REMOVED = 'scan-result-plugin-removed';
const ITEM_SCAN_RESULT_UPDATE_CHECK_FAILED = 'scan-result-update-check-failed';
const ITEM_SCAN_RESULT_OPTION_MALWARE_URL = 'scan-result-option-malware-url';
const ITEM_SCAN_RESULT_GEOIP_UPDATE = 'scan-result-geoip-update';
const ITEM_SCAN_RESULT_WAF_DISABLED = 'scan-result-waf-disabled';
@@ -178,6 +179,7 @@ class wfSupportController {
const ITEM_DIAGNOSTICS_OPTION_BETA_TDF = 'diagnostics-option-beta-tdf';
const ITEM_DIAGNOSTICS_OPTION_WORDFENCE_TRANSLATIONS = 'diagnostics-option-wordfence-translations';
const ITEM_DIAGNOSTICS_IPV6 = 'diagnostics-ipv6';
const ITEM_DIAGNOSTICS_CLOUDFLARE_BLOCK = 'compatibility-cloudflare';
const ITEM_MODULE_LOGIN_SECURITY = 'module-login-security';
const ITEM_MODULE_LOGIN_SECURITY_2FA = 'module-login-security-2fa';
@@ -341,6 +343,7 @@ class wfSupportController {
case self::ITEM_SCAN_RESULT_PUBLIC_CONFIG:
case self::ITEM_SCAN_RESULT_PLUGIN_ABANDONED:
case self::ITEM_SCAN_RESULT_PLUGIN_REMOVED:
case self::ITEM_SCAN_RESULT_UPDATE_CHECK_FAILED:
case self::ITEM_SCAN_RESULT_OPTION_MALWARE_URL:
case self::ITEM_SCAN_RESULT_GEOIP_UPDATE:
case self::ITEM_SCAN_RESULT_WAF_DISABLED:
@@ -370,6 +373,7 @@ class wfSupportController {
case self::ITEM_DIAGNOSTICS_OPTION_BETA_TDF:
case self::ITEM_DIAGNOSTICS_OPTION_WORDFENCE_TRANSLATIONS:
case self::ITEM_DIAGNOSTICS_IPV6:
case self::ITEM_DIAGNOSTICS_CLOUDFLARE_BLOCK:
case self::ITEM_MODULE_LOGIN_SECURITY:
case self::ITEM_MODULE_LOGIN_SECURITY_2FA:

View File

@@ -6,6 +6,9 @@ class wfUpdateCheck {
const VULN_SEVERITY_MEDIUM = 40;
const VULN_SEVERITY_LOW = 1;
const VULN_SEVERITY_NONE = 0;
const LAST_UPDATE_CHECK_ERROR_KEY = 'lastUpdateCheckError';
const LAST_UPDATE_CHECK_ERROR_SLUG_KEY = 'lastUpdateCheckErrorSlug';
private $needs_core_update = false;
private $core_update_version = 0;
@@ -169,6 +172,11 @@ class wfUpdateCheck {
* @return $this
*/
public function checkAllUpdates($useCachedValued = true) {
if (!$useCachedValued) {
wfConfig::remove(self::LAST_UPDATE_CHECK_ERROR_KEY);
wfConfig::remove(self::LAST_UPDATE_CHECK_ERROR_SLUG_KEY);
}
return $this->checkCoreUpdates($useCachedValued)
->checkPluginUpdates($useCachedValued)
->checkThemeUpdates($useCachedValued);
@@ -189,7 +197,7 @@ class wfUpdateCheck {
require_once(ABSPATH . 'wp-admin/includes/update.php');
}
include(ABSPATH . WPINC . '/version.php'); //defines $wp_version
include(ABSPATH . WPINC . '/version.php'); /** @var $wp_version */
$update_core = get_preferred_from_update_core();
if ($useCachedValued && isset($update_core->last_checked) && isset($update_core->version_checked) && 12 * HOUR_IN_SECONDS > (time() - $update_core->last_checked) && $update_core->version_checked == $wp_version) { //Duplicate of _maybe_update_core, which is a private call
@@ -276,7 +284,19 @@ class wfUpdateCheck {
return $update_plugins;
if (!function_exists('wp_update_plugins'))
require_once(ABSPATH . WPINC . '/update.php');
wp_update_plugins();
try {
wp_update_plugins();
}
catch (Exception $e) {
wfConfig::set(self::LAST_UPDATE_CHECK_ERROR_KEY, $e->getMessage(), false);
wfConfig::remove(self::LAST_UPDATE_CHECK_ERROR_SLUG_KEY);
error_log('Caught exception while attempting to refresh plugin update status: ' . $e->getMessage());
}
catch (Throwable $t) {
wfConfig::set(self::LAST_UPDATE_CHECK_ERROR_KEY, $t->getMessage(), false);
wfConfig::remove(self::LAST_UPDATE_CHECK_ERROR_SLUG_KEY);
error_log('Caught error while attempting to refresh plugin update status: ' . $t->getMessage());
}
return get_site_transient('update_plugins');
}
@@ -293,7 +313,7 @@ class wfUpdateCheck {
self::requirePluginsApi();
$update_plugins = $this->fetchPluginUpdates();
$update_plugins = $this->fetchPluginUpdates($useCachedValued);
//Get the full plugin list
if (!function_exists('get_plugins')) {
@@ -357,7 +377,18 @@ class wfUpdateCheck {
//Do nothing, use cached value
}
else {
wp_update_themes();
try {
wp_update_themes();
}
catch (Exception $e) {
wfConfig::set(self::LAST_UPDATE_CHECK_ERROR_KEY, $e->getMessage(), false);
error_log('Caught exception while attempting to refresh theme update status: ' . $e->getMessage());
}
catch (Throwable $t) {
wfConfig::set(self::LAST_UPDATE_CHECK_ERROR_KEY, $t->getMessage(), false);
error_log('Caught error while attempting to refresh theme update status: ' . $t->getMessage());
}
$update_themes = get_site_transient('update_themes');
}

View File

@@ -1341,39 +1341,12 @@ class wfUtils {
$string = str_replace(",", "\n", $string); // fix old format
return implode("\n", array_unique(array_filter(array_map('trim', explode("\n", $string)))));
}
public static function getScanFileError() {
$fileTime = wfConfig::get('scanFileProcessing');
if (!$fileTime) {
return;
}
list($file, $time) = unserialize($fileTime);
if ($time+10 < time()) {
$add = true;
$excludePatterns = wordfenceScanner::getExcludeFilePattern(wordfenceScanner::EXCLUSION_PATTERNS_USER);
if ($excludePatterns) {
foreach ($excludePatterns as $pattern) {
if (preg_match($pattern, $file)) {
$add = false;
break;
}
}
}
if ($add) {
$files = wfConfig::get('scan_exclude') . "\n" . $file;
wfConfig::set('scan_exclude', self::cleanupOneEntryPerLine($files));
}
self::endProcessingFile();
}
}
public static function beginProcessingFile($file) {
wfConfig::set('scanFileProcessing', serialize(array($file, time())));
//Do nothing
}
public static function endProcessingFile() {
wfConfig::set('scanFileProcessing', null);
if (wfScanner::shared()->useLowResourceScanning()) {
usleep(10000); //10 ms
}
@@ -3148,7 +3121,20 @@ class wfUtils {
}
return $encoded;
}
/**
* Returns whether or not MySQLi should be used directly when needed. Returns true if there's a valid DB handle,
* our database test succeeded, our constant is not set to prevent it, and then either $wpdb indicates it's using
* mysqli (older WordPress versions) or we're on PHP 7+ (only mysqli is ever used).
*
* @return bool
*/
public static function useMySQLi() {
global $wpdb;
$dbh = $wpdb->dbh;
$useMySQLi = (is_object($dbh) && (PHP_MAJOR_VERSION >= 7 || $wpdb->use_mysqli) && wfConfig::get('allowMySQLi', true) && WORDFENCE_ALLOW_DIRECT_MYSQLI);
return $useMySQLi;
}
}
// GeoIP lib uses these as well

View File

@@ -6,5 +6,5 @@ $wfPHPMinimumVersion = '5.5.0'; //The currently supported minimum
$wfOpenSSLDeprecatingVersion = '1.0.1';
$wfOpenSSLMinimumVersion = '1.0.1';
$wfWordPressDeprecatingVersion = '4.4.0';
$wfWordPressDeprecatingVersion = '4.7.0';
$wfWordPressMinimumVersion = '3.9.0';

View File

@@ -6098,7 +6098,7 @@ HTML;
'loadTwoFactor', 'sendTestEmail',
'email_summary_email_address_debug', 'unblockNetwork',
'sendDiagnostic', 'saveDisclosureState', 'saveWAFConfig', 'updateWAFRules', 'loadLiveTraffic', 'whitelistWAFParamKey',
'disableDirectoryListing', 'fixFPD', 'deleteAdminUser', 'revokeAdminUser',
'disableDirectoryListing', 'fixFPD', 'deleteAdminUser', 'revokeAdminUser', 'acknowledgeAdminUser',
'hideFileHtaccess', 'saveDebuggingConfig',
'whitelistBulkDelete', 'whitelistBulkEnable', 'whitelistBulkDisable',
'dismissNotification', 'utilityScanForBlacklisted', 'dashboardShowMore',
@@ -7608,6 +7608,35 @@ SQL
'user_login' => $userLogin,
);
}
public static function ajax_acknowledgeAdminUser_callback() {
$issueID = absint(!empty($_POST['issueID']) ? $_POST['issueID'] : 0);
$wfIssues = new wfIssues();
$issue = $wfIssues->getIssueByID($issueID);
if (!$issue) {
return array('errorMsg' => __("We could not find that issue in the database.", 'wordfence'));
}
$data = $issue['data'];
if (empty($data['userID'])) {
return array('errorMsg' => __("We could not find that user in the database.", 'wordfence'));
}
$user = new WP_User($data['userID']);
if (!$user->exists()) {
return array('errorMsg' => __("We could not find that user in the database.", 'wordfence'));
}
$userLogin = $user->user_login;
$adminUsers = new wfAdminUserMonitor();
$adminUsers->addAdmin($data['userID']);
$wfIssues->deleteIssue($issueID);
wfScanEngine::refreshScanNotification($wfIssues);
return array(
'ok' => 1,
'user_login' => $userLogin,
);
}
/**
*
@@ -9464,9 +9493,23 @@ if (file_exists(__DIR__.%1$s)) {
}
$request = new wfCentralAPIRequest('/site/access-token', 'GET', $authGrant);
$response = $request->execute();
try {
$response = $request->execute();
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
if ($response->isError()) {
if (!isset($response)) {
return array(
'err' => 1,
'errorMsg' => __('Internal error when connecting to Wordfence Central (see server error log)', 'wordfence'),
);
}
else if ($response->isError()) {
return $response->returnErrorArray();
}
@@ -9539,9 +9582,23 @@ if (file_exists(__DIR__.%1$s)) {
),
),
));
$response = $request->execute();
if ($response->isError()) {
try {
$response = $request->execute();
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
if (!isset($response)) {
return array(
'err' => 1,
'errorMsg' => __('Internal error when connecting to Wordfence Central (see server error log)', 'wordfence'),
);
}
else if ($response->isError()) {
return $response->returnErrorArray();
}
@@ -9577,12 +9634,27 @@ if (file_exists(__DIR__.%1$s)) {
'success' => 1,
);
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
return array(
'error' => 1,
'errorMsg' => $e->getMessage(),
);
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
return array(
'error' => 1,
'errorMsg' => $e->getMessage(),
);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
return array(
'error' => 1,
'errorMsg' => $t->getMessage(),
);
}
}
public static function ajax_wfcentral_step4_callback() {
@@ -9647,12 +9719,27 @@ if (file_exists(__DIR__.%1$s)) {
rawurlencode(wfConfig::get('wordfenceCentralSiteID')), rawurlencode($body['access-token'])),
);
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
return array(
'error' => 1,
'errorMsg' => $e->getMessage(),
);
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
return array(
'error' => 1,
'errorMsg' => $e->getMessage(),
);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
return array(
'error' => 1,
'errorMsg' => $t->getMessage(),
);
}
}
public static function ajax_wfcentral_step6_callback() {
$wfCentralUserSiteAccessToken = wfConfig::get('wordfenceCentralUserSiteAccessToken');
@@ -9683,9 +9770,16 @@ if (file_exists(__DIR__.%1$s)) {
sprintf('/site/%s', wfConfig::get('wordfenceCentralSiteID')),
'DELETE');
$response = $request->execute();
} catch (wfCentralAPIException $e) {
}
catch (wfCentralAPIException $e) {
}
catch (Exception $e) {
wfCentralAPIRequest::handleInternalCentralAPIError($e);
}
catch (Throwable $t) {
wfCentralAPIRequest::handleInternalCentralAPIError($t);
}
wfRESTConfigController::disconnectConfig();

View File

@@ -181,7 +181,7 @@ class wordfenceURLHoover {
if ($this->useDB) {
global $wpdb;
$dbh = $wpdb->dbh;
$useMySQLi = (is_object($dbh) && $wpdb->use_mysqli && wfConfig::get('allowMySQLi', true) && WORDFENCE_ALLOW_DIRECT_MYSQLI);
$useMySQLi = wfUtils::useMySQLi();
if ($useMySQLi) { //If direct-access MySQLi is available, we use it to minimize the memory footprint instead of letting it fetch everything into an array first
wordfence::status(4, 'info', __("Using MySQLi directly.", 'wordfence'));
$result = $dbh->query("SELECT DISTINCT hostKey FROM {$this->table} ORDER BY hostKey ASC LIMIT 100000"); /* We limit to 100,000 prefixes since more than that cannot be reliably checked within the default max_execution_time */