Wordfence Security – Firewall & Malware Scan - Version 6.2.3

Version Description

  • Improvement: Reworked blocking for IP ranges, country blocking, and direct IP blocking to minimize server impact when under attack.
  • Improvement: Live traffic better indicates the action taken by country blocking when it redirects a visitor.
  • Improvement: Added support for finding server logs to the Diagnostics page to help with troubleshooting.
  • Improvement: Whitelisted StatusCake IP addresses.
  • Improvement: Updated GeoIP database.
  • Improvement: Disabling Wordfence now sends an alert.
  • Improvement: Improved detection for uploaded PHP content in the firewall.
  • Fix: Eliminated memory-related errors resulting from the scan on sites with very large numbers of issues and low memory.
  • Fix: Fixed admin page layout for sites using RTL languages.
  • Fix: Reduced overhead of the dashboard widget.
  • Fix: Improved performance of checking for whitelisted IPs.
  • Fix: Changes to the default plugin hello.php are now detected correctly in scans.
  • Fix: Fixed IPv6 warning in the dashboard widget.
Download this release

Release Info

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

Code changes from version 6.2.2 to 6.2.3

js/admin.js CHANGED
@@ -63,6 +63,10 @@
63
$($this.data('selector')).show();
64
return false;
65
});
66
67
$('#doSendEmail').click(function() {
68
var ticket = $('#_ticketnumber').val();
@@ -111,11 +115,39 @@
111
jQuery('#consoleActivity').scrollTop(jQuery('#consoleActivity').prop('scrollHeight'));
112
jQuery('#consoleScan').scrollTop(jQuery('#consoleScan').prop('scrollHeight'));
113
this.noScanHTML = jQuery('#wfNoScanYetTmpl').tmpl().html();
114
- this.loadIssues();
115
this.startActivityLogUpdates();
116
if (this.needTour()) {
117
this.scanTourStart();
118
}
119
} else if (jQuery('#wordfenceMode_waf').length > 0) {
120
if (this.needTour()) {
121
this.tour('wfWAFTour', 'wfHeading', 'top', 'left', "Learn about Live Traffic", function() {
@@ -321,7 +353,9 @@
321
},
322
updateConfig: function(key, val, cb) {
323
this.ajax('wordfence_updateConfig', {key: key, val: val}, function() {
324
- cb();
325
});
326
},
327
tourFinish: function() {
@@ -790,15 +824,25 @@
790
jQuery('#wfAuditJobs').empty().html("<p>You don't have any password auditing jobs in progress or completed yet.</p>");
791
}
792
},
793
- loadIssues: function(callback) {
794
if (this.mode != 'scan') {
795
return;
796
}
797
var self = this;
798
- this.ajax('wordfence_loadIssues', {}, function(res) {
799
self.displayIssues(res, callback);
800
});
801
},
802
sev2num: function(str) {
803
if (/wfProbSev1/.test(str)) {
804
return 1;
@@ -869,7 +913,7 @@
869
"bPaginate": false,
870
"bLengthChange": false,
871
"bAutoWidth": false,
872
- "aaData": res.issuesLists[issueStatus],
873
"aoColumns": [
874
{
875
"sTitle": '<div class="th_wrapp">Severity</div>',
@@ -895,6 +939,22 @@
895
]
896
});
897
}
898
if (callback) {
899
jQuery('#wfIssues_' + this.visibleIssuesPanel).fadeIn(500, function() {
900
callback();
@@ -902,7 +962,6 @@
902
} else {
903
jQuery('#wfIssues_' + this.visibleIssuesPanel).fadeIn(500);
904
}
905
- return true;
906
},
907
ajax: function(action, data, cb, cbErr, noLoading) {
908
if (typeof(data) == 'string') {
63
$($this.data('selector')).show();
64
return false;
65
});
66
+
67
+ $('.downloadLogFile').each(function() {
68
+ $(this).attr('href', WordfenceAdminVars.ajaxURL + '?action=wordfence_downloadLogFile&nonce=' + WFAD.nonce + '&logfile=' + encodeURIComponent($(this).data('logfile')));
69
+ });
70
71
$('#doSendEmail').click(function() {
72
var ticket = $('#_ticketnumber').val();
115
jQuery('#consoleActivity').scrollTop(jQuery('#consoleActivity').prop('scrollHeight'));
116
jQuery('#consoleScan').scrollTop(jQuery('#consoleScan').prop('scrollHeight'));
117
this.noScanHTML = jQuery('#wfNoScanYetTmpl').tmpl().html();
118
+
119
+
120
+ var loadingIssues = true;
121
+
122
+ this.loadIssues(function() {
123
+ loadingIssues = false;
124
+ });
125
this.startActivityLogUpdates();
126
if (this.needTour()) {
127
this.scanTourStart();
128
}
129
+
130
+ var issuesWrapper = $('#wfScanIssuesWrapper');
131
+ var hasScrolled = false;
132
+ $(window).on('scroll', function() {
133
+ var win = $(this);
134
+ // console.log(win.scrollTop() + window.innerHeight, liveTrafficWrapper.outerHeight() + liveTrafficWrapper.offset().top);
135
+ var currentScrollBottom = win.scrollTop() + window.innerHeight;
136
+ var scrollThreshold = issuesWrapper.outerHeight() + issuesWrapper.offset().top;
137
+ if (hasScrolled && !loadingIssues && currentScrollBottom >= scrollThreshold) {
138
+ // console.log('infinite scroll');
139
+
140
+ loadingIssues = true;
141
+ hasScrolled = false;
142
+ var offset = $('div.wfIssue').length;
143
+ WFAD.loadMoreIssues(function() {
144
+ loadingIssues = false;
145
+ }, offset);
146
+ } else if (currentScrollBottom < scrollThreshold) {
147
+ hasScrolled = true;
148
+ // console.log('no infinite scroll');
149
+ }
150
+ });
151
} else if (jQuery('#wordfenceMode_waf').length > 0) {
152
if (this.needTour()) {
153
this.tour('wfWAFTour', 'wfHeading', 'top', 'left', "Learn about Live Traffic", function() {
353
},
354
updateConfig: function(key, val, cb) {
355
this.ajax('wordfence_updateConfig', {key: key, val: val}, function() {
356
+ if (cb) {
357
+ cb();
358
+ }
359
});
360
},
361
tourFinish: function() {
824
jQuery('#wfAuditJobs').empty().html("<p>You don't have any password auditing jobs in progress or completed yet.</p>");
825
}
826
},
827
+ loadIssues: function(callback, offset, limit) {
828
if (this.mode != 'scan') {
829
return;
830
}
831
+ offset = offset || 0;
832
+ limit = limit || WordfenceAdminVars.scanIssuesPerPage;
833
var self = this;
834
+ this.ajax('wordfence_loadIssues', {offset: offset, limit: limit}, function(res) {
835
self.displayIssues(res, callback);
836
});
837
},
838
+ loadMoreIssues: function(callback, offset, limit) {
839
+ offset = offset || 0;
840
+ limit = limit || WordfenceAdminVars.scanIssuesPerPage;
841
+ var self = this;
842
+ this.ajax('wordfence_loadIssues', {offset: offset, limit: limit}, function(res) {
843
+ self.appendIssues(res.issuesLists, callback);
844
+ });
845
+ },
846
sev2num: function(str) {
847
if (/wfProbSev1/.test(str)) {
848
return 1;
913
"bPaginate": false,
914
"bLengthChange": false,
915
"bAutoWidth": false,
916
+ //"aaData": res.issuesLists[issueStatus],
917
"aoColumns": [
918
{
919
"sTitle": '<div class="th_wrapp">Severity</div>',
939
]
940
});
941
}
942
+
943
+ this.appendIssues(res.issuesLists, callback);
944
+
945
+ return true;
946
+ },
947
+ appendIssues: function(issuesLists, callback) {
948
+ for (var issueStatus in issuesLists) {
949
+ var tableID = 'wfIssuesTable_' + issueStatus;
950
+ if (jQuery('#' + tableID).length < 1) {
951
+ //Invalid issue status
952
+ continue;
953
+ }
954
+
955
+ jQuery('#' + tableID).dataTable().fnAddData(issuesLists[issueStatus]);
956
+ }
957
+
958
if (callback) {
959
jQuery('#wfIssues_' + this.visibleIssuesPanel).fadeIn(500, function() {
960
callback();
962
} else {
963
jQuery('#wfIssues_' + this.visibleIssuesPanel).fadeIn(500);
964
}
965
},
966
ajax: function(action, data, cb, cbErr, noLoading) {
967
if (typeof(data) == 'string') {
js/admin.liveTraffic.js CHANGED
@@ -356,6 +356,7 @@
356
case 'lockedOut':
357
return 'locked out from logging in';
358
359
case 'blocked:wordfence':
360
case 'blocked:wfsnrepeat':
361
desc = self.actionDescription();
356
case 'lockedOut':
357
return 'locked out from logging in';
358
359
+ case 'blocked:waf-always':
360
case 'blocked:wordfence':
361
case 'blocked:wfsnrepeat':
362
desc = self.actionDescription();
lib/GeoIP.dat CHANGED
Binary file
lib/GeoIPv6.dat CHANGED
Binary file
lib/email_newIssues.php CHANGED
@@ -42,6 +42,10 @@
42
43
<?php } } } ?>
44
45
46
<?php if(! $isPaid){ ?>
47
<p>NOTE: You are using the free version of Wordfence. Upgrade today:</p>
42
43
<?php } } } ?>
44
45
+ <?php if ($issuesNotShown > 0) { ?>
46
+ <p><?php echo wfUtils::pluralize($issuesNotShown, 'issue'); ?> were omitted from this email. View every issue: <a href="<?php echo $adminURL; ?>admin.php?page=Wordfence"><?php echo $adminURL; ?>admin.php?page=Wordfence</a></p>
47
+ <?php } ?>
48
+
49
50
<?php if(! $isPaid){ ?>
51
<p>NOTE: You are using the free version of Wordfence. Upgrade today:</p>
lib/menu_blockedIPs.php CHANGED
@@ -1,5 +1,5 @@
1
<div class="wordfenceModeElem" id="wordfenceMode_blockedIPs"></div>
2
- <div class="wrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $helpLink="http://docs.wordfence.com/en/Blocked_IPs"; $helpLabel="Learn more about Blocked IPs"; $pageTitle = "Wordfence Blocked IPs"; include('pageTitle.php'); ?>
5
<div class="wordfenceLive">
1
<div class="wordfenceModeElem" id="wordfenceMode_blockedIPs"></div>
2
+ <div class="wrap wordfence">
3
<?php require('menuHeader.php'); ?>
4
<?php $helpLink="http://docs.wordfence.com/en/Blocked_IPs"; $helpLabel="Learn more about Blocked IPs"; $pageTitle = "Wordfence Blocked IPs"; include('pageTitle.php'); ?>
5
<div class="wordfenceLive">
lib/menu_countryBlocking.php CHANGED
@@ -5,7 +5,7 @@ require('wfBulkCountries.php');
5
WFAD.countryMap = <?php echo json_encode($wfBulkCountries); ?>;
6
</script>
7
<div class="wordfenceModeElem" id="wordfenceMode_countryBlocking"></div>
8
- <div class="wrap" id="paidWrap">
9
<?php require('menuHeader.php'); ?>
10
<?php $pageTitle = "Block Selected Countries from Accessing your Site"; $helpLink="http://docs.wordfence.com/en/Country_blocking"; $helpLabel="Learn more about Country Blocking"; include('pageTitle.php'); ?>
11
<?php
5
WFAD.countryMap = <?php echo json_encode($wfBulkCountries); ?>;
6
</script>
7
<div class="wordfenceModeElem" id="wordfenceMode_countryBlocking"></div>
8
+ <div class="wrap wordfence" id="paidWrap">
9
<?php require('menuHeader.php'); ?>
10
<?php $pageTitle = "Block Selected Countries from Accessing your Site"; $helpLink="http://docs.wordfence.com/en/Country_blocking"; $helpLabel="Learn more about Country Blocking"; include('pageTitle.php'); ?>
11
<?php
lib/menu_diagnostic.php CHANGED
@@ -19,8 +19,11 @@ $w = new wfConfig();
19
<br clear="both"/>
20
21
<?php
22
- $rightRail = new wfView('marketing/rightrail', array('additionalClasses' => 'wordfenceRightRailDiagnostics'));
23
- echo $rightRail;
24
?>
25
26
<form id="wfConfigForm">
@@ -346,6 +349,43 @@ $w = new wfConfig();
346
</table>
347
</div>
348
<?php endif ?>
349
</form>
350
</div>
351
19
<br clear="both"/>
20
21
<?php
22
+ if (!isset($sendingDiagnosticEmail)) { $sendingDiagnosticEmail = false; }
23
+ if (!$sendingDiagnosticEmail) {
24
+ $rightRail = new wfView('marketing/rightrail', array('additionalClasses' => 'wordfenceRightRailDiagnostics'));
25
+ echo $rightRail;
26
+ }
27
?>
28
29
<form id="wfConfigForm">
349
</table>
350
</div>
351
<?php endif ?>
352
+ <div style="max-width: 100%; overflow: auto; padding: 1px;">
353
+ <table class="wf-table"<?php echo !empty($inEmail) ? ' border=1' : '' ?>>
354
+ <tbody class="empty-row">
355
+ <tr>
356
+ <td colspan="2"></td>
357
+ </tr>
358
+ </tbody>
359
+ <tbody class="thead">
360
+ <tr>
361
+ <th colspan="2">Log Files (Error messages from WordPress core, plugins, and themes)</th>
362
+ </tr>
363
+ </tbody>
364
+ <tbody class="thead thead-subhead" style="font-size: 85%">
365
+ <tr>
366
+ <th>File</th>
367
+ <th>Download</th>
368
+ </tr>
369
+ </tbody>
370
+ <tbody style="font-size: 85%">
371
+ <?php
372
+ $errorLogs = wfErrorLogHandler::getErrorLogs();
373
+ if (count($errorLogs) < 1): ?>
374
+ <tr>
375
+ <td colspan="2"><em>No log files found.</em></td>
376
+ </tr>
377
+ <?php else:
378
+ foreach ($errorLogs as $log => $readable): ?>
379
+ <tr>
380
+ <td style="width: 100%"><?php echo esc_html($log) . ' (' . wfUtils::formatBytes(filesize($log)) . ')'; ?></td>
381
+ <td style="white-space: nowrap; text-align: right;"><?php echo ($readable ? '<a href="#" data-logfile="' . esc_html($log) . '" class="downloadLogFile" target="_blank">Download</a>' : '<em>Requires downloading from the server directly</em>'); ?></td>
382
+ </tr>
383
+ <?php endforeach;
384
+ endif; ?>
385
+ </tbody>
386
+
387
+ </table>
388
+ </div>
389
</form>
390
</div>
391
lib/menu_options.php CHANGED
@@ -2,7 +2,7 @@
2
$w = new wfConfig();
3
?>
4
<div class="wordfenceModeElem" id="wordfenceMode_options"></div>
5
- <div class="wrap">
6
<?php require( 'menuHeader.php' ); ?>
7
<?php $helpLink = "http://docs.wordfence.com/en/Wordfence_options";
8
$helpLabel = "Learn more about Wordfence Options";
@@ -271,6 +271,12 @@ $w = new wfConfig();
271
enabled (see above), you'll get an email when an update occurs.
272
</td>
273
</tr>
274
<tr>
275
<th>Alert on critical problems</th>
276
<td><input type="checkbox" id="alertOn_critical" class="wfConfigElem" name="alertOn_critical"
@@ -618,6 +624,14 @@ $w = new wfConfig();
618
name="scan_exclude"><?php echo wfUtils::cleanupOneEntryPerLine($w->getHTML( 'scan_exclude' )); ?></textarea>
619
</td>
620
</tr>
621
<tr>
622
<td colspan="2">
623
<div class="wfMarker" id="wfMarkerFirewallRules"></div>
@@ -1031,6 +1045,18 @@ $w = new wfConfig();
1031
name="disableCodeExecutionUploads"
1032
value="1" <?php $w->cb( 'disableCodeExecutionUploads' ); ?> /></td>
1033
</tr>
1034
1035
<tr>
1036
<td colspan="2">
2
$w = new wfConfig();
3
?>
4
<div class="wordfenceModeElem" id="wordfenceMode_options"></div>
5
+ <div class="wrap wordfence">
6
<?php require( 'menuHeader.php' ); ?>
7
<?php $helpLink = "http://docs.wordfence.com/en/Wordfence_options";
8
$helpLabel = "Learn more about Wordfence Options";
271
enabled (see above), you'll get an email when an update occurs.
272
</td>
273
</tr>
274
+ <tr>
275
+ <th>Email me if Wordfence is deactivated</th>
276
+ <td><input type="checkbox" id="alertOn_wordfenceDeactivated" class="wfConfigElem" name="alertOn_wordfenceDeactivated"
277
+ value="1" <?php $w->cb( 'alertOn_wordfenceDeactivated' ); ?>/>
278
+ </td>
279
+ </tr>
280
<tr>
281
<th>Alert on critical problems</th>
282
<td><input type="checkbox" id="alertOn_critical" class="wfConfigElem" name="alertOn_critical"
624
name="scan_exclude"><?php echo wfUtils::cleanupOneEntryPerLine($w->getHTML( 'scan_exclude' )); ?></textarea>
625
</td>
626
</tr>
627
+ <tr>
628
+ <th>Limit the number of issues sent in the scan results email.</th>
629
+ <td>
630
+ <input type="text" name="scan_maxIssues" id="scan_maxIssues"
631
+ value="<?php $w->f( 'scan_maxIssues' ); ?>"/> 0 or empty means unlimited
632
+ issues will be sent.
633
+ </td>
634
+ </tr>
635
<tr>
636
<td colspan="2">
637
<div class="wfMarker" id="wfMarkerFirewallRules"></div>
1045
name="disableCodeExecutionUploads"
1046
value="1" <?php $w->cb( 'disableCodeExecutionUploads' ); ?> /></td>
1047
</tr>
1048
+ <tr class="hidden">
1049
+ <th style="vertical-align: top;">Monitor Front-end Background Requests for False Positives</th>
1050
+ <td><input type="checkbox" name="ajaxWatcherDisabled_front" id="ajaxWatcherDisabled_front" value="1" <?php $w->cb( 'ajaxWatcherDisabled_front' ); ?>></td>
1051
+ </tr>
1052
+ <tr class="hidden">
1053
+ <th style="vertical-align: top;">Monitor Admin Panel Background Requests for False Positives</th>
1054
+ <td><input type="checkbox" name="ajaxWatcherDisabled_admin" id="ajaxWatcherDisabled_admin" value="1" <?php $w->cb( 'ajaxWatcherDisabled_admin' ); ?>></td>
1055
+ </tr>
1056
+ <tr class="hidden">
1057
+ <th style="vertical-align: top;">Delay IP and Country blocking until after WordPress and plugins have loaded (only process firewall rules early)</th>
1058
+ <td><input type="checkbox" name="disableWAFIPBlocking" id="disableWAFIPBlocking" value="1" <?php $w->cb( 'disableWAFIPBlocking' ); ?>></td>
1059
+ </tr>
1060
1061
<tr>
1062
<td colspan="2">
lib/menu_passwd.php CHANGED
@@ -1,5 +1,5 @@
1
<div class="wordfenceModeElem" id="wordfenceMode_passwd"></div>
2
- <div class="wrap" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "Audit the Strength of your Passwords";
5
$helpLink = "http://docs.wordfence.com/en/Wordfence_Password_Auditing";
1
<div class="wordfenceModeElem" id="wordfenceMode_passwd"></div>
2
+ <div class="wrap wordfence" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "Audit the Strength of your Passwords";
5
$helpLink = "http://docs.wordfence.com/en/Wordfence_Password_Auditing";
lib/menu_rangeBlocking.php CHANGED
@@ -1,5 +1,5 @@
1
<div class="wordfenceModeElem" id="wordfenceMode_rangeBlocking"></div>
2
- <div class="wrap" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $helpLink="http://docs.wordfence.com/en/Advanced_Blocking"; $helpLabel="Learn more about Advanced Blocking"; $pageTitle = "Advanced Blocking"; include('pageTitle.php'); ?>
5
<?php
1
<div class="wordfenceModeElem" id="wordfenceMode_rangeBlocking"></div>
2
+ <div class="wrap wordfence" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $helpLink="http://docs.wordfence.com/en/Advanced_Blocking"; $helpLabel="Learn more about Advanced Blocking"; $pageTitle = "Advanced Blocking"; include('pageTitle.php'); ?>
5
<?php
lib/menu_scan.php CHANGED
@@ -163,7 +163,7 @@ $sigUpdateTime = wfConfig::get('signatureUpdateTime');
163
164
165
</div>
166
- <div style="margin-top: 20px;">
167
<div id="wfTabs">
168
<a href="#" id="wfNewIssuesTab" class="wfTab2 wfTabSwitch selected" onclick="wordfenceAdmin.switchIssuesTab(this, 'new'); return false;">New Issues</a>
169
<a href="#" class="wfTab2 wfTabSwitch" onclick="wordfenceAdmin.switchIssuesTab(this, 'ignored'); return false;">Ignored Issues</a>
163
164
165
</div>
166
+ <div id="wfScanIssuesWrapper" style="margin-top: 20px;">
167
<div id="wfTabs">
168
<a href="#" id="wfNewIssuesTab" class="wfTab2 wfTabSwitch selected" onclick="wordfenceAdmin.switchIssuesTab(this, 'new'); return false;">New Issues</a>
169
<a href="#" class="wfTab2 wfTabSwitch" onclick="wordfenceAdmin.switchIssuesTab(this, 'ignored'); return false;">Ignored Issues</a>
lib/menu_scanSchedule.php CHANGED
@@ -1,5 +1,5 @@
1
<div class="wordfenceModeElem" id="wordfenceMode_scanScheduling"></div>
2
- <div class="wrap" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "Schedule when Wordfence Scans Occur"; $helpLink="http://docs.wordfence.com/en/Wordfence_scan_scheduling"; $helpLabel="Learn more about Scheduling Wordfence Scans"; include('pageTitle.php'); ?>
5
<?php
1
<div class="wordfenceModeElem" id="wordfenceMode_scanScheduling"></div>
2
+ <div class="wrap wordfence" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "Schedule when Wordfence Scans Occur"; $helpLink="http://docs.wordfence.com/en/Wordfence_scan_scheduling"; $helpLabel="Learn more about Scheduling Wordfence Scans"; include('pageTitle.php'); ?>
5
<?php
lib/menu_sitePerf.php CHANGED
@@ -2,7 +2,7 @@
2
$w = new wfConfig();
3
?>
4
<div class="wordfenceModeElem" id="wordfenceMode_caching"></div>
5
- <div class="wrap">
6
<?php require('menuHeader.php'); ?>
7
<?php $pageTitle = "Your Site Performance"; $helpLink="http://docs.wordfence.com/en/Falcon_Cache"; $helpLabel="Learn more about Wordfence Caching"; include('pageTitle.php'); ?>
8
<?php
2
$w = new wfConfig();
3
?>
4
<div class="wordfenceModeElem" id="wordfenceMode_caching"></div>
5
+ <div class="wrap wordfence">
6
<?php require('menuHeader.php'); ?>
7
<?php $pageTitle = "Your Site Performance"; $helpLink="http://docs.wordfence.com/en/Falcon_Cache"; $helpLabel="Learn more about Wordfence Caching"; include('pageTitle.php'); ?>
8
<?php
lib/menu_sitePerfStats.php CHANGED
@@ -44,7 +44,7 @@
44
}
45
</style>
46
47
- <div class="wrap">
48
<?php require('menuHeader.php'); ?>
49
<div class="wordfence-lock-icon wordfence-icon32"><br /></div>
50
<h2 id="wfHeading">
44
}
45
</style>
46
47
+ <div class="wrap wordfence">
48
<?php require('menuHeader.php'); ?>
49
<div class="wordfence-lock-icon wordfence-icon32"><br /></div>
50
<h2 id="wfHeading">
lib/menu_twoFactor.php CHANGED
@@ -1,5 +1,5 @@
1
<div class="wordfenceModeElem" id="wordfenceMode_twoFactor"></div>
2
- <div class="wrap" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "Cellphone Sign-in"; $helpLink="http://docs.wordfence.com/en/Cellphone_sign-in"; $helpLabel="Learn more about Cellphone Sign-in"; include('pageTitle.php'); ?>
5
<?php
1
<div class="wordfenceModeElem" id="wordfenceMode_twoFactor"></div>
2
+ <div class="wrap wordfence" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "Cellphone Sign-in"; $helpLink="http://docs.wordfence.com/en/Cellphone_sign-in"; $helpLabel="Learn more about Cellphone Sign-in"; include('pageTitle.php'); ?>
5
<?php
lib/menu_waf.php CHANGED
@@ -5,7 +5,7 @@ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configu
5
$wafRemoveURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeAutoPrepend');
6
/** @var array $wafData */
7
?>
8
- <div class="wrap" id="paidWrap">
9
<?php require('menuHeader.php'); ?>
10
<?php
11
$pageTitle = "Wordfence Web Application Firewall";
@@ -269,12 +269,17 @@ $wafRemoveURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeA
269
</p>
270
<br>
271
272
- <?php if (WFWAF_AUTO_PREPEND) : ?>
273
<h2>Advanced Configuration</h2>
274
275
- <p><strong>Remove Extended Protection<a href="https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F" target="_blank"
276
class="wfhelp"></a></strong><br>
277
-
278
<em>If you're moving to a new host or a new installation location, you may need to temporarily disable extended protection to avoid any file not found errors. Use this action to remove the configuration changes that enable extended protection mode or you can <a href="https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F" target="_blank">remove them manually</a>.</em></p>
279
280
<p><a href="<?php echo $wafRemoveURL; ?>" class="button button-small" id="waf-remove-extended">Remove Extended Protection</a></p>
@@ -746,6 +751,11 @@ $wafRemoveURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeA
746
var disabled = this.checked ? 0 : 1;
747
WFAD.updateConfig('ajaxWatcherDisabled_admin', disabled);
748
})
749
})(jQuery);
750
</script>
751
5
$wafRemoveURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeAutoPrepend');
6
/** @var array $wafData */
7
?>
8
+ <div class="wrap wordfence" id="paidWrap">
9
<?php require('menuHeader.php'); ?>
10
<?php
11
$pageTitle = "Wordfence Web Application Firewall";
269
</p>
270
<br>
271
272
<h2>Advanced Configuration</h2>
273
+
274
+ <p id="waf-advanced-options">
275
+ <strong>Other Options</strong><br>
276
+ <label><input type="checkbox" id="waf-disable-ip-blocking" name="waf-disable-ip-blocking" value="1"<?php echo $config->getConfig('disableWAFIPBlocking') ? ' checked' : ''; ?>>Delay IP and Country blocking until after WordPress and plugins have loaded (only process firewall rules early)</label>
277
+ </p>
278
279
+ <?php if (WFWAF_AUTO_PREPEND) : ?>
280
+ <p><strong>Remove Extended Protection<a href="https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F" target="_blank"
281
class="wfhelp"></a></strong><br>
282
+
283
<em>If you're moving to a new host or a new installation location, you may need to temporarily disable extended protection to avoid any file not found errors. Use this action to remove the configuration changes that enable extended protection mode or you can <a href="https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F" target="_blank">remove them manually</a>.</em></p>
284
285
<p><a href="<?php echo $wafRemoveURL; ?>" class="button button-small" id="waf-remove-extended">Remove Extended Protection</a></p>
751
var disabled = this.checked ? 0 : 1;
752
WFAD.updateConfig('ajaxWatcherDisabled_admin', disabled);
753
})
754
+
755
+ $('#waf-disable-ip-blocking').on('click', function() {
756
+ var disabled = this.checked ? 1 : 0;
757
+ WFAD.updateConfig('disableWAFIPBlocking', disabled);
758
+ })
759
})(jQuery);
760
</script>
761
lib/menu_whois.php CHANGED
@@ -1,5 +1,5 @@
1
<div class="wordfenceModeElem" id="wordfenceMode_whois"></div>
2
- <div class="wrap" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "WHOIS Lookup"; $helpLink="http://docs.wordfence.com/en/Whois_Lookup"; $helpLabel="Learn more about Whois Lookups"; include('pageTitle.php'); ?>
5
<?php
1
<div class="wordfenceModeElem" id="wordfenceMode_whois"></div>
2
+ <div class="wrap wordfence" id="paidWrap">
3
<?php require('menuHeader.php'); ?>
4
<?php $pageTitle = "WHOIS Lookup"; $helpLink="http://docs.wordfence.com/en/Whois_Lookup"; $helpLabel="Learn more about Whois Lookups"; include('pageTitle.php'); ?>
5
<?php
lib/wf503.php CHANGED
@@ -5,7 +5,7 @@
5
<h1>Your access to this site has been limited</h1>
6
<p>Your access to this service has been temporarily limited. Please try again in a few minutes. (HTTP response code 503)</p>
7
<p>Reason: <span style="color: #F00;"><?php echo $reason; ?></span></p>
8
- <p style="width: 600px;"><b>Important note for site admins: </b>If you are the administrator of this website note that your access has been limited because you broke one of the Wordfence firewall rules.
9
The reason your access was limited is: <b>"<?php echo $reason; ?>"</b>.
10
<br /><br />
11
If this is a false positive, meaning that your access to your own site has been limited incorrectly, then you
@@ -13,7 +13,7 @@ will need to regain access to your site, go to the Wordfence "options" page, go
13
if you were blocked because it was detected that you are a fake Google crawler, then disable the rule that blocks fake google crawlers. Or if you were blocked because you
14
were accessing your site too quickly, then increase the number of accesses allowed per minute.
15
<br /><br />
16
- If you're still having trouble, then simply disable the Wordfence firewall and you will
17
still benefit from the other security features that Wordfence provides.
18
19
<br /><br />
5
<h1>Your access to this site has been limited</h1>
6
<p>Your access to this service has been temporarily limited. Please try again in a few minutes. (HTTP response code 503)</p>
7
<p>Reason: <span style="color: #F00;"><?php echo $reason; ?></span></p>
8
+ <p style="width: 600px;"><b>Important note for site admins: </b>If you are the administrator of this website note that your access has been limited because you broke one of the Wordfence blocking rules.
9
The reason your access was limited is: <b>"<?php echo $reason; ?>"</b>.
10
<br /><br />
11
If this is a false positive, meaning that your access to your own site has been limited incorrectly, then you
13
if you were blocked because it was detected that you are a fake Google crawler, then disable the rule that blocks fake google crawlers. Or if you were blocked because you
14
were accessing your site too quickly, then increase the number of accesses allowed per minute.
15
<br /><br />
16
+ If you're still having trouble, then simply disable the Wordfence advanced blocking and you will
17
still benefit from the other security features that Wordfence provides.
18
19
<br /><br />
lib/wfActivityReport.php CHANGED
@@ -190,16 +190,10 @@ class wfActivityReport {
190
* @return mixed
191
*/
192
public function getTopIPsBlocked($limit = 10) {
193
- $where = $this->getBlockedIPWhitelistWhereClause();
194
- if ($where) {
195
- $where = 'WHERE NOT (' . $where . ')';
196
- }
197
-
198
$results = $this->db->get_results($this->db->prepare(<<<SQL
199
SELECT *,
200
SUM(blockCount) as blockCount
201
FROM {$this->db->prefix}wfBlockedIPLog
202
- $where
203
GROUP BY IP
204
ORDER BY blockCount DESC
205
LIMIT %d
@@ -218,15 +212,9 @@ SQL
218
* @return array
219
*/
220
public function getTopCountriesBlocked($limit = 10) {
221
- $where = $this->getBlockedIPWhitelistWhereClause();
222
- if ($where) {
223
- $where = 'WHERE NOT (' . $where . ')';
224
- }
225
-
226
$results = $this->db->get_results($this->db->prepare(<<<SQL
227
SELECT *, COUNT(IP) as totalIPs, SUM(blockCount) as totalBlockCount
228
FROM {$this->db->base_prefix}wfBlockedIPLog
229
- $where
230
GROUP BY countryCode
231
ORDER BY totalBlockCount DESC
232
LIMIT %d
190
* @return mixed
191
*/
192
public function getTopIPsBlocked($limit = 10) {
193
$results = $this->db->get_results($this->db->prepare(<<<SQL
194
SELECT *,
195
SUM(blockCount) as blockCount
196
FROM {$this->db->prefix}wfBlockedIPLog
197
GROUP BY IP
198
ORDER BY blockCount DESC
199
LIMIT %d
212
* @return array
213
*/
214
public function getTopCountriesBlocked($limit = 10) {
215
$results = $this->db->get_results($this->db->prepare(<<<SQL
216
SELECT *, COUNT(IP) as totalIPs, SUM(blockCount) as totalBlockCount
217
FROM {$this->db->base_prefix}wfBlockedIPLog
218
GROUP BY countryCode
219
ORDER BY totalBlockCount DESC
220
LIMIT %d
lib/wfConfig.php CHANGED
@@ -25,8 +25,8 @@ class wfConfig {
25
"alertOn_firstAdminLoginOnly" => array('value' => false, 'autoload' => self::AUTOLOAD),
26
"alertOn_nonAdminLogin" => array('value' => false, 'autoload' => self::AUTOLOAD),
27
"alertOn_firstNonAdminLoginOnly" => array('value' => false, 'autoload' => self::AUTOLOAD),
28
"liveTrafficEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD),
29
- "scansEnabled_checkReadableConfig" => array('value' => true, 'autoload' => self::AUTOLOAD),
30
"advancedCommentScanning" => array('value' => false, 'autoload' => self::AUTOLOAD),
31
"checkSpamIP" => array('value' => false, 'autoload' => self::AUTOLOAD),
32
"spamvertizeCheck" => array('value' => false, 'autoload' => self::AUTOLOAD),
@@ -42,6 +42,7 @@ class wfConfig {
42
"scansEnabled_coreUnknown" => array('value' => true, 'autoload' => self::AUTOLOAD),
43
"scansEnabled_malware" => array('value' => true, 'autoload' => self::AUTOLOAD),
44
"scansEnabled_fileContents" => array('value' => true, 'autoload' => self::AUTOLOAD),
45
"scansEnabled_suspectedFiles" => array('value' => true, 'autoload' => self::AUTOLOAD),
46
"scansEnabled_posts" => array('value' => true, 'autoload' => self::AUTOLOAD),
47
"scansEnabled_comments" => array('value' => true, 'autoload' => self::AUTOLOAD),
@@ -86,11 +87,12 @@ class wfConfig {
86
'ajaxWatcherDisabled_front' => array('value' => false, 'autoload' => self::AUTOLOAD),
87
'ajaxWatcherDisabled_admin' => array('value' => false, 'autoload' => self::AUTOLOAD),
88
'wafAlertOnAttacks' => array('value' => true, 'autoload' => self::AUTOLOAD),
89
),
90
"otherParams" => array(
91
"scan_include_extra" => "",
92
// 'securityLevel' => '2',
93
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
94
'liveTraf_maxRows' => 2000,
95
"neverBlockBG" => "neverBlockVerified",
96
"loginSec_countFailMins" => "240",
@@ -282,12 +284,16 @@ class wfConfig {
282
283
if (!self::$tableExists) {
284
return;
285
- }
286
287
$table = self::table();
288
if ($wpdb->query($wpdb->prepare("INSERT INTO {$table} (name, val, autoload) values (%s, %s, %s) ON DUPLICATE KEY UPDATE val = %s, autoload = %s", $key, $val, $autoload, $val, $autoload)) !== false && $autoload != self::DONT_AUTOLOAD) {
289
self::updateCachedOption($key, $val);
290
}
291
}
292
public static function get($key, $default = false) {
293
global $wpdb;
25
"alertOn_firstAdminLoginOnly" => array('value' => false, 'autoload' => self::AUTOLOAD),
26
"alertOn_nonAdminLogin" => array('value' => false, 'autoload' => self::AUTOLOAD),
27
"alertOn_firstNonAdminLoginOnly" => array('value' => false, 'autoload' => self::AUTOLOAD),
28
+ "alertOn_wordfenceDeactivated" => array('value' => true, 'autoload' => self::AUTOLOAD),
29
"liveTrafficEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD),
30
"advancedCommentScanning" => array('value' => false, 'autoload' => self::AUTOLOAD),
31
"checkSpamIP" => array('value' => false, 'autoload' => self::AUTOLOAD),
32
"spamvertizeCheck" => array('value' => false, 'autoload' => self::AUTOLOAD),
42
"scansEnabled_coreUnknown" => array('value' => true, 'autoload' => self::AUTOLOAD),
43
"scansEnabled_malware" => array('value' => true, 'autoload' => self::AUTOLOAD),
44
"scansEnabled_fileContents" => array('value' => true, 'autoload' => self::AUTOLOAD),
45
+ "scansEnabled_checkReadableConfig" => array('value' => true, 'autoload' => self::AUTOLOAD),
46
"scansEnabled_suspectedFiles" => array('value' => true, 'autoload' => self::AUTOLOAD),
47
"scansEnabled_posts" => array('value' => true, 'autoload' => self::AUTOLOAD),
48
"scansEnabled_comments" => array('value' => true, 'autoload' => self::AUTOLOAD),
87
'ajaxWatcherDisabled_front' => array('value' => false, 'autoload' => self::AUTOLOAD),
88
'ajaxWatcherDisabled_admin' => array('value' => false, 'autoload' => self::AUTOLOAD),
89
'wafAlertOnAttacks' => array('value' => true, 'autoload' => self::AUTOLOAD),
90
+ 'disableWAFIPBlocking' => array('value' => false, 'autoload' => self::AUTOLOAD),
91
),
92
"otherParams" => array(
93
"scan_include_extra" => "",
94
// 'securityLevel' => '2',
95
+ "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'scan_maxIssues' => 1000, 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
96
'liveTraf_maxRows' => 2000,
97
"neverBlockBG" => "neverBlockVerified",
98
"loginSec_countFailMins" => "240",
284
285
if (!self::$tableExists) {
286
return;
287
288
+ }
289
$table = self::table();
290
if ($wpdb->query($wpdb->prepare("INSERT INTO {$table} (name, val, autoload) values (%s, %s, %s) ON DUPLICATE KEY UPDATE val = %s, autoload = %s", $key, $val, $autoload, $val, $autoload)) !== false && $autoload != self::DONT_AUTOLOAD) {
291
self::updateCachedOption($key, $val);
292
}
293
+
294
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController') && (substr($key, 0, 4) == 'cbl_' || $key == 'blockedTime' || $key == 'disableWAFIPBlocking')) {
295
+ wfWAFIPBlocksController::synchronizeConfigSettings();
296
+ }
297
}
298
public static function get($key, $default = false) {
299
global $wpdb;
lib/wfIPWhitelist.php CHANGED
@@ -30,6 +30,7 @@ $wfIPWhitelist = array(
30
'69.46.36.8/29',
31
'69.46.36.16/28',
32
'69.46.36.32/32',
33
),
34
'sucuri' => array(
35
'97.74.127.171',
@@ -221,4 +222,156 @@ $wfIPWhitelist = array(
221
'69.162.124.224/28',
222
'63.143.42.240/28',
223
),
224
);
30
'69.46.36.8/29',
31
'69.46.36.16/28',
32
'69.46.36.32/32',
33
+ '68.64.48.0/27',
34
),
35
'sucuri' => array(
36
'97.74.127.171',
222
'69.162.124.224/28',
223
'63.143.42.240/28',
224
),
225
+ 'statuscake' => array(
226
+ '103.194.112.70',
227
+ '104.131.247.151',
228
+ '104.131.248.65',
229
+ '104.131.248.78',
230
+ '104.156.229.24',
231
+ '104.156.255.184',
232
+ '104.206.168.26',
233
+ '104.238.164.105',
234
+ '107.150.1.135',
235
+ '107.155.104.182',
236
+ '107.155.108.234',
237
+ '107.155.125.29',
238
+ '107.161.28.219',
239
+ '107.170.197.248',
240
+ '107.170.219.46',
241
+ '107.170.227.23',
242
+ '107.170.227.24',
243
+ '107.170.240.141',
244
+ '107.170.53.191',
245
+ '107.191.47.131',
246
+ '107.191.57.237',
247
+ '108.61.119.153',
248
+ '108.61.162.214',
249
+ '108.61.205.201',
250
+ '108.61.212.141',
251
+ '108.61.215.179',
252
+ '125.63.48.239',
253
+ '128.199.222.65',
254
+ '138.197.130.232',
255
+ '138.197.130.235',
256
+ '138.197.140.243',
257
+ '138.204.171.136',
258
+ '138.68.24.115',
259
+ '138.68.24.136',
260
+ '138.68.24.207',
261
+ '138.68.24.60',
262
+ '138.68.80.10',
263
+ '138.68.80.173',
264
+ '139.59.15.79',
265
+ '139.59.155.26',
266
+ '139.59.190.241',
267
+ '139.59.22.109',
268
+ '139.59.26.85',
269
+ '139.59.29.167',
270
+ '149.154.157.61',
271
+ '149.255.59.100',
272
+ '151.236.10.238',
273
+ '151.236.18.80',
274
+ '151.80.175.223',
275
+ '151.80.175.226',
276
+ '154.127.60.23',
277
+ '154.127.60.59',
278
+ '158.255.208.76',
279
+ '159.203.182.22',
280
+ '159.203.182.60',
281
+ '159.203.186.225',
282
+ '159.203.31.18',
283
+ '162.243.247.163',
284
+ '162.243.71.56',
285
+ '162.248.97.72',
286
+ '162.253.64.104',
287
+ '162.253.64.87',
288
+ '176.56.230.110',
289
+ '178.62.101.57',
290
+ '178.62.104.137',
291
+ '178.62.106.84',
292
+ '178.62.109.7',
293
+ '178.62.40.233',
294
+ '178.62.41.44',
295
+ '178.62.41.49',
296
+ '178.62.41.52',
297
+ '178.62.65.162',
298
+ '178.62.71.227',
299
+ '178.62.78.199',
300
+ '178.62.80.93',
301
+ '178.62.86.69',
302
+ '178.73.210.99',
303
+ '181.41.201.117',
304
+ '181.41.214.137',
305
+ '185.112.157.185',
306
+ '185.12.45.70',
307
+ '185.47.129.168',
308
+ '185.60.135.86',
309
+ '188.166.158.224',
310
+ '188.166.253.148',
311
+ '188.226.139.158',
312
+ '188.226.158.160',
313
+ '188.226.169.228',
314
+ '188.226.171.58',
315
+ '188.226.184.152',
316
+ '188.226.185.106',
317
+ '188.226.186.199',
318
+ '188.226.203.84',
319
+ '188.226.247.184',
320
+ '188.68.238.79',
321
+ '192.241.221.11',
322
+ '193.124.178.54',
323
+ '193.124.178.61',
324
+ '193.182.144.105',
325
+ '193.182.144.147',
326
+ '199.167.128.80',
327
+ '209.222.30.242',
328
+ '213.183.56.107',
329
+ '217.148.43.188',
330
+ '217.148.43.202',
331
+ '31.220.7.237',
332
+ '37.157.246.146',
333
+ '37.235.48.42',
334
+ '37.235.52.25',
335
+ '37.235.53.240',
336
+ '37.235.55.205',
337
+ '37.97.188.103',
338
+ '45.32.128.80',
339
+ '45.32.145.79',
340
+ '45.32.151.21',
341
+ '45.32.160.172',
342
+ '45.32.166.195',
343
+ '45.32.171.24',
344
+ '45.32.192.198',
345
+ '45.32.195.186',
346
+ '45.32.195.93',
347
+ '45.32.212.56',
348
+ '45.32.36.158',
349
+ '45.32.7.22',
350
+ '45.63.121.159',
351
+ '45.63.26.78',
352
+ '45.63.51.63',
353
+ '45.63.61.213',
354
+ '45.63.76.68',
355
+ '45.63.78.84',
356
+ '45.63.86.120',
357
+ '45.63.88.213',
358
+ '45.76.1.44',
359
+ '45.76.192.50',
360
+ '45.76.3.112',
361
+ '46.101.0.24',
362
+ '46.101.110.32',
363
+ '46.101.110.43',
364
+ '46.101.110.45',
365
+ '46.101.20.96',
366
+ '46.101.238.182',
367
+ '46.101.238.189',
368
+ '46.101.240.208',
369
+ '46.101.27.186',
370
+ '46.101.61.83',
371
+ '46.101.74.251',
372
+ '5.45.179.103',
373
+ '50.2.139.16',
374
+ '82.221.95.161',
375
+ '91.236.116.163',
376
+ ),
377
);
lib/wfIssues.php CHANGED
@@ -6,16 +6,18 @@ class wfIssues {
6
//Properties that are serialized on sleep:
7
private $updateCalled = false;
8
private $issuesTable = '';
9
private $newIssues = array();
10
public $totalIssues = 0;
11
public $totalCriticalIssues = 0;
12
public $totalWarningIssues = 0;
13
public function __sleep(){ //Same order here as vars above
14
- return array('updateCalled', 'issuesTable', 'newIssues', 'totalIssues', 'totalCriticalIssues', 'totalWarningIssues');
15
}
16
public function __construct(){
17
global $wpdb;
18
$this->issuesTable = $wpdb->base_prefix . 'wfIssues';
19
}
20
public function __wakeup(){
21
$this->db = new wfDB();
@@ -48,15 +50,18 @@ class wfIssues {
48
$this->totalWarningIssues++;
49
}
50
$this->totalIssues++;
51
- $this->newIssues[] = array(
52
- 'type' => $type,
53
- 'severity' => $severity,
54
- 'ignoreP' => $ignoreP,
55
- 'ignoreC' => $ignoreC,
56
- 'shortMsg' => $shortMsg,
57
- 'longMsg' => $longMsg,
58
- 'tmplData' => $templateData
59
- );
60
61
$this->getDB()->queryWrite("insert into " . $this->issuesTable . " (time, status, type, severity, ignoreP, ignoreC, shortMsg, longMsg, data) values (unix_timestamp(), '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s')",
62
'new',
@@ -93,6 +98,7 @@ class wfIssues {
93
if(! is_array($emailedIssues)){
94
$emailedIssues = array();
95
}
96
$finalIssues = array();
97
foreach($this->newIssues as $newIssue){
98
$alreadyEmailed = false;
@@ -105,8 +111,14 @@ class wfIssues {
105
if(! $alreadyEmailed){
106
$finalIssues[] = $newIssue;
107
}
108
}
109
if(sizeof($finalIssues) < 1){ return; }
110
111
$totalWarningIssues = 0;
112
$totalCriticalIssues = 0;
@@ -126,7 +138,9 @@ class wfIssues {
126
'issues' => $finalIssues,
127
'totalCriticalIssues' => $totalCriticalIssues,
128
'totalWarningIssues' => $totalWarningIssues,
129
- 'level' => $level
130
));
131
132
wp_mail(implode(',', $emails), $subject, $content, 'Content-type: text/html');
@@ -146,7 +160,7 @@ class wfIssues {
146
$rec['data'] = unserialize($rec['data']);
147
return $rec;
148
}
149
- public function getIssues(){
150
/** @var wpdb $wpdb */
151
global $wpdb;
152
$ret = array(
@@ -154,7 +168,7 @@ class wfIssues {
154
'ignored' => array()
155
);
156
$userIni = ini_get('user_ini.filename');
157
- $q1 = $this->getDB()->querySelect("select * from " . $this->issuesTable . " order by time desc");
158
foreach($q1 as $i){
159
$i['data'] = unserialize($i['data']);
160
$i['timeAgo'] = wfUtils::makeTimeAgo(time() - $i['time']);
6
//Properties that are serialized on sleep:
7
private $updateCalled = false;
8
private $issuesTable = '';
9
+ private $maxIssues = 0;
10
private $newIssues = array();
11
public $totalIssues = 0;
12
public $totalCriticalIssues = 0;
13
public $totalWarningIssues = 0;
14
public function __sleep(){ //Same order here as vars above
15
+ return array('updateCalled', 'issuesTable', 'maxIssues', 'newIssues', 'totalIssues', 'totalCriticalIssues', 'totalWarningIssues');
16
}
17
public function __construct(){
18
global $wpdb;
19
$this->issuesTable = $wpdb->base_prefix . 'wfIssues';
20
+ $this->maxIssues = wfConfig::get('scan_maxIssues', 0);
21
}
22
public function __wakeup(){
23
$this->db = new wfDB();
50
$this->totalWarningIssues++;
51
}
52
$this->totalIssues++;
53
+ if (empty($this->maxIssues) || $this->totalIssues <= $this->maxIssues)
54
+ {
55
+ $this->newIssues[] = array(
56
+ 'type' => $type,
57
+ 'severity' => $severity,
58
+ 'ignoreP' => $ignoreP,
59
+ 'ignoreC' => $ignoreC,
60
+ 'shortMsg' => $shortMsg,
61
+ 'longMsg' => $longMsg,
62
+ 'tmplData' => $templateData
63
+ );
64
+ }
65
66
$this->getDB()->queryWrite("insert into " . $this->issuesTable . " (time, status, type, severity, ignoreP, ignoreC, shortMsg, longMsg, data) values (unix_timestamp(), '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s')",
67
'new',
98
if(! is_array($emailedIssues)){
99
$emailedIssues = array();
100
}
101
+ $overflowCount = $this->totalIssues - count($this->newIssues);
102
$finalIssues = array();
103
foreach($this->newIssues as $newIssue){
104
$alreadyEmailed = false;
111
if(! $alreadyEmailed){
112
$finalIssues[] = $newIssue;
113
}
114
+ else {
115
+ $overflowCount--;
116
+ }
117
}
118
if(sizeof($finalIssues) < 1){ return; }
119
+
120
+ $this->newIssues = array();
121
+ $this->totalIssues = 0;
122
123
$totalWarningIssues = 0;
124
$totalCriticalIssues = 0;
138
'issues' => $finalIssues,
139
'totalCriticalIssues' => $totalCriticalIssues,
140
'totalWarningIssues' => $totalWarningIssues,
141
+ 'level' => $level,
142
+ 'issuesNotShown' => $overflowCount,
143
+ 'adminURL' => get_admin_url(),
144
));
145
146
wp_mail(implode(',', $emails), $subject, $content, 'Content-type: text/html');
160
$rec['data'] = unserialize($rec['data']);
161
return $rec;
162
}
163
+ public function getIssues($offset = 0, $limit = 100){
164
/** @var wpdb $wpdb */
165
global $wpdb;
166
$ret = array(
168
'ignored' => array()
169
);
170
$userIni = ini_get('user_ini.filename');
171
+ $q1 = $this->getDB()->querySelect("select * from " . $this->issuesTable . " order by time desc LIMIT %d,%d", $offset, $limit);
172
foreach($q1 as $i){
173
$i['data'] = unserialize($i['data']);
174
$i['timeAgo'] = wfUtils::makeTimeAgo(time() - $i['time']);
lib/wfLog.php CHANGED
@@ -304,17 +304,33 @@ class wfLog {
304
public function unblockAllIPs(){
305
$this->getDB()->queryWrite("delete from " . $this->blocksTable);
306
wfCache::updateBlockedIPs('add');
307
}
308
public function unlockAllIPs(){
309
$this->getDB()->queryWrite("delete from " . $this->lockOutTable);
310
}
311
public function unblockIP($IP){
312
$this->getDB()->queryWrite("delete from " . $this->blocksTable . " where IP=%s", wfUtils::inet_pton($IP));
313
wfCache::updateBlockedIPs('add');
314
}
315
public function unblockRange($id){
316
$this->getDB()->queryWrite("delete from " . $this->ipRangesTable . " where id=%d", $id);
317
wfCache::updateBlockedIPs('add');
318
}
319
320
/**
@@ -328,6 +344,11 @@ class wfLog {
328
$reason = stripslashes($reason);
329
$this->getDB()->queryWrite("insert IGNORE into " . $this->ipRangesTable . " (blockType, blockString, ctime, reason, totalBlocked, lastBlocked) values ('%s', '%s', unix_timestamp(), '%s', 0, 0)", $blockType, $range, $reason);
330
wfCache::updateBlockedIPs('add');
331
return true;
332
}
333
public function getRangesBasic(){
@@ -430,6 +451,11 @@ class wfLog {
430
431
wfCache::updateBlockedIPs('add');
432
wfConfig::inc('totalIPsBlocked');
433
return true;
434
}
435
public function lockOutIP($IP, $reason){
@@ -450,10 +476,19 @@ class wfLog {
450
}
451
452
wfConfig::inc('totalIPsLocked');
453
return true;
454
}
455
public function unlockOutIP($IP){
456
$this->getDB()->queryWrite("delete from " . $this->lockOutTable . " where IP=%s", wfUtils::inet_pton($IP));
457
}
458
public function isIPLockedOut($IP){
459
if($this->getDB()->querySingle("select IP from " . $this->lockOutTable . " where IP=%s and blockedTime + %s > unix_timestamp()", wfUtils::inet_pton($IP), wfConfig::get('loginSec_lockoutMins') * 60)){
@@ -1030,7 +1065,7 @@ class wfLog {
1030
$hasRun = true;
1031
1032
$blockedCountries = wfConfig::get('cbl_countries', false);
1033
- $bareRequestURI = wfUtils::extractBareURI($_SERVER['REQUEST_URI']);
1034
$IP = wfUtils::getIP();
1035
if($country = wfUtils::IP2Country($IP) ){
1036
foreach(explode(',', $blockedCountries) as $blocked){
@@ -1042,7 +1077,7 @@ class wfLog {
1042
if($eRedirHost && $eRedirHost != wfUtils::extractHostname(home_url())){ //It's an external redirect...
1043
$isExternalRedir = true;
1044
}
1045
- if( (! $isExternalRedir) && wfUtils::extractBareURI($redirURL) == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it
1046
//Do nothing
1047
/* Uncomment the following if page components aren't loading for the page we redirect to.
1048
Uncommenting is not recommended because it means that anyone from a blocked country
@@ -1052,11 +1087,24 @@ class wfLog {
1052
//Do nothing
1053
*/
1054
} else {
1055
$this->redirect(wfConfig::get('cbl_redirURL'));
1056
}
1057
} else {
1058
$this->currentRequest->actionDescription = 'blocked access via country blocking';
1059
wfConfig::inc('totalCountryBlocked');
1060
$this->do503(3600, "Access from your area has been temporarily limited for security reasons");
1061
}
1062
}
@@ -1233,6 +1281,15 @@ class wfUserIPRange {
1233
1234
// IPv4 range
1235
if (strpos($ip_string, '.') !== false && strpos($ip, '.') !== false) {
1236
if (preg_match('/\[\d+\-\d+\]/', $ip_string)) {
1237
$IPparts = explode('.', $ip);
1238
$whiteParts = explode('.', $ip_string);
@@ -1314,23 +1371,26 @@ class wfUserIPRange {
1314
$sql = substr($sql, 0, -5) . ')';
1315
return $sql;
1316
1317
- } else if (strpos($ip_string, ':') !== false && preg_match('/\[[a-f0-9]+\-[a-f0-9]+\]/', $ip_string)) {
1318
- $whiteParts = explode(':', strtolower(self::expandIPv6Range($ip_string)));
1319
- $sql = '(';
1320
-
1321
- for ($i = 0; $i <= 7; $i++) {
1322
- // MySQL can only perform bitwise operations on integers
1323
- $conv = sprintf('CAST(CONV(HEX(SUBSTR(%s, %d, 8)), 16, 10) as UNSIGNED INTEGER)', $column, $i < 4 ? 1 : 9);
1324
- $j = 16 * (3 - ($i % 4));
1325
- if (preg_match('/^\[([a-f0-9]+)\-([a-f0-9]+)\]#x2F;', $whiteParts[$i], $m)) {
1326
- $sql .= $wpdb->prepare("$conv >> $j & 0xFFFF BETWEEN 0x%x AND 0x%x", hexdec($m[1]), hexdec($m[2]));
1327
- } else {
1328
- $sql .= $wpdb->prepare("$conv >> $j & 0xFFFF = 0x%x", hexdec($whiteParts[$i]));
1329
}
1330
- $sql .= ' AND ';
1331
}
1332
- $sql = substr($sql, 0, -5) . ')';
1333
- return $sql;
1334
}
1335
return $wpdb->prepare("($column = %s)", wfUtils::inet_pton($ip_string));
1336
}
@@ -1427,7 +1487,7 @@ class wfUserIPRange {
1427
* @param string|null $ip_string
1428
*/
1429
public function setIPString($ip_string) {
1430
- $this->ip_string = preg_replace('/[\x{2013}-\x{2015}]/u', '-', $ip_string); //Replace em-dash, en-dash, and horizontal bar with a regular dash
1431
}
1432
}
1433
@@ -2264,3 +2324,100 @@ class wfLiveTrafficQueryGroupBy {
2264
class wfLiveTrafficQueryException extends Exception {
2265
2266
}
304
public function unblockAllIPs(){
305
$this->getDB()->queryWrite("delete from " . $this->blocksTable);
306
wfCache::updateBlockedIPs('add');
307
+
308
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
309
+ wfWAFIPBlocksController::synchronizeConfigSettings();
310
+ }
311
}
312
public function unlockAllIPs(){
313
$this->getDB()->queryWrite("delete from " . $this->lockOutTable);
314
+
315
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
316
+ wfWAFIPBlocksController::synchronizeConfigSettings();
317
+ }
318
}
319
public function unblockIP($IP){
320
$this->getDB()->queryWrite("delete from " . $this->blocksTable . " where IP=%s", wfUtils::inet_pton($IP));
321
wfCache::updateBlockedIPs('add');
322
+
323
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
324
+ wfWAFIPBlocksController::synchronizeConfigSettings();
325
+ }
326
}
327
public function unblockRange($id){
328
$this->getDB()->queryWrite("delete from " . $this->ipRangesTable . " where id=%d", $id);
329
wfCache::updateBlockedIPs('add');
330
+
331
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
332
+ wfWAFIPBlocksController::synchronizeConfigSettings();
333
+ }
334
}
335
336
/**
344
$reason = stripslashes($reason);
345
$this->getDB()->queryWrite("insert IGNORE into " . $this->ipRangesTable . " (blockType, blockString, ctime, reason, totalBlocked, lastBlocked) values ('%s', '%s', unix_timestamp(), '%s', 0, 0)", $blockType, $range, $reason);
346
wfCache::updateBlockedIPs('add');
347
+
348
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
349
+ wfWAFIPBlocksController::synchronizeConfigSettings();
350
+ }
351
+
352
return true;
353
}
354
public function getRangesBasic(){
451
452
wfCache::updateBlockedIPs('add');
453
wfConfig::inc('totalIPsBlocked');
454
+
455
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
456
+ wfWAFIPBlocksController::synchronizeConfigSettings();
457
+ }
458
+
459
return true;
460
}
461
public function lockOutIP($IP, $reason){
476
}
477
478
wfConfig::inc('totalIPsLocked');
479
+
480
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
481
+ wfWAFIPBlocksController::synchronizeConfigSettings();
482
+ }
483
+
484
return true;
485
}
486
public function unlockOutIP($IP){
487
$this->getDB()->queryWrite("delete from " . $this->lockOutTable . " where IP=%s", wfUtils::inet_pton($IP));
488
+
489
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
490
+ wfWAFIPBlocksController::synchronizeConfigSettings();
491
+ }
492
}
493
public function isIPLockedOut($IP){
494
if($this->getDB()->querySingle("select IP from " . $this->lockOutTable . " where IP=%s and blockedTime + %s > unix_timestamp()", wfUtils::inet_pton($IP), wfConfig::get('loginSec_lockoutMins') * 60)){
1065
$hasRun = true;
1066
1067
$blockedCountries = wfConfig::get('cbl_countries', false);
1068
+ $bareRequestURI = untrailingslashit(wfUtils::extractBareURI($_SERVER['REQUEST_URI']));
1069
$IP = wfUtils::getIP();
1070
if($country = wfUtils::IP2Country($IP) ){
1071
foreach(explode(',', $blockedCountries) as $blocked){
1077
if($eRedirHost && $eRedirHost != wfUtils::extractHostname(home_url())){ //It's an external redirect...
1078
$isExternalRedir = true;
1079
}
1080
+ if( (! $isExternalRedir) && untrailingslashit(wfUtils::extractBareURI($redirURL)) == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it
1081
//Do nothing
1082
/* Uncomment the following if page components aren't loading for the page we redirect to.
1083
Uncommenting is not recommended because it means that anyone from a blocked country
1087
//Do nothing
1088
*/
1089
} else {
1090
+ wfConfig::inc('totalCountryBlocked');
1091
+
1092
+ $this->initLogRequest();
1093
+ $this->currentRequest->actionDescription = 'blocked access via country blocking and redirected to URL (' . wfConfig::get('cbl_redirURL') . ')';
1094
+ $this->currentRequest->statusCode = 503;
1095
+ if (!$this->currentRequest->action) {
1096
+ $this->currentRequest->action = 'blocked:wordfence';
1097
+ }
1098
+ $this->logHit();
1099
+
1100
+ wfActivityReport::logBlockedIP($IP);
1101
+
1102
$this->redirect(wfConfig::get('cbl_redirURL'));
1103
}
1104
} else {
1105
$this->currentRequest->actionDescription = 'blocked access via country blocking';
1106
wfConfig::inc('totalCountryBlocked');
1107
+ wfActivityReport::logBlockedIP($IP);
1108
$this->do503(3600, "Access from your area has been temporarily limited for security reasons");
1109
}
1110
}
1281
1282
// IPv4 range
1283
if (strpos($ip_string, '.') !== false && strpos($ip, '.') !== false) {
1284
+ // IPv4-mapped-IPv6
1285
+ if (preg_match('/:ffff:([^:]+)#x2F;i', $ip_string, $matches)) {
1286
+ $ip_string = $matches[1];
1287
+ }
1288
+ if (preg_match('/:ffff:([^:]+)#x2F;i', $ip, $matches)) {
1289
+ $ip = $matches[1];
1290
+ }
1291
+
1292
+ // Range check
1293
if (preg_match('/\[\d+\-\d+\]/', $ip_string)) {
1294
$IPparts = explode('.', $ip);
1295
$whiteParts = explode('.', $ip_string);
1371
$sql = substr($sql, 0, -5) . ')';
1372
return $sql;
1373
1374
+ } else if (strpos($ip_string, ':') !== false) {
1375
+ $ip_string = strtolower(self::expandIPv6Range($ip_string));
1376
+ if (preg_match('/\[[a-f0-9]+\-[a-f0-9]+\]/i', $ip_string)) {
1377
+ $whiteParts = explode(':', $ip_string);
1378
+ $sql = '(';
1379
+
1380
+ for ($i = 0; $i <= 7; $i++) {
1381
+ // MySQL can only perform bitwise operations on integers
1382
+ $conv = sprintf('CAST(CONV(HEX(SUBSTR(%s, %d, 8)), 16, 10) as UNSIGNED INTEGER)', $column, $i < 4 ? 1 : 9);
1383
+ $j = 16 * (3 - ($i % 4));
1384
+ if (preg_match('/^\[([a-f0-9]+)\-([a-f0-9]+)\]#x2F;i', $whiteParts[$i], $m)) {
1385
+ $sql .= $wpdb->prepare("$conv >> $j & 0xFFFF BETWEEN 0x%x AND 0x%x", hexdec($m[1]), hexdec($m[2]));
1386
+ } else {
1387
+ $sql .= $wpdb->prepare("$conv >> $j & 0xFFFF = 0x%x", hexdec($whiteParts[$i]));
1388
+ }
1389
+ $sql .= ' AND ';
1390
}
1391
+ $sql = substr($sql, 0, -5) . ')';
1392
+ return $sql;
1393
}
1394
}
1395
return $wpdb->prepare("($column = %s)", wfUtils::inet_pton($ip_string));
1396
}
1487
* @param string|null $ip_string
1488
*/
1489
public function setIPString($ip_string) {
1490
+ $this->ip_string = strtolower(preg_replace('/[\x{2013}-\x{2015}]/u', '-', $ip_string)); //Replace em-dash, en-dash, and horizontal bar with a regular dash
1491
}
1492
}
1493
2324
class wfLiveTrafficQueryException extends Exception {
2325
2326
}
2327
+
2328
+ class wfErrorLogHandler {
2329
+ public static function getErrorLogs($deepSearch = false) {
2330
+ static $errorLogs = null;
2331
+
2332
+ if ($errorLogs === null) {
2333
+ $searchPaths = array(ABSPATH, ABSPATH . 'wp-admin', ABSPATH . 'wp-content');
2334
+
2335
+ $homePath = get_home_path();
2336
+ if (!in_array($homePath, $searchPaths)) {
2337
+ $searchPaths[] = $homePath;
2338
+ }
2339
+
2340
+ $errorLogPath = ini_get('error_log');
2341
+ if (!empty($errorLogPath) && !in_array($errorLogPath, $searchPaths)) {
2342
+ $searchPaths[] = $errorLogPath;
2343
+ }
2344
+
2345
+ $errorLogs = array();
2346
+ foreach ($searchPaths as $s) {
2347
+ $errorLogs = array_merge($errorLogs, self::_scanForLogs($s, $deepSearch));
2348
+ }
2349
+ }
2350
+ return $errorLogs;
2351
+ }
2352
+
2353
+ private static function _scanForLogs($path, $deepSearch = false) {
2354
+ static $processedFolders = array(); //Protection for endless loops caused by symlinks
2355
+ if (is_file($path)) {
2356
+ $file = basename($path);
2357
+ if (preg_match('#(?:error_log(\-\d+)?$|\.log$)#i', $file)) {
2358
+ return array($path => is_readable($path));
2359
+ }
2360
+ return array();
2361
+ }
2362
+
2363
+ $path = untrailingslashit($path);
2364
+ $contents = @scandir($path);
2365
+ if (!is_array($contents)) {
2366
+ return array();
2367
+ }
2368
+
2369
+ $processedFolders[$path] = true;
2370
+ $errorLogs = array();
2371
+ foreach ($contents as $name) {
2372
+ if ($name == '.' || $name == '..') { continue; }
2373
+ $testPath = $path . DIRECTORY_SEPARATOR . $name;
2374
+ if (!array_key_exists($testPath, $processedFolders)) {
2375
+ if ((is_dir($testPath) && $deepSearch) || !is_dir($testPath)) {
2376
+ $errorLogs = array_merge($errorLogs, self::_scanForLogs($testPath, $deepSearch));
2377
+ }
2378
+ }
2379
+ }
2380
+ return $errorLogs;
2381
+ }
2382
+
2383
+ public static function outputErrorLog($path) {
2384
+ $errorLogs = self::getErrorLogs();
2385
+ if (!isset($errorLogs[$path])) { //Only allow error logs we've identified
2386
+ status_header(404);
2387
+ nocache_headers();
2388
+
2389
+ $template = get_404_template();
2390
+ if ($template && file_exists($template)) {
2391
+ include($template);
2392
+ }
2393
+ exit;
2394
+ }
2395
+
2396
+ $fh = @fopen($path, 'r');
2397
+ if (!$fh) {
2398
+ status_header(503);
2399
+ nocache_headers();
2400
+ echo "503 Service Unavailable";
2401
+ exit;
2402
+ }
2403
+
2404
+ $headersOutputted = false;
2405
+ while (!feof($fh)) {
2406
+ $data = fread($fh, 1 * 1024 * 1024); //read 1 megs max per chunk
2407
+ if ($data === false) { //Handle the error where the file was reported readable but we can't actually read it
2408
+ status_header(503);
2409
+ nocache_headers();
2410
+ echo "503 Service Unavailable";
2411
+ exit;
2412
+ }
2413
+
2414
+ if (!$headersOutputted) {
2415
+ header('Content-Type: text/plain');
2416
+ header('Content-Disposition: attachment; filename="' . basename($path));
2417
+ $headersOutputted = true;
2418
+ }
2419
+ echo $data;
2420
+ }
2421
+ exit;
2422
+ }
2423
+ }
lib/wfUtils.php CHANGED
@@ -134,13 +134,17 @@ class wfUtils {
134
return false;
135
}
136
}
137
-
138
- // Convert human readable addresses to 128 bit (IPv6) binary strings
139
- // Note: self::inet_pton converts IPv4 addresses to IPv6 compatible versions
140
- $binary_network = str_pad(wfHelperBin::bin2str(self::inet_pton($network)), 128, '0', STR_PAD_LEFT);
141
- $binary_ip = str_pad(wfHelperBin::bin2str(self::inet_pton($ip)), 128, '0', STR_PAD_LEFT);
142
-
143
- return 0 === substr_compare($binary_ip, $binary_network, 0, $prefix);
144
}
145
146
/**
@@ -647,7 +651,7 @@ class wfUtils {
647
return self::getCleanIPAndServerVar(array($connectionIP));
648
} else {
649
$ipsToCheck = array(
650
- array($_SERVER[$howGet], $howGet),
651
$connectionIP,
652
);
653
return self::getCleanIPAndServerVar($ipsToCheck);
134
return false;
135
}
136
}
137
+
138
+ $bin_network = substr(self::inet_pton($network), 0, ceil($prefix / 8));
139
+ $bin_ip = substr(self::inet_pton($ip), 0, ceil($prefix / 8));
140
+ if ($prefix % 8 != 0) { //Adjust the last relevant character to fit the mask length since the character's bits are split over it
141
+ $pos = intval($prefix / 8);
142
+ $adjustment = chr(((0xff << (8 - ($prefix % 8))) & 0xff));
143
+ $bin_network[$pos] = ($bin_network[$pos] & $adjustment);
144
+ $bin_ip[$pos] = ($bin_ip[$pos] & $adjustment);
145
+ }
146
+
147
+ return ($bin_network === $bin_ip);
148
}
149
150
/**
651
return self::getCleanIPAndServerVar(array($connectionIP));
652
} else {
653
$ipsToCheck = array(
654
+ array((isset($_SERVER[$howGet]) ? $_SERVER[$howGet] : ''), $howGet),
655
$connectionIP,
656
);
657
return self::getCleanIPAndServerVar($ipsToCheck);
lib/wordfenceClass.php CHANGED
@@ -48,6 +48,13 @@ class wordfence {
48
update_option('wordfenceActivated', 1);
49
}
50
public static function uninstallPlugin(){
51
//Check if caching is enabled and if it is, disable it and fix the .htaccess file.
52
$cacheType = wfConfig::get('cacheType', false);
53
if($cacheType == 'falcon'){
@@ -552,6 +559,11 @@ SQL
552
553
wp_schedule_single_event(time(), 'wordfence_sendFalconDeprecationNotice');
554
}
555
556
//Must be the final line
557
}
@@ -1018,7 +1030,11 @@ SQL
1018
1019
$wfFunc = isset($_GET['_wfsf']) ? @$_GET['_wfsf'] : false;
1020
if($wfFunc == 'unlockEmail'){
1021
- if(! wp_verify_nonce(@$_POST['nonce'], 'wf-form')){
1022
die("Sorry but your browser sent an invalid security token when trying to use this form.");
1023
}
1024
$numTries = get_transient('wordfenceUnlockTries');
@@ -1029,9 +1045,10 @@ SQL
1029
if(! $numTries){ $numTries = 1; } else { $numTries = $numTries + 1; }
1030
set_transient('wordfenceUnlockTries', $numTries, 180);
1031
1032
- $email = trim($_POST['email']);
1033
global $wpdb;
1034
$ws = $wpdb->get_results($wpdb->prepare("SELECT ID, user_login FROM $wpdb->users WHERE user_email = %s", $email));
1035
foreach($ws as $user){
1036
$userDat = get_userdata($user->ID);
1037
if(wfUtils::isAdmin($userDat)){
@@ -1116,10 +1133,15 @@ SQL
1116
'whitelistedIPs' => (string) wfConfig::get('whitelisted'),
1117
'howGetIPs' => (string) wfConfig::get('howGetIPs'),
1118
'other_WFNet' => wfConfig::get('other_WFNet', true),
1119
);
1120
foreach ($configDefaults as $key => $value) {
1121
$waf->getStorageEngine()->setConfig($key, $value);
1122
}
1123
1124
if (empty($_GET['wordfence_syncAttackData'])) {
1125
$lastAttackMicroseconds = $wpdb->get_var("SELECT MAX(attackLogTime) FROM {$wpdb->base_prefix}wfHits");
@@ -2001,6 +2023,7 @@ SQL
2001
public static function ajax_sendDiagnostic_callback(){
2002
$inEmail = true;
2003
$body = "This email is the diagnostic from " . site_url() . ".\nThe IP address that requested this was: " . wfUtils::getIP() . "\nTicket Number/Forum Username: " . $_POST['ticket'];
2004
ob_start();
2005
require 'menu_diagnostic.php';
2006
$body = nl2br($body) . ob_get_clean();
@@ -2685,6 +2708,15 @@ SQL
2685
readfile($file);
2686
die();
2687
}
2688
public static function ajax_addCacheExclusion_callback(){
2689
$ex = wfConfig::get('cacheExclusions', false);
2690
if($ex){
@@ -3205,8 +3237,11 @@ HTACCESS;
3205
);
3206
}
3207
public static function ajax_loadIssues_callback(){
3208
$i = new wfIssues();
3209
- $iss = $i->getIssues();
3210
return array(
3211
'issuesLists' => $iss,
3212
'summary' => $i->getSummaryItems(),
@@ -4253,7 +4288,7 @@ HTML;
4253
'exportSettings', 'importSettings', 'bulkOperation', 'deleteFile', 'deleteDatabaseOption', 'removeExclusion',
4254
'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues',
4255
'reverseLookup', 'unlockOutIP', 'loadBlockRanges', 'unblockRange', 'blockIPUARange', 'whois', 'unblockIP',
4256
- 'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'downloadHtaccess', 'checkFalconHtaccess',
4257
'updateConfig', 'saveCacheConfig', 'removeFromCache', 'autoUpdateChoice', 'adminEmailChoice', 'suPHPWAFUpdateChoice', 'falconDeprecationChoice', 'saveCacheOptions', 'clearPageCache',
4258
'getCacheStats', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule', 'tourClosed',
4259
'welcomeClosed', 'startTourAgain', 'downgradeLicense', 'addTwoFactor', 'twoFacActivate', 'twoFacDel',
@@ -4390,7 +4425,8 @@ HTML;
4390
'tourClosed' => wfConfig::get('tourClosed', 0),
4391
'welcomeClosed' => wfConfig::get('welcomeClosed', 0),
4392
'cacheType' => wfConfig::get('cacheType'),
4393
- 'liveTrafficEnabled' => wfConfig::liveTrafficEnabled()
4394
));
4395
}
4396
public static function activation_warning(){
@@ -6287,7 +6323,7 @@ ALERTMSG;
6287
$limit = 500;
6288
$lastSendTime = wfConfig::get('lastAttackDataSendTime');
6289
$attackData = $wpdb->get_results($wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$wpdb->base_prefix}wfHits
6290
- WHERE action in ('blocked:waf', 'learned:waf', 'logged:waf')
6291
AND attackLogTime > %.6f
6292
LIMIT %d", $lastSendTime, $limit));
6293
$totalRows = $wpdb->get_var('SELECT FOUND_ROWS()');
@@ -6330,6 +6366,7 @@ LIMIT %d", $lastSendTime, $limit));
6330
'k' => $waf->getStorageEngine()->getConfig('apiKey'),
6331
's' => $waf->getStorageEngine()->getConfig('siteURL') ? $waf->getStorageEngine()->getConfig('siteURL') :
6332
sprintf('%s://%s/', $waf->getRequest()->getProtocol(), rawurlencode($waf->getRequest()->getHost())),
6333
), null, '&'),
6334
array(
6335
'body' => json_encode($dataToSend),
@@ -6382,11 +6419,11 @@ LIMIT %d", $lastSendTime, $limit));
6382
$attackData = $waf->getStorageEngine()->getNewestAttackDataArray($lastAttackMicroseconds);
6383
if ($attackData) {
6384
foreach ($attackData as $request) {
6385
- if (count($request) !== 9) {
6386
continue;
6387
}
6388
6389
- list($logTimeMicroseconds, $requestTime, $ip, $learningMode, $paramKey, $paramValue, $failedRules, $ssl, $requestString) = $request;
6390
6391
// Skip old entries and hits in learning mode, since they'll get picked up anyways.
6392
if ($logTimeMicroseconds <= $lastAttackMicroseconds || $learningMode) {
@@ -6437,12 +6474,59 @@ LIMIT %d", $lastSendTime, $limit));
6437
$path = $matches[1];
6438
}
6439
}
6440
-
6441
- if ($failedRules == 'logged') {
6442
- $hit->action = 'logged:waf';
6443
}
6444
else {
6445
- $hit->action = 'blocked:waf';
6446
}
6447
6448
/** @var wfWAFRule $rule */
@@ -6457,13 +6541,13 @@ LIMIT %d", $lastSendTime, $limit));
6457
if ($ruleIDs && $ruleIDs[0]) {
6458
$rule = $waf->getRule($ruleIDs[0]);
6459
if ($rule) {
6460
- $hit->actionDescription = $rule->getDescription();
6461
$actionData['category'] = $rule->getCategory();
6462
$actionData['ssl'] = $ssl;
6463
$actionData['fullRequest'] = base64_encode($requestString);
6464
}
6465
else if ($ruleIDs[0] == 'logged') {
6466
- $hit->actionDescription = 'Watched IP Traffic: ' . $ip;
6467
$actionData['category'] = 'logged';
6468
$actionData['ssl'] = $ssl;
6469
$actionData['fullRequest'] = base64_encode($requestString);
48
update_option('wordfenceActivated', 1);
49
}
50
public static function uninstallPlugin(){
51
+ //Send admin alert
52
+ if (wfConfig::get('alertOn_wordfenceDeactivated')) {
53
+ $currentUser = wp_get_current_user();
54
+ $username = $currentUser->user_login;
55
+ wordfence::alert("Wordfence Deactivated", "A user with username \"$username\" deactivated Wordfence on your WordPress site.", wfUtils::getIP());
56
+ }
57
+
58
//Check if caching is enabled and if it is, disable it and fix the .htaccess file.
59
$cacheType = wfConfig::get('cacheType', false);
60
if($cacheType == 'falcon'){
559
560
wp_schedule_single_event(time(), 'wordfence_sendFalconDeprecationNotice');
561
}
562
+
563
+ //6.2.3
564
+ if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
565
+ wfWAFIPBlocksController::synchronizeConfigSettings();
566
+ }
567
568
//Must be the final line
569
}
1030
1031
$wfFunc = isset($_GET['_wfsf']) ? @$_GET['_wfsf'] : false;
1032
if($wfFunc == 'unlockEmail'){
1033
+ $nonceValid = wp_verify_nonce(@$_POST['nonce'], 'wf-form');
1034
+ if (!$nonceValid && method_exists(wfWAF::getInstance(), 'createNonce')) {
1035
+ $nonceValid = wfWAF::getInstance()->verifyNonce(@$_POST['nonce'], 'wf-form');
1036
+ }
1037
+ if(!$nonceValid){
1038
die("Sorry but your browser sent an invalid security token when trying to use this form.");
1039
}
1040
$numTries = get_transient('wordfenceUnlockTries');
1045
if(! $numTries){ $numTries = 1; } else { $numTries = $numTries + 1; }
1046
set_transient('wordfenceUnlockTries', $numTries, 180);
1047
1048
+ $email = trim(@$_POST['email']);
1049
global $wpdb;
1050
$ws = $wpdb->get_results($wpdb->prepare("SELECT ID, user_login FROM $wpdb->users WHERE user_email = %s", $email));
1051
+ $found = false;
1052
foreach($ws as $user){
1053
$userDat = get_userdata($user->ID);
1054
if(wfUtils::isAdmin($userDat)){
1133
'whitelistedIPs' => (string) wfConfig::get('whitelisted'),
1134
'howGetIPs' => (string) wfConfig::get('howGetIPs'),
1135
'other_WFNet' => wfConfig::get('other_WFNet', true),
1136
+ 'pluginABSPATH' => ABSPATH,
1137
);
1138
foreach ($configDefaults as $key => $value) {
1139
$waf->getStorageEngine()->setConfig($key, $value);
1140
}
1141
+
1142
+ if (class_exists('wfWAFIPBlocksController')) {
1143
+ wfWAFIPBlocksController::synchronizeConfigSettings();
1144
+ }
1145
1146
if (empty($_GET['wordfence_syncAttackData'])) {
1147
$lastAttackMicroseconds = $wpdb->get_var("SELECT MAX(attackLogTime) FROM {$wpdb->base_prefix}wfHits");
2023
public static function ajax_sendDiagnostic_callback(){
2024
$inEmail = true;
2025
$body = "This email is the diagnostic from " . site_url() . ".\nThe IP address that requested this was: " . wfUtils::getIP() . "\nTicket Number/Forum Username: " . $_POST['ticket'];
2026
+ $sendingDiagnosticEmail = true;
2027
ob_start();
2028
require 'menu_diagnostic.php';
2029
$body = nl2br($body) . ob_get_clean();
2708
readfile($file);
2709
die();
2710
}
2711
+ public static function ajax_downloadLogFile_callback() {
2712
+ if (!isset($_GET['logfile'])) {
2713
+ status_header(400);
2714
+ nocache_headers();
2715
+ exit;
2716
+ }
2717
+
2718
+ wfErrorLogHandler::outputErrorLog($_GET['logfile']); //exits
2719
+ }
2720
public static function ajax_addCacheExclusion_callback(){
2721
$ex = wfConfig::get('cacheExclusions', false);
2722
if($ex){
3237
);
3238
}
3239
public static function ajax_loadIssues_callback(){
3240
+ $offset = isset($_POST['offset']) ? intval($_POST['offset']) : 0;
3241
+ $limit = isset($_POST['limit']) ? intval($_POST['limit']) : WORDFENCE_SCAN_ISSUES_PER_PAGE;
3242
+
3243
$i = new wfIssues();
3244
+ $iss = $i->getIssues($offset, $limit);
3245
return array(
3246
'issuesLists' => $iss,
3247
'summary' => $i->getSummaryItems(),
4288
'exportSettings', 'importSettings', 'bulkOperation', 'deleteFile', 'deleteDatabaseOption', 'removeExclusion',
4289
'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues',
4290
'reverseLookup', 'unlockOutIP', 'loadBlockRanges', 'unblockRange', 'blockIPUARange', 'whois', 'unblockIP',
4291
+ 'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'downloadHtaccess', 'downloadLogFile', 'checkFalconHtaccess',
4292
'updateConfig', 'saveCacheConfig', 'removeFromCache', 'autoUpdateChoice', 'adminEmailChoice', 'suPHPWAFUpdateChoice', 'falconDeprecationChoice', 'saveCacheOptions', 'clearPageCache',
4293
'getCacheStats', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule', 'tourClosed',
4294
'welcomeClosed', 'startTourAgain', 'downgradeLicense', 'addTwoFactor', 'twoFacActivate', 'twoFacDel',
4425
'tourClosed' => wfConfig::get('tourClosed', 0),
4426
'welcomeClosed' => wfConfig::get('welcomeClosed', 0),
4427
'cacheType' => wfConfig::get('cacheType'),
4428
+ 'liveTrafficEnabled' => wfConfig::liveTrafficEnabled(),
4429
+ 'scanIssuesPerPage' => WORDFENCE_SCAN_ISSUES_PER_PAGE,
4430
));
4431
}
4432
public static function activation_warning(){
6323
$limit = 500;
6324
$lastSendTime = wfConfig::get('lastAttackDataSendTime');
6325
$attackData = $wpdb->get_results($wpdb->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM {$wpdb->base_prefix}wfHits
6326
+ WHERE action in ('blocked:waf', 'learned:waf', 'logged:waf', 'blocked:waf-always')
6327
AND attackLogTime > %.6f
6328
LIMIT %d", $lastSendTime, $limit));
6329
$totalRows = $wpdb->get_var('SELECT FOUND_ROWS()');
6366
'k' => $waf->getStorageEngine()->getConfig('apiKey'),
6367
's' => $waf->getStorageEngine()->getConfig('siteURL') ? $waf->getStorageEngine()->getConfig('siteURL') :
6368
sprintf('%s://%s/', $waf->getRequest()->getProtocol(), rawurlencode($waf->getRequest()->getHost())),
6369
+ 't' => microtime(true),
6370
), null, '&'),
6371
array(
6372
'body' => json_encode($dataToSend),
6419
$attackData = $waf->getStorageEngine()->getNewestAttackDataArray($lastAttackMicroseconds);
6420
if ($attackData) {
6421
foreach ($attackData as $request) {
6422
+ if (count($request) !== 9 && count($request) !== 10 /* with metadata */) {
6423
continue;
6424
}
6425
6426
+ list($logTimeMicroseconds, $requestTime, $ip, $learningMode, $paramKey, $paramValue, $failedRules, $ssl, $requestString, $metadata) = $request;
6427
6428
// Skip old entries and hits in learning mode, since they'll get picked up anyways.
6429
if ($logTimeMicroseconds <= $lastAttackMicroseconds || $learningMode) {
6474
$path = $matches[1];
6475
}
6476
}
6477
+
6478
+ $metadata = ($metadata != null ? (array) $metadata : array());
6479
+ if (isset($metadata['finalAction']) && $metadata['finalAction']) { // The request was blocked/redirected because of its IP based on the plugin's blocking settings. WAF blocks should be reported but not shown in live traffic with that as a reason.
6480
+ $action = $metadata['finalAction']['action'];
6481
+ $actionDescription = $action;
6482
+ if (class_exists('wfWAFIPBlocksController')) {
6483
+ if ($action == wfWAFIPBlocksController::WFWAF_BLOCK_UAREFIPRANGE) {
6484
+ $id = $metadata['finalAction']['id'];
6485
+ $wpdb->query($wpdb->prepare("UPDATE {$wpdb->base_prefix}wfBlocksAdv SET totalBlocked = totalBlocked + 1, lastBlocked = %d WHERE id = %d", $requestTime, $id));
6486
+ wfActivityReport::logBlockedIP($ip);
6487
+ }
6488
+ else if ($action == wfWAFIPBlocksController::WFWAF_BLOCK_COUNTRY_REDIR) {
6489
+ $actionDescription .= ' (' . wfConfig::get('cbl_redirURL') . ')';
6490
+ wfConfig::inc('totalCountryBlocked');
6491
+ wfActivityReport::logBlockedIP($ip);
6492
+ }
6493
+ else if ($action == wfWAFIPBlocksController::WFWAF_BLOCK_COUNTRY) {
6494
+ wfConfig::inc('totalCountryBlocked');
6495
+ wfActivityReport::logBlockedIP($ip);
6496
+ }
6497
+ else if ($action == wfWAFIPBlocksController::WFWAF_BLOCK_WFSN) {
6498
+ wordfence::wfsnReportBlockedAttempt($ip, 'login');
6499
+ }
6500
+ }
6501
+
6502
+ if (strlen($actionDescription) == 0) {
6503
+ $actionDescription = 'Blocked by Wordfence';
6504
+ }
6505
+
6506
+ if (empty($failedRules)) { // Just a plugin block
6507
+ $hit->action = 'blocked:wordfence';
6508
+ if (class_exists('wfWAFIPBlocksController')) {
6509
+ if ($action == wfWAFIPBlocksController::WFWAF_BLOCK_WFSN) {
6510
+ $hit->action = 'blocked:wfsnrepeat';
6511
+ }
6512
+ }
6513
+ $hit->actionDescription = $actionDescription;
6514
+ }
6515
+ else if ($failedRules == 'logged') {
6516
+ $hit->action = 'logged:waf';
6517
+ }
6518
+ else { // Blocked by the WAF but would've been blocked anyway by the plugin settings so that message takes priority
6519
+ $hit->action = 'blocked:waf-always';
6520
+ $hit->actionDescription = $actionDescription;
6521
+ }
6522
}
6523
else {
6524
+ if ($failedRules == 'logged') {
6525
+ $hit->action = 'logged:waf';
6526
+ }
6527
+ else {
6528
+ $hit->action = 'blocked:waf';
6529
+ }
6530
}
6531
6532
/** @var wfWAFRule $rule */
6541
if ($ruleIDs && $ruleIDs[0]) {
6542
$rule = $waf->getRule($ruleIDs[0]);
6543
if ($rule) {
6544
+ if ($hit->action == 'logged:waf' || $hit->action == 'blocked:waf') { $hit->actionDescription = $rule->getDescription(); }
6545
$actionData['category'] = $rule->getCategory();
6546
$actionData['ssl'] = $ssl;
6547
$actionData['fullRequest'] = base64_encode($requestString);
6548
}
6549
else if ($ruleIDs[0] == 'logged') {
6550
+ if ($hit->action == 'logged:waf' || $hit->action == 'blocked:waf') { $hit->actionDescription = 'Watched IP Traffic: ' . $ip; }
6551
$actionData['category'] = 'logged';
6552
$actionData['ssl'] = $ssl;
6553
$actionData['fullRequest'] = base64_encode($requestString);
lib/wordfenceConstants.php CHANGED
@@ -13,4 +13,5 @@ define('WORDFENCE_REVERSE_LOOKUP_CACHE_TIME', 86400);
13
define('WORDFENCE_MAX_FILE_SIZE_TO_PROCESS', 52428800); //50 megs
14
define('WORDFENCE_TWO_FACTOR_GRACE_TIME_AUTHENTICATOR', 90);
15
define('WORDFENCE_TWO_FACTOR_GRACE_TIME_PHONE', 1800);
16
?>
13
define('WORDFENCE_MAX_FILE_SIZE_TO_PROCESS', 52428800); //50 megs
14
define('WORDFENCE_TWO_FACTOR_GRACE_TIME_AUTHENTICATOR', 90);
15
define('WORDFENCE_TWO_FACTOR_GRACE_TIME_PHONE', 1800);
16
+ if (!defined('WORDFENCE_SCAN_ISSUES_PER_PAGE')) { define('WORDFENCE_SCAN_ISSUES_PER_PAGE', 100); }
17
?>
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
Requires at least: 3.9
5
Tested up to: 4.6.1
6
- Stable tag: 6.2.2
7
8
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
@@ -190,6 +190,21 @@ Secure your website with Wordfence.
190
191
== Changelog ==
192
193
= 6.2.2 =
194
* Fix: Replaced a slow query in the dashboard widget that could affect sites with very large numbers of users.
195
3
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
Requires at least: 3.9
5
Tested up to: 4.6.1
6
+ Stable tag: 6.2.3
7
8
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
190
191
== Changelog ==
192
193
+ = 6.2.3 =
194
+ * Improvement: Reworked blocking for IP ranges, country blocking, and direct IP blocking to minimize server impact when under attack.
195
+ * Improvement: Live traffic better indicates the action taken by country blocking when it redirects a visitor.
196
+ * Improvement: Added support for finding server logs to the Diagnostics page to help with troubleshooting.
197
+ * Improvement: Whitelisted StatusCake IP addresses.
198
+ * Improvement: Updated GeoIP database.
199
+ * Improvement: Disabling Wordfence now sends an alert.
200
+ * Improvement: Improved detection for uploaded PHP content in the firewall.
201
+ * Fix: Eliminated memory-related errors resulting from the scan on sites with very large numbers of issues and low memory.
202
+ * Fix: Fixed admin page layout for sites using RTL languages.
203
+ * Fix: Reduced overhead of the dashboard widget.
204
+ * Fix: Improved performance of checking for whitelisted IPs.
205
+ * Fix: Changes to the default plugin hello.php are now detected correctly in scans.
206
+ * Fix: Fixed IPv6 warning in the dashboard widget.
207
+
208
= 6.2.2 =
209
* Fix: Replaced a slow query in the dashboard widget that could affect sites with very large numbers of users.
210
vendor/wordfence/wf-waf/src/lib/request.php CHANGED
@@ -21,6 +21,9 @@ interface wfWAFRequestInterface {
21
public function getHost();
22
23
public function getURI();
24
25
public function getPath();
26
@@ -73,6 +76,7 @@ class wfWAFRequest implements wfWAFRequestInterface {
73
$request->setMd5QueryString(array());
74
$request->setTimestamp('');
75
$request->setURI('');
76
77
list($headersString, $bodyString) = explode("\n\n", $requestString, 2);
78
$headersString = trim($headersString);
@@ -241,6 +245,7 @@ class wfWAFRequest implements wfWAFRequestInterface {
241
$request->setProtocol('');
242
$request->setTimestamp('');
243
$request->setURI('');
244
245
$request->setBody(wfWAFUtils::stripMagicQuotes($_POST));
246
$request->setQueryString(wfWAFUtils::stripMagicQuotes($_GET));
@@ -332,6 +337,7 @@ class wfWAFRequest implements wfWAFRequestInterface {
332
private $md5QueryString;
333
private $timestamp;
334
private $uri;
335
336
private $highlightParamFormat;
337
private $highlightMatchFormat;
@@ -467,6 +473,14 @@ class wfWAFRequest implements wfWAFRequestInterface {
467
public function getURI() {
468
return $this->uri;
469
}
470
471
public function getPath() {
472
return $this->path;
@@ -909,5 +923,12 @@ FORM;
909
public function setUri($uri) {
910
$this->uri = $uri;
911
}
912
}
913
21
public function getHost();
22
23
public function getURI();
24
+
25
+ public function setMetadata($metadata);
26
+ public function getMetadata();
27
28
public function getPath();
29
76
$request->setMd5QueryString(array());
77
$request->setTimestamp('');
78
$request->setURI('');
79
+ $request->setMetadata(array());
80
81
list($headersString, $bodyString) = explode("\n\n", $requestString, 2);
82
$headersString = trim($headersString);
245
$request->setProtocol('');
246
$request->setTimestamp('');
247
$request->setURI('');
248
+ $request->setMetadata(array());
249
250
$request->setBody(wfWAFUtils::stripMagicQuotes($_POST));
251
$request->setQueryString(wfWAFUtils::stripMagicQuotes($_GET));
337
private $md5QueryString;
338
private $timestamp;
339
private $uri;
340
+ private $metadata;
341
342
private $highlightParamFormat;
343
private $highlightMatchFormat;
473
public function getURI() {
474
return $this->uri;
475
}
476
+
477
+ public function getMetadata() {
478
+ if (func_num_args() > 0) {
479
+ $args = func_get_args();
480
+ return $this->_arrayValueByKeys($this->metadata, $args);
481
+ }
482
+ return $this->metadata;
483
+ }
484
485
public function getPath() {
486
return $this->path;
923
public function setUri($uri) {
924
$this->uri = $uri;
925
}
926
+
927
+ /**
928
+ * @param array $metadata
929
+ */
930
+ public function setMetadata($metadata) {
931
+ $this->metadata = $metadata;
932
+ }
933
}
934
vendor/wordfence/wf-waf/src/lib/rules.php CHANGED
@@ -751,6 +751,7 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
751
}
752
753
$totalRead = 0;
754
$hasExecutablePHP = false;
755
$possiblyHasExecutablePHP = false;
756
$hasOpenParen = false;
@@ -760,7 +761,7 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
760
$maxTokenSize = 15; //__halt_compiler
761
$possibleWrappedTokens = array('<?php', '<?=', '<?', '?>', 'exit', 'new', 'clone', 'echo', 'print', 'require', 'include', 'require_once', 'include_once', '__halt_compiler');
762
763
- $readsize = 512 * 1024; //512k at a time
764
while (!feof($fh)) {
765
$data = fread($fh, $readsize);
766
$actualReadsize = strlen($data);
@@ -782,26 +783,81 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
782
}
783
}
784
785
//Tokenize the data and check for PHP
786
$tokens = @token_get_all($data);
787
foreach ($tokens as $token) {
788
if (is_array($token)) {
789
switch ($token[0]) {
790
case T_OPEN_TAG:
791
$hasOpenParen = false;
792
$hasCloseParen = false;
793
$backtickCount = 0;
794
$possiblyHasExecutablePHP = false;
795
break;
796
797
case T_OPEN_TAG_WITH_ECHO:
798
$hasOpenParen = false;
799
$hasCloseParen = false;
800
$backtickCount = 0;
801
$possiblyHasExecutablePHP = true;
802
break;
803
804
case T_CLOSE_TAG:
805
if ($possiblyHasExecutablePHP) {
806
$hasExecutablePHP = true; //Assume the echo short tag outputted something useful
807
}
@@ -822,6 +878,7 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
822
}
823
}
824
else {
825
switch ($token) {
826
case '(':
827
$hasOpenParen = true;
@@ -841,16 +898,35 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
841
}
842
843
if ($hasExecutablePHP) {
844
return true;
845
}
846
847
$wrappedTokenCheckBytes = substr($data, - min($maxTokenSize, $actualReadsize));
848
}
849
}
850
}
851
852
return false;
853
}
854
855
/**
856
* @return mixed
751
}
752
753
$totalRead = 0;
754
+ $insideOpenTag = false;
755
$hasExecutablePHP = false;
756
$possiblyHasExecutablePHP = false;
757
$hasOpenParen = false;
761
$maxTokenSize = 15; //__halt_compiler
762
$possibleWrappedTokens = array('<?php', '<?=', '<?', '?>', 'exit', 'new', 'clone', 'echo', 'print', 'require', 'include', 'require_once', 'include_once', '__halt_compiler');
763
764
+ $readsize = 100 * 1024; //100k at a time
765
while (!feof($fh)) {
766
$data = fread($fh, $readsize);
767
$actualReadsize = strlen($data);
783
}
784
}
785
786
+ //Make sure it tokenizes correctly if chunked
787
+ if ($insideOpenTag) {
788
+ if ($possiblyHasExecutablePHP) {
789
+ $data = '<?= ' . $data;
790
+ }
791
+ else {
792
+ $data = '<?php ' . $data;
793
+ }
794
+ }
795
+
796
//Tokenize the data and check for PHP
797
+ $this->_resetErrors();
798
$tokens = @token_get_all($data);
799
+ $error = error_get_last();
800
+ if ($error !== null && stripos($error['message'], 'Unexpected character in input') !== false) {
801
+ break;
802
+ }
803
+
804
+ if ($error !== null && feof($fh) && stripos($error['message'], 'Unterminated comment') !== false) {
805
+ break;
806
+ }
807
+
808
+ $offset = 0;
809
foreach ($tokens as $token) {
810
if (is_array($token)) {
811
+ $offset += strlen($token[1]);
812
switch ($token[0]) {
813
case T_OPEN_TAG:
814
+ $insideOpenTag = true;
815
$hasOpenParen = false;
816
$hasCloseParen = false;
817
$backtickCount = 0;
818
$possiblyHasExecutablePHP = false;
819
+
820
+ if ($error !== null && stripos($error['message'], 'Unterminated comment') !== false) {
821
+ $testOffset = $offset - strlen($token[1]);
822
+ $commentStart = strpos($data, '/*', $testOffset);
823
+ if ($commentStart !== false) {
824
+ $testBytes = substr($data, $testOffset, $commentStart - $testOffset);
825
+ $this->_resetErrors();
826
+ @token_get_all($testBytes);
827
+ $error = error_get_last();
828
+ if ($error !== null && stripos($error['message'], 'Unexpected character in input') !== false) {
829
+ break 3;
830
+ }
831
+ }
832
+ }
833
+
834
break;
835
836
case T_OPEN_TAG_WITH_ECHO:
837
+ $insideOpenTag = true;
838
$hasOpenParen = false;
839
$hasCloseParen = false;
840
$backtickCount = 0;
841
$possiblyHasExecutablePHP = true;
842
+
843
+ if ($error !== null && stripos($error['message'], 'Unterminated comment') !== false) {
844
+ $testOffset = $offset - strlen($token[1]);
845
+ $commentStart = strpos($data, '/*', $testOffset);
846
+ if ($commentStart !== false) {
847
+ $testBytes = substr($data, $testOffset, $commentStart - $testOffset);
848
+ $this->_resetErrors();
849
+ @token_get_all($testBytes);
850
+ $error = error_get_last();
851
+ if ($error !== null && stripos($error['message'], 'Unexpected character in input') !== false) {
852
+ break 3;
853
+ }
854
+ }
855
+ }
856
+
857
break;
858
859
case T_CLOSE_TAG:
860
+ $insideOpenTag = false;
861
if ($possiblyHasExecutablePHP) {
862
$hasExecutablePHP = true; //Assume the echo short tag outputted something useful
863
}
878
}
879
}
880
else {
881
+ $offset += strlen($token);
882
switch ($token) {
883
case '(':
884
$hasOpenParen = true;
898
}
899
900
if ($hasExecutablePHP) {
901
+ fclose($fh);
902
return true;
903
}
904
905
$wrappedTokenCheckBytes = substr($data, - min($maxTokenSize, $actualReadsize));
906
}
907
+
908
+ fclose($fh);
909
}
910
}
911
912
return false;
913
}
914
+
915
+ private function _resetErrors() {
916
+ if (function_exists('error_clear_last')) {
917
+ error_clear_last();
918
+ }
919
+ else {
920
+ // set error_get_last() to defined state by forcing an undefined variable error
921
+ set_error_handler(array($this, '_resetErrorsHandler'), 0);
922
+ @$undefinedVariable;
923
+ restore_error_handler();
924
+ }
925
+ }
926
+
927
+ public function _resetErrorsHandler($errno, $errstr, $errfile, $errline) {
928
+ //Do nothing
929
+ }
930
931
/**
932
* @return mixed
vendor/wordfence/wf-waf/src/lib/utils.php CHANGED
@@ -544,4 +544,200 @@ class wfWAFUtils {
544
545
return intval($val);
546
}
547
}
544
545
return intval($val);
546
}
547
+
548
+ public static function reverseLookup($IP) {
549
+ $IPn = self::inet_pton($IP);
550
+ // This function works for IPv4 or IPv6
551
+ if (function_exists('gethostbyaddr')) {
552
+ $host = @gethostbyaddr($IP);
553
+ }
554
+ if (!$host) {
555
+ $ptr = false;
556
+ if (filter_var($IP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
557
+ $ptr = implode(".", array_reverse(explode(".", $IP))) . ".in-addr.arpa";
558
+ } else if (filter_var($IP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
559
+ $ptr = implode(".", array_reverse(str_split(bin2hex($IPn)))) . ".ip6.arpa";
560
+ }
561
+
562
+ if ($ptr && function_exists('dns_get_record')) {
563
+ $host = @dns_get_record($ptr, DNS_PTR);
564
+ if ($host) {
565
+ $host = $host[0]['target'];
566
+ }
567
+ }
568
+ }
569
+ if (!$host) {
570
+ return '';
571
+ }
572
+ return $host;
573
+ }
574
+
575
+ public static function patternToRegex($pattern, $mod = 'i', $sep = '/') {
576
+ $pattern = preg_quote(trim($pattern), $sep);
577
+ $pattern = str_replace(' ', '\s', $pattern);
578
+ return $sep . '^' . str_replace('\*', '.*', $pattern) . '#x27; . $sep . $mod;
579
+ }
580
+
581
+ public static function isUABlocked($uaPattern, $ua) { // takes a pattern using asterisks as wildcards, turns it into regex and checks it against the visitor UA returning true if blocked
582
+ return fnmatch($uaPattern, $ua, FNM_CASEFOLD);
583
+ }
584
+
585
+ public static function isRefererBlocked($refPattern, $referer) {
586
+ return fnmatch($refPattern, $referer, FNM_CASEFOLD);
587
+ }
588
+
589
+ public static function extractBareURI($URL) {
590
+ $URL = preg_replace('/^https?:\/\/[^\/]+/i', '', $URL); //strip of method and host
591
+ $URL = preg_replace('/\#.*#x2F;', '', $URL); //strip off fragment
592
+ $URL = preg_replace('/\?.*#x2F;', '', $URL); //strip off query string
593
+ return $URL;
594
+ }
595
+
596
+ public static function extractHostname($str) {
597
+ if (preg_match('/https?:\/\/([a-zA-Z0-9\.\-]+)(?:\/|$)/i', $str, $matches)) {
598
+ return strtolower($matches[1]);
599
+ }
600
+ else {
601
+ return false;
602
+ }
603
+ }
604
+
605
+ public static function redirect($location, $status = 302) {
606
+ $is_apache = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false);
607
+ $is_IIS = !$is_apache && (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false);
608
+
609
+ if (!$is_IIS && PHP_SAPI != 'cgi-fcgi') {
610
+ self::statusHeader($status); // This causes problems on IIS and some FastCGI setups
611
+ }
612
+
613
+ header("Location: {$location}", true, $status);
614
+ exit;
615
+ }
616
+
617
+ public static function statusHeader($code) {
618
+ $code = abs(intval($code));
619
+
620
+ $statusCodes = array(
621
+ 100 => 'Continue',
622
+ 101 => 'Switching Protocols',
623
+ 102 => 'Processing',
624
+
625
+ 200 => 'OK',
626
+ 201 => 'Created',
627
+ 202 => 'Accepted',
628
+ 203 => 'Non-Authoritative Information',
629
+ 204 => 'No Content',
630
+ 205 => 'Reset Content',
631
+ 206 => 'Partial Content',
632
+ 207 => 'Multi-Status',
633
+ 226 => 'IM Used',
634
+
635
+ 300 => 'Multiple Choices',
636
+ 301 => 'Moved Permanently',
637
+ 302 => 'Found',
638
+ 303 => 'See Other',
639
+ 304 => 'Not Modified',
640
+ 305 => 'Use Proxy',
641
+ 306 => 'Reserved',
642
+ 307 => 'Temporary Redirect',
643
+ 308 => 'Permanent Redirect',