Wordfence Security – Firewall & Malware Scan - Version 3.2.7

Version Description

  • Fixed dates and times in activity log alert emails and other emails to be in site's local timezone.
  • Added advanced country blocking options which allow bypass if a special URL is hit.
  • Added warning in options page if alert email is not configured under alert checkboxes.
  • Modified scan times to be within 60 minute window after scheduled time to prevent stampede at the top of the hour on our scanning server.
  • Fixed bug on Godaddy and a few other hosts where viewing list of files not in the repo caused error. This was caused by posix functions not being supported on Godaddy and some other hosts.
Download this release

Release Info

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

Code changes from version 3.2.6 to 3.2.7

js/admin.js CHANGED
@@ -959,10 +959,28 @@ window['wordfenceAdmin'] = {
959
  saveCountryBlocking: function(){
960
  var action = jQuery('#wfBlockAction').val();
961
  var redirURL = jQuery('#wfRedirURL').val();
 
 
 
 
962
  if(action == 'redir' && (! /^https?:\/\/[^\/]+/i.test(redirURL))){
963
  this.colorbox('400px', "Please enter a URL for redirection", "You have chosen to redirect blocked countries to a specific page. You need to enter a URL in the text box provided that starts with http:// or https://");
964
  return;
965
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
966
  var codesArr = [];
967
  var ownCountryBlocked = false;
968
  var self = this;
@@ -984,11 +1002,18 @@ window['wordfenceAdmin'] = {
984
  this.confirmSaveCountryBlocking();
985
  }
986
  },
 
 
 
 
987
  confirmSaveCountryBlocking: function(){
988
  var action = jQuery('#wfBlockAction').val();
989
  var redirURL = jQuery('#wfRedirURL').val();
990
  var loggedInBlocked = jQuery('#wfLoggedInBlocked').is(':checked') ? '1' : '0';
991
  var loginFormBlocked = jQuery('#wfLoginFormBlocked').is(':checked') ? '1' : '0';
 
 
 
992
 
993
  jQuery('.wfAjax24').show();
994
  var self = this;
@@ -997,6 +1022,9 @@ window['wordfenceAdmin'] = {
997
  redirURL: redirURL,
998
  loggedInBlocked: loggedInBlocked,
999
  loginFormBlocked: loginFormBlocked,
 
 
 
1000
  codes: this.countryCodesToSave
1001
  }, function(res){
1002
  jQuery('.wfAjax24').hide();
959
  saveCountryBlocking: function(){
960
  var action = jQuery('#wfBlockAction').val();
961
  var redirURL = jQuery('#wfRedirURL').val();
962
+ var bypassRedirURL = jQuery('#wfBypassRedirURL').val();
963
+ var bypassRedirDest = jQuery('#wfBypassRedirDest').val();
964
+ var bypassViewURL = jQuery('#wfBypassViewURL').val();
965
+
966
  if(action == 'redir' && (! /^https?:\/\/[^\/]+/i.test(redirURL))){
967
  this.colorbox('400px', "Please enter a URL for redirection", "You have chosen to redirect blocked countries to a specific page. You need to enter a URL in the text box provided that starts with http:// or https://");
968
  return;
969
  }
970
+ if( bypassRedirURL || bypassRedirDest ){
971
+ if(! (bypassRedirURL && bypassRedirDest)){
972
+ this.colorbox('400px', "Missing data from form", "If you want to set up a URL that will bypass country blocking, you must enter a URL that a visitor can hit and the destination they will be redirected to. You have only entered one of these components. Please enter both.");
973
+ return;
974
+ }
975
+ if(bypassRedirURL == bypassRedirDest){
976
+ this.colorbox('400px', "URLs are the same", "The URL that a user hits to bypass country blocking and the URL they are redirected to are the same. This would cause a circular redirect. Please fix this.");
977
+ return;
978
+ }
979
+ }
980
+ if(bypassRedirURL && (! /^(?:\/|http:\/\/)/.test(bypassRedirURL))){ this.invalidCountryURLMsg(bypassRedirURL); return; }
981
+ if(bypassRedirDest && (! /^(?:\/|http:\/\/)/.test(bypassRedirDest))){ this.invalidCountryURLMsg(bypassRedirDest); return; }
982
+ if(bypassViewURL && (! /^(?:\/|http:\/\/)/.test(bypassViewURL))){ this.invalidCountryURLMsg(bypassViewURL); return; }
983
+
984
  var codesArr = [];
985
  var ownCountryBlocked = false;
986
  var self = this;
1002
  this.confirmSaveCountryBlocking();
1003
  }
1004
  },
1005
+ invalidCountryURLMsg: function(URL){
1006
+ this.colorbox('400px', "Invalid URL", "URL's that you provide for bypassing country blocking must start with '/' or 'http://' without quotes. The URL that is invalid is: " + URL);
1007
+ return;
1008
+ },
1009
  confirmSaveCountryBlocking: function(){
1010
  var action = jQuery('#wfBlockAction').val();
1011
  var redirURL = jQuery('#wfRedirURL').val();
1012
  var loggedInBlocked = jQuery('#wfLoggedInBlocked').is(':checked') ? '1' : '0';
1013
  var loginFormBlocked = jQuery('#wfLoginFormBlocked').is(':checked') ? '1' : '0';
1014
+ var bypassRedirURL = jQuery('#wfBypassRedirURL').val();
1015
+ var bypassRedirDest = jQuery('#wfBypassRedirDest').val();
1016
+ var bypassViewURL = jQuery('#wfBypassViewURL').val();
1017
 
1018
  jQuery('.wfAjax24').show();
1019
  var self = this;
1022
  redirURL: redirURL,
1023
  loggedInBlocked: loggedInBlocked,
1024
  loginFormBlocked: loginFormBlocked,
1025
+ bypassRedirURL: bypassRedirURL,
1026
+ bypassRedirDest: bypassRedirDest,
1027
+ bypassViewURL: bypassViewURL,
1028
  codes: this.countryCodesToSave
1029
  }, function(res){
1030
  jQuery('.wfAjax24').hide();
lib/email_newIssues.php CHANGED
@@ -1,5 +1,7 @@
1
  Wordfence found the following new issues on "<?php echo get_bloginfo('name', 'raw'); ?>".
2
 
 
 
3
  <?php if($totalCriticalIssues > 0){ ?>
4
  Critical Problems:
5
 
1
  Wordfence found the following new issues on "<?php echo get_bloginfo('name', 'raw'); ?>".
2
 
3
+ Alert generated at <?php echo wfUtils::localHumanDate(); ?>
4
+
5
  <?php if($totalCriticalIssues > 0){ ?>
6
  Critical Problems:
7
 
lib/email_unlockRequest.php CHANGED
@@ -1,6 +1,8 @@
1
  Either you or someone else at IP address <b><?php echo $IP; ?></b> requesed instructions to<br />
2
  regain access to the website <a href="<?php echo wfUtils::getSiteBaseURL(); ?>"><b><?php echo $siteName; ?></b></a>.<br />
3
  <br />
 
 
4
  If you did not request these instructions then you can safely ignore them.<br />
5
  These instructions <b>will be valid for 30 minutes</b>
6
  from the time they were sent.
1
  Either you or someone else at IP address <b><?php echo $IP; ?></b> requesed instructions to<br />
2
  regain access to the website <a href="<?php echo wfUtils::getSiteBaseURL(); ?>"><b><?php echo $siteName; ?></b></a>.<br />
3
  <br />
4
+ Request was generated at: <?php echo wfUtils::localHumanDate(); ?><br />
5
+ <br />
6
  If you did not request these instructions then you can safely ignore them.<br />
7
  These instructions <b>will be valid for 30 minutes</b>
8
  from the time they were sent.
lib/menu_countryBlocking.php CHANGED
@@ -19,6 +19,19 @@ WFAD.countryMap = <?php echo json_encode($wfBulkCountries); ?>;
19
  <tr><th>URL to redirect blocked users to:</th><td><input type="text" id="wfRedirURL" value="<?php if(wfConfig::get('cbl_redirURL')){ echo htmlspecialchars(wfConfig::get('cbl_redirURL')); } ?>" /></td></tr>
20
  <tr><th>Block countries even if they are logged in:</th><td><input type="checkbox" id="wfLoggedInBlocked" value="1" <?php if(wfConfig::get('cbl_loggedInBlocked')){ echo 'checked'; } ?> /></td></tr>
21
  <tr><th>Block access to the login form too:</th><td><input type="checkbox" id="wfLoginFormBlocked" value="1" <?php if(wfConfig::get('cbl_loginFormBlocked')){ echo 'checked'; } ?> /></td></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  </table>
23
  <h2>Select which countries to block</h2>
24
  <div id="wfBulkBlockingContainer" style="margin-bottom: 10px;">
19
  <tr><th>URL to redirect blocked users to:</th><td><input type="text" id="wfRedirURL" value="<?php if(wfConfig::get('cbl_redirURL')){ echo htmlspecialchars(wfConfig::get('cbl_redirURL')); } ?>" /></td></tr>
20
  <tr><th>Block countries even if they are logged in:</th><td><input type="checkbox" id="wfLoggedInBlocked" value="1" <?php if(wfConfig::get('cbl_loggedInBlocked')){ echo 'checked'; } ?> /></td></tr>
21
  <tr><th>Block access to the login form too:</th><td><input type="checkbox" id="wfLoginFormBlocked" value="1" <?php if(wfConfig::get('cbl_loginFormBlocked')){ echo 'checked'; } ?> /></td></tr>
22
+ <tr><td colspan="2"><h2>Advanced Country Blocking Options</h2></td></tr>
23
+ <tr><th colspan="2">
24
+ If user hits the URL
25
+ <input type="text" id="wfBypassRedirURL" value="<?php echo htmlspecialchars(wfConfig::get('cbl_cblBypassURL', "")); ?>" size="20" />
26
+ then redirect that user to
27
+ <input type="text" id="wfBypassRedirDest" value="<?php echo htmlspecialchars(wfConfig::get('cbl_cblBypassURLRedir', "")); ?>" size="20" /> and set a cookie that will bypass all country blocking.
28
+ </th></tr>
29
+ <tr><th colspan="2">
30
+ If user who is allowed to access the site views the URL
31
+ <input type="text" id="wfBypassViewURL" value="<?php echo htmlspecialchars(wfConfig::get('cbl_cblBypassURL', "")); ?>" size="20" />
32
+ then set a cookie that will bypass country blocking in future in case that user hits the site from a blocked country.
33
+ </th></tr>
34
+
35
  </table>
36
  <h2>Select which countries to block</h2>
37
  <div id="wfBulkBlockingContainer" style="margin-bottom: 10px;">
lib/menu_options.php CHANGED
@@ -50,6 +50,12 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
50
  <div id="wfConfigAdvanced">
51
  <table class="wfConfigForm">
52
  <tr><td colspan="2"><h3 class="wfConfigHeading">Alerts</h3></td></tr>
 
 
 
 
 
 
53
  <tr><th>Alert on critical problems</th><td><input type="checkbox" id="alertOn_critical" class="wfConfigElem" name="alertOn_critical" value="1" <?php $w->cb('alertOn_critical'); ?>/></td></tr>
54
  <tr><th>Alert on warnings</th><td><input type="checkbox" id="alertOn_warnings" class="wfConfigElem" name="alertOn_warnings" value="1" <?php $w->cb('alertOn_warnings'); ?>/></td></tr>
55
  <tr><th>Alert when an IP address is blocked</th><td><input type="checkbox" id="alertOn_block" class="wfConfigElem" name="alertOn_block" value="1" <?php $w->cb('alertOn_block'); ?>/></td></tr>
50
  <div id="wfConfigAdvanced">
51
  <table class="wfConfigForm">
52
  <tr><td colspan="2"><h3 class="wfConfigHeading">Alerts</h3></td></tr>
53
+ <?php
54
+ $emails = wfConfig::getAlertEmails();
55
+ if(sizeof($emails) < 1){
56
+ echo "<tr><th colspan=\"2\" style=\"color: #F00;\">You have not configured an email to receive alerts yet. Set this up under \"Basic Options\" above.</th></tr>\n";
57
+ }
58
+ ?>
59
  <tr><th>Alert on critical problems</th><td><input type="checkbox" id="alertOn_critical" class="wfConfigElem" name="alertOn_critical" value="1" <?php $w->cb('alertOn_critical'); ?>/></td></tr>
60
  <tr><th>Alert on warnings</th><td><input type="checkbox" id="alertOn_warnings" class="wfConfigElem" name="alertOn_warnings" value="1" <?php $w->cb('alertOn_warnings'); ?>/></td></tr>
61
  <tr><th>Alert when an IP address is blocked</th><td><input type="checkbox" id="alertOn_block" class="wfConfigElem" name="alertOn_block" value="1" <?php $w->cb('alertOn_block'); ?>/></td></tr>
lib/menu_scan.php CHANGED
@@ -52,6 +52,7 @@
52
  $debugOn = wfConfig::get('debugOn', false);
53
  $newestItem = 0;
54
  $sumEvents = array();
 
55
  foreach($events as $e){
56
  if(strpos($e['msg'], 'SUM_') !== 0){
57
  if( $debugOn || $e['level'] < 4){
@@ -59,7 +60,7 @@
59
  if($debugOn){
60
  $typeClass = ' wf' . $e['type'];
61
  }
62
- echo '<div class="wfActivityLine' . $typeClass . '">[' . date('M d H:i:s', $e['ctime']) . ']&nbsp;' . $e['msg'] . '</div>';
63
  }
64
  }
65
  $newestItem = $e['ctime'];
52
  $debugOn = wfConfig::get('debugOn', false);
53
  $newestItem = 0;
54
  $sumEvents = array();
55
+ $timeOffset = 3600 * get_option('gmt_offset');
56
  foreach($events as $e){
57
  if(strpos($e['msg'], 'SUM_') !== 0){
58
  if( $debugOn || $e['level'] < 4){
60
  if($debugOn){
61
  $typeClass = ' wf' . $e['type'];
62
  }
63
+ echo '<div class="wfActivityLine' . $typeClass . '">[' . date('M d H:i:s', $e['ctime'] + $timeOffset) . ']&nbsp;' . $e['msg'] . '</div>';
64
  }
65
  }
66
  $newestItem = $e['ctime'];
lib/menu_scanSchedule.php CHANGED
@@ -22,6 +22,8 @@
22
  You can go to the Settings/General menu to change your timezone.
23
  Use the links provided as shortcuts to select scan times. Try clicking
24
  the links several times to advance the time. You can also manually select scan start times for each day.
 
 
25
  </p>
26
  <p>
27
  <strong>Scan mode:</strong><select id="schedMode" onchange="WFAD.sched_modeChange();">
22
  You can go to the Settings/General menu to change your timezone.
23
  Use the links provided as shortcuts to select scan times. Try clicking
24
  the links several times to advance the time. You can also manually select scan start times for each day.
25
+ <br /><br />
26
+ NOTE: Scans run within 1 hour after scheduled time. E.g. A scan scheduled for 1pm will run between 1pm and 2pm. This prevents a stampede on our scanning server at the top of the hour.
27
  </p>
28
  <p>
29
  <strong>Scan mode:</strong><select id="schedMode" onchange="WFAD.sched_modeChange();">
lib/unknownFiles.php CHANGED
@@ -76,10 +76,18 @@ if($fileList){
76
  // http://test3.com/?_wfsf=view&nonce=c1ad72bcbd&file=wp-content%2Fplugins%2Fwordfence%2Flib%2Fmenu_options.php
77
  $viewLink = wfUtils::siteURLRelative() . '?_wfsf=view&nonce=' . wp_create_nonce('wp-ajax') . '&file=' . urlencode($file);
78
  $stat = stat($fullFile);
79
- $owner = posix_getpwuid($stat['uid']);
80
- $owner = $owner['name'];
81
- $group = posix_getgrgid($stat['gid']);
82
- $group = $group['name'];
 
 
 
 
 
 
 
 
83
  $perms = substr(sprintf('%o', fileperms($fullFile)), -4);
84
  $files[] = array($file, $fullFile, $stat['size'], $stat['mtime'], $viewLink, $owner, $group, $perms);
85
  }
76
  // http://test3.com/?_wfsf=view&nonce=c1ad72bcbd&file=wp-content%2Fplugins%2Fwordfence%2Flib%2Fmenu_options.php
77
  $viewLink = wfUtils::siteURLRelative() . '?_wfsf=view&nonce=' . wp_create_nonce('wp-ajax') . '&file=' . urlencode($file);
78
  $stat = stat($fullFile);
79
+ if(function_exists('posix_getpwuid')){
80
+ $owner = posix_getpwuid($stat['uid']);
81
+ $owner = $owner['name'];
82
+ } else {
83
+ $owner = "unknown";
84
+ }
85
+ if(function_exists('posix_getgrgid')){
86
+ $group = posix_getgrgid($stat['gid']);
87
+ $group = $group['name'];
88
+ } else {
89
+ $group = 'unknown';
90
+ }
91
  $perms = substr(sprintf('%o', fileperms($fullFile)), -4);
92
  $files[] = array($file, $fullFile, $stat['size'], $stat['mtime'], $viewLink, $owner, $group, $perms);
93
  }
lib/viewFullActivityLog.php CHANGED
@@ -14,9 +14,10 @@ global $wpdb;
14
  $debugOn = wfConfig::get('debugOn', 0);
15
  $table = $wpdb->base_prefix . 'wfStatus';
16
  $q = $db->query("select ctime, level, type, msg from $table order by ctime desc");
 
17
  while($r = mysql_fetch_assoc($q)){
18
  if($r['level'] < 4 || $debugOn){
19
- echo '<div' . ($r['type'] == 'error' ? ' class="error"' : '') . '>[' . date('M d H:i:s', $r['ctime']) . ':' . $r['ctime'] . ':' . $r['level'] . ':' . $r['type'] . ']&nbsp;' . htmlspecialchars($r['msg']) . "</div>\n";
20
  }
21
  }
22
  ?>
14
  $debugOn = wfConfig::get('debugOn', 0);
15
  $table = $wpdb->base_prefix . 'wfStatus';
16
  $q = $db->query("select ctime, level, type, msg from $table order by ctime desc");
17
+ $timeOffset = 3600 * get_option('gmt_offset');
18
  while($r = mysql_fetch_assoc($q)){
19
  if($r['level'] < 4 || $debugOn){
20
+ echo '<div' . ($r['type'] == 'error' ? ' class="error"' : '') . '>[' . date('M d H:i:s', $r['ctime'] + $timeOffset) . ':' . $r['ctime'] . ':' . $r['level'] . ':' . $r['type'] . ']&nbsp;' . htmlspecialchars($r['msg']) . "</div>\n";
21
  }
22
  }
23
  ?>
lib/wfLog.php CHANGED
@@ -486,7 +486,25 @@ class wfLog {
486
  }
487
  public function firewallBadIPs(){
488
  $blockedCountries = wfConfig::get('cbl_countries', false);
489
- if($blockedCountries && wfConfig::get('isPaid')){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  if(is_user_logged_in() && (! wfConfig::get('cbl_loggedInBlocked', false)) ){ //User is logged in and we're allowing logins
491
  //Do nothing
492
  } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') !== false && (! wfConfig::get('cbl_loginFormBlocked', false)) ){ //It's the login form and we're allowing that
@@ -494,10 +512,10 @@ class wfLog {
494
  } else {
495
  if($country = wfUtils::IP2Country(wfUtils::getIP()) ){
496
  foreach(explode(',', $blockedCountries) as $blocked){
497
- if(strtoupper($blocked) == strtoupper($country)){
498
  if(wfConfig::get('cbl_action') == 'redir'){
499
  $redirURL = wfConfig::get('cbl_redirURL');
500
- if(wfUtils::extractBareURI($redirURL) == wfUtils::extractBareURI($_SERVER['REQUEST_URI'])){ //Is this the URI we want to redirect to, then don't block it
501
  //Do nothing
502
  /* Uncomment the following if page components aren't loading for the page we redirect to.
503
  Uncommenting is not recommended because it means that anyone from a blocked country
@@ -526,6 +544,23 @@ class wfLog {
526
  $this->do503($secsToGo, $rec['reason']);
527
  }
528
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
  private function takeBlockingAction($configVar, $reason){
530
  if($this->googleSafetyCheckOK()){
531
  $action = wfConfig::get($configVar . '_action');
@@ -617,9 +652,10 @@ class wfLog {
617
  $res = $this->getDB()->query("select ctime, level, type, msg from " . $this->statusTable . " where ctime > %f order by ctime asc", $lastCtime);
618
  $results = array();
619
  $lastTime = false;
 
620
  while($rec = mysql_fetch_assoc($res)){
621
  //$rec['timeAgo'] = wfUtils::makeTimeAgo(time() - $rec['ctime']);
622
- $rec['date'] = date('M d H:i:s', $rec['ctime']);
623
  array_push($results, $rec);
624
  }
625
  return $results;
@@ -628,8 +664,9 @@ class wfLog {
628
  $res = $this->getDB()->query("select ctime, level, type, msg from " . $this->statusTable . " where level = 10 order by ctime desc limit 100");
629
  $results = array();
630
  $lastTime = false;
 
631
  while($rec = mysql_fetch_assoc($res)){
632
- $rec['date'] = date('M d H:i:s', $rec['ctime']);
633
  array_push($results, $rec);
634
  if(strpos($rec['msg'], 'SUM_PREP:') === 0){
635
  break;
486
  }
487
  public function firewallBadIPs(){
488
  $blockedCountries = wfConfig::get('cbl_countries', false);
489
+ $bareRequestURI = wfUtils::extractBareURI($_SERVER['REQUEST_URI']);
490
+ $bareBypassRedirURI = wfUtils::extractBareURI(wfConfig::get('cbl_bypassRedirURL', ''));
491
+ $skipCountryBlocking = false;
492
+
493
+ if($bareBypassRedirURI && $bareRequestURI == $bareBypassRedirURI){ //Run this before country blocking because even if the user isn't blocked we need to set the bypass cookie so they can bypass future blocks.
494
+ $bypassRedirDest = wfConfig::get('cbl_bypassRedirDest', '');
495
+ if($bypassRedirDest){
496
+ self::setCBLCookieBypass();
497
+ $this->redirect($bypassRedirDest); //exits
498
+ }
499
+ }
500
+ $bareBypassViewURI = wfUtils::extractBareURI(wfConfig::get('cbl_bypassViewURL', ''));
501
+ if($bareBypassViewURI && $bareBypassViewURI == $bareRequestURI){
502
+ self::setCBLCookieBypass();
503
+ $skipCountryBlocking = true;
504
+ }
505
+
506
+
507
+ if((! $skipCountryBlocking) && $blockedCountries && wfConfig::get('isPaid') && (! self::isCBLBypassCookieSet()) ){
508
  if(is_user_logged_in() && (! wfConfig::get('cbl_loggedInBlocked', false)) ){ //User is logged in and we're allowing logins
509
  //Do nothing
510
  } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') !== false && (! wfConfig::get('cbl_loginFormBlocked', false)) ){ //It's the login form and we're allowing that
512
  } else {
513
  if($country = wfUtils::IP2Country(wfUtils::getIP()) ){
514
  foreach(explode(',', $blockedCountries) as $blocked){
515
+ if(strtoupper($blocked) == strtoupper($country)){ //At this point we know the user has been blocked
516
  if(wfConfig::get('cbl_action') == 'redir'){
517
  $redirURL = wfConfig::get('cbl_redirURL');
518
+ if(wfUtils::extractBareURI($redirURL) == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it
519
  //Do nothing
520
  /* Uncomment the following if page components aren't loading for the page we redirect to.
521
  Uncommenting is not recommended because it means that anyone from a blocked country
544
  $this->do503($secsToGo, $rec['reason']);
545
  }
546
  }
547
+ public function getCBLCookieVal(){
548
+ $val = wfConfig::get('cbl_cookieVal', false);
549
+ if(! $val){
550
+ $val = uniqid();
551
+ wfConfig::set('cbl_cookieVal', $val);
552
+ }
553
+ return $val;
554
+ }
555
+ public function setCBLCookieBypass(){
556
+ @setcookie('wfCBLBypass', self::getCBLCookieVal(), time() + (86400 * 365), '/');
557
+ }
558
+ public function isCBLBypassCookieSet(){
559
+ if(isset($_COOKIE['wfCBLBypass']) && $_COOKIE['wfCBLBypass'] == wfConfig::get('cbl_cookieVal')){
560
+ return true;
561
+ }
562
+ return false;
563
+ }
564
  private function takeBlockingAction($configVar, $reason){
565
  if($this->googleSafetyCheckOK()){
566
  $action = wfConfig::get($configVar . '_action');
652
  $res = $this->getDB()->query("select ctime, level, type, msg from " . $this->statusTable . " where ctime > %f order by ctime asc", $lastCtime);
653
  $results = array();
654
  $lastTime = false;
655
+ $timeOffset = 3600 * get_option('gmt_offset');
656
  while($rec = mysql_fetch_assoc($res)){
657
  //$rec['timeAgo'] = wfUtils::makeTimeAgo(time() - $rec['ctime']);
658
+ $rec['date'] = date('M d H:i:s', $rec['ctime'] + $timeOffset);
659
  array_push($results, $rec);
660
  }
661
  return $results;
664
  $res = $this->getDB()->query("select ctime, level, type, msg from " . $this->statusTable . " where level = 10 order by ctime desc limit 100");
665
  $results = array();
666
  $lastTime = false;
667
+ $timeOffset = 3600 * get_option('gmt_offset');
668
  while($rec = mysql_fetch_assoc($res)){
669
+ $rec['date'] = date('M d H:i:s', $rec['ctime'] + $timeOffset);
670
  array_push($results, $rec);
671
  if(strpos($rec['msg'], 'SUM_PREP:') === 0){
672
  break;
lib/wfUtils.php CHANGED
@@ -452,6 +452,9 @@ class wfUtils {
452
  $URL = rtrim($URL, '/') . '/';
453
  return $URL;
454
  }
 
 
 
455
 
456
  }
457
 
452
  $URL = rtrim($URL, '/') . '/';
453
  return $URL;
454
  }
455
+ public static function localHumanDate(){
456
+ return date('l jS \of F Y \a\t h:i:s A', time() + (3600 * get_option('gmt_offset')));
457
+ }
458
 
459
  }
460
 
lib/wordfenceClass.php CHANGED
@@ -617,6 +617,7 @@ class wordfence {
617
  $secondsInFuture += (86400 * 7); //Add a week
618
  }
619
  $futureTime = time() - (time() % 3600) + $secondsInFuture; //Modulo rounds down to top of the hour
 
620
  wordfence::status(4, 'info', "Scheduled time for day $scheduledDay hour $scheduledHour is: " . date('l jS \of F Y h:i:s A', $futureTime));
621
  self::scheduleSingleScan($futureTime);
622
  }
@@ -650,6 +651,9 @@ class wordfence {
650
  wfConfig::set('cbl_redirURL', $_POST['redirURL']);
651
  wfConfig::set('cbl_loggedInBlocked', $_POST['loggedInBlocked']);
652
  wfConfig::set('cbl_loginFormBlocked', $_POST['loginFormBlocked']);
 
 
 
653
  return array('ok' => 1);
654
  }
655
  public static function ajax_sendActivityLog_callback(){
@@ -658,11 +662,12 @@ class wordfence {
658
  global $wpdb;
659
  $p = $wpdb->base_prefix;
660
  $q = $wfdb->query("select ctime, level, type, msg from $p"."wfStatus order by ctime desc limit 10000");
 
661
  while($r = mysql_fetch_assoc($q)){
662
  if($r['type'] == 'error'){
663
  $content .= "\n";
664
  }
665
- $content .= date(DATE_RFC822, $r['ctime']) . '::' . sprintf('%.4f', $r['ctime']) . ':' . $r['level'] . ':' . $r['type'] . '::' . $r['msg'] . "\n";
666
  }
667
  $content .= "\n\n";
668
 
@@ -1270,7 +1275,7 @@ class wordfence {
1270
  $wp->add_query_var('_wfsf');
1271
  //add_rewrite_rule('wfStaticFunc/([a-zA-Z0-9]+)/?$', 'index.php?wfStaticFunc=' . $matches[1], 'top');
1272
  $cookieName = 'wfvt_' . crc32(site_url());
1273
- $c = isset($_COOKIES[$cookieName]) ? isset($_COOKIES[$cookieName]) : false;
1274
  if($c){
1275
  self::$newVisit = false;
1276
  } else {
@@ -1447,7 +1452,7 @@ class wordfence {
1447
  'blogName' => get_bloginfo('name', 'raw'),
1448
  'alertMsg' => $alertMsg,
1449
  'IPMsg' => $IPMsg,
1450
- 'date' => date('l jS \of F Y \a\t h:i:s A'),
1451
  'myHomeURL' => self::getMyHomeURL(),
1452
  'myOptionsURL' => self::getMyOptionsURL()
1453
  ));
617
  $secondsInFuture += (86400 * 7); //Add a week
618
  }
619
  $futureTime = time() - (time() % 3600) + $secondsInFuture; //Modulo rounds down to top of the hour
620
+ $futureTime += rand(0,3600); //Prevent a stampede of scans on our scanning server
621
  wordfence::status(4, 'info', "Scheduled time for day $scheduledDay hour $scheduledHour is: " . date('l jS \of F Y h:i:s A', $futureTime));
622
  self::scheduleSingleScan($futureTime);
623
  }
651
  wfConfig::set('cbl_redirURL', $_POST['redirURL']);
652
  wfConfig::set('cbl_loggedInBlocked', $_POST['loggedInBlocked']);
653
  wfConfig::set('cbl_loginFormBlocked', $_POST['loginFormBlocked']);
654
+ wfConfig::set('cbl_bypassRedirURL', $_POST['bypassRedirURL']);
655
+ wfConfig::set('cbl_bypassRedirDest', $_POST['bypassRedirDest']);
656
+ wfConfig::set('cbl_bypassViewURL', $_POST['bypassViewURL']);
657
  return array('ok' => 1);
658
  }
659
  public static function ajax_sendActivityLog_callback(){
662
  global $wpdb;
663
  $p = $wpdb->base_prefix;
664
  $q = $wfdb->query("select ctime, level, type, msg from $p"."wfStatus order by ctime desc limit 10000");
665
+ $timeOffset = 3600 * get_option('gmt_offset');
666
  while($r = mysql_fetch_assoc($q)){
667
  if($r['type'] == 'error'){
668
  $content .= "\n";
669
  }
670
+ $content .= date(DATE_RFC822, $r['ctime'] + $timeOffset) . '::' . sprintf('%.4f', $r['ctime']) . ':' . $r['level'] . ':' . $r['type'] . '::' . $r['msg'] . "\n";
671
  }
672
  $content .= "\n\n";
673
 
1275
  $wp->add_query_var('_wfsf');
1276
  //add_rewrite_rule('wfStaticFunc/([a-zA-Z0-9]+)/?$', 'index.php?wfStaticFunc=' . $matches[1], 'top');
1277
  $cookieName = 'wfvt_' . crc32(site_url());
1278
+ $c = isset($_COOKIE[$cookieName]) ? isset($_COOKIE[$cookieName]) : false;
1279
  if($c){
1280
  self::$newVisit = false;
1281
  } else {
1452
  'blogName' => get_bloginfo('name', 'raw'),
1453
  'alertMsg' => $alertMsg,
1454
  'IPMsg' => $IPMsg,
1455
+ 'date' => wfUtils::localHumanDate(),
1456
  'myHomeURL' => self::getMyHomeURL(),
1457
  'myOptionsURL' => self::getMyOptionsURL()
1458
  ));
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
  Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
4
  Requires at least: 3.3.1
5
  Tested up to: 3.4.1
6
- Stable tag: 3.2.6
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
@@ -153,6 +153,13 @@ or a theme, because often these have been updated to fix a security hole.
153
  5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
154
 
155
  == Changelog ==
 
 
 
 
 
 
 
156
  = 3.2.6 =
157
  * Paid feature: Remote site vulnerability and infection scanning.
158
 
3
  Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
4
  Requires at least: 3.3.1
5
  Tested up to: 3.4.1
6
+ Stable tag: 3.2.7
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
153
  5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
154
 
155
  == Changelog ==
156
+ = 3.2.7 =
157
+ * Fixed dates and times in activity log alert emails and other emails to be in site's local timezone.
158
+ * Added advanced country blocking options which allow bypass if a special URL is hit.
159
+ * Added warning in options page if alert email is not configured under alert checkboxes.
160
+ * Modified scan times to be within 60 minute window after scheduled time to prevent stampede at the top of the hour on our scanning server.
161
+ * Fixed bug on Godaddy and a few other hosts where viewing list of files not in the repo caused error. This was caused by posix functions not being supported on Godaddy and some other hosts.
162
+
163
  = 3.2.6 =
164
  * Paid feature: Remote site vulnerability and infection scanning.
165
 
wordfence.php CHANGED
@@ -4,10 +4,10 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://wordfence.com/
5
  Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
- Version: 3.2.6
8
  Author URI: http://wordfence.com/
9
  */
10
- define('WORDFENCE_VERSION', '3.2.6');
11
  if(! defined('WORDFENCE_VERSIONONLY_MODE')){
12
  if((int) @ini_get('memory_limit') < 64){
13
  @ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.
4
  Plugin URI: http://wordfence.com/
5
  Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
+ Version: 3.2.7
8
  Author URI: http://wordfence.com/
9
  */
10
+ define('WORDFENCE_VERSION', '3.2.7');
11
  if(! defined('WORDFENCE_VERSIONONLY_MODE')){
12
  if((int) @ini_get('memory_limit') < 64){
13
  @ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.