Version Description
- Improvement: Now performing malware scanning on all uploaded files in real-time.
- Improvement: Added Web Application Firewall activity to Wordfence summary email.
- Fix: Now using 503 response code in the page displayed when an IP is locked out.
- Fix:
wflogs
directory is now correctly removed on uninstall. - Fix: Fixed recently introduced bug which caused the Whitelisted 404 URLs feature to no longer work.
- Fix: Added try/catch to uncaught exception thrown when pinging the API key.
- Improvement: Improved performance of the Live Traffic page in Firefox.
- Improvement: Updated GeoIP database.
Download this release
Release Info
Developer | wfmatt |
Plugin | ![]() |
Version | 6.1.16 |
Comparing to | |
See all releases |
Code changes from version 6.1.15 to 6.1.16
- js/admin.js +10 -0
- lib/GeoIP.dat +0 -0
- lib/GeoIPv6.dat +0 -0
- lib/menu_options.php +25 -4
- lib/wfActivityReport.php +119 -18
- lib/wfConfig.php +7 -3
- lib/wfLockedOut.php +6 -1
- lib/wfLog.php +1 -1
- lib/wfScanEngine.php +3 -1
- lib/wfUpdateCheck.php +11 -6
- lib/wfUtils.php +20 -0
- lib/wordfenceClass.php +151 -38
- lib/wordfenceScanner.php +9 -0
- readme.txt +12 -2
- vendor/wordfence/wf-waf/src/init.php +2 -2
- vendor/wordfence/wf-waf/src/lib/rules.php +37 -0
- vendor/wordfence/wf-waf/src/lib/utils.php +19 -0
- vendor/wordfence/wf-waf/src/lib/waf.php +99 -0
- views/reports/activity-report-email-inline.php +48 -2
- waf/bootstrap.php +6 -0
- wordfence.php +2 -2
js/admin.js
CHANGED
@@ -2463,6 +2463,16 @@
|
|
2463 |
var self = this;
|
2464 |
jQuery('.wfTimeAgo-timestamp').each(function(idx, elem) {
|
2465 |
var el = jQuery(elem);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2466 |
var timestamp = el.data('wfctime');
|
2467 |
if (!timestamp) {
|
2468 |
timestamp = el.attr('data-timestamp');
|
2463 |
var self = this;
|
2464 |
jQuery('.wfTimeAgo-timestamp').each(function(idx, elem) {
|
2465 |
var el = jQuery(elem);
|
2466 |
+
var testEl = el;
|
2467 |
+
if (typeof jQuery === "function" && testEl instanceof jQuery) {
|
2468 |
+
testEl = testEl[0];
|
2469 |
+
}
|
2470 |
+
|
2471 |
+
var rect = testEl.getBoundingClientRect();
|
2472 |
+
if (!(rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth))) {
|
2473 |
+
return;
|
2474 |
+
}
|
2475 |
+
|
2476 |
var timestamp = el.data('wfctime');
|
2477 |
if (!timestamp) {
|
2478 |
timestamp = el.attr('data-timestamp');
|
lib/GeoIP.dat
CHANGED
Binary file
|
lib/GeoIPv6.dat
CHANGED
Binary file
|
lib/menu_options.php
CHANGED
@@ -299,6 +299,11 @@ $w = new wfConfig();
|
|
299 |
<td><input type="checkbox" id="alertOn_nonAdminLogin" class="wfConfigElem"
|
300 |
name="alertOn_nonAdminLogin" value="1" <?php $w->cb( 'alertOn_nonAdminLogin' ); ?>/></td>
|
301 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
302 |
<tr>
|
303 |
<th>Maximum email alerts to send per hour</th>
|
304 |
<td> <input type="text" id="alert_maxHourly" name="alert_maxHourly"
|
@@ -324,8 +329,8 @@ $w = new wfConfig();
|
|
324 |
<th>Email summary frequency:</th>
|
325 |
<td>
|
326 |
<select id="email_summary_interval" class="wfConfigElem" name="email_summary_interval">
|
|
|
327 |
<option value="weekly"<?php $w->sel( 'email_summary_interval', 'weekly' ); ?>>Once a week</option>
|
328 |
-
<option value="biweekly"<?php $w->sel( 'email_summary_interval', 'biweekly' ); ?>>Once every 2 weeks</option>
|
329 |
<option value="monthly"<?php $w->sel( 'email_summary_interval', 'monthly' ); ?>>Once a month</option>
|
330 |
</select>
|
331 |
</td>
|
@@ -824,7 +829,7 @@ $w = new wfConfig();
|
|
824 |
</td>
|
825 |
</tr>
|
826 |
<tr>
|
827 |
-
<th>Immediately block the IP of users who try to sign in as these usernames<a
|
828 |
href="http://docs.wordfence.com/en/Wordfence_options#Immediately_block_the_IP_of_users_who_try_to_sign_in_as_these_usernames"
|
829 |
target="_blank" class="wfhelp"></a></th>
|
830 |
<td>
|
@@ -844,7 +849,7 @@ $w = new wfConfig();
|
|
844 |
</tr>
|
845 |
|
846 |
<tr>
|
847 |
-
<th>Whitelisted IP addresses that bypass all rules:<a
|
848 |
href="http://docs.wordfence.com/en/Wordfence_options#Whitelisted_IP_addresses_that_bypass_all_rules"
|
849 |
target="_blank" class="wfhelp"></a></th>
|
850 |
<td><textarea name="whitelisted" id="whitelisted" cols="40" rows="4"><?php echo esc_html(preg_replace('/,/', "\n", $w->get('whitelisted'))); ?></textarea></td>
|
@@ -857,7 +862,7 @@ $w = new wfConfig();
|
|
857 |
</tr>
|
858 |
|
859 |
<tr>
|
860 |
-
<th>Immediately block IPs that access these URLs:<a
|
861 |
href="http://docs.wordfence.com/en/Wordfence_options#Immediately_block_IP.27s_that_access_these_URLs"
|
862 |
target="_blank" class="wfhelp"></a></th>
|
863 |
<td><textarea type="text" name="bannedURLs" id="bannedURLs" cols="40" rows="4"><?php echo esc_html(preg_replace('/,/', "\n", $w->get('bannedURLs'))); ?></textarea></td>
|
@@ -879,6 +884,22 @@ $w = new wfConfig();
|
|
879 |
the throttling rules used to limit crawlers.
|
880 |
<br/><br/></th>
|
881 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
882 |
|
883 |
<tr>
|
884 |
<th>Hide WordPress version<a
|
299 |
<td><input type="checkbox" id="alertOn_nonAdminLogin" class="wfConfigElem"
|
300 |
name="alertOn_nonAdminLogin" value="1" <?php $w->cb( 'alertOn_nonAdminLogin' ); ?>/></td>
|
301 |
</tr>
|
302 |
+
<tr>
|
303 |
+
<th>Alert me when there's a large increase in attacks detected on my site</th>
|
304 |
+
<td><input type="checkbox" id="wafAlertOnAttacks" class="wfConfigElem"
|
305 |
+
name="wafAlertOnAttacks" value="1" <?php $w->cb( 'wafAlertOnAttacks' ); ?>/></td>
|
306 |
+
</tr>
|
307 |
<tr>
|
308 |
<th>Maximum email alerts to send per hour</th>
|
309 |
<td> <input type="text" id="alert_maxHourly" name="alert_maxHourly"
|
329 |
<th>Email summary frequency:</th>
|
330 |
<td>
|
331 |
<select id="email_summary_interval" class="wfConfigElem" name="email_summary_interval">
|
332 |
+
<option value="daily"<?php $w->sel( 'email_summary_interval', 'daily' ); ?>>Once a day</option>
|
333 |
<option value="weekly"<?php $w->sel( 'email_summary_interval', 'weekly' ); ?>>Once a week</option>
|
|
|
334 |
<option value="monthly"<?php $w->sel( 'email_summary_interval', 'monthly' ); ?>>Once a month</option>
|
335 |
</select>
|
336 |
</td>
|
829 |
</td>
|
830 |
</tr>
|
831 |
<tr>
|
832 |
+
<th style="vertical-align: top;">Immediately block the IP of users who try to sign in as these usernames<a
|
833 |
href="http://docs.wordfence.com/en/Wordfence_options#Immediately_block_the_IP_of_users_who_try_to_sign_in_as_these_usernames"
|
834 |
target="_blank" class="wfhelp"></a></th>
|
835 |
<td>
|
849 |
</tr>
|
850 |
|
851 |
<tr>
|
852 |
+
<th style="vertical-align: top;">Whitelisted IP addresses that bypass all rules:<a
|
853 |
href="http://docs.wordfence.com/en/Wordfence_options#Whitelisted_IP_addresses_that_bypass_all_rules"
|
854 |
target="_blank" class="wfhelp"></a></th>
|
855 |
<td><textarea name="whitelisted" id="whitelisted" cols="40" rows="4"><?php echo esc_html(preg_replace('/,/', "\n", $w->get('whitelisted'))); ?></textarea></td>
|
862 |
</tr>
|
863 |
|
864 |
<tr>
|
865 |
+
<th style="vertical-align: top;">Immediately block IPs that access these URLs:<a
|
866 |
href="http://docs.wordfence.com/en/Wordfence_options#Immediately_block_IP.27s_that_access_these_URLs"
|
867 |
target="_blank" class="wfhelp"></a></th>
|
868 |
<td><textarea type="text" name="bannedURLs" id="bannedURLs" cols="40" rows="4"><?php echo esc_html(preg_replace('/,/', "\n", $w->get('bannedURLs'))); ?></textarea></td>
|
884 |
the throttling rules used to limit crawlers.
|
885 |
<br/><br/></th>
|
886 |
</tr>
|
887 |
+
|
888 |
+
<tr>
|
889 |
+
<th style="vertical-align: top;">Whitelisted IP addresses for Wordfence Web Application Firewall alerting:</th>
|
890 |
+
<td><textarea name="wafAlertWhitelist" id="wafAlertWhitelist" cols="40" rows="4"><?php echo esc_html(preg_replace('/,/', "\n", $w->get('wafAlertWhitelist'))); ?></textarea></td>
|
891 |
+
</tr>
|
892 |
+
<tr>
|
893 |
+
<th colspan="2" style="color: #999;">Whitelisted IPs must be separated by commas or placed on separate lines. These addresses will be ignored from any alerts about increased attacks and can be used to ignore things like standalone website security scanners.<br/><br/></th>
|
894 |
+
</tr>
|
895 |
+
<tr class="hidden">
|
896 |
+
<th style="vertical-align: top;">Minimum number of blocked attacks before sending an alert</th>
|
897 |
+
<td><input type="text" name="wafAlertThreshold" id=""wafAlertThreshold" value="<?php $w->f( 'wafAlertThreshold' ); ?>"></td>
|
898 |
+
</tr>
|
899 |
+
<tr class="hidden">
|
900 |
+
<th style="vertical-align: top;">Number of seconds to count the attacks over</th>
|
901 |
+
<td><input type="text" name="wafAlertInterval" id=""wafAlertInterval" value="<?php $w->f( 'wafAlertInterval' ); ?>"></td>
|
902 |
+
</tr>
|
903 |
|
904 |
<tr>
|
905 |
<th>Hide WordPress version<a
|
lib/wfActivityReport.php
CHANGED
@@ -96,18 +96,18 @@ class wfActivityReport {
|
|
96 |
$end_time = 0;
|
97 |
|
98 |
switch ($interval) {
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
// Send a report 4pm every Monday
|
100 |
case 'weekly':
|
101 |
$start_time = gmmktime(16, 0, 0, $month, $day_of_month - $day + 1, $year) + (-$offset * 60 * 60);
|
102 |
$end_time = $start_time + (86400 * 7);
|
103 |
break;
|
104 |
|
105 |
-
// Send a report 4pm every other Monday
|
106 |
-
case 'biweekly':
|
107 |
-
$start_time = gmmktime(16, 0, 0, $month, $day_of_month - $day + 1, $year) + (-$offset * 60 * 60);
|
108 |
-
$end_time = $start_time + (86400 * 14);
|
109 |
-
break;
|
110 |
-
|
111 |
// Send a report at 4pm the first of every month
|
112 |
case 'monthly':
|
113 |
$start_time = gmmktime(16, 0, 0, $month, 1, $year) + (-$offset * 60 * 60);
|
@@ -139,8 +139,8 @@ class wfActivityReport {
|
|
139 |
// weekly
|
140 |
$from = $time - (86400 * 7);
|
141 |
switch ($interval) {
|
142 |
-
case '
|
143 |
-
$from = $time -
|
144 |
break;
|
145 |
|
146 |
// Send a report at 4pm the first of every month
|
@@ -157,13 +157,17 @@ class wfActivityReport {
|
|
157 |
*/
|
158 |
public function getFullReport() {
|
159 |
$start_time = microtime(true);
|
|
|
|
|
160 |
return array(
|
161 |
-
'top_ips_blocked'
|
162 |
-
'top_countries_blocked'
|
163 |
-
'top_failed_logins'
|
164 |
-
'
|
165 |
-
'
|
166 |
-
'
|
|
|
|
|
167 |
);
|
168 |
}
|
169 |
|
@@ -243,8 +247,8 @@ SQL
|
|
243 |
public function getTopFailedLogins($limit = 10) {
|
244 |
$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day))';
|
245 |
switch (wfConfig::get('email_summary_interval', 'weekly')) {
|
246 |
-
case '
|
247 |
-
$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval
|
248 |
break;
|
249 |
case 'monthly':
|
250 |
$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month))';
|
@@ -316,6 +320,19 @@ SQL
|
|
316 |
}
|
317 |
return false;
|
318 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
319 |
|
320 |
/**
|
321 |
* Returns list of files modified within given timeframe.
|
@@ -342,8 +359,8 @@ SQL
|
|
342 |
// default to weekly
|
343 |
$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day)) / 86400)';
|
344 |
switch (wfConfig::get('email_summary_interval', 'weekly')) {
|
345 |
-
case '
|
346 |
-
$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval
|
347 |
break;
|
348 |
case 'monthly':
|
349 |
$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month)) / 86400)';
|
@@ -466,6 +483,77 @@ SQL
|
|
466 |
}
|
467 |
}
|
468 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
469 |
|
470 |
class wfRecentlyModifiedFiles extends wfDirectoryIterator {
|
471 |
|
@@ -581,4 +669,17 @@ class wfActivityReportView extends wfView {
|
|
581 |
}
|
582 |
return date_i18n('F j, Y g:ia', $unix_time);
|
583 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
584 |
}
|
96 |
$end_time = 0;
|
97 |
|
98 |
switch ($interval) {
|
99 |
+
// Send a report 4pm every day
|
100 |
+
case 'daily':
|
101 |
+
$start_time = gmmktime(16, 0, 0, $month, $day_of_month, $year) + (-$offset * 60 * 60);
|
102 |
+
$end_time = $start_time + 86400;
|
103 |
+
break;
|
104 |
+
|
105 |
// Send a report 4pm every Monday
|
106 |
case 'weekly':
|
107 |
$start_time = gmmktime(16, 0, 0, $month, $day_of_month - $day + 1, $year) + (-$offset * 60 * 60);
|
108 |
$end_time = $start_time + (86400 * 7);
|
109 |
break;
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
// Send a report at 4pm the first of every month
|
112 |
case 'monthly':
|
113 |
$start_time = gmmktime(16, 0, 0, $month, 1, $year) + (-$offset * 60 * 60);
|
139 |
// weekly
|
140 |
$from = $time - (86400 * 7);
|
141 |
switch ($interval) {
|
142 |
+
case 'daily':
|
143 |
+
$from = $time - 86400;
|
144 |
break;
|
145 |
|
146 |
// Send a report at 4pm the first of every month
|
157 |
*/
|
158 |
public function getFullReport() {
|
159 |
$start_time = microtime(true);
|
160 |
+
$remainder = 0;
|
161 |
+
$recent_firewall_activity = $this->getRecentFirewallActivity($this->limit, $remainder);
|
162 |
return array(
|
163 |
+
'top_ips_blocked' => $this->getTopIPsBlocked($this->limit),
|
164 |
+
'top_countries_blocked' => $this->getTopCountriesBlocked($this->limit),
|
165 |
+
'top_failed_logins' => $this->getTopFailedLogins($this->limit),
|
166 |
+
'recent_firewall_activity' => $recent_firewall_activity,
|
167 |
+
'omitted_firewall_activity'=> $remainder,
|
168 |
+
'recently_modified_files' => $this->getRecentFilesModified($this->limit),
|
169 |
+
'updates_needed' => $this->getUpdatesNeeded(),
|
170 |
+
'microseconds' => microtime(true) - $start_time,
|
171 |
);
|
172 |
}
|
173 |
|
247 |
public function getTopFailedLogins($limit = 10) {
|
248 |
$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day))';
|
249 |
switch (wfConfig::get('email_summary_interval', 'weekly')) {
|
250 |
+
case 'daily':
|
251 |
+
$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 day))';
|
252 |
break;
|
253 |
case 'monthly':
|
254 |
$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month))';
|
320 |
}
|
321 |
return false;
|
322 |
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Returns list of firewall activity up to $limit number of entries.
|
326 |
+
*
|
327 |
+
* @param int $limit Max events to return in results
|
328 |
+
* @return array
|
329 |
+
*/
|
330 |
+
public function getRecentFirewallActivity($limit = 300, &$remainder) {
|
331 |
+
$dateRange = wfActivityReport::getReportDateRange();
|
332 |
+
$recent_firewall_activity = new wfRecentFirewallActivity(null, max(604800, $dateRange[1] - $dateRange[0]));
|
333 |
+
$recent_firewall_activity->run();
|
334 |
+
return $recent_firewall_activity->mostRecentActivity($limit, $remainder);
|
335 |
+
}
|
336 |
|
337 |
/**
|
338 |
* Returns list of files modified within given timeframe.
|
359 |
// default to weekly
|
360 |
$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day)) / 86400)';
|
361 |
switch (wfConfig::get('email_summary_interval', 'weekly')) {
|
362 |
+
case 'daily':
|
363 |
+
$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 day)) / 86400)';
|
364 |
break;
|
365 |
case 'monthly':
|
366 |
$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month)) / 86400)';
|
483 |
}
|
484 |
}
|
485 |
|
486 |
+
class wfRecentFirewallActivity {
|
487 |
+
private $activity = array();
|
488 |
+
|
489 |
+
private $max_fetch = 2000;
|
490 |
+
private $time_range = 604800;
|
491 |
+
|
492 |
+
public function __construct($max_fetch = null, $time_range = null) {
|
493 |
+
if ($max_fetch !== null) {
|
494 |
+
$this->max_fetch = $max_fetch;
|
495 |
+
}
|
496 |
+
|
497 |
+
if ($time_range !== null) {
|
498 |
+
$this->time_range = $time_range;
|
499 |
+
}
|
500 |
+
}
|
501 |
+
|
502 |
+
public function run() {
|
503 |
+
global $wpdb;
|
504 |
+
|
505 |
+
$results = $wpdb->get_results($wpdb->prepare(<<<SQL
|
506 |
+
SELECT attackLogTime, IP, URL, UA, actionDescription, actionData
|
507 |
+
FROM {$wpdb->prefix}wfHits
|
508 |
+
WHERE action = 'blocked:waf' AND attackLogTime > (UNIX_TIMESTAMP() - %d)
|
509 |
+
ORDER BY attackLogTime DESC
|
510 |
+
LIMIT %d
|
511 |
+
SQL
|
512 |
+
, $this->time_range, $this->max_fetch));
|
513 |
+
if ($results) {
|
514 |
+
foreach ($results as &$row) {
|
515 |
+
$row->longDescription = "Blocked for " . $row->actionDescription;
|
516 |
+
|
517 |
+
$actionData = json_decode($row->actionData, true);
|
518 |
+
if (!is_array($actionData) || !isset($actionData['paramKey']) || !isset($actionData['paramValue'])) {
|
519 |
+
continue;
|
520 |
+
}
|
521 |
+
|
522 |
+
$paramKey = base64_decode($actionData['paramKey']);
|
523 |
+
$paramValue = base64_decode($actionData['paramValue']);
|
524 |
+
if (strlen($paramValue) > 100) {
|
525 |
+
$paramValue = substr($paramValue, 0, 100) . chr(2026);
|
526 |
+
}
|
527 |
+
|
528 |
+
if (preg_match('/([a-z0-9_]+\.[a-z0-9_]+)(?:\[(.+?)\](.*))?/i', $paramKey, $matches)) {
|
529 |
+
switch ($matches[1]) {
|
530 |
+
case 'request.queryString':
|
531 |
+
$row->longDescription = "Blocked for " . $row->actionDescription . ' in query string: ' . $matches[2] . '=' . $paramValue;
|
532 |
+
break;
|
533 |
+
case 'request.body':
|
534 |
+
$row->longDescription = "Blocked for " . $row->actionDescription . ' in POST body: ' . $matches[2] . '=' . $paramValue;
|
535 |
+
break;
|
536 |
+
case 'request.cookie':
|
537 |
+
$row->longDescription = "Blocked for " . $row->actionDescription . ' in cookie: ' . $matches[2] . '=' . $paramValue;
|
538 |
+
break;
|
539 |
+
case 'request.fileNames':
|
540 |
+
$row->longDescription = "Blocked for a " . $row->actionDescription . ' in file: ' . $matches[2] . '=' . $paramValue;
|
541 |
+
break;
|
542 |
+
}
|
543 |
+
}
|
544 |
+
}
|
545 |
+
}
|
546 |
+
|
547 |
+
$this->activity = $results;
|
548 |
+
}
|
549 |
+
|
550 |
+
public function mostRecentActivity($limit, &$remainder = null) {
|
551 |
+
if ($remainder !== null) {
|
552 |
+
$remainder = count($this->activity) - $limit;
|
553 |
+
}
|
554 |
+
return array_slice($this->activity, 0, $limit);
|
555 |
+
}
|
556 |
+
}
|
557 |
|
558 |
class wfRecentlyModifiedFiles extends wfDirectoryIterator {
|
559 |
|
669 |
}
|
670 |
return date_i18n('F j, Y g:ia', $unix_time);
|
671 |
}
|
672 |
+
|
673 |
+
public function attackTime($unix_time = null) {
|
674 |
+
if ($unix_time === null) {
|
675 |
+
$unix_time = time();
|
676 |
+
}
|
677 |
+
return date_i18n('F j, Y', $unix_time) . "<br>" . date_i18n('g:ia', $unix_time);
|
678 |
+
}
|
679 |
+
|
680 |
+
public function displayIP($binaryIP) {
|
681 |
+
$readableIP = wfUtils::inet_ntop($binaryIP);
|
682 |
+
$country = wfUtils::countryCode2Name(wfUtils::IP2Country($readableIP));
|
683 |
+
return "{$readableIP} (" . ($country ? $country : 'Unknown') . ")";
|
684 |
+
}
|
685 |
}
|
lib/wfConfig.php
CHANGED
@@ -81,6 +81,7 @@ class wfConfig {
|
|
81 |
'ssl_verify' => array('value' => true, 'autoload' => self::AUTOLOAD),
|
82 |
'ajaxWatcherDisabled_front' => array('value' => false, 'autoload' => self::AUTOLOAD),
|
83 |
'ajaxWatcherDisabled_admin' => array('value' => false, 'autoload' => self::AUTOLOAD),
|
|
|
84 |
),
|
85 |
"otherParams" => array(
|
86 |
"scan_include_extra" => "",
|
@@ -106,9 +107,12 @@ class wfConfig {
|
|
106 |
'maxScanHits' => "DISABLED",
|
107 |
'maxScanHits_action' => "throttle",
|
108 |
'blockedTime' => "300",
|
109 |
-
'email_summary_interval' => '
|
110 |
'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
|
111 |
-
'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png",
|
|
|
|
|
|
|
112 |
)
|
113 |
);
|
114 |
public static $serializedOptions = array('lastAdminLogin', 'scanSched', 'emailedIssuesList', 'wf_summaryItems', 'adminUserList', 'twoFactorUsers', 'alertFreqTrack', 'wfStatusStartMsgs');
|
@@ -264,7 +268,7 @@ class wfConfig {
|
|
264 |
return;
|
265 |
}
|
266 |
|
267 |
-
if (($key == 'apiKey' || $key == 'isPaid') && wfWAF::getInstance() && !WFWAF_SUBDIRECTORY_INSTALL) {
|
268 |
try {
|
269 |
wfWAF::getInstance()->getStorageEngine()->setConfig($key, $val);
|
270 |
} catch (wfWAFStorageFileException $e) {
|
81 |
'ssl_verify' => array('value' => true, 'autoload' => self::AUTOLOAD),
|
82 |
'ajaxWatcherDisabled_front' => array('value' => false, 'autoload' => self::AUTOLOAD),
|
83 |
'ajaxWatcherDisabled_admin' => array('value' => false, 'autoload' => self::AUTOLOAD),
|
84 |
+
'wafAlertOnAttacks' => array('value' => true, 'autoload' => self::AUTOLOAD),
|
85 |
),
|
86 |
"otherParams" => array(
|
87 |
"scan_include_extra" => "",
|
107 |
'maxScanHits' => "DISABLED",
|
108 |
'maxScanHits_action' => "throttle",
|
109 |
'blockedTime' => "300",
|
110 |
+
'email_summary_interval' => 'weekly',
|
111 |
'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
|
112 |
+
'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png\n/browserconfig.xml",
|
113 |
+
'wafAlertWhitelist' => '',
|
114 |
+
'wafAlertInterval' => 600,
|
115 |
+
'wafAlertThreshold' => 100,
|
116 |
)
|
117 |
);
|
118 |
public static $serializedOptions = array('lastAdminLogin', 'scanSched', 'emailedIssuesList', 'wf_summaryItems', 'adminUserList', 'twoFactorUsers', 'alertFreqTrack', 'wfStatusStartMsgs');
|
268 |
return;
|
269 |
}
|
270 |
|
271 |
+
if (($key == 'apiKey' || $key == 'isPaid' || $key == 'other_WFNet') && wfWAF::getInstance() && !WFWAF_SUBDIRECTORY_INSTALL) {
|
272 |
try {
|
273 |
wfWAF::getInstance()->getStorageEngine()->setConfig($key, $val);
|
274 |
} catch (wfWAFStorageFileException $e) {
|
lib/wfLockedOut.php
CHANGED
@@ -1,4 +1,9 @@
|
|
1 |
-
<?php
|
|
|
|
|
|
|
|
|
|
|
2 |
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
|
3 |
<head>
|
4 |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
1 |
+
<?php
|
2 |
+
wfUtils::doNotCache();
|
3 |
+
header('HTTP/1.1 503 Service Temporarily Unavailable');
|
4 |
+
header('Status: 503 Service Temporarily Unavailable');
|
5 |
+
?>
|
6 |
+
<!DOCTYPE html>
|
7 |
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
|
8 |
<head>
|
9 |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
lib/wfLog.php
CHANGED
@@ -203,7 +203,7 @@ class wfLog {
|
|
203 |
if ($type == '404') {
|
204 |
$allowed404s = wfConfig::get('allowed404s');
|
205 |
if (is_string($allowed404s)) {
|
206 |
-
$allowed404s = array_filter(
|
207 |
$allowed404sPattern = '';
|
208 |
foreach ($allowed404s as $allowed404) {
|
209 |
$allowed404sPattern .= preg_replace('/\\\\\*/', '.*?', preg_quote($allowed404, '/')) . '|';
|
203 |
if ($type == '404') {
|
204 |
$allowed404s = wfConfig::get('allowed404s');
|
205 |
if (is_string($allowed404s)) {
|
206 |
+
$allowed404s = array_filter(preg_split("/[\r\n]+/", $allowed404s));
|
207 |
$allowed404sPattern = '';
|
208 |
foreach ($allowed404s as $allowed404) {
|
209 |
$allowed404sPattern .= preg_replace('/\\\\\*/', '.*?', preg_quote($allowed404, '/')) . '|';
|
lib/wfScanEngine.php
CHANGED
@@ -158,7 +158,9 @@ class wfScanEngine {
|
|
158 |
$this->i->emailNewIssues();
|
159 |
}
|
160 |
public function submitMetrics() {
|
161 |
-
|
|
|
|
|
162 |
}
|
163 |
private function doScan(){
|
164 |
while(sizeof($this->jobList) > 0){
|
158 |
$this->i->emailNewIssues();
|
159 |
}
|
160 |
public function submitMetrics() {
|
161 |
+
if (wfConfig::get('other_WFNet', true)) {
|
162 |
+
$this->api->call('record_scan_metrics', array(), array('metrics' => $this->metrics));
|
163 |
+
}
|
164 |
}
|
165 |
private function doScan(){
|
166 |
while(sizeof($this->jobList) > 0){
|
lib/wfUpdateCheck.php
CHANGED
@@ -92,12 +92,17 @@ class wfUpdateCheck {
|
|
92 |
|
93 |
//Check the vulnerability database
|
94 |
if (isset($valsArray['slug']) && isset($valsArray['new_version'])) {
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
|
|
|
101 |
}
|
102 |
else {
|
103 |
$data['vulnerabilityPatched'] = false;
|
92 |
|
93 |
//Check the vulnerability database
|
94 |
if (isset($valsArray['slug']) && isset($valsArray['new_version'])) {
|
95 |
+
try {
|
96 |
+
$result = $this->api->call('plugin_vulnerability_check', array(), array(
|
97 |
+
'slug' => $valsArray['slug'],
|
98 |
+
'fromVersion' => $data['Version'],
|
99 |
+
'toVersion' => $valsArray['new_version'],
|
100 |
+
));
|
101 |
+
$data['vulnerabilityPatched'] = isset($result['vulnerable']) && $result['vulnerable'];
|
102 |
+
}
|
103 |
+
catch(Exception $e){
|
104 |
+
$data['vulnerabilityPatched'] = false;
|
105 |
+
}
|
106 |
}
|
107 |
else {
|
108 |
$data['vulnerabilityPatched'] = false;
|
lib/wfUtils.php
CHANGED
@@ -38,6 +38,26 @@ class wfUtils {
|
|
38 |
}
|
39 |
}
|
40 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
public static function pluralize($m1, $t1, $m2 = false, $t2 = false) {
|
42 |
if($m1 != 1) {
|
43 |
$t1 = $t1 . 's';
|
38 |
}
|
39 |
}
|
40 |
}
|
41 |
+
public static function makeDuration($secs) {
|
42 |
+
$months = floor($secs / (86400 * 30));
|
43 |
+
$days = floor($secs / 86400);
|
44 |
+
$hours = floor($secs / 3600);
|
45 |
+
$minutes = floor($secs / 60);
|
46 |
+
if($months) {
|
47 |
+
$days -= $months * 30;
|
48 |
+
return self::pluralize($months, 'month', $days, 'day');
|
49 |
+
} else if($days) {
|
50 |
+
$hours -= $days * 24;
|
51 |
+
return self::pluralize($days, 'day', $hours, 'hour');
|
52 |
+
} else if($hours) {
|
53 |
+
$minutes -= $hours * 60;
|
54 |
+
return self::pluralize($hours, 'hour', $minutes, 'minute');
|
55 |
+
} else if($minutes) {
|
56 |
+
return self::pluralize($minutes, 'minute');
|
57 |
+
} else {
|
58 |
+
return self::pluralize($secs, 'second');
|
59 |
+
}
|
60 |
+
}
|
61 |
public static function pluralize($m1, $t1, $m2 = false, $t2 = false) {
|
62 |
if($m1 != 1) {
|
63 |
$t1 = $t1 . 's';
|
lib/wordfenceClass.php
CHANGED
@@ -170,45 +170,50 @@ class wordfence {
|
|
170 |
}
|
171 |
public static function dailyCron(){
|
172 |
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
173 |
-
|
174 |
-
|
175 |
-
$
|
176 |
-
|
177 |
-
|
178 |
-
if ($
|
179 |
-
|
180 |
-
|
181 |
-
wfConfig::
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
if($keyExpDays <= 15 && $keyExpDays
|
194 |
-
wfConfig::
|
195 |
-
|
196 |
-
|
197 |
-
wfConfig::
|
198 |
-
|
199 |
-
|
200 |
-
wfConfig::
|
201 |
-
|
202 |
-
|
203 |
-
wfConfig::
|
204 |
-
|
|
|
|
|
|
|
|
|
|
|
205 |
}
|
206 |
-
} else if($keyIsExpired && (! wfConfig::get('keyExpFinalSent')) ){
|
207 |
-
wfConfig::set('keyExpFinalSent', 1);
|
208 |
-
self::keyAlert("Your Wordfence Premium API Key has Expired!");
|
209 |
}
|
210 |
}
|
211 |
}
|
|
|
|
|
|
|
212 |
|
213 |
$wfdb = new wfDB();
|
214 |
global $wpdb; $p = $wpdb->base_prefix;
|
@@ -518,6 +523,23 @@ SQL
|
|
518 |
if (!$hasAttackLogTimeIndex) {
|
519 |
$wpdb->query("ALTER TABLE $hitsTable ADD INDEX `attackLogTime` (`attackLogTime`)");
|
520 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
521 |
|
522 |
//Must be the final line
|
523 |
}
|
@@ -1038,6 +1060,7 @@ SQL
|
|
1038 |
'homeURL' => home_url(),
|
1039 |
'whitelistedIPs' => (string) wfConfig::get('whitelisted'),
|
1040 |
'howGetIPs' => (string) wfConfig::get('howGetIPs'),
|
|
|
1041 |
);
|
1042 |
foreach ($configDefaults as $key => $value) {
|
1043 |
$waf->getStorageEngine()->setConfig($key, $value);
|
@@ -5262,8 +5285,8 @@ HTML
|
|
5262 |
wp_enqueue_style('wordfence-activity-report-widget', wfUtils::getBaseURL() . 'css/activity-report-widget.css', '', WORDFENCE_VERSION);
|
5263 |
$report_date_range = 'week';
|
5264 |
switch (wfConfig::get('email_summary_interval')) {
|
5265 |
-
case '
|
5266 |
-
$report_date_range = '
|
5267 |
break;
|
5268 |
|
5269 |
case 'monthly':
|
@@ -5887,7 +5910,94 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
|
|
5887 |
if ($waf->getStorageEngine()->getConfig('attackDataKey', false) === false) {
|
5888 |
$waf->getStorageEngine()->setConfig('attackDataKey', mt_rand(0, 0xfff));
|
5889 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5890 |
|
|
|
|
|
|
|
|
|
|
|
|
|
5891 |
$limit = 500;
|
5892 |
$lastSendTime = wfConfig::get('lastAttackDataSendTime');
|
5893 |
$attackData = $wpdb->get_results($wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$wpdb->base_prefix}wfHits
|
@@ -5896,7 +6006,7 @@ AND attackLogTime > %.6f
|
|
5896 |
LIMIT %d", $lastSendTime, $limit));
|
5897 |
$totalRows = $wpdb->get_var('SELECT FOUND_ROWS()');
|
5898 |
|
5899 |
-
if ($attackData) {
|
5900 |
$response = wp_remote_get(sprintf(WFWAF_API_URL_SEC . "waf-rules/%d.txt", $waf->getStorageEngine()->getConfig('attackDataKey')));
|
5901 |
|
5902 |
if (!is_wp_error($response)) {
|
@@ -5971,6 +6081,9 @@ LIMIT %d", $lastSendTime, $limit));
|
|
5971 |
self::scheduleSendAttackData(time() + 7200);
|
5972 |
}
|
5973 |
}
|
|
|
|
|
|
|
5974 |
|
5975 |
self::trimWfHits();
|
5976 |
}
|
170 |
}
|
171 |
public static function dailyCron(){
|
172 |
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
173 |
+
try {
|
174 |
+
$keyData = $api->call('ping_api_key');
|
175 |
+
if(isset($keyData['_isPaidKey']) && $keyData['_isPaidKey']){
|
176 |
+
$keyExpDays = $keyData['_keyExpDays'];
|
177 |
+
$keyIsExpired = $keyData['_expired'];
|
178 |
+
if (!empty($keyData['_autoRenew'])) {
|
179 |
+
if ($keyExpDays > 12) {
|
180 |
+
wfConfig::set('keyAutoRenew10Sent', '');
|
181 |
+
} else if ($keyExpDays <= 12 && $keyExpDays > 0 && !wfConfig::get('keyAutoRenew10Sent')) {
|
182 |
+
wfConfig::set('keyAutoRenew10Sent', 1);
|
183 |
+
$email = "Your Premium Wordfence API Key is set to auto-renew in 10 days.";
|
184 |
+
self::alert($email, "$email To update your API key settings please visit http://www.wordfence.com/zz9/dashboard", false);
|
185 |
+
}
|
186 |
+
} else {
|
187 |
+
if($keyExpDays > 15){
|
188 |
+
wfConfig::set('keyExp15Sent', '');
|
189 |
+
wfConfig::set('keyExp7Sent', '');
|
190 |
+
wfConfig::set('keyExp2Sent', '');
|
191 |
+
wfConfig::set('keyExp1Sent', '');
|
192 |
+
wfConfig::set('keyExpFinalSent', '');
|
193 |
+
} else if($keyExpDays <= 15 && $keyExpDays > 0){
|
194 |
+
if($keyExpDays <= 15 && $keyExpDays >= 11 && (! wfConfig::get('keyExp15Sent'))){
|
195 |
+
wfConfig::set('keyExp15Sent', 1);
|
196 |
+
self::keyAlert("Your Premium Wordfence API Key expires in less than 2 weeks.");
|
197 |
+
} else if($keyExpDays <= 7 && $keyExpDays >= 4 && (! wfConfig::get('keyExp7Sent'))){
|
198 |
+
wfConfig::set('keyExp7Sent', 1);
|
199 |
+
self::keyAlert("Your Premium Wordfence API Key expires in less than a week.");
|
200 |
+
} else if($keyExpDays == 2 && (! wfConfig::get('keyExp2Sent'))){
|
201 |
+
wfConfig::set('keyExp2Sent', 1);
|
202 |
+
self::keyAlert("Your Premium Wordfence API Key expires in 2 days.");
|
203 |
+
} else if($keyExpDays == 1 && (! wfConfig::get('keyExp1Sent'))){
|
204 |
+
wfConfig::set('keyExp1Sent', 1);
|
205 |
+
self::keyAlert("Your Premium Wordfence API Key expires in 1 day.");
|
206 |
+
}
|
207 |
+
} else if($keyIsExpired && (! wfConfig::get('keyExpFinalSent')) ){
|
208 |
+
wfConfig::set('keyExpFinalSent', 1);
|
209 |
+
self::keyAlert("Your Wordfence Premium API Key has Expired!");
|
210 |
}
|
|
|
|
|
|
|
211 |
}
|
212 |
}
|
213 |
}
|
214 |
+
catch(Exception $e){
|
215 |
+
wordfence::status(4, 'error', "Could not verify Wordfence API Key: " . $e->getMessage());
|
216 |
+
}
|
217 |
|
218 |
$wfdb = new wfDB();
|
219 |
global $wpdb; $p = $wpdb->base_prefix;
|
523 |
if (!$hasAttackLogTimeIndex) {
|
524 |
$wpdb->query("ALTER TABLE $hitsTable ADD INDEX `attackLogTime` (`attackLogTime`)");
|
525 |
}
|
526 |
+
|
527 |
+
//6.1.16
|
528 |
+
$allowed404s = wfConfig::get('allowed404s', '');
|
529 |
+
if (!wfConfig::get('allowed404s6116Migration', false)) {
|
530 |
+
if (!preg_match('/(?:^|\b)browserconfig\.xml(?:\b|$)/i', $allowed404s)) {
|
531 |
+
if (strlen($allowed404s) > 0) {
|
532 |
+
$allowed404s .= "\n";
|
533 |
+
}
|
534 |
+
$allowed404s .= "/browserconfig.xml";
|
535 |
+
wfConfig::set('allowed404s', $allowed404s);
|
536 |
+
}
|
537 |
+
|
538 |
+
wfConfig::set('allowed404s6116Migration', 1);
|
539 |
+
}
|
540 |
+
if (wfConfig::get('email_summary_interval') == 'biweekly') {
|
541 |
+
wfConfig::set('email_summary_interval', 'weekly');
|
542 |
+
}
|
543 |
|
544 |
//Must be the final line
|
545 |
}
|
1060 |
'homeURL' => home_url(),
|
1061 |
'whitelistedIPs' => (string) wfConfig::get('whitelisted'),
|
1062 |
'howGetIPs' => (string) wfConfig::get('howGetIPs'),
|
1063 |
+
'other_WFNet' => wfConfig::get('other_WFNet', true),
|
1064 |
);
|
1065 |
foreach ($configDefaults as $key => $value) {
|
1066 |
$waf->getStorageEngine()->setConfig($key, $value);
|
5285 |
wp_enqueue_style('wordfence-activity-report-widget', wfUtils::getBaseURL() . 'css/activity-report-widget.css', '', WORDFENCE_VERSION);
|
5286 |
$report_date_range = 'week';
|
5287 |
switch (wfConfig::get('email_summary_interval')) {
|
5288 |
+
case 'daily':
|
5289 |
+
$report_date_range = 'day';
|
5290 |
break;
|
5291 |
|
5292 |
case 'monthly':
|
5910 |
if ($waf->getStorageEngine()->getConfig('attackDataKey', false) === false) {
|
5911 |
$waf->getStorageEngine()->setConfig('attackDataKey', mt_rand(0, 0xfff));
|
5912 |
}
|
5913 |
+
|
5914 |
+
//Send alert email if needed
|
5915 |
+
if (wfConfig::get('wafAlertOnAttacks')) {
|
5916 |
+
$alertInterval = wfConfig::get('wafAlertInterval', 0);
|
5917 |
+
$cutoffTime = max(time() - $alertInterval, wfConfig::get('wafAlertLastSendTime'));
|
5918 |
+
$wafAlertWhitelist = wfConfig::get('wafAlertWhitelist', '');
|
5919 |
+
$wafAlertWhitelist = preg_split("/[,\r\n]+/", $wafAlertWhitelist);
|
5920 |
+
foreach ($wafAlertWhitelist as $index => &$entry) {
|
5921 |
+
$entry = trim($entry);
|
5922 |
+
if (!preg_match('/^(?:\d{1,3}(?:\.|$)){4}/', $entry) && !preg_match('/^((?:[\da-f]{1,4}(?::|)){0,8})(::)?((?:[\da-f]{1,4}(?::|)){0,8})$/i', $entry)) {
|
5923 |
+
unset($wafAlertWhitelist[$index]);
|
5924 |
+
continue;
|
5925 |
+
}
|
5926 |
+
|
5927 |
+
$packed = @wfUtils::inet_pton($entry);
|
5928 |
+
if ($packed === false) {
|
5929 |
+
unset($wafAlertWhitelist[$index]);
|
5930 |
+
continue;
|
5931 |
+
}
|
5932 |
+
$entry = bin2hex($packed);
|
5933 |
+
}
|
5934 |
+
$wafAlertWhitelist = array_filter($wafAlertWhitelist);
|
5935 |
+
$attackData = $wpdb->get_results($wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$wpdb->base_prefix}wfHits
|
5936 |
+
WHERE action = 'blocked:waf' " .
|
5937 |
+
(count($wafAlertWhitelist) ? "AND HEX(IP) NOT IN (" . implode(", ", array_fill(0, count($wafAlertWhitelist), '%s')) . ")" : "")
|
5938 |
+
. "AND attackLogTime > %.6f
|
5939 |
+
ORDER BY attackLogTime DESC
|
5940 |
+
LIMIT 10", array_merge($wafAlertWhitelist, array($cutoffTime))));
|
5941 |
+
$attackCount = $wpdb->get_var('SELECT FOUND_ROWS()');
|
5942 |
+
if ($attackCount >= wfConfig::get('wafAlertThreshold')) {
|
5943 |
+
$durationMessage = wfUtils::makeDuration($alertInterval);
|
5944 |
+
$message = <<<ALERTMSG
|
5945 |
+
The Wordfence Web Application Firewall has blocked {$attackCount} attacks over the last {$durationMessage}. Below is a sample of these recent attacks:
|
5946 |
+
|
5947 |
+
|
5948 |
+
ALERTMSG;
|
5949 |
+
$attackTable = array();
|
5950 |
+
$dateMax = $ipMax = $countryMax = 0;
|
5951 |
+
foreach ($attackData as $row) {
|
5952 |
+
$row->longDescription = "Blocked for " . $row->actionDescription;
|
5953 |
+
|
5954 |
+
$actionData = json_decode($row->actionData, true);
|
5955 |
+
if (!is_array($actionData) || !isset($actionData['paramKey']) || !isset($actionData['paramValue'])) {
|
5956 |
+
continue;
|
5957 |
+
}
|
5958 |
+
|
5959 |
+
$paramKey = base64_decode($actionData['paramKey']);
|
5960 |
+
$paramValue = base64_decode($actionData['paramValue']);
|
5961 |
+
if (strlen($paramValue) > 100) {
|
5962 |
+
$paramValue = substr($paramValue, 0, 100) . chr(2026);
|
5963 |
+
}
|
5964 |
+
|
5965 |
+
if (preg_match('/([a-z0-9_]+\.[a-z0-9_]+)(?:\[(.+?)\](.*))?/i', $paramKey, $matches)) {
|
5966 |
+
switch ($matches[1]) {
|
5967 |
+
case 'request.queryString':
|
5968 |
+
$row->longDescription = "Blocked for " . $row->actionDescription . ' in query string: ' . $matches[2] . '=' . $paramValue;
|
5969 |
+
break;
|
5970 |
+
case 'request.body':
|
5971 |
+
$row->longDescription = "Blocked for " . $row->actionDescription . ' in POST body: ' . $matches[2] . '=' . $paramValue;
|
5972 |
+
break;
|
5973 |
+
case 'request.cookie':
|
5974 |
+
$row->longDescription = "Blocked for " . $row->actionDescription . ' in cookie: ' . $matches[2] . '=' . $paramValue;
|
5975 |
+
break;
|
5976 |
+
case 'request.fileNames':
|
5977 |
+
$row->longDescription = "Blocked for a " . $row->actionDescription . ' in file: ' . $matches[2] . '=' . $paramValue;
|
5978 |
+
break;
|
5979 |
+
}
|
5980 |
+
}
|
5981 |
+
|
5982 |
+
$date = date_i18n('F j, Y g:ia', floor($row->attackLogTime)); $dateMax = max(strlen($date), $dateMax);
|
5983 |
+
$ip = wfUtils::inet_ntop($row->IP); $ipMax = max(strlen($ip), $ipMax);
|
5984 |
+
$country = wfUtils::countryCode2Name(wfUtils::IP2Country($ip)); $country = (empty($country) ? 'Unknown' : $country); $countryMax = max(strlen($country), $countryMax);
|
5985 |
+
$attackTable[] = array('date' => $date, 'IP' => $ip, 'country' => $country, 'message' => $row->longDescription);
|
5986 |
+
}
|
5987 |
+
|
5988 |
+
foreach ($attackTable as $row) {
|
5989 |
+
$date = str_pad($row['date'], $dateMax + 2);
|
5990 |
+
$ip = str_pad($row['IP'] . " ({$row['country']})", $ipMax + $countryMax + 8);
|
5991 |
+
$attackMessage = $row['message'];
|
5992 |
+
$message .= $date . $ip . $attackMessage . "\n";
|
5993 |
+
}
|
5994 |
|
5995 |
+
self::alert('Increased Attack Rate', $message, false);
|
5996 |
+
wfConfig::set('wafAlertLastSendTime', time());
|
5997 |
+
}
|
5998 |
+
}
|
5999 |
+
|
6000 |
+
//Send attack data
|
6001 |
$limit = 500;
|
6002 |
$lastSendTime = wfConfig::get('lastAttackDataSendTime');
|
6003 |
$attackData = $wpdb->get_results($wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$wpdb->base_prefix}wfHits
|
6006 |
LIMIT %d", $lastSendTime, $limit));
|
6007 |
$totalRows = $wpdb->get_var('SELECT FOUND_ROWS()');
|
6008 |
|
6009 |
+
if ($attackData && wfConfig::get('other_WFNet', true)) {
|
6010 |
$response = wp_remote_get(sprintf(WFWAF_API_URL_SEC . "waf-rules/%d.txt", $waf->getStorageEngine()->getConfig('attackDataKey')));
|
6011 |
|
6012 |
if (!is_wp_error($response)) {
|
6081 |
self::scheduleSendAttackData(time() + 7200);
|
6082 |
}
|
6083 |
}
|
6084 |
+
else if (!wfConfig::get('other_WFNet', true)) {
|
6085 |
+
wfConfig::set('lastAttackDataSendTime', time());
|
6086 |
+
}
|
6087 |
|
6088 |
self::trimWfHits();
|
6089 |
}
|
lib/wordfenceScanner.php
CHANGED
@@ -74,15 +74,24 @@ class wordfenceScanner {
|
|
74 |
if(! (is_array($sigData) && isset($sigData['rules'])) ){
|
75 |
throw new Exception("Wordfence could not get the attack signature patterns from the scanning server.");
|
76 |
}
|
|
|
|
|
77 |
|
78 |
if (is_array($sigData['rules'])) {
|
|
|
79 |
foreach ($sigData['rules'] as $key => $signatureRow) {
|
80 |
list(, , $pattern) = $signatureRow;
|
|
|
81 |
if (@preg_match('/' . $pattern . '/i', null) === false) {
|
82 |
wordfence::status(1, 'error', "A regex Wordfence received from it's servers is invalid. The pattern is: " . esc_html($pattern));
|
83 |
unset($sigData['rules'][$key]);
|
84 |
}
|
|
|
|
|
|
|
85 |
}
|
|
|
|
|
86 |
}
|
87 |
|
88 |
$extra = wfConfig::get('scan_include_extra');
|
74 |
if(! (is_array($sigData) && isset($sigData['rules'])) ){
|
75 |
throw new Exception("Wordfence could not get the attack signature patterns from the scanning server.");
|
76 |
}
|
77 |
+
|
78 |
+
try { wfWAF::getInstance()->setMalwareSignatures(array()); } catch (Exception $e) { /* Ignore */ }
|
79 |
|
80 |
if (is_array($sigData['rules'])) {
|
81 |
+
$wafPatterns = array();
|
82 |
foreach ($sigData['rules'] as $key => $signatureRow) {
|
83 |
list(, , $pattern) = $signatureRow;
|
84 |
+
$logOnly = (isset($signatureRow[5]) && !empty($signatureRow[5])) ? $signatureRow[5] : false;
|
85 |
if (@preg_match('/' . $pattern . '/i', null) === false) {
|
86 |
wordfence::status(1, 'error', "A regex Wordfence received from it's servers is invalid. The pattern is: " . esc_html($pattern));
|
87 |
unset($sigData['rules'][$key]);
|
88 |
}
|
89 |
+
else if (!$logOnly) {
|
90 |
+
$wafPatterns[] = $pattern;
|
91 |
+
}
|
92 |
}
|
93 |
+
|
94 |
+
try { wfWAF::getInstance()->setMalwareSignatures($wafPatterns); } catch (Exception $e) { /* Ignore */ }
|
95 |
}
|
96 |
|
97 |
$extra = wfConfig::get('scan_include_extra');
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: mmaunder
|
3 |
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking, block hackers
|
4 |
Requires at least: 3.9
|
5 |
-
Tested up to: 4.6.
|
6 |
-
Stable tag: 6.1.
|
7 |
|
8 |
Secure your website with the Wordfence security plugin for WordPress. Wordfence provides free enterprise-class WordPress security, protecting your website from hacks and malware.
|
9 |
|
@@ -200,6 +200,16 @@ Secure your website with Wordfence.
|
|
200 |
|
201 |
== Changelog ==
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
= 6.1.15 =
|
204 |
* Improvement: Removed file-based config caching, added support for caching via WordPress's object cache.
|
205 |
* Improvement: Whitelisted Uptime Robot's IP range.
|
2 |
Contributors: mmaunder
|
3 |
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking, block hackers
|
4 |
Requires at least: 3.9
|
5 |
+
Tested up to: 4.6.1
|
6 |
+
Stable tag: 6.1.16
|
7 |
|
8 |
Secure your website with the Wordfence security plugin for WordPress. Wordfence provides free enterprise-class WordPress security, protecting your website from hacks and malware.
|
9 |
|
200 |
|
201 |
== Changelog ==
|
202 |
|
203 |
+
= 6.1.16 =
|
204 |
+
* Improvement: Now performing malware scanning on all uploaded files in real-time.
|
205 |
+
* Improvement: Added Web Application Firewall activity to Wordfence summary email.
|
206 |
+
* Fix: Now using 503 response code in the page displayed when an IP is locked out.
|
207 |
+
* Fix: `wflogs` directory is now correctly removed on uninstall.
|
208 |
+
* Fix: Fixed recently introduced bug which caused the Whitelisted 404 URLs feature to no longer work.
|
209 |
+
* Fix: Added try/catch to uncaught exception thrown when pinging the API key.
|
210 |
+
* Improvement: Improved performance of the Live Traffic page in Firefox.
|
211 |
+
* Improvement: Updated GeoIP database.
|
212 |
+
|
213 |
= 6.1.15 =
|
214 |
* Improvement: Removed file-based config caching, added support for caching via WordPress's object cache.
|
215 |
* Improvement: Whitelisted Uptime Robot's IP range.
|
vendor/wordfence/wf-waf/src/init.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
define('WFWAF_VERSION', '1.0.
|
4 |
define('WFWAF_PATH', dirname(__FILE__) . '/');
|
5 |
define('WFWAF_LIB_PATH', WFWAF_PATH . 'lib/');
|
6 |
define('WFWAF_VIEW_PATH', WFWAF_PATH . 'views/');
|
7 |
-
define('WFWAF_API_URL_SEC', 'https://noc4.wordfence.com/v1.
|
8 |
if (!defined('WFWAF_DEBUG')) {
|
9 |
define('WFWAF_DEBUG', false);
|
10 |
}
|
1 |
<?php
|
2 |
|
3 |
+
define('WFWAF_VERSION', '1.0.2');
|
4 |
define('WFWAF_PATH', dirname(__FILE__) . '/');
|
5 |
define('WFWAF_LIB_PATH', WFWAF_PATH . 'lib/');
|
6 |
define('WFWAF_VIEW_PATH', WFWAF_PATH . 'views/');
|
7 |
+
define('WFWAF_API_URL_SEC', 'https://noc4.wordfence.com/v1.4/');
|
8 |
if (!defined('WFWAF_DEBUG')) {
|
9 |
define('WFWAF_DEBUG', false);
|
10 |
}
|
vendor/wordfence/wf-waf/src/lib/rules.php
CHANGED
@@ -456,6 +456,7 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
|
|
456 |
'currentuseris',
|
457 |
'currentuserisnot',
|
458 |
'md5equals',
|
|
|
459 |
);
|
460 |
|
461 |
/**
|
@@ -697,6 +698,42 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
|
|
697 |
public function md5Equals($subject) {
|
698 |
return md5((string) $subject) === $this->getExpected();
|
699 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
700 |
|
701 |
/**
|
702 |
* @return mixed
|
456 |
'currentuseris',
|
457 |
'currentuserisnot',
|
458 |
'md5equals',
|
459 |
+
'filepatternsmatch',
|
460 |
);
|
461 |
|
462 |
/**
|
698 |
public function md5Equals($subject) {
|
699 |
return md5((string) $subject) === $this->getExpected();
|
700 |
}
|
701 |
+
|
702 |
+
public function filePatternsMatch($subject) {
|
703 |
+
$request = $this->getWAF()->getRequest();
|
704 |
+
$files = $request->getFiles();
|
705 |
+
$patterns = $this->getWAF()->getMalwareSignatures();
|
706 |
+
if (!is_array($patterns)) {
|
707 |
+
return false;
|
708 |
+
}
|
709 |
+
|
710 |
+
foreach ($files as $file) {
|
711 |
+
if ($file['name'] == (string) $subject) {
|
712 |
+
$fh = @fopen($file['tmp_name'], 'r');
|
713 |
+
if (!$fh) {
|
714 |
+
return false;
|
715 |
+
}
|
716 |
+
$totalRead = 0;
|
717 |
+
|
718 |
+
$readsize = max(min(10 * 1024 * 1024, wfWAFUtils::iniSizeToBytes(ini_get('upload_max_filesize'))), 1 * 1024 * 1024);
|
719 |
+
while (!feof($fh)) {
|
720 |
+
$data = fread($fh, $readsize);
|
721 |
+
$totalRead += strlen($data);
|
722 |
+
if ($totalRead < 1) {
|
723 |
+
return false;
|
724 |
+
}
|
725 |
+
|
726 |
+
foreach ($patterns as $rule) {
|
727 |
+
if (preg_match('/(' . $rule . ')/i', $data, $matches)) {
|
728 |
+
return true;
|
729 |
+
}
|
730 |
+
}
|
731 |
+
}
|
732 |
+
}
|
733 |
+
}
|
734 |
+
|
735 |
+
return false;
|
736 |
+
}
|
737 |
|
738 |
/**
|
739 |
* @return mixed
|
vendor/wordfence/wf-waf/src/lib/utils.php
CHANGED
@@ -525,4 +525,23 @@ class wfWAFUtils {
|
|
525 |
$args = func_get_args();
|
526 |
return self::callMBSafeStrFunction('strrpos', $args);
|
527 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
528 |
}
|
525 |
$args = func_get_args();
|
526 |
return self::callMBSafeStrFunction('strrpos', $args);
|
527 |
}
|
528 |
+
|
529 |
+
/**
|
530 |
+
* @param string $val An ini byte size value (e.g., 20M)
|
531 |
+
* @return int
|
532 |
+
*/
|
533 |
+
public static function iniSizeToBytes($val) {
|
534 |
+
$val = trim($val);
|
535 |
+
$last = strtolower(substr($val, -1));
|
536 |
+
switch ($last) {
|
537 |
+
case 'g':
|
538 |
+
$val *= 1024;
|
539 |
+
case 'm':
|
540 |
+
$val *= 1024;
|
541 |
+
case 'k':
|
542 |
+
$val *= 1024;
|
543 |
+
}
|
544 |
+
|
545 |
+
return intval($val);
|
546 |
+
}
|
547 |
}
|
vendor/wordfence/wf-waf/src/lib/waf.php
CHANGED
@@ -323,6 +323,12 @@ auEa+7b+FGTKs7dUo2BNGR7OVifK4GZ8w/ajS0TelhrSRi3BBQCGXLzUO/UURUAh
|
|
323 |
$this->getStorageEngine()->setConfig('cron', $cron);
|
324 |
}
|
325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
$this->getStorageEngine()->setConfig('version', WFWAF_VERSION);
|
327 |
}
|
328 |
}
|
@@ -416,6 +422,57 @@ auEa+7b+FGTKs7dUo2BNGR7OVifK4GZ8w/ajS0TelhrSRi3BBQCGXLzUO/UURUAh
|
|
416 |
}
|
417 |
return false;
|
418 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
419 |
|
420 |
/**
|
421 |
* @param $rules
|
@@ -879,6 +936,12 @@ HTML
|
|
879 |
if ($this->getStorageEngine()->getConfig('attackDataKey', false) === false) {
|
880 |
$this->getStorageEngine()->setConfig('attackDataKey', mt_rand(0, 0xfff));
|
881 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
882 |
|
883 |
$request = new wfWAFHTTP();
|
884 |
try {
|
@@ -1309,6 +1372,42 @@ class wfWAFCronFetchRulesEvent extends wfWAFCronEvent {
|
|
1309 |
|
1310 |
}
|
1311 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1312 |
} catch (wfWAFHTTPTransportException $e) {
|
1313 |
error_log($e->getMessage());
|
1314 |
} catch (wfWAFBuildRulesException $e) {
|
323 |
$this->getStorageEngine()->setConfig('cron', $cron);
|
324 |
}
|
325 |
|
326 |
+
if (version_compare($currentVersion, '1.0.2') === -1) {
|
327 |
+
$event = new wfWAFCronFetchRulesEvent(time() - 2);
|
328 |
+
$event->setWaf($this);
|
329 |
+
$event->fire();
|
330 |
+
}
|
331 |
+
|
332 |
$this->getStorageEngine()->setConfig('version', WFWAF_VERSION);
|
333 |
}
|
334 |
}
|
422 |
}
|
423 |
return false;
|
424 |
}
|
425 |
+
|
426 |
+
/**
|
427 |
+
* @return array
|
428 |
+
*/
|
429 |
+
public function getMalwareSignatures() {
|
430 |
+
try {
|
431 |
+
$encoded = $this->getStorageEngine()->getConfig('filePatterns');
|
432 |
+
if (empty($encoded)) {
|
433 |
+
return array();
|
434 |
+
}
|
435 |
+
|
436 |
+
$authKey = $this->getStorageEngine()->getConfig('authKey');
|
437 |
+
$encoded = base64_decode($encoded);
|
438 |
+
$paddedKey = substr(str_repeat($authKey, ceil(strlen($encoded) / strlen($authKey))), 0, strlen($encoded));
|
439 |
+
$json = $encoded ^ $paddedKey;
|
440 |
+
$signatures = json_decode($json, true);
|
441 |
+
if (!is_array($signatures)) {
|
442 |
+
return array();
|
443 |
+
}
|
444 |
+
return $signatures;
|
445 |
+
}
|
446 |
+
catch (Exception $e) {
|
447 |
+
//Ignore
|
448 |
+
}
|
449 |
+
return array();
|
450 |
+
}
|
451 |
+
|
452 |
+
/**
|
453 |
+
* @param array $signatures
|
454 |
+
* @param bool $updateLastUpdatedTimestamp
|
455 |
+
*/
|
456 |
+
public function setMalwareSignatures($signatures, $updateLastUpdatedTimestamp = true) {
|
457 |
+
try {
|
458 |
+
if (!is_array($signatures)) {
|
459 |
+
$signatures = array();
|
460 |
+
}
|
461 |
+
|
462 |
+
$authKey = $this->getStorageEngine()->getConfig('authKey');
|
463 |
+
$json = json_encode($signatures);
|
464 |
+
$paddedKey = substr(str_repeat($authKey, ceil(strlen($json) / strlen($authKey))), 0, strlen($json));
|
465 |
+
$payload = $json ^ $paddedKey;
|
466 |
+
$this->getStorageEngine()->setConfig('filePatterns', base64_encode($payload));
|
467 |
+
|
468 |
+
if ($updateLastUpdatedTimestamp) {
|
469 |
+
$this->getStorageEngine()->setConfig('signaturesLastUpdated', is_int($updateLastUpdatedTimestamp) ? $updateLastUpdatedTimestamp : time());
|
470 |
+
}
|
471 |
+
}
|
472 |
+
catch (Exception $e) {
|
473 |
+
//Ignore
|
474 |
+
}
|
475 |
+
}
|
476 |
|
477 |
/**
|
478 |
* @param $rules
|
936 |
if ($this->getStorageEngine()->getConfig('attackDataKey', false) === false) {
|
937 |
$this->getStorageEngine()->setConfig('attackDataKey', mt_rand(0, 0xfff));
|
938 |
}
|
939 |
+
|
940 |
+
if (!$this->getStorageEngine()->getConfig('other_WFNet', true)) {
|
941 |
+
$this->getStorageEngine()->truncateAttackData();
|
942 |
+
$this->getStorageEngine()->unsetConfig('attackDataNextInterval');
|
943 |
+
return;
|
944 |
+
}
|
945 |
|
946 |
$request = new wfWAFHTTP();
|
947 |
try {
|
1372 |
|
1373 |
}
|
1374 |
}
|
1375 |
+
|
1376 |
+
$this->response = wfWAFHTTP::get(WFWAF_API_URL_SEC . "?" . http_build_query(array(
|
1377 |
+
'action' => 'get_malware_signatures',
|
1378 |
+
'k' => $waf->getStorageEngine()->getConfig('apiKey'),
|
1379 |
+
's' => $waf->getStorageEngine()->getConfig('siteURL') ? $waf->getStorageEngine()->getConfig('siteURL') : $guessSiteURL,
|
1380 |
+
'h' => $waf->getStorageEngine()->getConfig('homeURL') ? $waf->getStorageEngine()->getConfig('homeURL') : $guessSiteURL,
|
1381 |
+
'openssl' => $waf->hasOpenSSL() ? 1 : 0,
|
1382 |
+
'betaFeed' => (int) $waf->getStorageEngine()->getConfig('betaThreatDefenseFeed'),
|
1383 |
+
), null, '&'));
|
1384 |
+
if ($this->response) {
|
1385 |
+
$jsonData = wfWAFUtils::json_decode($this->response->getBody(), true);
|
1386 |
+
if (is_array($jsonData)) {
|
1387 |
+
if ($waf->hasOpenSSL() &&
|
1388 |
+
isset($jsonData['data']['signature']) &&
|
1389 |
+
isset($jsonData['data']['signatures']) &&
|
1390 |
+
$waf->verifySignedRequest(base64_decode($jsonData['data']['signature']), $jsonData['data']['signatures'])
|
1391 |
+
) {
|
1392 |
+
$waf->setMalwareSignatures(json_decode(base64_decode($jsonData['data']['signatures'])),
|
1393 |
+
isset($jsonData['data']['timestamp']) ? $jsonData['data']['timestamp'] : true);
|
1394 |
+
if (array_key_exists('premiumCount', $jsonData['data'])) {
|
1395 |
+
$waf->getStorageEngine()->setConfig('signaturePremiumCount', $jsonData['data']['premiumCount']);
|
1396 |
+
}
|
1397 |
+
|
1398 |
+
} else if (!$waf->hasOpenSSL() &&
|
1399 |
+
isset($jsonData['data']['hash']) &&
|
1400 |
+
isset($jsonData['data']['signatures']) &&
|
1401 |
+
$waf->verifyHashedRequest($jsonData['data']['hash'], $jsonData['data']['signatures'])
|
1402 |
+
) {
|
1403 |
+
$waf->setMalwareSignatures(json_decode(base64_decode($jsonData['data']['signatures'])),
|
1404 |
+
isset($jsonData['data']['timestamp']) ? $jsonData['data']['timestamp'] : true);
|
1405 |
+
if (array_key_exists('premiumCount', $jsonData['data'])) {
|
1406 |
+
$waf->getStorageEngine()->setConfig('signaturePremiumCount', $jsonData['data']['premiumCount']);
|
1407 |
+
}
|
1408 |
+
}
|
1409 |
+
}
|
1410 |
+
}
|
1411 |
} catch (wfWAFHTTPTransportException $e) {
|
1412 |
error_log($e->getMessage());
|
1413 |
} catch (wfWAFBuildRulesException $e) {
|
views/reports/activity-report-email-inline.php
CHANGED
@@ -256,6 +256,52 @@ h6 a:visited { color: purple !important; }
|
|
256 |
<p style="font-size: 100%; vertical-align: baseline; margin: 1em 0; padding: 0; border: 0;">
|
257 |
<a class="button" href="<?php echo network_admin_url('admin.php?page=WordfenceSecOpt#wfMarkerLoginSecurity') ?>" style="font-size: 13px; vertical-align: baseline; outline: none; color: #FFF; text-decoration: none; display: inline-block; line-height: 26px; height: 28px; cursor: pointer; border-radius: 3px; white-space: nowrap; box-sizing: border-box; box-shadow: 0 1px 0 rgba(120, 200, 230, 0.5) inset, 0 1px 0 rgba(0, 0, 0, 0.15); background-image: none; background-attachment: scroll; background-repeat: repeat; background-color: #2EA2CC; margin: 0; padding: 0 10px 1px; border: 1px solid #0074a2;">Update Login Security Options</a>
|
258 |
</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
|
260 |
<?php wfHelperString::cycle(); ?>
|
261 |
|
@@ -303,7 +349,7 @@ h6 a:visited { color: purple !important; }
|
|
303 |
$newVersion = ($plugin['newVersion'] == 'Unknown' ? $plugin['newVersion'] : "v{$plugin['newVersion']}");
|
304 |
?>
|
305 |
<li style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
306 |
-
A new version of the plugin "<?php echo esc_html("{$plugin['Name']} ({$newVersion})") ?>" is available
|
307 |
</li>
|
308 |
<?php endforeach ?>
|
309 |
</ul>
|
@@ -316,7 +362,7 @@ h6 a:visited { color: purple !important; }
|
|
316 |
$newVersion = ($theme['newVersion'] == 'Unknown' ? $theme['newVersion'] : "v{$theme['newVersion']}");
|
317 |
?>
|
318 |
<li style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
319 |
-
A new version of the theme "<?php echo esc_html("{$theme['name']} ({$newVersion})") ?>" is available
|
320 |
</li>
|
321 |
<?php endforeach ?>
|
322 |
</ul>
|
256 |
<p style="font-size: 100%; vertical-align: baseline; margin: 1em 0; padding: 0; border: 0;">
|
257 |
<a class="button" href="<?php echo network_admin_url('admin.php?page=WordfenceSecOpt#wfMarkerLoginSecurity') ?>" style="font-size: 13px; vertical-align: baseline; outline: none; color: #FFF; text-decoration: none; display: inline-block; line-height: 26px; height: 28px; cursor: pointer; border-radius: 3px; white-space: nowrap; box-sizing: border-box; box-shadow: 0 1px 0 rgba(120, 200, 230, 0.5) inset, 0 1px 0 rgba(0, 0, 0, 0.15); background-image: none; background-attachment: scroll; background-repeat: repeat; background-color: #2EA2CC; margin: 0; padding: 0 10px 1px; border: 1px solid #0074a2;">Update Login Security Options</a>
|
258 |
</p>
|
259 |
+
|
260 |
+
<?php wfHelperString::cycle(); ?>
|
261 |
+
|
262 |
+
<h2 style="font-size: 20px; vertical-align: baseline; clear: both; color: #222 !important; margin: 20px 0 4px; padding: 0; border: 0;">Recently Blocked Attacks</h2>
|
263 |
+
|
264 |
+
<table class="activity-table" style="font-size: 100%; vertical-align: baseline; border-collapse: collapse; border-spacing: 0; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; max-width: 100%; margin: 0; padding: 0; border: 0;">
|
265 |
+
<thead style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
266 |
+
<tr style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
267 |
+
<th style="font-size: 100%; vertical-align: baseline; font-weight: bold; text-align: left; color: #FFFFFF; background-color: #222; margin: 0; padding: 6px 4px; border: 1px solid #474747;" align="left" bgcolor="#222" valign="baseline">Time</th>
|
268 |
+
<th style="font-size: 100%; vertical-align: baseline; font-weight: bold; text-align: left; color: #FFFFFF; background-color: #222; margin: 0; padding: 6px 4px; border: 1px solid #474747;" align="left" bgcolor="#222" valign="baseline">IP / Action</th>
|
269 |
+
</tr>
|
270 |
+
</thead>
|
271 |
+
<tbody style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
272 |
+
<?php if (count($recent_firewall_activity) > 0): ?>
|
273 |
+
<?php foreach ($recent_firewall_activity as $attack_row):
|
274 |
+
?>
|
275 |
+
<?php
|
276 |
+
$stripe = wfHelperString::cycle('odd', 'even');
|
277 |
+
?>
|
278 |
+
<tr class="<?php echo $stripe ?>" style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
279 |
+
<td style="font-size: 100%; vertical-align: baseline; font-weight: normal; text-align: left; border-collapse: collapse; margin: 0; padding: 6px 4px; border: 1px solid #cccccc;white-space: nowrap;<?php echo $bg_colors[$stripe] ?>" align="left" valign="baseline"><?php echo $this->attackTime($attack_row->attackLogTime) ?></td>
|
280 |
+
<td style="font-size: 100%; vertical-align: baseline; font-weight: normal; text-align: left; border-collapse: collapse; margin: 0; padding: 6px 4px; border: 1px solid #cccccc;<?php echo $bg_colors[$stripe] ?>" align="left" valign="baseline">
|
281 |
+
<div style="font-weight: bold; font-size: 12px;"><?php echo $this->displayIP($attack_row->IP) ?></div>
|
282 |
+
<pre class="display-file" style="font-size: 12px; vertical-align: baseline; width: 420px; margin: 0; padding: 0; border: 0; white-space: normal;"><?php echo esc_html($attack_row->longDescription) ?></pre>
|
283 |
+
</td>
|
284 |
+
</tr>
|
285 |
+
<?php endforeach ?>
|
286 |
+
<?php else: ?>
|
287 |
+
<tr>
|
288 |
+
<td colspan="2">
|
289 |
+
No blocked attacks yet.
|
290 |
+
</td>
|
291 |
+
</tr>
|
292 |
+
<?php endif ?>
|
293 |
+
</tbody>
|
294 |
+
</table>
|
295 |
+
|
296 |
+
<?php
|
297 |
+
if ($omitted_firewall_activity > 10):
|
298 |
+
?>
|
299 |
+
<div style="font-size: 14px; vertical-align: baseline; clear: both; color: #f00 !important; margin: 8px 0 4px; padding: 0; border: 0;">and <?php echo $omitted_firewall_activity ?> additional attacks</div>
|
300 |
+
<?php endif ?>
|
301 |
+
|
302 |
+
<p style="font-size: 100%; vertical-align: baseline; margin: 1em 0; padding: 0; border: 0;">
|
303 |
+
<a class="button" href="<?php echo network_admin_url('admin.php?page=WordfenceActivity') ?>" style="font-size: 13px; vertical-align: baseline; outline: none; color: #FFF; text-decoration: none; display: inline-block; line-height: 26px; height: 28px; cursor: pointer; border-radius: 3px; white-space: nowrap; box-sizing: border-box; box-shadow: 0 1px 0 rgba(120, 200, 230, 0.5) inset, 0 1px 0 rgba(0, 0, 0, 0.15); background-image: none; background-attachment: scroll; background-repeat: repeat; background-color: #2EA2CC; margin: 0; padding: 0 10px 1px; border: 1px solid #0074a2;">View Recent Traffic</a>
|
304 |
+
</p>
|
305 |
|
306 |
<?php wfHelperString::cycle(); ?>
|
307 |
|
349 |
$newVersion = ($plugin['newVersion'] == 'Unknown' ? $plugin['newVersion'] : "v{$plugin['newVersion']}");
|
350 |
?>
|
351 |
<li style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
352 |
+
A new version of the plugin "<?php echo esc_html("{$plugin['Name']} ({$newVersion})") ?>" is available.<?php if (isset($plugin['vulnerabilityPatched']) && $plugin['vulnerabilityPatched']) { echo " <strong>This update includes security-related fixes.</strong>"; } ?>
|
353 |
</li>
|
354 |
<?php endforeach ?>
|
355 |
</ul>
|
362 |
$newVersion = ($theme['newVersion'] == 'Unknown' ? $theme['newVersion'] : "v{$theme['newVersion']}");
|
363 |
?>
|
364 |
<li style="font-size: 100%; vertical-align: baseline; margin: 0; padding: 0; border: 0;">
|
365 |
+
A new version of the theme "<?php echo esc_html("{$theme['name']} ({$newVersion})") ?>" is available.<?php if (isset($theme['vulnerabilityPatched']) && $theme['vulnerabilityPatched']) { echo " <strong>This update includes security-related fixes.</strong>"; } ?>
|
366 |
</li>
|
367 |
<?php endforeach ?>
|
368 |
</ul>
|
waf/bootstrap.php
CHANGED
@@ -184,6 +184,12 @@ class wfWAFWordPress extends wfWAF {
|
|
184 |
public function isIPBlocked($ip) {
|
185 |
return false;
|
186 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
|
188 |
/**
|
189 |
* @return wfWAFRunException
|
184 |
public function isIPBlocked($ip) {
|
185 |
return false;
|
186 |
}
|
187 |
+
|
188 |
+
public function uninstall() {
|
189 |
+
parent::uninstall();
|
190 |
+
@unlink(rtrim(WFWAF_LOG_PATH . '/') . '/.htaccess');
|
191 |
+
@rmdir(WFWAF_LOG_PATH);
|
192 |
+
}
|
193 |
|
194 |
/**
|
195 |
* @return wfWAFRunException
|
wordfence.php
CHANGED
@@ -4,14 +4,14 @@ Plugin Name: Wordfence Security
|
|
4 |
Plugin URI: http://www.wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
|
6 |
Author: Wordfence
|
7 |
-
Version: 6.1.
|
8 |
Author URI: http://www.wordfence.com/
|
9 |
Network: true
|
10 |
*/
|
11 |
if(defined('WP_INSTALLING') && WP_INSTALLING){
|
12 |
return;
|
13 |
}
|
14 |
-
define('WORDFENCE_VERSION', '6.1.
|
15 |
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
|
16 |
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
17 |
|
4 |
Plugin URI: http://www.wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
|
6 |
Author: Wordfence
|
7 |
+
Version: 6.1.16
|
8 |
Author URI: http://www.wordfence.com/
|
9 |
Network: true
|
10 |
*/
|
11 |
if(defined('WP_INSTALLING') && WP_INSTALLING){
|
12 |
return;
|
13 |
}
|
14 |
+
define('WORDFENCE_VERSION', '6.1.16');
|
15 |
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
|
16 |
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
17 |
|