rebase from live enviornment
This commit is contained in:
@@ -234,7 +234,12 @@ if (!isset($sendingDiagnosticEmail)) {
|
||||
<?php endforeach ?>
|
||||
<tr>
|
||||
<td><?php esc_html_e('Trusted Proxies', 'wordfence'); ?></td>
|
||||
<td><?php echo esc_html(implode(', ', explode("\n", wfConfig::get('howGetIPs_trusted_proxies', '')))); ?></td>
|
||||
<td><?php $proxies = wfConfig::get('howGetIPs_trusted_proxies', ''); echo esc_html(implode(', ', explode("\n", empty($proxies) ? __('(not set)', 'wordfence') : $proxies))); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php esc_html_e('Trusted Proxy Preset', 'wordfence'); ?></td>
|
||||
<td><?php $preset = wfConfig::get('howGetIPs_trusted_proxy_preset'); $presets = wfConfig::getJSON('ipResolutionList', array()); echo esc_html((is_array($presets) && isset($presets[$preset])) ? $presets[$preset]['name'] : __('(not set)', 'wordfence')); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -524,8 +529,8 @@ if (!isset($sendingDiagnosticEmail)) {
|
||||
global $wpdb;
|
||||
$wfdb = new wfDB();
|
||||
//This must be done this way because MySQL with InnoDB tables does a full regeneration of all metadata if we don't. That takes a long time with a large table count.
|
||||
$tables = $wfdb->querySelect('SELECT SQL_CALC_FOUND_ROWS TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() ORDER BY TABLE_NAME ASC LIMIT 250');
|
||||
$total = $wfdb->querySingle('SELECT FOUND_ROWS()');
|
||||
$tables = $wfdb->querySelect('SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() ORDER BY TABLE_NAME ASC LIMIT 250');
|
||||
$total = $wfdb->querySingle('SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()');
|
||||
foreach ($tables as &$t) {
|
||||
$t = "'" . esc_sql($t['TABLE_NAME']) . "'";
|
||||
}
|
||||
@@ -548,7 +553,7 @@ if (!isset($sendingDiagnosticEmail)) {
|
||||
</div>
|
||||
<div class="wf-block-content wf-clearfix wf-padding-no-left wf-padding-no-right">
|
||||
<ul class="wf-block-list wf-padding-add-left-large wf-padding-add-right-large">
|
||||
<li style="border-bottom: 1px solid #e2e2e2;">
|
||||
<li>
|
||||
<div style="width: 75%; min-width: 300px;"><?php esc_html_e('Wordfence Table Check', 'wordfence'); ?></div>
|
||||
<div class="wf-right">
|
||||
<?php if ($total > 250): ?>
|
||||
@@ -590,6 +595,12 @@ if (!isset($sendingDiagnosticEmail)) {
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</li>
|
||||
<li style="border-bottom: 1px solid #e2e2e2;">
|
||||
<div style="width: 75%; min-width: 300px;"><?php esc_html_e('Number of Database Tables', 'wordfence'); ?></div>
|
||||
<div class="wf-right">
|
||||
<div class="wf-result-info"><?php echo esc_html( $total ); ?></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="wf-add-top-large" style="max-width: 100%; overflow: auto; padding: 1px;">
|
||||
<table class="wf-striped-table"<?php echo !empty($inEmail) ? ' border=1' : '' ?>>
|
||||
@@ -906,4 +917,4 @@ if (!isset($sendingDiagnosticEmail)) {
|
||||
'secondaryButtons' => array(array('id' => 'wf-restore-defaults-prompt-confirm', 'labelHTML' => wp_kses(/* translators: word order may be reversed as long as HTML remains around "Defaults" */ __('Restore<span class="wf-hidden-xs"> Defaults</span>', 'wordfence'), array('span'=>array('class'=>array()))), 'link' => '#')),
|
||||
))->render();
|
||||
?>
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -567,6 +567,8 @@ class wfCentral {
|
||||
$scan = array();
|
||||
}
|
||||
}
|
||||
|
||||
wfScanner::shared()->flushSummaryItems();
|
||||
|
||||
$siteID = wfConfig::get('wordfenceCentralSiteID');
|
||||
$running = wfScanner::shared()->isRunning();
|
||||
|
||||
@@ -176,6 +176,7 @@ class wfConfig {
|
||||
'wafAlertInterval' => array('value' => 600, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
|
||||
'wafAlertThreshold' => array('value' => 100, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
|
||||
'howGetIPs_trusted_proxies' => array('value' => '', 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
|
||||
'howGetIPs_trusted_proxy_preset' => array('value' => '', 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
|
||||
'scanType' => array('value' => wfScanner::SCAN_TYPE_STANDARD, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
|
||||
'manualScanType' => array('value' => wfScanner::MANUAL_SCHEDULING_ONCE_DAILY, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
|
||||
'schedStartHour' => array('value' => -1, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
|
||||
@@ -227,6 +228,9 @@ class wfConfig {
|
||||
'lastPermissionsTemplateCheck' => array('value' => 0, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
|
||||
'previousWflogsFileList' => array('value' => '[]', 'autoload' => self::DONT_AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
|
||||
'diagnosticsWflogsRemovalHistory' => array('value' => '[]', 'autoload' => self::DONT_AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
|
||||
'satisfactionPromptDismissed' => array('value' => 0, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
|
||||
'satisfactionPromptInstallDate' => array('value' => 0, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
|
||||
'satisfactionPromptOverride' => array('value' => true, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_BOOL)),
|
||||
),
|
||||
);
|
||||
public static $serializedOptions = array('lastAdminLogin', 'scanSched', 'emailedIssuesList', 'wf_summaryItems', 'adminUserList', 'twoFactorUsers', 'alertFreqTrack', 'wfStatusStartMsgs', 'vulnerabilities_plugin', 'vulnerabilities_theme', 'dashboardData', 'malwarePrefixes', 'coreHashes', 'noc1ScanSchedule', 'allScansScheduled', 'disclosureStates', 'scanStageStatuses', 'adminNoticeQueue', 'suspiciousAdminUsernames', 'wordpressPluginVersions', 'wordpressThemeVersions');
|
||||
@@ -517,6 +521,9 @@ class wfConfig {
|
||||
public static function setJSON($key, $val, $autoload = self::AUTOLOAD) {
|
||||
self::set($key, @json_encode($val), $autoload);
|
||||
}
|
||||
public static function setBool($key, $val, $autoload = self::AUTOLOAD) {
|
||||
self::set($key, wfUtils::truthyToBoolean($val) ? 1 : 0, $autoload);
|
||||
}
|
||||
public static function setOrRemove($key, $value, $autoload = self::AUTOLOAD) {
|
||||
if ($value === null) {
|
||||
self::remove($key);
|
||||
@@ -564,6 +571,10 @@ class wfConfig {
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
public static function getBool($key, $default = false, $allowCached = true) {
|
||||
return wfUtils::truthyToBoolean(self::get($key, $default, $allowCached));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a test against the database to verify set_ser is working via MySQLi.
|
||||
*
|
||||
@@ -1309,6 +1320,21 @@ Options -ExecCGI
|
||||
$checked = true;
|
||||
break;
|
||||
}
|
||||
case 'howGetIPs_trusted_proxy_preset':
|
||||
{
|
||||
$presets = wfConfig::getJSON('ipResolutionList', array());
|
||||
if (!is_array($presets)) {
|
||||
$presets = array();
|
||||
}
|
||||
|
||||
if (!(empty($value) /* "None" */ || isset($presets[$value]))) {
|
||||
$errors[] = array('option' => $key, 'error' => __('The selected trusted proxy preset is not valid: ', 'wordfence') . esc_html($value));
|
||||
}
|
||||
|
||||
$checked = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 'apiKey':
|
||||
{
|
||||
$value = trim($value);
|
||||
@@ -1830,7 +1856,7 @@ Options -ExecCGI
|
||||
$api = new wfAPI($apiKey, wfUtils::getWPVersion());
|
||||
try {
|
||||
$keyType = wfLicense::KEY_TYPE_FREE;
|
||||
$keyData = $api->call('ping_api_key', array(), array('supportHash' => wfConfig::get('supportHash', ''), 'whitelistHash' => wfConfig::get('whitelistHash', ''), 'tldlistHash' => wfConfig::get('tldlistHash', '')));
|
||||
$keyData = $api->call('ping_api_key', array(), array('supportHash' => wfConfig::get('supportHash', ''), 'whitelistHash' => wfConfig::get('whitelistHash', ''), 'tldlistHash' => wfConfig::get('tldlistHash', ''), 'ipResolutionListHash' => wfConfig::get('ipResolutionListHash', '')));
|
||||
if (isset($keyData['_isPaidKey'])) {
|
||||
$keyType = wfConfig::get('keyType');
|
||||
}
|
||||
@@ -1850,6 +1876,10 @@ Options -ExecCGI
|
||||
wfConfig::set('tldlist', $keyData['_tldlist']);
|
||||
wfConfig::set('tldlistHash', $keyData['_tldlistHash']);
|
||||
}
|
||||
if (isset($keyData['_ipResolutionList']) && isset($keyData['_ipResolutionListHash'])) {
|
||||
wfConfig::setJSON('ipResolutionList', $keyData['_ipResolutionList']);
|
||||
wfConfig::set('ipResolutionListHash', $keyData['_ipResolutionListHash']);
|
||||
}
|
||||
if (isset($keyData['scanSchedule']) && is_array($keyData['scanSchedule'])) {
|
||||
wfConfig::set_ser('noc1ScanSchedule', $keyData['scanSchedule']);
|
||||
if (wfScanner::shared()->schedulingMode() == wfScanner::SCAN_SCHEDULING_MODE_AUTOMATIC) {
|
||||
@@ -1910,6 +1940,7 @@ Options -ExecCGI
|
||||
'email_summary_interval',
|
||||
'email_summary_excluded_directories',
|
||||
'howGetIPs_trusted_proxies',
|
||||
'howGetIPs_trusted_proxy_preset',
|
||||
'displayTopLevelOptions',
|
||||
);
|
||||
break;
|
||||
@@ -2075,6 +2106,7 @@ Options -ExecCGI
|
||||
'email_summary_interval',
|
||||
'email_summary_excluded_directories',
|
||||
'howGetIPs_trusted_proxies',
|
||||
'howGetIPs_trusted_proxy_preset',
|
||||
'firewallEnabled',
|
||||
'autoBlockScanners',
|
||||
'loginSecurityEnabled',
|
||||
|
||||
@@ -92,7 +92,11 @@ class wfDiagnostic
|
||||
'wafAutoPrependFilePath' => __('wordfence-waf.php path', 'wordfence'),
|
||||
'wafFilePermissions' => __('WAF File Permissions', 'wordfence'),
|
||||
'wafRecentlyRemoved' => __('Recently removed wflogs files', 'wordfence'),
|
||||
'wafLoaded' => __('WAF Loaded Successfully', 'wordfence')
|
||||
'wafLoaded' => __('WAF Loaded Successfully', 'wordfence'),
|
||||
'wafAutoPrependHtaccess' => __('WAF .htaccess contents', 'wordfence'),
|
||||
'wafAutoPrependUserIni' => __('WAF .user.ini contents', 'wordfence'),
|
||||
'wafAutoPrependHtaccessOther' => __('.htaccess other auto prepend', 'wordfence'),
|
||||
'wafAutoPrependUserIniOther' => __('.user.ini other auto prepend', 'wordfence'),
|
||||
),
|
||||
),
|
||||
'MySQL' => array(
|
||||
@@ -362,6 +366,78 @@ class wfDiagnostic
|
||||
public function wafAutoPrepend() {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => (defined('WFWAF_AUTO_PREPEND') && WFWAF_AUTO_PREPEND ? __('Yes', 'wordfence') : __('No', 'wordfence')));
|
||||
}
|
||||
public function wafAutoPrependHtaccess() {
|
||||
$htaccessPath = wfWAFAutoPrependHelper::getHtaccessPath();
|
||||
if (!file_exists($htaccessPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.htaccess not present)', 'wordfence'));
|
||||
}
|
||||
else if (!is_readable($htaccessPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.htaccess not readable)', 'wordfence'));
|
||||
}
|
||||
|
||||
$htaccessContents = file_get_contents($htaccessPath);
|
||||
$section = wfWAFAutoPrependHelper::getHtaccessSectionContent($htaccessContents);
|
||||
if ($section === false) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(not set)', 'wordfence'));
|
||||
}
|
||||
|
||||
$snippet = wfUtils::pregExtract("/auto_prepend_file\s+['\"]?[^'\"]*['\"]?/", $section);
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => $snippet, 'detail' => array('escaped' => nl2br(esc_html($section)), 'textonly' => $section));
|
||||
}
|
||||
public function wafAutoPrependHtaccessOther() {
|
||||
$htaccessPath = wfWAFAutoPrependHelper::getHtaccessPath();
|
||||
if (!file_exists($htaccessPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.htaccess not present)', 'wordfence'));
|
||||
}
|
||||
else if (!is_readable($htaccessPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.htaccess not readable)', 'wordfence'));
|
||||
}
|
||||
|
||||
$htaccessContents = file_get_contents($htaccessPath);
|
||||
$section = wfWAFAutoPrependHelper::getHtaccessSectionContent($htaccessContents);
|
||||
if ($section !== false) {
|
||||
$htaccessContents = str_replace($section, '', $htaccessContents);
|
||||
}
|
||||
|
||||
$snippet = wfUtils::pregExtract("/auto_prepend_file\s+['\"]?[^'\"]*['\"]?/", $htaccessContents, true);
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => ($snippet === false ? __('(not present)', 'wordfence') : trim($snippet)));
|
||||
}
|
||||
public function wafAutoPrependUserIni() {
|
||||
$userIniPath = wfWAFAutoPrependHelper::getUserIniPath();
|
||||
if (!file_exists($userIniPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.user.ini not present)', 'wordfence'));
|
||||
}
|
||||
else if (!is_readable($userIniPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.user.ini not readable)', 'wordfence'));
|
||||
}
|
||||
|
||||
$userIniContents = file_get_contents($userIniPath);
|
||||
$section = wfWAFAutoPrependHelper::getUserIniSectionContent($userIniContents);
|
||||
if ($section === false) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(not set)', 'wordfence'));
|
||||
}
|
||||
|
||||
$snippet = wfUtils::pregExtract("/auto_prepend_file\s*=\s*['\"]?[^'\"]*['\"]?/", $section);
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => $snippet, 'detail' => $section);
|
||||
}
|
||||
public function wafAutoPrependUserIniOther() {
|
||||
$userIniPath = wfWAFAutoPrependHelper::getUserIniPath();
|
||||
if (!file_exists($userIniPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.user.ini not present)', 'wordfence'));
|
||||
}
|
||||
else if (!is_readable($userIniPath)) {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => __('(.user.ini not readable)', 'wordfence'));
|
||||
}
|
||||
|
||||
$userIniContents = file_get_contents($userIniPath);
|
||||
$section = wfWAFAutoPrependHelper::getUserIniSectionContent($userIniContents);
|
||||
if ($section !== false) {
|
||||
$userIniContents = str_replace($section, '', $userIniContents);
|
||||
}
|
||||
|
||||
$snippet = wfUtils::pregExtract("/auto_prepend_file\s*=\s*['\"]?[^'\"]*['\"]?/", $userIniContents, true);
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => ($snippet === false ? __('(not present)', 'wordfence') : trim($snippet)));
|
||||
}
|
||||
public function wafStorageEngine() {
|
||||
return array('test' => true, 'infoOnly' => true, 'message' => (defined('WFWAF_STORAGE_ENGINE') ? WFWAF_STORAGE_ENGINE : __('(default)', 'wordfence')));
|
||||
}
|
||||
@@ -669,13 +745,17 @@ class wfDiagnostic
|
||||
$detail = '';
|
||||
if (is_wp_error($result)) {
|
||||
$message = __('wp_remote_post() test back to this server failed! Response was: ', 'wordfence') . $result->get_error_message();
|
||||
$messageTextOnly = __('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') . '<br>' . $result['response']['code'] . " " . $result['response']['message'] . '<br><br>';
|
||||
$message = __('wp_remote_post() test back to this server failed! Response was: ', 'wordfence') . '<br>' . $result['response']['code'] . ' ' . $result['response']['message'] . '<br><br>';
|
||||
$messageTextOnly = __('wp_remote_post() test back to this server failed! Response was: ', 'wordfence') . "\n" . $result['response']['code'] . ' ' . $result['response']['message'] . "\n\n";
|
||||
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>';
|
||||
$messageTextOnly .= __('Cloudflare appears to be blocking your site from connecting to itself.', 'wordfence') . "\n" . __('Get help with Cloudflare compatibility', 'wordfence') . ': ' . wfSupportController::esc_supportURL(wfSupportController::ITEM_DIAGNOSTICS_CLOUDFLARE_BLOCK) . "\n\n";
|
||||
}
|
||||
$message .= __('This additional info may help you diagnose the issue. The response headers we received were:', 'wordfence') . '<br><br>';
|
||||
$messageTextOnly .= __('This additional info may help you diagnose the issue. The response headers we received were:', 'wordfence') . "\n\n";
|
||||
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);
|
||||
}
|
||||
@@ -685,7 +765,7 @@ class wfDiagnostic
|
||||
|
||||
return array(
|
||||
'test' => false,
|
||||
'message' => array('escaped' => $message),
|
||||
'message' => array('escaped' => $message, 'textonly' => $messageTextOnly),
|
||||
'detail' => $detail,
|
||||
);
|
||||
}
|
||||
@@ -705,12 +785,13 @@ class wfDiagnostic
|
||||
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()));
|
||||
$detailTextOnly = 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']['textonly'] : strip_tags($result['message']));
|
||||
|
||||
return array(
|
||||
'test' => false,
|
||||
'infoOnly' => true,
|
||||
'message' => __('IPv6 DNS resolution failed', 'wordfence'),
|
||||
'detail' => array('escaped' => $detail),
|
||||
'detail' => array('escaped' => $detail, 'textonly' => $detailTextOnly),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,6 +772,7 @@ class wfScanEngine {
|
||||
$this->scanController->startStage(wfScanner::STAGE_PUBLIC_FILES);
|
||||
|
||||
$backupFileTests = array(
|
||||
wfCommonBackupFileTest::createFromRootPath('.env'),
|
||||
wfCommonBackupFileTest::createFromRootPath('.user.ini'),
|
||||
// wfCommonBackupFileTest::createFromRootPath('.htaccess'),
|
||||
wfCommonBackupFileTest::createFromRootPath('wp-config.php.bak'),
|
||||
@@ -2081,7 +2082,17 @@ class wfScanEngine {
|
||||
($lastUpdateTimestamp = strtotime($statusArray['last_updated'])) &&
|
||||
(time() - $lastUpdateTimestamp) > 63072000 /* ~2 years */) {
|
||||
|
||||
$statusArray['dateUpdated'] = wfUtils::formatLocalTime(get_option('date_format'), $lastUpdateTimestamp);
|
||||
try {
|
||||
$statusArray['dateUpdated'] = wfUtils::formatLocalTime(get_option('date_format'), $lastUpdateTimestamp);
|
||||
}
|
||||
catch (Exception $e) { //DateMalformedStringException in PHP >= 8.3, Exception previously
|
||||
wordfence::status(3, 'error', sprintf(
|
||||
/* translators: 1. Plugin slug. 2. Malformed date string. */
|
||||
__('Encountered bad date string for plugin "%s" in abandoned plugin check: %s', 'wordfence'),
|
||||
$slug,
|
||||
$statusArray['last_updated']));
|
||||
continue;
|
||||
}
|
||||
$severity = wfIssues::SEVERITY_MEDIUM;
|
||||
$statusArray['abandoned'] = true;
|
||||
$statusArray['vulnerable'] = false;
|
||||
@@ -2104,7 +2115,7 @@ class wfScanEngine {
|
||||
/* translators: 1. Plugin name. 2. Software version. 3. Software version. */
|
||||
__('The Plugin "%1$s" appears to be abandoned (updated %2$s, tested to WP %3$s).', 'wordfence'),
|
||||
(empty($statusArray['name']) ? $slug : $statusArray['name']),
|
||||
wfUtils::formatLocalTime(get_option('date_format'), $lastUpdateTimestamp),
|
||||
$statusArray['dateUpdated'],
|
||||
$statusArray['tested']
|
||||
);
|
||||
$longMsg = sprintf(
|
||||
@@ -2118,7 +2129,7 @@ class wfScanEngine {
|
||||
/* translators: 1. Plugin name. 2. Software version. */
|
||||
__('The Plugin "%1$s" appears to be abandoned (updated %2$s).', 'wordfence'),
|
||||
(empty($statusArray['name']) ? $slug : $statusArray['name']),
|
||||
wfUtils::formatLocalTime(get_option('date_format'), $lastUpdateTimestamp)
|
||||
$statusArray['dateUpdated']
|
||||
);
|
||||
$longMsg = sprintf(
|
||||
/* translators: Time duration. */
|
||||
@@ -2130,7 +2141,7 @@ class wfScanEngine {
|
||||
if ($statusArray['vulnerable']) {
|
||||
$longMsg .= ' ' . __('It has unpatched security issues and may have compatibility problems with the current version of WordPress.', 'wordfence');
|
||||
} else {
|
||||
$longMsg .= ' ' . __('Your site is still using this plugin, but it is not currently available on wordpress.org. Plugins can be removed from wordpress.org for various reasons. This can include benign issues like a plugin author discontinuing development or moving the plugin distribution to their own site, but some might also be due to security issues. In any case, future updates may or may not be available, so it is worth investigating the cause and deciding whether to temporarily or permanently replace or remove the plugin.', 'wordfence');
|
||||
$longMsg .= ' ' . __('It may have compatibility problems with the current version of WordPress or unknown security issues.', 'wordfence');
|
||||
}
|
||||
$longMsg .= ' ' . sprintf(
|
||||
/* translators: Support URL. */
|
||||
|
||||
@@ -120,8 +120,8 @@ class wfScanMonitor {
|
||||
}
|
||||
|
||||
public static function registerActions() {
|
||||
add_filter('cron_schedules', array(get_class(), 'registerCronInterval'));
|
||||
add_action(self::CRON_HOOK, array(get_class(), 'monitorScan'));
|
||||
add_filter('cron_schedules', array(self::class, 'registerCronInterval'));
|
||||
add_action(self::CRON_HOOK, array(self::class, 'monitorScan'));
|
||||
}
|
||||
|
||||
public static function handleDeactivation() {
|
||||
|
||||
@@ -383,4 +383,56 @@ class wfSupportController {
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function shouldShowSatisfactionPrompt() {
|
||||
//Don't show if overridden
|
||||
if (!wfConfig::getBool('satisfactionPromptOverride')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Only show on our pages
|
||||
if (!isset($_REQUEST['page'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!preg_match('/^Wordfence/', $_REQUEST['page'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Only show until dismissed
|
||||
if (wfConfig::get('satisfactionPromptDismissed') > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Only show to users installing after the release date of the version this was introduced
|
||||
if (WORDFENCE_FEEDBACK_EPOCH > wfConfig::get('satisfactionPromptInstallDate')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Don't show for at least 7 days post-install
|
||||
if ((time() - wfConfig::get('satisfactionPromptInstallDate')) < 86400 * 7) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function satisfactionPromptNotice() {
|
||||
?>
|
||||
<div id="wordfenceSatisfactionPrompt" class="fade notice notice-info">
|
||||
<p id="wordfenceSatisfactionPrompt-initial"><strong><?php printf(__('Are you enjoying using Wordfence Security?', 'wordfence')); ?></strong> <a href="#" onclick="WFAD.wordfenceSatisfactionChoice('yes'); return false;" class="wf-btn wf-btn-default wf-btn-sm" role="button"><?php printf(__('Yes', 'wordfence')); ?></a> <a href="#" onclick="WFAD.wordfenceSatisfactionChoice('no'); return false;" class="wf-btn wf-btn-default wf-btn-sm" role="button"><?php printf(__('No', 'wordfence')); ?></a></p>
|
||||
<div id="wordfenceSatisfactionPrompt-yes" style="display: none;">
|
||||
<p><?php printf(__('Please consider leaving us a 5-star review on wordpress.org. Your review helps other members of the WordPress community find plugins that fit their needs.', 'wordfence')); ?></p>
|
||||
<p><a href="https://wordpress.org/support/plugin/wordfence/reviews/" class="wf-btn wf-btn-default wf-btn-sm" role="button" target="_blank" rel="noopener noreferrer"><?php printf(__('Leave Review', 'wordfence')); ?></a></p>
|
||||
</div>
|
||||
<div id="wordfenceSatisfactionPrompt-no" style="display: none;">
|
||||
<p><?php printf(__('What can we do to improve Wordfence Security?', 'wordfence')); ?></p>
|
||||
<p><textarea rows="6" cols="50" id="wordfenceSatisfactionPrompt-feedback"></textarea></p>
|
||||
<p><a href="#" onclick="WFAD.wordfenceSatisfactionChoice('feedback'); return false;" class="wf-btn wf-btn-default wf-btn-sm" role="button" target="_blank" rel="noopener noreferrer"><?php printf(__('Submit Feedback', 'wordfence')); ?></a> <a href="#" onclick="WFAD.wordfenceSatisfactionChoice('dismiss'); return false;" class="wf-btn wf-btn-default wf-btn-sm" role="button"><?php printf(__('Dismiss', 'wordfence')); ?></a></p>
|
||||
</div>
|
||||
<p id="wordfenceSatisfactionPrompt-complete" style="display: none;"><?php printf(__('Thank you for providing your feedback on Wordfence Security', 'wordfence')); ?></p>
|
||||
<button type="button" class="notice-dismiss" onclick="WFAD.wordfenceSatisfactionChoice('dismiss'); return false;"><span class="screen-reader-text">Dismiss this notice.</span></button>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -886,7 +886,7 @@ class wfUtils {
|
||||
}
|
||||
$skipToNext = false;
|
||||
if ($trustedProxies === null) {
|
||||
$trustedProxies = explode("\n", wfConfig::get('howGetIPs_trusted_proxies', ''));
|
||||
$trustedProxies = self::unifiedTrustedProxies();
|
||||
}
|
||||
foreach(array(',', ' ', "\t") as $char){
|
||||
if(strpos($item, $char) !== false){
|
||||
@@ -944,6 +944,29 @@ class wfUtils {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all trusted proxies, combining both the user-entered ones and those from the selected preset.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function unifiedTrustedProxies() {
|
||||
$trustedProxies = explode("\n", wfConfig::get('howGetIPs_trusted_proxies', ''));
|
||||
|
||||
$preset = wfConfig::get('howGetIPs_trusted_proxy_preset');
|
||||
$presets = wfConfig::getJSON('ipResolutionList', array());
|
||||
if (is_array($presets) && isset($presets[$preset])) {
|
||||
$testIPs = array_merge($presets[$preset]['ipv4'], $presets[$preset]['ipv6']);
|
||||
foreach ($testIPs as $val) {
|
||||
if (strlen($val) > 0) {
|
||||
if (wfUtils::isValidIP($val) || wfUtils::isValidCIDRRange($val)) {
|
||||
$trustedProxies[] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $trustedProxies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ip
|
||||
@@ -3122,6 +3145,52 @@ class wfUtils {
|
||||
return $encoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to extract a matched pattern from a string. If $pattern has no matching groups, the entire
|
||||
* matched portion is returned. If it has at least one matching group, the first one is returned (others are
|
||||
* ignored). If there is no match, false is returned.
|
||||
*
|
||||
* @param string $pattern
|
||||
* @param string $subject
|
||||
* @param bool $expandToLine Whether or not to expand the captured value to include the entire line's contents
|
||||
* @return false|string
|
||||
*/
|
||||
public static function pregExtract($pattern, $subject, $expandToLine = false) {
|
||||
if (preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
if (count($matches) > 1) {
|
||||
$start = $matches[1][1];
|
||||
$text = $matches[1][0];
|
||||
$end = $start + strlen($text);
|
||||
}
|
||||
else {
|
||||
$start = $matches[0][1];
|
||||
$text = $matches[0][0];
|
||||
$end = $start + strlen($text);
|
||||
}
|
||||
|
||||
if ($expandToLine) {
|
||||
if (preg_match_all('/[\r\n]/', substr($subject, 0, $start), $matches, PREG_OFFSET_CAPTURE)) {
|
||||
$start = $matches[0][count($matches[0]) - 1][1] + 1;
|
||||
}
|
||||
else {
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
if (preg_match('/[\r\n]/', $subject, $matches, PREG_OFFSET_CAPTURE, $end)) {
|
||||
$end = $matches[0][1];
|
||||
}
|
||||
else {
|
||||
$end = strlen($subject) - 0;
|
||||
}
|
||||
|
||||
$text = substr($subject, $start, $end - $start);
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -179,7 +179,7 @@ class wordfence {
|
||||
wfRateLimit::trimData();
|
||||
|
||||
wfCentral::checkForUnsentSecurityEvents();
|
||||
|
||||
|
||||
wfVersionCheckController::shared()->checkVersionsAndWarn();
|
||||
}
|
||||
private static function keyAlert($msg){
|
||||
@@ -192,11 +192,15 @@ class wordfence {
|
||||
$api = new wfAPI($apiKey, wfUtils::getWPVersion());
|
||||
try {
|
||||
$keyType = wfLicense::KEY_TYPE_FREE;
|
||||
$keyData = $api->call('ping_api_key', array(), array('supportHash' => wfConfig::get('supportHash', ''), 'whitelistHash' => wfConfig::get('whitelistHash', ''), 'tldlistHash' => wfConfig::get('tldlistHash', '')));
|
||||
$keyData = $api->call('ping_api_key', array(), array('supportHash' => wfConfig::get('supportHash', ''), 'whitelistHash' => wfConfig::get('whitelistHash', ''), 'tldlistHash' => wfConfig::get('tldlistHash', ''), 'ipResolutionListHash' => wfConfig::get('ipResolutionListHash', '')));
|
||||
if (isset($keyData['_isPaidKey'])) {
|
||||
$keyType = wfConfig::get('keyType');
|
||||
}
|
||||
|
||||
if (isset($keyData['_feedbackBasis'])) {
|
||||
wfConfig::setBool('satisfactionPromptOverride', $keyData['_feedbackBasis'] > WORDFENCE_FEEDBACK_EPOCH);
|
||||
}
|
||||
|
||||
if(isset($keyData['_isPaidKey']) && $keyData['_isPaidKey']){
|
||||
$keyExpDays = $keyData['_keyExpDays'];
|
||||
$keyIsExpired = $keyData['_expired'];
|
||||
@@ -251,6 +255,10 @@ class wordfence {
|
||||
wfConfig::set('tldlist', $keyData['_tldlist']);
|
||||
wfConfig::set('tldlistHash', $keyData['_tldlistHash']);
|
||||
}
|
||||
if (isset($keyData['_ipResolutionList']) && isset($keyData['_ipResolutionListHash'])) {
|
||||
wfConfig::setJSON('ipResolutionList', $keyData['_ipResolutionList']);
|
||||
wfConfig::set('ipResolutionListHash', $keyData['_ipResolutionListHash']);
|
||||
}
|
||||
if (isset($keyData['scanSchedule']) && is_array($keyData['scanSchedule'])) {
|
||||
wfConfig::set_ser('noc1ScanSchedule', $keyData['scanSchedule']);
|
||||
if (wfScanner::shared()->schedulingMode() == wfScanner::SCAN_SCHEDULING_MODE_AUTOMATIC) {
|
||||
@@ -1080,6 +1088,11 @@ SQL
|
||||
if (wfConfig::get('isPaid') && (wfCredentialsController::hasOld2FARecords() || version_compare(phpversion(), '5.3', '<'))) {
|
||||
wfConfig::set(wfCredentialsController::ALLOW_LEGACY_2FA_OPTION, true);
|
||||
}
|
||||
|
||||
//Record the installation timestamp if activating the plugin for the first time
|
||||
if (get_option('wordfenceActivated') != 1 && wfConfig::get('satisfactionPromptInstallDate') == 0 && empty(wfConfig::get('apiKey'))) {
|
||||
wfConfig::set('satisfactionPromptInstallDate', time());
|
||||
}
|
||||
|
||||
//Check the How does Wordfence get IPs setting
|
||||
wfUtils::requestDetectProxyCallback();
|
||||
@@ -2168,6 +2181,7 @@ SQL
|
||||
}
|
||||
hash_update($scontext, $data);
|
||||
}
|
||||
|
||||
fclose($sp);
|
||||
if ($scontext !== false) {
|
||||
$shash = hash_final($scontext, false);
|
||||
@@ -2184,6 +2198,7 @@ SQL
|
||||
}
|
||||
hash_update($dcontext, $data);
|
||||
}
|
||||
|
||||
fclose($dp);
|
||||
if ($scontext !== false) {
|
||||
$dhash = hash_final($dcontext, false);
|
||||
@@ -2292,7 +2307,7 @@ SQL
|
||||
'whitelistedIPs' => (string) wfConfig::get('whitelisted'),
|
||||
'whitelistedServiceIPs' => @json_encode(wfUtils::whitelistedServiceIPs()),
|
||||
'howGetIPs' => (string) wfConfig::get('howGetIPs'),
|
||||
'howGetIPs_trusted_proxies' => wfConfig::get('howGetIPs_trusted_proxies', ''),
|
||||
'howGetIPs_trusted_proxies_unified' => implode("\n", wfUtils::unifiedTrustedProxies()),
|
||||
'detectProxyRecommendation' => (string) wfConfig::get('detectProxyRecommendation'),
|
||||
'other_WFNet' => !!wfConfig::get('other_WFNet', true),
|
||||
'pluginABSPATH' => ABSPATH,
|
||||
@@ -3232,10 +3247,9 @@ SQL
|
||||
$threshold = wfConfig::get('lastBruteForceDataSendTime', 0);;
|
||||
|
||||
$wfdb = new wfDB();
|
||||
global $wpdb;
|
||||
$table_wfHits = wfDB::networkTable('wfHits');
|
||||
$rawBlocks = $wfdb->querySelect("SELECT SQL_CALC_FOUND_ROWS IP, ctime, actionData FROM {$table_wfHits} WHERE ctime > %f AND action = 'blocked:wfsnrepeat' ORDER BY ctime ASC LIMIT 100", sprintf('%.6f', $threshold));
|
||||
$totalRows = $wpdb->get_var('SELECT FOUND_ROWS()');
|
||||
$rawBlocks = $wfdb->querySelect("SELECT IP, ctime, actionData FROM {$table_wfHits} WHERE ctime > %f AND action = 'blocked:wfsnrepeat' ORDER BY ctime ASC LIMIT 100", sprintf('%.6f', $threshold));
|
||||
$totalRows = $wfdb->querySingle("SELECT COUNT(*) FROM {$table_wfHits} WHERE ctime > %f AND action = 'blocked:wfsnrepeat'", sprintf('%.6f', $threshold));
|
||||
$ipCounts = array();
|
||||
$maxctime = 0;
|
||||
foreach ($rawBlocks as $record) {
|
||||
@@ -4076,6 +4090,7 @@ SQL
|
||||
if (isset($_POST['page'])) {
|
||||
$page = $_POST['page'];
|
||||
}
|
||||
|
||||
|
||||
$keys = array(wfOnboardingController::TOUR_DASHBOARD, wfOnboardingController::TOUR_FIREWALL, wfOnboardingController::TOUR_SCAN, wfOnboardingController::TOUR_BLOCKING, wfOnboardingController::TOUR_LIVE_TRAFFIC, wfOnboardingController::TOUR_LOGIN_SECURITY);
|
||||
if (in_array($page, $keys)) {
|
||||
@@ -4126,6 +4141,16 @@ SQL
|
||||
}
|
||||
return array('ok' => 1);
|
||||
}
|
||||
public static function ajax_wordfenceSatisfactionChoice_callback() {
|
||||
wfConfig::set('satisfactionPromptDismissed', time());
|
||||
$choice = $_POST['choice'];
|
||||
if ($choice == 'feedback' && isset($_POST['feedback']) && !empty($_POST['feedback'])) {
|
||||
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
||||
$result = $api->call('plugin_feedback', array(), array('feedback' => $_POST['feedback']));
|
||||
}
|
||||
//else -- no additional action for yes/no
|
||||
return array('ok' => 1);
|
||||
}
|
||||
public static function ajax_dismissAdminNotice_callback() {
|
||||
if (isset($_POST['id'])) {
|
||||
wfAdminNoticeQueue::removeAdminNotice($_POST['id']);
|
||||
@@ -4658,9 +4683,22 @@ SQL
|
||||
}
|
||||
$trustedProxies = $validIPs;
|
||||
|
||||
$preset = $_POST['howGetIPs_trusted_proxy_preset'];
|
||||
$presets = wfConfig::getJSON('ipResolutionList', array());
|
||||
if (is_array($presets) && isset($presets[$preset])) {
|
||||
$testIPs = array_merge($presets[$preset]['ipv4'], $presets[$preset]['ipv6']);
|
||||
foreach ($testIPs as $val) {
|
||||
if (strlen($val) > 0) {
|
||||
if (wfUtils::isValidIP($val) || wfUtils::isValidCIDRRange($val)) {
|
||||
$trustedProxies[] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ipAll = wfUtils::getIPPreview($howGet, $trustedProxies);
|
||||
$ip = wfUtils::getIPForField($howGet, $trustedProxies);
|
||||
return array('ok' => 1, 'ip' => $ip, 'ipAll' => $ipAll);
|
||||
return array('ok' => 1, 'ip' => $ip, 'ipAll' => $ipAll, 'resolvedProxies' => $trustedProxies);
|
||||
}
|
||||
|
||||
public static function ajax_hideFileHtaccess_callback(){
|
||||
@@ -6081,6 +6119,8 @@ HTML;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (wfConfig::get('touppBypassNextCheck')) {
|
||||
wfConfig::set('touppBypassNextCheck', 0);
|
||||
wfConfig::set('touppPromptNeeded', 0);
|
||||
@@ -6092,7 +6132,7 @@ HTML;
|
||||
'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues',
|
||||
'avatarLookup', 'reverseLookup', 'unlockOutIP', 'unblockRange', 'whois', 'recentTraffic', 'unblockIP',
|
||||
'blockIP', 'permBlockIP', 'loadStaticPanel', 'updateIPPreview', 'downloadHtaccess', 'downloadLogFile', 'checkHtaccess',
|
||||
'updateConfig', 'autoUpdateChoice', 'misconfiguredHowGetIPsChoice', 'switchLiveTrafficSecurityOnlyChoice', 'dismissAdminNotice',
|
||||
'updateConfig', 'autoUpdateChoice', 'misconfiguredHowGetIPsChoice', 'switchLiveTrafficSecurityOnlyChoice', 'dismissAdminNotice', 'wordfenceSatisfactionChoice',
|
||||
'killScan', 'saveCountryBlocking', 'tourClosed',
|
||||
'downgradeLicense', 'addTwoFactor', 'twoFacActivate', 'twoFacDel',
|
||||
'loadTwoFactor', 'sendTestEmail',
|
||||
@@ -6153,7 +6193,7 @@ HTML;
|
||||
wp_enqueue_style('wordfence-global-style', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/wf-global.css'), '', WORDFENCE_VERSION);
|
||||
self::setupAdminVars();
|
||||
}
|
||||
|
||||
|
||||
if (is_admin()) { //Back end only
|
||||
if (wfOnboardingController::shouldShowAnyAttempt()) {
|
||||
wp_enqueue_script('wordfenceOnboardingjs', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/wfonboarding.js'), array('jquery', 'wordfenceAdminExtjs'), WORDFENCE_VERSION);
|
||||
@@ -6807,6 +6847,15 @@ HTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$warningAdded && wfSupportController::shouldShowSatisfactionPrompt()) {
|
||||
if (is_multisite()) {
|
||||
add_action('network_admin_notices', 'wfSupportController::satisfactionPromptNotice');
|
||||
}
|
||||
else {
|
||||
add_action('admin_notices', 'wfSupportController::satisfactionPromptNotice');
|
||||
}
|
||||
}
|
||||
|
||||
if (self::isWordfenceAdminPage()) {
|
||||
$dashboardExtra = '';
|
||||
@@ -8699,13 +8748,25 @@ SQL;
|
||||
$entry = bin2hex($packed);
|
||||
}
|
||||
$wafAlertWhitelist = array_filter($wafAlertWhitelist);
|
||||
$attackData = $wpdb->get_results($wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$table_wfHits}
|
||||
WHERE action = 'blocked:waf' " .
|
||||
(count($wafAlertWhitelist) ? "AND HEX(IP) NOT IN (" . implode(", ", array_fill(0, count($wafAlertWhitelist), '%s')) . ")" : "")
|
||||
. "AND attackLogTime > %f
|
||||
ORDER BY attackLogTime DESC
|
||||
LIMIT 10", array_merge($wafAlertWhitelist, array(sprintf('%.6f', $cutoffTime)))));
|
||||
$attackCount = $wpdb->get_var('SELECT FOUND_ROWS()');
|
||||
$attackDataQuery = $wpdb->prepare(
|
||||
"SELECT * FROM {$table_wfHits}
|
||||
WHERE action = 'blocked:waf' " .
|
||||
(count($wafAlertWhitelist) ? "AND HEX(IP) NOT IN (" . implode(", ", array_fill(0, count($wafAlertWhitelist), '%s')) . ")" : "")
|
||||
. " AND attackLogTime > %f
|
||||
ORDER BY attackLogTime DESC
|
||||
LIMIT 10",
|
||||
array_merge($wafAlertWhitelist, array(sprintf('%.6f', $cutoffTime))));
|
||||
$attackDataCountQuery = str_replace(
|
||||
array(
|
||||
"SELECT * FROM",
|
||||
"ORDER BY attackLogTime DESC",
|
||||
"LIMIT 10",
|
||||
),
|
||||
array( "SELECT COUNT(*) FROM", "", "" ), $attackDataQuery
|
||||
);
|
||||
$attackData = $wpdb->get_results($attackDataQuery);
|
||||
$attackCount = $wpdb->get_var($attackDataCountQuery);
|
||||
unset( $attackDataQuery, $attackDataCountQuery );
|
||||
$threshold = (int) wfConfig::get('wafAlertThreshold');
|
||||
if ($threshold < 1) {
|
||||
$threshold = 100;
|
||||
@@ -8803,21 +8864,38 @@ SQL;
|
||||
$lastSendTime = wfConfig::get('lastAttackDataSendTime');
|
||||
$lastSendId = wfConfig::get('lastAttackDataSendId');
|
||||
if($lastSendId===false){
|
||||
$query=$wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$table_wfHits}
|
||||
$query=$wpdb->prepare("SELECT * FROM {$table_wfHits}
|
||||
WHERE action in ('blocked:waf', 'learned:waf', 'logged:waf', 'blocked:waf-always')
|
||||
AND attackLogTime > %f
|
||||
LIMIT %d", sprintf('%.6f', $lastSendTime), $limit);
|
||||
|
||||
$count_query = str_replace(
|
||||
array(
|
||||
"SELECT * FROM",
|
||||
"LIMIT " . $limit,
|
||||
),
|
||||
array( "SELECT COUNT(*) FROM", "" ), $query
|
||||
);
|
||||
}
|
||||
else{
|
||||
$query=$wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$table_wfHits}
|
||||
$query=$wpdb->prepare("SELECT * FROM {$table_wfHits}
|
||||
WHERE action in ('blocked:waf', 'learned:waf', 'logged:waf', 'blocked:waf-always')
|
||||
AND id > %d
|
||||
ORDER BY id LIMIT %d", $lastSendId, $limit);
|
||||
|
||||
$count_query = str_replace(
|
||||
array(
|
||||
"SELECT * FROM",
|
||||
"ORDER BY id LIMIT " . $limit,
|
||||
),
|
||||
array( "SELECT COUNT(*) FROM", "" ), $query
|
||||
);
|
||||
}
|
||||
|
||||
$params[]=$limit;
|
||||
$attackData = $wpdb->get_results($query);
|
||||
$totalRows = $wpdb->get_var('SELECT FOUND_ROWS()');
|
||||
|
||||
$totalRows = $wpdb->get_var($count_query);
|
||||
|
||||
if ($attackData) { // Build JSON to send
|
||||
$dataToSend = array();
|
||||
$attackDataToUpdate = array();
|
||||
@@ -9909,7 +9987,7 @@ class wfWAFAutoPrependHelper {
|
||||
|
||||
public function getFilesNeededForBackup() {
|
||||
$backups = array();
|
||||
$htaccess = $this->getHtaccessPath();
|
||||
$htaccess = wfWAFAutoPrependHelper::getHtaccessPath();
|
||||
switch ($this->getServerConfig()) {
|
||||
case 'apache-mod_php':
|
||||
case 'apache-suphp':
|
||||
@@ -9921,7 +9999,7 @@ class wfWAFAutoPrependHelper {
|
||||
break;
|
||||
}
|
||||
if ($userIni = ini_get('user_ini.filename')) {
|
||||
$userIniPath = $this->getUserIniPath();
|
||||
$userIniPath = wfWAFAutoPrependHelper::getUserIniPath();
|
||||
switch ($this->getServerConfig()) {
|
||||
case 'cgi':
|
||||
case 'apache-suphp':
|
||||
@@ -9979,10 +10057,10 @@ class wfWAFAutoPrependHelper {
|
||||
|
||||
$serverConfig = $this->getServerConfig();
|
||||
|
||||
$htaccessPath = $this->getHtaccessPath();
|
||||
$htaccessPath = wfWAFAutoPrependHelper::getHtaccessPath();
|
||||
$homePath = dirname($htaccessPath);
|
||||
|
||||
$userIniPath = $this->getUserIniPath();
|
||||
$userIniPath = wfWAFAutoPrependHelper::getUserIniPath();
|
||||
$userIni = ini_get('user_ini.filename');
|
||||
|
||||
$userIniHtaccessDirectives = '';
|
||||
@@ -10122,9 +10200,9 @@ auto_prepend_file = '%s'
|
||||
public function performIniRemoval($wp_filesystem) {
|
||||
$serverConfig = $this->getServerConfig();
|
||||
|
||||
$htaccessPath = $this->getHtaccessPath();
|
||||
$htaccessPath = wfWAFAutoPrependHelper::getHtaccessPath();
|
||||
|
||||
$userIniPath = $this->getUserIniPath();
|
||||
$userIniPath = wfWAFAutoPrependHelper::getUserIniPath();
|
||||
$userIni = ini_get('user_ini.filename');
|
||||
|
||||
// Modify .htaccess
|
||||
@@ -10174,12 +10252,12 @@ auto_prepend_file = '%s'
|
||||
throw new wfWAFAutoPrependHelperException(__('We were unable to remove the <code>wordfence-waf.php</code> file in the root of the WordPress installation. It\'s possible WordPress cannot remove the <code>wordfence-waf.php</code> file because of file permissions. Please verify the permissions are correct and retry the removal.', 'wordfence'));
|
||||
}
|
||||
}
|
||||
|
||||
public function getHtaccessPath() {
|
||||
|
||||
public static function getHtaccessPath() {
|
||||
return wfUtils::getHomePath() . '.htaccess';
|
||||
}
|
||||
|
||||
public function getUserIniPath() {
|
||||
|
||||
public static function getUserIniPath() {
|
||||
$userIni = ini_get('user_ini.filename');
|
||||
if ($userIni) {
|
||||
return wfUtils::getHomePath() . $userIni;
|
||||
@@ -10187,6 +10265,36 @@ auto_prepend_file = '%s'
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the WAF section from the .htaccess content and returns it (inclusive of the section markers). If not
|
||||
* present, returns false.
|
||||
*
|
||||
* @param string $htaccessContent
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getHtaccessSectionContent($htaccessContent) {
|
||||
$regex = '/# Wordfence WAF.*?# END Wordfence WAF/is';
|
||||
if (preg_match($regex, $htaccessContent, $matches)) {
|
||||
return $matches[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the WAF section from the .user.ini content and returns it (inclusive of the section markers). If not
|
||||
* present, returns false.
|
||||
*
|
||||
* @param string $userIniContent
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getUserIniSectionContent($userIniContent) {
|
||||
$regex = '/; Wordfence WAF.*?; END Wordfence WAF/is';
|
||||
if (preg_match($regex, $userIniContent, $matches)) {
|
||||
return $matches[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function usesUserIni() {
|
||||
$userIni = ini_get('user_ini.filename');
|
||||
if (!$userIni) {
|
||||
@@ -10207,8 +10315,8 @@ auto_prepend_file = '%s'
|
||||
/** @var WP_Filesystem_Base $wp_filesystem */
|
||||
global $wp_filesystem;
|
||||
|
||||
$htaccessPath = $this->getHtaccessPath();
|
||||
$userIniPath = $this->getUserIniPath();
|
||||
$htaccessPath = wfWAFAutoPrependHelper::getHtaccessPath();
|
||||
$userIniPath = wfWAFAutoPrependHelper::getUserIniPath();
|
||||
|
||||
$adminURL = admin_url('/');
|
||||
$allow_relaxed_file_ownership = true;
|
||||
@@ -10267,4 +10375,4 @@ auto_prepend_file = '%s'
|
||||
}
|
||||
|
||||
class wfWAFAutoPrependHelperException extends Exception {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
define('WORDFENCE_EPOCH', 1312156800);
|
||||
define('WORDFENCE_FEEDBACK_EPOCH', 1704213261);
|
||||
define('WORDFENCE_API_VERSION', '2.26');
|
||||
define('WORDFENCE_API_URL_SEC', 'https://noc1.wordfence.com/');
|
||||
define('WORDFENCE_API_URL_NONSEC', 'http://noc1.wordfence.com/');
|
||||
|
||||
@@ -110,6 +110,10 @@ class wordfenceURLHoover {
|
||||
public function captureURL($matches) {
|
||||
$id = $this->currentHooverID;
|
||||
$url = 'http:' . $matches[0];
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$components = parse_url($url);
|
||||
if (preg_match('/\.(xn--(?:[a-z0-9-]*)[a-z0-9]+|[a-z\xa1-\xff0-9]{2,})$/i', $components['host'], $tld)) {
|
||||
$tld = strtolower($tld[1]);
|
||||
@@ -126,9 +130,6 @@ class wordfenceURLHoover {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_foundSome++;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user