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:
Binary file not shown.
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user