Wordfence Security – Firewall & Malware Scan - Version 7.1.17

Version Description

  • Improvement: Increased frequency of filesystem permission check and update of the WAF config files.
  • Improvement: More complete data removal when deactivating with remove tables and files checked.
  • Improvement: Better diagnostics logging for GeoIP conflicts.
  • Fix: Text fix in invalid username lockout message.
  • Fix: PHP 7.3 syntax compatibility fixes.
Download this release

Release Info

Developer wfryan
Plugin Icon 128x128 Wordfence Security – Firewall & Malware Scan
Version 7.1.17
Comparing to
See all releases

Code changes from version 7.1.16 to 7.1.17

Files changed (50) hide show
  1. css/{activity-report-widget.1539704326.css → activity-report-widget.1541524007.css} +0 -0
  2. css/{diff.1539704326.css → diff.1541524007.css} +0 -0
  3. css/{dt_table.1539704326.css → dt_table.1541524007.css} +0 -0
  4. css/{fullLog.1539704326.css → fullLog.1541524007.css} +0 -0
  5. css/{iptraf.1539704326.css → iptraf.1541524007.css} +0 -0
  6. css/{jquery-ui-timepicker-addon.1539704326.css → jquery-ui-timepicker-addon.1541524007.css} +0 -0
  7. css/{jquery-ui.min.1539704326.css → jquery-ui.min.1541524007.css} +0 -0
  8. css/{jquery-ui.structure.min.1539704326.css → jquery-ui.structure.min.1541524007.css} +0 -0
  9. css/{jquery-ui.theme.min.1539704326.css → jquery-ui.theme.min.1541524007.css} +0 -0
  10. css/{main.1539704326.css → main.1541524007.css} +0 -0
  11. css/{phpinfo.1539704326.css → phpinfo.1541524007.css} +0 -0
  12. css/{wf-adminbar.1539704326.css → wf-adminbar.1541524007.css} +0 -0
  13. css/{wf-colorbox.1539704326.css → wf-colorbox.1541524007.css} +0 -0
  14. css/{wf-font-awesome.1539704326.css → wf-font-awesome.1541524007.css} +0 -0
  15. css/{wf-ionicons.1539704326.css → wf-ionicons.1541524007.css} +0 -0
  16. css/{wf-onboarding.1539704326.css → wf-onboarding.1541524007.css} +0 -0
  17. css/{wf-roboto-font.1539704326.css → wf-roboto-font.1541524007.css} +0 -0
  18. css/{wfselect2.min.1539704326.css → wfselect2.min.1541524007.css} +0 -0
  19. css/{wordfenceBox.1539704326.css → wordfenceBox.1541524007.css} +0 -0
  20. js/{Chart.bundle.min.1539704326.js → Chart.bundle.min.1541524007.js} +0 -0
  21. js/{admin.1539704326.js → admin.1541524007.js} +0 -0
  22. js/{admin.ajaxWatcher.1539704326.js → admin.ajaxWatcher.1541524007.js} +0 -0
  23. js/{admin.liveTraffic.1539704326.js → admin.liveTraffic.1541524007.js} +0 -0
  24. js/{date.1539704326.js → date.1541524007.js} +0 -0
  25. js/{jquery-ui-timepicker-addon.1539704326.js → jquery-ui-timepicker-addon.1541524007.js} +0 -0
  26. js/{jquery.colorbox-min.1539704326.js → jquery.colorbox-min.1541524007.js} +0 -0
  27. js/{jquery.colorbox.1539704326.js → jquery.colorbox.1541524007.js} +0 -0
  28. js/{jquery.dataTables.min.1539704326.js → jquery.dataTables.min.1541524007.js} +0 -0
  29. js/{jquery.qrcode.min.1539704326.js → jquery.qrcode.min.1541524007.js} +0 -0
  30. js/{jquery.tmpl.min.1539704326.js → jquery.tmpl.min.1541524007.js} +0 -0
  31. js/{jquery.tools.min.1539704326.js → jquery.tools.min.1541524007.js} +0 -0
  32. js/{knockout-3.3.0.1539704326.js → knockout-3.3.0.1541524007.js} +0 -0
  33. js/{perf.1539704326.js → perf.1541524007.js} +0 -0
  34. js/{wfdashboard.1539704326.js → wfdashboard.1541524007.js} +0 -0
  35. js/{wfdropdown.1539704326.js → wfdropdown.1541524007.js} +0 -0
  36. js/{wfglobal.1539704326.js → wfglobal.1541524007.js} +0 -0
  37. js/{wfpopover.1539704326.js → wfpopover.1541524007.js} +0 -0
  38. js/{wfselect2.min.1539704326.js → wfselect2.min.1541524007.js} +0 -0
  39. lib/wfConfig.php +3 -0
  40. lib/wfDiagnostic.php +35 -2
  41. lib/wfUtils.php +73 -3
  42. lib/wordfenceClass.php +113 -5
  43. lib/wordfenceScanner.php +3 -2
  44. models/block/wfBlock.php +5 -5
  45. readme.txt +9 -2
  46. vendor/wordfence/wf-waf/src/lib/storage.php +2 -0
  47. vendor/wordfence/wf-waf/src/lib/storage/file.php +30 -0
  48. vendor/wordfence/wf-waf/src/lib/waf.php +9 -1
  49. waf/bootstrap.php +88 -13
  50. wordfence.php +3 -3
css/{activity-report-widget.1539704326.css → activity-report-widget.1541524007.css} RENAMED
File without changes
css/{diff.1539704326.css → diff.1541524007.css} RENAMED
File without changes
css/{dt_table.1539704326.css → dt_table.1541524007.css} RENAMED
File without changes
css/{fullLog.1539704326.css → fullLog.1541524007.css} RENAMED
File without changes
css/{iptraf.1539704326.css → iptraf.1541524007.css} RENAMED
File without changes
css/{jquery-ui-timepicker-addon.1539704326.css → jquery-ui-timepicker-addon.1541524007.css} RENAMED
File without changes
css/{jquery-ui.min.1539704326.css → jquery-ui.min.1541524007.css} RENAMED
File without changes
css/{jquery-ui.structure.min.1539704326.css → jquery-ui.structure.min.1541524007.css} RENAMED
File without changes
css/{jquery-ui.theme.min.1539704326.css → jquery-ui.theme.min.1541524007.css} RENAMED
File without changes
css/{main.1539704326.css → main.1541524007.css} RENAMED
File without changes
css/{phpinfo.1539704326.css → phpinfo.1541524007.css} RENAMED
File without changes
css/{wf-adminbar.1539704326.css → wf-adminbar.1541524007.css} RENAMED
File without changes
css/{wf-colorbox.1539704326.css → wf-colorbox.1541524007.css} RENAMED
File without changes
css/{wf-font-awesome.1539704326.css → wf-font-awesome.1541524007.css} RENAMED
File without changes
css/{wf-ionicons.1539704326.css → wf-ionicons.1541524007.css} RENAMED
File without changes
css/{wf-onboarding.1539704326.css → wf-onboarding.1541524007.css} RENAMED
File without changes
css/{wf-roboto-font.1539704326.css → wf-roboto-font.1541524007.css} RENAMED
File without changes
css/{wfselect2.min.1539704326.css → wfselect2.min.1541524007.css} RENAMED
File without changes
css/{wordfenceBox.1539704326.css → wordfenceBox.1541524007.css} RENAMED
File without changes
js/{Chart.bundle.min.1539704326.js → Chart.bundle.min.1541524007.js} RENAMED
File without changes
js/{admin.1539704326.js → admin.1541524007.js} RENAMED
File without changes
js/{admin.ajaxWatcher.1539704326.js → admin.ajaxWatcher.1541524007.js} RENAMED
File without changes
js/{admin.liveTraffic.1539704326.js → admin.liveTraffic.1541524007.js} RENAMED
File without changes
js/{date.1539704326.js → date.1541524007.js} RENAMED
File without changes
js/{jquery-ui-timepicker-addon.1539704326.js → jquery-ui-timepicker-addon.1541524007.js} RENAMED
File without changes
js/{jquery.colorbox-min.1539704326.js → jquery.colorbox-min.1541524007.js} RENAMED
File without changes
js/{jquery.colorbox.1539704326.js → jquery.colorbox.1541524007.js} RENAMED
File without changes
js/{jquery.dataTables.min.1539704326.js → jquery.dataTables.min.1541524007.js} RENAMED
File without changes
js/{jquery.qrcode.min.1539704326.js → jquery.qrcode.min.1541524007.js} RENAMED
File without changes
js/{jquery.tmpl.min.1539704326.js → jquery.tmpl.min.1541524007.js} RENAMED
File without changes
js/{jquery.tools.min.1539704326.js → jquery.tools.min.1541524007.js} RENAMED
File without changes
js/{knockout-3.3.0.1539704326.js → knockout-3.3.0.1541524007.js} RENAMED
File without changes
js/{perf.1539704326.js → perf.1541524007.js} RENAMED
File without changes
js/{wfdashboard.1539704326.js → wfdashboard.1541524007.js} RENAMED
File without changes
js/{wfdropdown.1539704326.js → wfdropdown.1541524007.js} RENAMED
File without changes
js/{wfglobal.1539704326.js → wfglobal.1541524007.js} RENAMED
File without changes
js/{wfpopover.1539704326.js → wfpopover.1541524007.js} RENAMED
File without changes
js/{wfselect2.min.1539704326.js → wfselect2.min.1541524007.js} RENAMED
File without changes
lib/wfConfig.php CHANGED
@@ -217,6 +217,9 @@ class wfConfig {
217
'touppPromptNeeded' => array('value' => false, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_BOOL)),
218
'touppBypassNextCheck' => array('value' => false, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_BOOL)),
219
'autoUpdateAttempts' => array('value' => 0, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
220
),
221
);
222
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');
217
'touppPromptNeeded' => array('value' => false, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_BOOL)),
218
'touppBypassNextCheck' => array('value' => false, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_BOOL)),
219
'autoUpdateAttempts' => array('value' => 0, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
220
+ 'lastPermissionsTemplateCheck' => array('value' => 0, 'autoload' => self::AUTOLOAD, 'validation' => array('type' => self::TYPE_INT)),
221
+ 'previousWflogsFileList' => array('value' => '[]', 'autoload' => self::DONT_AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
222
+ 'diagnosticsWflogsRemovalHistory' => array('value' => '[]', 'autoload' => self::DONT_AUTOLOAD, 'validation' => array('type' => self::TYPE_STRING)),
223
),
224
);
225
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');
lib/wfDiagnostic.php CHANGED
@@ -58,6 +58,7 @@ class wfDiagnostic
58
'description' => __('General information about the Wordfence installation.', 'wordfence'),
59
'tests' => array(
60
'wfVersion' => __('Wordfence Version', 'wordfence'),
61
),
62
),
63
'Filesystem' => array(
@@ -84,6 +85,7 @@ class wfDiagnostic
84
'wafSubdirectoryInstall' => __('WAF subdirectory installation', 'wordfence'),
85
'wafAutoPrependFilePath' => __('wordfence-waf.php path', 'wordfence'),
86
'wafFilePermissions' => __('WAF File Permissions', 'wordfence'),
87
),
88
),
89
'MySQL' => array(
@@ -161,6 +163,15 @@ class wfDiagnostic
161
public function wfVersion() {
162
return array('test' => true, 'message' => WORDFENCE_VERSION . ' (' . WORDFENCE_BUILD_NUMBER . ')');
163
}
164
165
public function isPluginReadable() {
166
return is_readable(WORDFENCE_PATH);
@@ -180,7 +191,6 @@ class wfDiagnostic
180
WFWAF_LOG_PATH . 'ips.php',
181
WFWAF_LOG_PATH . 'config.php',
182
WFWAF_LOG_PATH . 'rules.php',
183
- WFWAF_LOG_PATH . 'wafRules.rules',
184
);
185
$unreadable = array();
186
foreach ($files as $f) {
@@ -209,7 +219,6 @@ class wfDiagnostic
209
WFWAF_LOG_PATH . 'ips.php',
210
WFWAF_LOG_PATH . 'config.php',
211
WFWAF_LOG_PATH . 'rules.php',
212
- WFWAF_LOG_PATH . 'wafRules.rules',
213
);
214
$unwritable = array();
215
foreach ($files as $f) {
@@ -347,6 +356,30 @@ class wfDiagnostic
347
}
348
return array('test' => true, 'infoOnly' => true, 'message' => __('0660 - using default', 'wordfence'));
349
}
350
351
public function processOwner() {
352
$disabledFunctions = explode(',', ini_get('disable_functions'));
58
'description' => __('General information about the Wordfence installation.', 'wordfence'),
59
'tests' => array(
60
'wfVersion' => __('Wordfence Version', 'wordfence'),
61
+ 'geoIPVersion' => __('GeoIP Version', 'wordfence'),
62
),
63
),
64
'Filesystem' => array(
85
'wafSubdirectoryInstall' => __('WAF subdirectory installation', 'wordfence'),
86
'wafAutoPrependFilePath' => __('wordfence-waf.php path', 'wordfence'),
87
'wafFilePermissions' => __('WAF File Permissions', 'wordfence'),
88
+ 'wafRecentlyRemoved' => __('Recently removed wflogs files', 'wordfence'),
89
),
90
),
91
'MySQL' => array(
163
public function wfVersion() {
164
return array('test' => true, 'message' => WORDFENCE_VERSION . ' (' . WORDFENCE_BUILD_NUMBER . ')');
165
}
166
+
167
+ public function geoIPVersion() {
168
+ return array('test' => true, 'infoOnly' => true, 'message' => wfUtils::geoIPVersion());
169
+ }
170
+
171
+ public function geoIPError() {
172
+ $error = wfUtils::last_error('geoip');
173
+ return array('test' => true, 'infoOnly' => true, 'message' => $error ? $error : __('None', 'wordfence'));
174
+ }
175
176
public function isPluginReadable() {
177
return is_readable(WORDFENCE_PATH);
191
WFWAF_LOG_PATH . 'ips.php',
192
WFWAF_LOG_PATH . 'config.php',
193
WFWAF_LOG_PATH . 'rules.php',
194
);
195
$unreadable = array();
196
foreach ($files as $f) {
219
WFWAF_LOG_PATH . 'ips.php',
220
WFWAF_LOG_PATH . 'config.php',
221
WFWAF_LOG_PATH . 'rules.php',
222
);
223
$unwritable = array();
224
foreach ($files as $f) {
356
}
357
return array('test' => true, 'infoOnly' => true, 'message' => __('0660 - using default', 'wordfence'));
358
}
359
+
360
+ public function wafRecentlyRemoved() {
361
+ $removalHistory = wfConfig::getJSON('diagnosticsWflogsRemovalHistory', array());
362
+ if (empty($removalHistory)) {
363
+ return array('test' => true, 'infoOnly' => true, 'message' => __('None', 'wordfence'));
364
+ }
365
+
366
+ $message = array();
367
+ foreach ($removalHistory as $r) {
368
+ $m = wfUtils::formatLocalTime('M j, Y', $r[0]) . ': (' . count($r[1]) . ')';
369
+ $r[1] = array_filter($r[1], array($this, '_filterOutNestedEntries'));
370
+ $m .= ' ' . implode(', ', array_slice($r[1], 0, 5));
371
+ if (count($r[1]) > 5) {
372
+ $m .= ', ...';
373
+ }
374
+ $message[] = $m;
375
+ }
376
+
377
+ return array('test' => true, 'infoOnly' => true, 'message' => implode("\n", $message));
378
+ }
379
+
380
+ private function _filterOutNestedEntries($a) {
381
+ return !is_array($a);
382
+ }
383
384
public function processOwner() {
385
$disabledFunctions = explode(',', ini_get('disable_functions'));
lib/wfUtils.php CHANGED
@@ -1387,16 +1387,22 @@ class wfUtils {
1387
}
1388
1389
if (!class_exists('wfGeoIP2')) {
1390
require_once(dirname(__FILE__) . '/../models/common/wfGeoIP2.php');
1391
}
1392
1393
try {
1394
$geoip = @wfGeoIP2::shared();
1395
$code = @$geoip->countryCode($IP);
1396
return is_string($code) ? $code : '';
1397
}
1398
catch (Exception $e) {
1399
- //Ignore
1400
}
1401
1402
return '';
@@ -1407,15 +1413,22 @@ class wfUtils {
1407
}
1408
1409
if (!class_exists('wfGeoIP2')) {
1410
require_once(dirname(__FILE__) . '/../models/common/wfGeoIP2.php');
1411
}
1412
1413
try {
1414
$geoip = @wfGeoIP2::shared();
1415
- return @$geoip->version();
1416
}
1417
catch (Exception $e) {
1418
- //Ignore
1419
}
1420
1421
return 0;
@@ -1465,6 +1478,63 @@ class wfUtils {
1465
public static function isRefererBlocked($refPattern){
1466
return fnmatch($refPattern, !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', FNM_CASEFOLD);
1467
}
1468
1469
/**
1470
* @param $startIP
1387
}
1388
1389
if (!class_exists('wfGeoIP2')) {
1390
+ wfUtils::error_clear_last();
1391
require_once(dirname(__FILE__) . '/../models/common/wfGeoIP2.php');
1392
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:');
1393
}
1394
1395
try {
1396
+ wfUtils::error_clear_last();
1397
$geoip = @wfGeoIP2::shared();
1398
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:');
1399
+ wfUtils::error_clear_last();
1400
$code = @$geoip->countryCode($IP);
1401
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:');
1402
return is_string($code) ? $code : '';
1403
}
1404
catch (Exception $e) {
1405
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:', $e->getMessage());
1406
}
1407
1408
return '';
1413
}
1414
1415
if (!class_exists('wfGeoIP2')) {
1416
+ wfUtils::error_clear_last();
1417
require_once(dirname(__FILE__) . '/../models/common/wfGeoIP2.php');
1418
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:');
1419
}
1420
1421
try {
1422
+ wfUtils::error_clear_last();
1423
$geoip = @wfGeoIP2::shared();
1424
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:');
1425
+ wfUtils::error_clear_last();
1426
+ $version = @$geoip->version();
1427
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:');
1428
+ return $version;
1429
}
1430
catch (Exception $e) {
1431
+ wfUtils::check_and_log_last_error('geoip', 'GeoIP Error:', $e->getMessage());
1432
}
1433
1434
return 0;
1478
public static function isRefererBlocked($refPattern){
1479
return fnmatch($refPattern, !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', FNM_CASEFOLD);
1480
}
1481
+
1482
+ public static function error_clear_last() {
1483
+ if (function_exists('error_clear_last')) {
1484
+ error_clear_last();
1485
+ }
1486
+ else {
1487
+ // set error_get_last() to defined state by forcing an undefined variable error
1488
+ set_error_handler('wfUtils::_resetErrorsHandler', 0);
1489
+ @$undefinedVariable;
1490
+ restore_error_handler();
1491
+ }
1492
+ }
1493
+
1494
+ /**
1495
+ * Logs the error given or the last PHP error to our log, rate limiting if needed.
1496
+ *
1497
+ * @param string $limiter_key
1498
+ * @param string $label
1499
+ * @param null|string $error The error to log. If null, it will be the result of error_get_last
1500
+ * @param int $rate Logging will only occur once per $rate seconds.
1501
+ */
1502
+ public static function check_and_log_last_error($limiter_key, $label, $error = null, $rate = 3600 /* 1 hour */) {
1503
+ if ($error === null) {
1504
+ $error = error_get_last();
1505
+ if ($error === null) {
1506
+ return;
1507
+ }
1508
+ else if ($error['file'] === __FILE__) {
1509
+ return;
1510
+ }
1511
+ $error = $error['message'];
1512
+ }
1513
+
1514
+ $rateKey = 'lastError_rate_' . $limiter_key;
1515
+ $previousKey = 'lastError_prev_' . $limiter_key;
1516
+ $previousError = wfConfig::getJSON($previousKey, array(0, false));
1517
+ if ($previousError[1] != $error) {
1518
+ if (wfConfig::getInt($rateKey) < time() - $rate) {
1519
+ wfConfig::set($rateKey, time());
1520
+ wfConfig::setJSON($previousKey, array(time(), $error));
1521
+ wordfence::status(2, 'error', $label . ' ' . $error);
1522
+ }
1523
+ }
1524
+ }
1525
+
1526
+ public static function last_error($limiter_key) {
1527
+ $previousKey = 'lastError_prev_' . $limiter_key;
1528
+ $previousError = wfConfig::getJSON($previousKey, array(0, false));
1529
+ if ($previousError[1]) {
1530
+ return wfUtils::formatLocalTime(get_option('date_format') . ' ' . get_option('time_format'), $previousError[0]) . ': ' . $previousError[1];
1531
+ }
1532
+ return false;
1533
+ }
1534
+
1535
+ public static function _resetErrorsHandler($errno, $errstr, $errfile, $errline) {
1536
+ //Do nothing
1537
+ }
1538
1539
/**
1540
* @param $startIP
lib/wordfenceClass.php CHANGED
@@ -285,6 +285,8 @@ class wordfence {
285
if ($next - time() > 3600 && wfConfig::get('scheduledScansEnabled')) {
286
wfScanEngine::startScan(false, wfScanner::SCAN_TYPE_QUICK);
287
}
288
}
289
public static function _scheduleRefreshUpdateNotification($upgrader, $options) {
290
$defer = false;
@@ -1832,7 +1834,8 @@ SQL
1832
}
1833
1834
try {
1835
- if (wfUtils::isAdmin()) {
1836
$lastPermissionsTemplateCheck = wfConfig::getInt('lastPermissionsTemplateCheck', 0);
1837
if (defined('WFWAF_LOG_PATH') && ($lastPermissionsTemplateCheck + 43200) < time()) { //Run no more frequently than every 12 hours
1838
$timestamp = preg_replace('/[^0-9]/', '', microtime(false)); //We avoid using tmpfile since it can potentially create one with different permissions than the defaults
@@ -1866,10 +1869,41 @@ SQL
1866
}
1867
1868
wfConfig::set('lastPermissionsTemplateCheck', time());
1869
- }
1870
1871
- @chmod(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
1872
- @chmod(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess', (wfWAFWordPress::permissions() | 0444));
1873
}
1874
}
1875
catch (Exception $e) {
@@ -2034,6 +2068,80 @@ SQL
2034
}
2035
}
2036
}
2037
2038
public static function loginAction($username){
2039
if(sizeof($_POST) < 1){ return; } //only execute if login form is posted
@@ -2648,7 +2756,7 @@ SQL
2648
}
2649
if(wfConfig::get('loginSec_lockInvalidUsers')){
2650
if(strlen($username) > 0 && preg_match('/[^\r\s\n\t]+/', $username)){
2651
- self::lockOutIP($IP, "Used an invalid username '" . $username . "' to try to sign in.");
2652
self::getLog()->logLogin('loginFailInvalidUsername', true, $username);
2653
}
2654
$customText = wpautop(wp_strip_all_tags(wfConfig::get('blockCustomText', '')));
285
if ($next - time() > 3600 && wfConfig::get('scheduledScansEnabled')) {
286
wfScanEngine::startScan(false, wfScanner::SCAN_TYPE_QUICK);
287
}
288
+
289
+ wfConfig::remove('lastPermissionsTemplateCheck');
290
}
291
public static function _scheduleRefreshUpdateNotification($upgrader, $options) {
292
$defer = false;
1834
}
1835
1836
try {
1837
+ $sapi = @php_sapi_name();
1838
+ if ($sapi != "cli") {
1839
$lastPermissionsTemplateCheck = wfConfig::getInt('lastPermissionsTemplateCheck', 0);
1840
if (defined('WFWAF_LOG_PATH') && ($lastPermissionsTemplateCheck + 43200) < time()) { //Run no more frequently than every 12 hours
1841
$timestamp = preg_replace('/[^0-9]/', '', microtime(false)); //We avoid using tmpfile since it can potentially create one with different permissions than the defaults
1869
}
1870
1871
wfConfig::set('lastPermissionsTemplateCheck', time());
1872
1873
+ @chmod(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
1874
+ wfWAFWordPress::writeHtaccess();
1875
+
1876
+ $contents = self::_wflogsContents();
1877
+ if ($contents) {
1878
+ $validFiles = wfWAF::getInstance()->fileList();
1879
+ foreach ($validFiles as &$vf) {
1880
+ $vf = basename($vf);
1881
+ }
1882
+ $validFiles = array_filter($validFiles);
1883
+
1884
+ $previousWflogsFileList = wfConfig::getJSON('previousWflogsFileList', array());
1885
+
1886
+ $wflogs = realpath(WFWAF_LOG_PATH);
1887
+ $filesRemoved = array();
1888
+ foreach ($contents as $f) {
1889
+ if (!in_array($f, $validFiles) && in_array($f, $previousWflogsFileList)) {
1890
+ $fullPath = $f;
1891
+ $removed = self::_recursivelyRemoveWflogs($f);
1892
+ $filesRemoved = array_merge($filesRemoved, $removed);
1893
+ }
1894
+ }
1895
+
1896
+ $contents = self::_wflogsContents();
1897
+ wfConfig::setJSON('previousWflogsFileList', $contents);
1898
+
1899
+ if (!empty($filesRemoved)) {
1900
+ $removalHistory = wfConfig::getJSON('diagnosticsWflogsRemovalHistory', array());
1901
+ $removalHistory = array_slice($removalHistory, 0, 4);
1902
+ array_unshift($removalHistory, array(time(), $filesRemoved));
1903
+ wfConfig::setJSON('diagnosticsWflogsRemovalHistory', $removalHistory);
1904
+ }
1905
+ }
1906
+ }
1907
}
1908
}
1909
catch (Exception $e) {
2068
}
2069
}
2070
}
2071
+
2072
+ private static function _wflogsContents() {
2073
+ $dir = opendir(WFWAF_LOG_PATH);
2074
+ if ($dir) {
2075
+ $contents = array();
2076
+ while ($path = readdir($dir)) {
2077
+ if ($path == '.' || $path == '..') { continue; }
2078
+ $contents[] = $path;
2079
+ }
2080
+ closedir($dir);
2081
+ return $contents;
2082
+ }
2083
+ return false;
2084
+ }
2085
+
2086
+ /**
2087
+ * Removes a path within wflogs, recursing as necessary.
2088
+ *
2089
+ * @param string $file
2090
+ * @param array $processedDirs
2091
+ * @return array The list of removed files/folders.
2092
+ */
2093
+ private static function _recursivelyRemoveWflogs($file, $processedDirs = array()) {
2094
+ if (preg_match('~(?:^|/|\\\\)\.\.(?:/|\\\\|$)~', $file)) {
2095
+ return array();
2096
+ }
2097
+
2098
+ if (stripos(WFWAF_LOG_PATH, 'wflogs') === false) { //Sanity check -- if not in a wflogs folder, user will have to do removal manually
2099
+ return array();
2100
+ }
2101
+
2102
+ $path = rtrim(WFWAF_LOG_PATH, '/') . '/' . $file;
2103
+ if (is_link($path)) {
2104
+ if (@unlink($path)) {
2105
+ return array($file);
2106
+ }
2107
+ return array();
2108
+ }
2109
+
2110
+ if (is_dir($path)) {
2111
+ $real = realpath($file);
2112
+ if (in_array($real, $processedDirs)) {
2113
+ return array();
2114
+ }
2115
+ $processedDirs[] = $real;
2116
+
2117
+ $count = 0;
2118
+ $dir = opendir($path);
2119
+ if ($dir) {
2120
+ $contents = array();
2121
+ while ($sub = readdir($dir)) {
2122
+ if ($sub == '.' || $sub == '..') { continue; }
2123
+ $contents[] = $sub;
2124
+ }
2125
+ closedir($dir);
2126
+
2127
+ $filesRemoved = array();
2128
+ foreach ($contents as $f) {
2129
+ $removed = self::_recursivelyRemoveWflogs($file . '/' . $f, $processedDirs);
2130
+ $filesRemoved = array($filesRemoved, $removed);
2131
+ }
2132
+ }
2133
+
2134
+ if (@rmdir($path)) {
2135
+ $filesRemoved[] = $file;
2136
+ }
2137
+ return $filesRemoved;
2138
+ }
2139
+
2140
+ if (@unlink($path)) {
2141
+ return array($file);
2142
+ }
2143
+ return array();
2144
+ }
2145
2146
public static function loginAction($username){
2147
if(sizeof($_POST) < 1){ return; } //only execute if login form is posted
2756
}
2757
if(wfConfig::get('loginSec_lockInvalidUsers')){
2758
if(strlen($username) > 0 && preg_match('/[^\r\s\n\t]+/', $username)){
2759
+ self::lockOutIP($IP, "Used an invalid username '" . $username . "' to try to sign in");
2760
self::getLog()->logLogin('loginFailInvalidUsername', true, $username);
2761
}
2762
$customText = wpautop(wp_strip_all_tags(wfConfig::get('blockCustomText', '')));
lib/wordfenceScanner.php CHANGED
@@ -365,7 +365,8 @@ class wordfenceScanner {
365
366
$type = (isset($rule[4]) && !empty($rule[4])) ? $rule[4] : 'server';
367
$logOnly = (isset($rule[5]) && !empty($rule[5])) ? $rule[5] : false;
368
- $commonStringIndexes = (isset($rule[8]) && is_array($rule[8])) ? $rule[8] : array();
369
if ($type == 'server' && !$treatAsBinary) { continue; }
370
else if (($type == 'both' || $type == 'browser') && $isJS) { $extraMsg = ''; }
371
else if (($type == 'both' || $type == 'browser') && !$treatAsBinary) { continue; }
@@ -398,7 +399,7 @@ class wordfenceScanner {
398
'ignoreP' => $this->path . $file,
399
'ignoreC' => $fileSum,
400
'shortMsg' => __('File appears to be malicious: ', 'wordfence') . esc_html($file),
401
- 'longMsg' => sprintf(__('This file appears to be installed or modified by a hacker to perform malicious activity. If you know about this file you can choose to ignore it to exclude it from future scans. The text we found in this file that matches a known malicious file is: <strong style="color: #F00;" class="wf-split-word">%s</strong>', 'wordfence'), wfUtils::potentialBinaryStringToHTML((wfUtils::strlen($matchString) > 200 ? wfUtils::substr($matchString, 0, 200) . '...' : $matchString))) . '<br><br>' . sprintf(__('The infection type is: <strong>%s</strong>', 'wordfence'), esc_html($rule[7])) . '<br>' . sprintf(__('Description: <strong>%s</strong>', 'wordfence'), esc_html($rule[3])) . $extraMsg,
402
'data' => array_merge(array(
403
'file' => $file,
404
'shac' => $record->SHAC,
365
366
$type = (isset($rule[4]) && !empty($rule[4])) ? $rule[4] : 'server';
367
$logOnly = (isset($rule[5]) && !empty($rule[5])) ? $rule[5] : false;
368
+ $commonStringIndexes = (isset($rule[8]) && is_array($rule[8])) ? $rule[8] : array();
369
+ $customMessage = isset($rule[9]) ? $rule[9] : __('This file appears to be installed or modified by a hacker to perform malicious activity. If you know about this file you can choose to ignore it to exclude it from future scans.', 'wordfence');
370
if ($type == 'server' && !$treatAsBinary) { continue; }
371
else if (($type == 'both' || $type == 'browser') && $isJS) { $extraMsg = ''; }
372
else if (($type == 'both' || $type == 'browser') && !$treatAsBinary) { continue; }
399
'ignoreP' => $this->path . $file,
400
'ignoreC' => $fileSum,
401
'shortMsg' => __('File appears to be malicious: ', 'wordfence') . esc_html($file),
402
+ 'longMsg' => $customMessage . ' ' . __('The matched text in this file is:', 'wordfence') . ' ' . '<strong style="color: #F00;" class="wf-split-word">' . wfUtils::potentialBinaryStringToHTML((wfUtils::strlen($matchString) > 200 ? wfUtils::substr($matchString, 0, 200) . '...' : $matchString)) . '</strong>' . '<br><br>' . sprintf(__('The issue type is: <strong>%s</strong>', 'wordfence'), esc_html($rule[7])) . '<br>' . sprintf(__('Description: <strong>%s</strong>', 'wordfence'), esc_html($rule[3])) . $extraMsg,
403
'data' => array_merge(array(
404
'file' => $file,
405
'shac' => $record->SHAC,
models/block/wfBlock.php CHANGED
@@ -549,10 +549,10 @@ class wfBlock {
549
550
return $wpdb->query($wpdb->prepare("INSERT INTO `{$blocksTable}` (`type`, `IP`, `blockedTime`, `reason`, `lastAttempt`, `blockedHits`, `expiration`, `parameters`) VALUES (%d, %s, %d, %s, %d, %d, %d, NULL)", (int) $b['type'], wfUtils::inet_pton($ip), (int) $b['blockedTime'], $b['reason'], (int) $b['lastAttempt'], (int) $b['blockedHits'], self::DURATION_FOREVER)) !== false;
551
case self::TYPE_COUNTRY:
552
- if (!isset($b['parameters'])) { continue; }
553
- if (wfUtils::inet_pton($ip) != self::MARKER_COUNTRY) { continue; }
554
$parameters = @json_decode($b['parameters'], true);
555
- if (!isset($parameters['blockLogin']) || !isset($parameters['blockSite']) || !isset($parameters['countries'])) { continue; }
556
$parameters['blockLogin'] = wfUtils::truthyToInt($parameters['blockLogin']);
557
$parameters['blockSite'] = wfUtils::truthyToInt($parameters['blockSite']);
558
@@ -567,10 +567,10 @@ class wfBlock {
567
568
return $wpdb->query($wpdb->prepare("INSERT INTO `{$blocksTable}` (`type`, `IP`, `blockedTime`, `reason`, `lastAttempt`, `blockedHits`, `expiration`, `parameters`) VALUES (%d, %s, %d, %s, %d, %d, %d, %s)", self::TYPE_COUNTRY, self::MARKER_COUNTRY, (int) $b['blockedTime'], $b['reason'], (int) $b['lastAttempt'], (int) $b['blockedHits'], self::DURATION_FOREVER, json_encode($parameters))) !== false;
569
case self::TYPE_PATTERN:
570
- if (!isset($b['parameters'])) { continue; }
571
if (wfUtils::inet_pton($ip) != self::MARKER_PATTERN) { return false; }
572
$parameters = @json_decode($b['parameters'], true);
573
- if (!isset($parameters['ipRange']) || !isset($parameters['hostname']) || !isset($parameters['userAgent']) || !isset($parameters['referrer'])) { continue; }
574
575
$hasOne = false;
576
if (!empty($parameters['ipRange'])) {
549
550
return $wpdb->query($wpdb->prepare("INSERT INTO `{$blocksTable}` (`type`, `IP`, `blockedTime`, `reason`, `lastAttempt`, `blockedHits`, `expiration`, `parameters`) VALUES (%d, %s, %d, %s, %d, %d, %d, NULL)", (int) $b['type'], wfUtils::inet_pton($ip), (int) $b['blockedTime'], $b['reason'], (int) $b['lastAttempt'], (int) $b['blockedHits'], self::DURATION_FOREVER)) !== false;
551
case self::TYPE_COUNTRY:
552
+ if (!isset($b['parameters'])) { return false; }
553
+ if (wfUtils::inet_pton($ip) != self::MARKER_COUNTRY) { return false; }
554
$parameters = @json_decode($b['parameters'], true);
555
+ if (!isset($parameters['blockLogin']) || !isset($parameters['blockSite']) || !isset($parameters['countries'])) { return false; }
556
$parameters['blockLogin'] = wfUtils::truthyToInt($parameters['blockLogin']);
557
$parameters['blockSite'] = wfUtils::truthyToInt($parameters['blockSite']);
558
567
568
return $wpdb->query($wpdb->prepare("INSERT INTO `{$blocksTable}` (`type`, `IP`, `blockedTime`, `reason`, `lastAttempt`, `blockedHits`, `expiration`, `parameters`) VALUES (%d, %s, %d, %s, %d, %d, %d, %s)", self::TYPE_COUNTRY, self::MARKER_COUNTRY, (int) $b['blockedTime'], $b['reason'], (int) $b['lastAttempt'], (int) $b['blockedHits'], self::DURATION_FOREVER, json_encode($parameters))) !== false;
569
case self::TYPE_PATTERN:
570
+ if (!isset($b['parameters'])) { return false; }
571
if (wfUtils::inet_pton($ip) != self::MARKER_PATTERN) { return false; }
572
$parameters = @json_decode($b['parameters'], true);
573
+ if (!isset($parameters['ipRange']) || !isset($parameters['hostname']) || !isset($parameters['userAgent']) || !isset($parameters['referrer'])) { return false; }
574
575
$hasOne = false;
576
if (!empty($parameters['ipRange'])) {
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: mmaunder
3
Tags: security, firewall, malware scanner, web application firewall, antivirus, block hackers, country blocking, clean hacked site, blacklist, waf, login security
4
Requires at least: 3.9
5
Requires PHP: 5.3
6
- Tested up to: 4.9.8
7
- Stable tag: 7.1.16
8
9
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
10
@@ -171,6 +171,13 @@ Secure your website with Wordfence.
171
172
== Changelog ==
173
174
= 7.1.16 =
175
* Improvement: Service whitelisting can now be selectively toggled on or off per service.
176
* Improvement: Updated bundled GeoIP database.
3
Tags: security, firewall, malware scanner, web application firewall, antivirus, block hackers, country blocking, clean hacked site, blacklist, waf, login security
4
Requires at least: 3.9
5
Requires PHP: 5.3
6
+ Tested up to: 5.0
7
+ Stable tag: 7.1.17
8
9
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
10
171
172
== Changelog ==
173
174
+ = 7.1.17 =
175
+ * Improvement: Increased frequency of filesystem permission check and update of the WAF config files.
176
+ * Improvement: More complete data removal when deactivating with remove tables and files checked.
177
+ * Improvement: Better diagnostics logging for GeoIP conflicts.
178
+ * Fix: Text fix in invalid username lockout message.
179
+ * Fix: PHP 7.3 syntax compatibility fixes.
180
+
181
= 7.1.16 =
182
* Improvement: Service whitelisting can now be selectively toggled on or off per service.
183
* Improvement: Updated bundled GeoIP database.
vendor/wordfence/wf-waf/src/lib/storage.php CHANGED
@@ -57,6 +57,8 @@ interface wfWAFStorageInterface {
57
public function unsetConfig($key, $category = '');
58
59
public function uninstall();
60
61
public function isInLearningMode();
62
57
public function unsetConfig($key, $category = '');
58
59
public function uninstall();
60
+
61
+ //optional public function fileList();
62
63
public function isInLearningMode();
64
vendor/wordfence/wf-waf/src/lib/storage/file.php CHANGED
@@ -668,6 +668,36 @@ class wfWAFStorageFile implements wfWAFStorageInterface {
668
@unlink($this->getRulesDSLCacheFile());
669
}
670
671
public function removeConfigFiles() {
672
@unlink($this->getConfigFile());
673
$configDir = dirname($this->getConfigFile());
668
@unlink($this->getRulesDSLCacheFile());
669
}
670
671
+ public function fileList() {
672
+ $fileList = array();
673
+ $fileList[] = $this->getAttackDataFile();
674
+ $fileList[] = $this->getIPCacheFile();
675
+ if (defined('WFWAF_DEBUG') && WFWAF_DEBUG) {
676
+ $fileList[] = $this->getRulesDSLCacheFile();
677
+ }
678
+ $fileList[] = $this->getConfigFile();
679
+ $configDir = dirname($this->getConfigFile());
680
+ $dir = opendir($configDir);
681
+ if ($dir) {
682
+ $escapedPath = preg_quote($this->getConfigFile(), '/');
683
+ $components = explode('\\/', $escapedPath);
684
+ $pattern = $components[count($components) - 1];
685
+ if (preg_match('/^(.+?)(\\\..+$|$)/i', $pattern, $matches)) {
686
+ $pattern = $matches[1] . '\\-[a-z0-9]+' . $matches[2]; //Results in a pattern like config\-[a-z0-9]\.php
687
+ }
688
+
689
+ while ($path = readdir($dir)) {
690
+ if ($path == '.' || $path == '..') { continue; }
691
+ if (is_dir($configDir . '/' . $path)) { continue; }
692
+ if (preg_match('/^' . $pattern . '#x2F;i', $path)) {
693
+ $fileList[] = $configDir . '/' . $path;
694
+ }
695
+ }
696
+ closedir($dir);
697
+ }
698
+ return $fileList;
699
+ }
700
+
701
public function removeConfigFiles() {
702
@unlink($this->getConfigFile());
703
$configDir = dirname($this->getConfigFile());
vendor/wordfence/wf-waf/src/lib/waf.php CHANGED
@@ -726,7 +726,7 @@ if (!defined('WFWAF_VERSION')) {
726
%s?>
727
PHP
728
, $this->buildRuleSet($rules)), 'rules');
729
- if (!empty($ruleString) && !WFWAF_DEBUG) {
730
wfWAFStorageFile::atomicFilePutContents($this->getStorageEngine()->getRulesDSLCacheFile(), $ruleString, 'rules');
731
}
732
@@ -1367,6 +1367,14 @@ HTML
1367
@unlink($this->getCompiledRulesFile());
1368
$this->getStorageEngine()->uninstall();
1369
}
1370
1371
/**
1372
* @param int $ruleID
726
%s?>
727
PHP
728
, $this->buildRuleSet($rules)), 'rules');
729
+ if (!empty($ruleString) && WFWAF_DEBUG && !file_exists($this->getStorageEngine()->getRulesDSLCacheFile())) {
730
wfWAFStorageFile::atomicFilePutContents($this->getStorageEngine()->getRulesDSLCacheFile(), $ruleString, 'rules');
731
}
732
1367
@unlink($this->getCompiledRulesFile());
1368
$this->getStorageEngine()->uninstall();
1369
}
1370
+
1371
+ public function fileList() {
1372
+ $fileList = array($this->getCompiledRulesFile());
1373
+ if (method_exists($this->getStorageEngine(), 'fileList')) {
1374
+ $fileList = array_merge($fileList, $this->getStorageEngine()->fileList());
1375
+ }
1376
+ return $fileList;
1377
+ }
1378
1379
/**
1380
* @param int $ruleID
waf/bootstrap.php CHANGED
@@ -512,8 +512,79 @@ class wfWAFWordPress extends wfWAF {
512
513
public function uninstall() {
514
parent::uninstall();
515
- @unlink(rtrim(WFWAF_LOG_PATH . '/') . '/.htaccess');
516
- @rmdir(WFWAF_LOG_PATH);
517
}
518
519
/**
@@ -560,6 +631,20 @@ class wfWAFWordPress extends wfWAF {
560
}
561
return $_cachedPermissions;
562
}
563
}
564
565
if (!defined('WFWAF_LOG_PATH')) {
@@ -571,17 +656,7 @@ if (!defined('WFWAF_LOG_PATH')) {
571
if (!is_dir(WFWAF_LOG_PATH)) {
572
@mkdir(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
573
@chmod(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
574
- @file_put_contents(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess', <<<APACHE
575
- <IfModule mod_authz_core.c>
576
- Require all denied
577
- </IfModule>
578
- <IfModule !mod_authz_core.c>
579
- Order deny,allow
580
- Deny from all
581
- </IfModule>
582
- APACHE
583
- );
584
- @chmod(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess', (wfWAFWordPress::permissions() | 0444));
585
}
586
587
wfWAF::setSharedStorageEngine(new wfWAFStorageFile(WFWAF_LOG_PATH . 'attack-data.php', WFWAF_LOG_PATH . 'ips.php', WFWAF_LOG_PATH . 'config.php', WFWAF_LOG_PATH . 'wafRules.rules'));
512
513
public function uninstall() {
514
parent::uninstall();
515
+ @unlink(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess');
516
+ @unlink(rtrim(WFWAF_LOG_PATH, '/') . '/template.php');
517
+ @unlink(rtrim(WFWAF_LOG_PATH, '/') . '/GeoLite2-Country.mmdb');
518
+
519
+ self::_recursivelyRemoveWflogs(''); //Removes any remaining files and the directory itself
520
+ }
521
+
522
+ /**
523
+ * Removes a path within wflogs, recursing as necessary.
524
+ *
525
+ * @param string $file
526
+ * @param array $processedDirs
527
+ * @return array The list of removed files/folders.
528
+ */
529
+ private static function _recursivelyRemoveWflogs($file, $processedDirs = array()) {
530
+ if (preg_match('~(?:^|/|\\\\)\.\.(?:/|\\\\|$)~', $file)) {
531
+ return array();
532
+ }
533
+
534
+ if (stripos(WFWAF_LOG_PATH, 'wflogs') === false) { //Sanity check -- if not in a wflogs folder, user will have to do removal manually
535
+ return array();
536
+ }
537
+
538
+ $path = rtrim(WFWAF_LOG_PATH, '/') . '/' . $file;
539
+ if (is_link($path)) {
540
+ if (@unlink($path)) {
541
+ return array($file);
542
+ }
543
+ return array();
544
+ }
545
+
546
+ if (is_dir($path)) {
547
+ $real = realpath($file);
548
+ if (in_array($real, $processedDirs)) {
549
+ return array();
550
+ }
551
+ $processedDirs[] = $real;
552
+
553
+ $count = 0;
554
+ $dir = opendir($path);
555
+ if ($dir) {
556
+ $contents = array();
557
+ while ($sub = readdir($dir)) {
558
+ if ($sub == '.' || $sub == '..') { continue; }
559
+ $contents[] = $sub;
560
+ }
561
+ closedir($dir);
562
+
563
+ $filesRemoved = array();
564
+ foreach ($contents as $f) {
565
+ $removed = self::_recursivelyRemoveWflogs($file . '/' . $f, $processedDirs);
566
+ $filesRemoved = array($filesRemoved, $removed);
567
+ }
568
+ }
569
+
570
+ if (@rmdir($path)) {
571
+ $filesRemoved[] = $file;
572
+ }
573
+ return $filesRemoved;
574
+ }
575
+
576
+ if (@unlink($path)) {
577
+ return array($file);
578
+ }
579
+ return array();
580
+ }
581
+
582
+ public function fileList() {
583
+ $fileList = parent::fileList();
584
+ $fileList[] = rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess';
585
+ $fileList[] = rtrim(WFWAF_LOG_PATH, '/') . '/template.php';
586
+ $fileList[] = rtrim(WFWAF_LOG_PATH, '/') . '/GeoLite2-Country.mmdb';
587
+ return $fileList;
588
}
589
590
/**
631
}
632
return $_cachedPermissions;
633
}
634
+
635
+ public static function writeHtaccess() {
636
+ @file_put_contents(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess', <<<APACHE
637
+ <IfModule mod_authz_core.c>
638
+ Require all denied
639
+ </IfModule>
640
+ <IfModule !mod_authz_core.c>
641
+ Order deny,allow
642
+ Deny from all
643
+ </IfModule>
644
+ APACHE
645
+ );
646
+ @chmod(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess', (wfWAFWordPress::permissions() | 0444));
647
+ }
648
}
649
650
if (!defined('WFWAF_LOG_PATH')) {
656
if (!is_dir(WFWAF_LOG_PATH)) {
657
@mkdir(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
658
@chmod(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
659
+ wfWAFWordPress::writeHtaccess();
660
}
661
662
wfWAF::setSharedStorageEngine(new wfWAFStorageFile(WFWAF_LOG_PATH . 'attack-data.php', WFWAF_LOG_PATH . 'ips.php', WFWAF_LOG_PATH . 'config.php', WFWAF_LOG_PATH . 'wafRules.rules'));
wordfence.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Wordfence Security
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
Author: Wordfence
7
- Version: 7.1.16
8
Author URI: http://www.wordfence.com/
9
Network: true
10
*/
@@ -14,8 +14,8 @@ if(defined('WP_INSTALLING') && WP_INSTALLING){
14
if (!defined('ABSPATH')) {
15
exit;
16
}
17
- define('WORDFENCE_VERSION', '7.1.16');
18
- define('WORDFENCE_BUILD_NUMBER', '1539704326');
19
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
20
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
21
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
Author: Wordfence
7
+ Version: 7.1.17
8
Author URI: http://www.wordfence.com/
9
Network: true
10
*/
14
if (!defined('ABSPATH')) {
15
exit;
16
}
17
+ define('WORDFENCE_VERSION', '7.1.17');
18
+ define('WORDFENCE_BUILD_NUMBER', '1541524007');
19
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
20
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
21