Version Description
- Theme and plugin scanning is now free. Woohoo!
- Added introductory tour for Wordfence.
- Upgraded to Wordfence scanning API version 2.0 to allow free theme and plugin scanning.
- Fixed two issue with scheduled scanning for premium users that would cause scans to not run or run at wrong times under certain conditions.
- Added feature to view unknown files on system to help clean badly infected systems. See on scanning page in "Tools" under yellow box.
- Fixed blocked countries overflowing their container in the user interface.
- Fixed case where if user is using MySQL >
Download this release
Release Info
Developer | mmaunder |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 3.2.1 |
Comparing to | |
See all releases |
Code changes from version 3.1.6 to 3.2.1
- css/main.css +6 -0
- js/admin.js +88 -0
- js/tourTip.js +30 -0
- lib/menu_activity.php +38 -1
- lib/menu_blockedIPs.php +21 -1
- lib/menu_countryBlocking.php +29 -4
- lib/menu_options.php +115 -16
- lib/menu_scan.php +86 -6
- lib/menu_scanSchedule.php +43 -3
- lib/unknownFiles.php +149 -0
- lib/wfDB.php +5 -1
- lib/wfScanEngine.php +14 -17
- lib/wordfenceClass.php +78 -24
- lib/wordfenceConstants.php +3 -3
- lib/wordfenceHash.php +7 -3
- lib/wordfenceScanner.php +96 -0
- lib/wordfenceURLHoover.php +1 -1
- readme.txt +36 -9
- wordfence.php +2 -2
css/main.css
CHANGED
@@ -85,6 +85,7 @@ div.wordfenceScanButton input.button-wf-grey {
|
|
85 |
background: #EFEFEF url(../images/button-grad-grey.png) repeat-x scroll left top;
|
86 |
border-color: #EFEFEF;
|
87 |
}
|
|
|
88 |
|
89 |
.wfTabsContainer {
|
90 |
overflow: hidden;
|
@@ -300,3 +301,8 @@ input.wfStartScanButton { width: 160px; text-align: left; padding-left: 20px; }
|
|
300 |
text-align: center;
|
301 |
-webkit-font-smoothing: antialiased;
|
302 |
}
|
|
|
|
|
|
|
|
|
|
85 |
background: #EFEFEF url(../images/button-grad-grey.png) repeat-x scroll left top;
|
86 |
border-color: #EFEFEF;
|
87 |
}
|
88 |
+
.wordfenceScanButton table td { vertical-align: top; }
|
89 |
|
90 |
.wfTabsContainer {
|
91 |
overflow: hidden;
|
301 |
text-align: center;
|
302 |
-webkit-font-smoothing: antialiased;
|
303 |
}
|
304 |
+
.wfMarker {
|
305 |
+
height: 1px;
|
306 |
+
width: 1px;
|
307 |
+
}
|
308 |
+
|
js/admin.js
CHANGED
@@ -30,9 +30,11 @@ window['wordfenceAdmin'] = {
|
|
30 |
blockedCountriesPending: [],
|
31 |
ownCountry: "",
|
32 |
schedStartHour: false,
|
|
|
33 |
init: function(){
|
34 |
this.nonce = WordfenceAdminVars.firstNonce;
|
35 |
this.debugOn = WordfenceAdminVars.debugOn == '1' ? true : false;
|
|
|
36 |
var startTicker = false;
|
37 |
if(jQuery('#wordfenceMode_scan').length > 0){
|
38 |
this.mode = 'scan';
|
@@ -42,28 +44,61 @@ window['wordfenceAdmin'] = {
|
|
42 |
this.noScanHTML = jQuery('#wfNoScanYetTmpl').tmpl().html();
|
43 |
this.loadIssues();
|
44 |
this.startActivityLogUpdates();
|
|
|
|
|
|
|
45 |
} else if(jQuery('#wordfenceMode_activity').length > 0){
|
46 |
this.mode = 'activity';
|
47 |
this.activityMode = 'hit';
|
48 |
startTicker = true;
|
|
|
|
|
|
|
|
|
49 |
} else if(jQuery('#wordfenceMode_options').length > 0){
|
50 |
this.mode = 'options';
|
51 |
jQuery('.wfConfigElem').change(function(){ jQuery('#securityLevel').val('CUSTOM'); });
|
52 |
this.updateTicker(true);
|
53 |
startTicker = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
} else if(jQuery('#wordfenceMode_blockedIPs').length > 0){
|
55 |
this.mode = 'blocked';
|
56 |
this.staticTabChanged();
|
57 |
this.updateTicker(true);
|
58 |
startTicker = true;
|
|
|
|
|
|
|
|
|
59 |
} else if(jQuery('#wordfenceMode_countryBlocking').length > 0){
|
60 |
this.mode = 'countryBlocking';
|
61 |
startTicker = false;
|
62 |
this.drawBlockedCountries();
|
|
|
|
|
|
|
|
|
63 |
} else if(jQuery('#wordfenceMode_scanScheduling').length > 0){
|
64 |
this.mode = 'scanScheduling';
|
65 |
startTicker = false;
|
66 |
this.sched_modeChange();
|
|
|
|
|
|
|
|
|
67 |
} else {
|
68 |
this.mode = false;
|
69 |
}
|
@@ -75,6 +110,58 @@ window['wordfenceAdmin'] = {
|
|
75 |
jQuery(document).bind('cbox_closed', function(){ self.colorboxIsOpen = false; self.colorboxServiceQueue(); });
|
76 |
}
|
77 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
showLoading: function(){
|
79 |
this.removeLoading();
|
80 |
jQuery('<div id="wordfenceWorking">Wordfence is working...</div>').appendTo('body');
|
@@ -1024,6 +1111,7 @@ window['wordfenceAdmin'] = {
|
|
1024 |
schedMode: schedMode,
|
1025 |
schedTxt: scheduleTxt
|
1026 |
}, function(res){
|
|
|
1027 |
jQuery('.wfAjax24').hide();
|
1028 |
self.pulse('.wfSaveMsg');
|
1029 |
});
|
30 |
blockedCountriesPending: [],
|
31 |
ownCountry: "",
|
32 |
schedStartHour: false,
|
33 |
+
currentPointer: false,
|
34 |
init: function(){
|
35 |
this.nonce = WordfenceAdminVars.firstNonce;
|
36 |
this.debugOn = WordfenceAdminVars.debugOn == '1' ? true : false;
|
37 |
+
this.tourClosed = WordfenceAdminVars.tourClosed == '1' ? true : false;
|
38 |
var startTicker = false;
|
39 |
if(jQuery('#wordfenceMode_scan').length > 0){
|
40 |
this.mode = 'scan';
|
44 |
this.noScanHTML = jQuery('#wfNoScanYetTmpl').tmpl().html();
|
45 |
this.loadIssues();
|
46 |
this.startActivityLogUpdates();
|
47 |
+
if(! this.tourClosed){
|
48 |
+
this.scanTourStart();
|
49 |
+
}
|
50 |
} else if(jQuery('#wordfenceMode_activity').length > 0){
|
51 |
this.mode = 'activity';
|
52 |
this.activityMode = 'hit';
|
53 |
startTicker = true;
|
54 |
+
if(! this.tourClosed){
|
55 |
+
var self = this;
|
56 |
+
this.tour('wfWelcomeContent3', 'wfHeading', 'top', 'left', "Learn about IP Blocking", function(){ self.tourRedir('WordfenceBlockedIPs'); });
|
57 |
+
}
|
58 |
} else if(jQuery('#wordfenceMode_options').length > 0){
|
59 |
this.mode = 'options';
|
60 |
jQuery('.wfConfigElem').change(function(){ jQuery('#securityLevel').val('CUSTOM'); });
|
61 |
this.updateTicker(true);
|
62 |
startTicker = true;
|
63 |
+
if(! this.tourClosed){
|
64 |
+
var self = this;
|
65 |
+
this.tour('wfContentBasicOptions', 'wfMarkerBasicOptions', 'top', 'left', "Learn about Live Traffic Options", function(){
|
66 |
+
self.tour('wfContentLiveTrafficOptions', 'wfMarkerLiveTrafficOptions', 'bottom', 'left', "Learn about Scanning Options", function(){
|
67 |
+
self.tour('wfContentScansToInclude', 'wfMarkerScansToInclude', 'bottom', 'left', "Learn about Firewall Rules", function(){
|
68 |
+
self.tour('wfContentFirewallRules', 'wfMarkerFirewallRules', 'bottom', 'left', "Learn about Login Security", function(){
|
69 |
+
self.tour('wfContentLoginSecurity', 'wfMarkerLoginSecurity', 'bottom', 'left', "Learn about Other Options", function(){
|
70 |
+
self.tour('wfContentOtherOptions', 'wfMarkerOtherOptions', 'bottom', 'left', false, false);
|
71 |
+
});
|
72 |
+
});
|
73 |
+
});
|
74 |
+
});
|
75 |
+
});
|
76 |
+
}
|
77 |
} else if(jQuery('#wordfenceMode_blockedIPs').length > 0){
|
78 |
this.mode = 'blocked';
|
79 |
this.staticTabChanged();
|
80 |
this.updateTicker(true);
|
81 |
startTicker = true;
|
82 |
+
if(! this.tourClosed){
|
83 |
+
var self = this;
|
84 |
+
this.tour('wfWelcomeContent4', 'wfHeading', 'top', 'left', "Learn how to Block Countries", function(){ self.tourRedir('WordfenceCountryBlocking'); });
|
85 |
+
}
|
86 |
} else if(jQuery('#wordfenceMode_countryBlocking').length > 0){
|
87 |
this.mode = 'countryBlocking';
|
88 |
startTicker = false;
|
89 |
this.drawBlockedCountries();
|
90 |
+
if(! this.tourClosed){
|
91 |
+
var self = this;
|
92 |
+
this.tour('wfWelcomeContentCntBlk', 'wfHeading', 'top', 'left', "Learn how to Schedule Scans", function(){ self.tourRedir('WordfenceScanSchedule'); });
|
93 |
+
}
|
94 |
} else if(jQuery('#wordfenceMode_scanScheduling').length > 0){
|
95 |
this.mode = 'scanScheduling';
|
96 |
startTicker = false;
|
97 |
this.sched_modeChange();
|
98 |
+
if(! this.tourClosed){
|
99 |
+
var self = this;
|
100 |
+
this.tour('wfWelcomeContentScanSched', 'wfHeading', 'top', 'left', "Learn how to Customize Wordfence", function(){ self.tourRedir('WordfenceSecOpt'); });
|
101 |
+
}
|
102 |
} else {
|
103 |
this.mode = false;
|
104 |
}
|
110 |
jQuery(document).bind('cbox_closed', function(){ self.colorboxIsOpen = false; self.colorboxServiceQueue(); });
|
111 |
}
|
112 |
},
|
113 |
+
scanTourStart: function(){
|
114 |
+
var self = this;
|
115 |
+
this.tour('wfWelcomeContent1', 'wfHeading', 'top', 'left', "Continue the Tour", function(){
|
116 |
+
self.tour('wfWelcomeContent2', 'wfHeading', 'top', 'left', "Learn how to use Wordfence", function(){
|
117 |
+
self.tour('wfWelcomeContent3', 'wfHeading', 'top', 'left', "Learn about Live Traffic", function(){ self.tourRedir('WordfenceActivity'); });
|
118 |
+
});
|
119 |
+
});
|
120 |
+
},
|
121 |
+
tourRedir: function(menuItem){
|
122 |
+
window.location.href = 'admin.php?page=' + menuItem;
|
123 |
+
},
|
124 |
+
tourFinish: function(){
|
125 |
+
this.ajax('wordfence_tourClosed', {}, function(res){});
|
126 |
+
},
|
127 |
+
tour: function(contentID, elemID, edge, align, buttonLabel, buttonCallback){
|
128 |
+
var self = this;
|
129 |
+
if(this.currentPointer){
|
130 |
+
this.currentPointer.pointer('destroy');
|
131 |
+
this.currentPointer = false;
|
132 |
+
}
|
133 |
+
var options = {
|
134 |
+
buttons: function(event, t){
|
135 |
+
var buttonElem = jQuery('<div id="wfTourButCont"><a id="pointer-close" style="margin-left:5px" class="button-secondary">End the Tour</a></div><div><a id="wfRateLink" href="http://wordpress.org/extend/plugins/wordfence/" target="_blank" style="font-size: 10px; font-family: Verdana;">Help spread the word by rating us 5★ on WordPress.org</a></div>');
|
136 |
+
buttonElem.find('#pointer-close').bind('click.pointer', function (evtObj) {
|
137 |
+
if(evtObj.srcElement.id == 'wfRateLink'){
|
138 |
+
return true;
|
139 |
+
}
|
140 |
+
self.tourFinish();
|
141 |
+
t.element.pointer('close');
|
142 |
+
return false;
|
143 |
+
});
|
144 |
+
return buttonElem;
|
145 |
+
},
|
146 |
+
close: function(){},
|
147 |
+
content: jQuery('#' + contentID).tmpl().html(),
|
148 |
+
pointerWidth: 400,
|
149 |
+
position: {
|
150 |
+
edge: edge,
|
151 |
+
align: align,
|
152 |
+
}
|
153 |
+
};
|
154 |
+
this.currentPointer = jQuery('#' + elemID).pointer(options).pointer('open');
|
155 |
+
if(buttonLabel && buttonCallback){
|
156 |
+
jQuery('#pointer-close').after('<a id="pointer-primary" class="button-primary">' + buttonLabel + '</a>');
|
157 |
+
jQuery('#pointer-primary').click(buttonCallback);
|
158 |
+
}
|
159 |
+
},
|
160 |
+
startTourAgain: function(){
|
161 |
+
this.ajax('wordfence_startTourAgain', {}, function(res){});
|
162 |
+
this.tourClosed = false;
|
163 |
+
this.scanTourStart();
|
164 |
+
},
|
165 |
showLoading: function(){
|
166 |
this.removeLoading();
|
167 |
jQuery('<div id="wordfenceWorking">Wordfence is working...</div>').appendTo('body');
|
1111 |
schedMode: schedMode,
|
1112 |
schedTxt: scheduleTxt
|
1113 |
}, function(res){
|
1114 |
+
jQuery('#wfScanStartTime').html(res.nextStart);
|
1115 |
jQuery('.wfAjax24').hide();
|
1116 |
self.pulse('.wfSaveMsg');
|
1117 |
});
|
js/tourTip.js
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function(){
|
2 |
+
if(WordfenceAdminVars.tourClosed != '1'){
|
3 |
+
jQuery('#toplevel_page_Wordfence').pointer({
|
4 |
+
close: function(){},
|
5 |
+
content: "<h3>Congratulations!</h3><p>You've just installed Wordfence! Click \"Start Tour\" to get a quick introduction to how Wordfence protects your site, keeps you off Google's SEO black-list and can even help clean a hacked site.</p>",
|
6 |
+
pointerWidth: 300,
|
7 |
+
position: { edge: 'top', align: 'left' },
|
8 |
+
buttons: function(event, t){
|
9 |
+
buttonElem = jQuery('<a id="pointer-close" style="margin-left:5px" class="button-secondary">Close</a>');
|
10 |
+
buttonElem.bind('click.pointer', function(){ t.element.pointer('close');
|
11 |
+
var ajaxData = {
|
12 |
+
action: 'wordfence_tourClosed',
|
13 |
+
nonce: WordfenceAdminVars.firstNonce
|
14 |
+
};
|
15 |
+
jQuery.ajax({
|
16 |
+
type: 'POST',
|
17 |
+
url: WordfenceAdminVars.ajaxURL,
|
18 |
+
dataType: "json",
|
19 |
+
data: ajaxData,
|
20 |
+
success: function(json){},
|
21 |
+
error: function(){}
|
22 |
+
});
|
23 |
+
});
|
24 |
+
return buttonElem;
|
25 |
+
}
|
26 |
+
}).pointer('open');
|
27 |
+
jQuery('#pointer-close').after('<a id="pointer-primary" class="button-primary">Start Tour</a>');
|
28 |
+
jQuery('#pointer-primary').click(function(){ window.location.href = 'admin.php?page=Wordfence'; });
|
29 |
+
}
|
30 |
+
});
|
lib/menu_activity.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_activity"></div>
|
2 |
<div class="wrap wordfence">
|
3 |
-
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2>Live Site Activity</h2>
|
4 |
<div class="wordfenceLive">
|
5 |
<table border="0" cellpadding="0" cellspacing="0">
|
6 |
<tr><td><h2>Wordfence Live Activity:</h2></td><td id="wfLiveStatus"></td></tr>
|
@@ -162,3 +162,40 @@
|
|
162 |
</div>
|
163 |
</div>
|
164 |
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_activity"></div>
|
2 |
<div class="wrap wordfence">
|
3 |
+
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Live Site Activity</h2>
|
4 |
<div class="wordfenceLive">
|
5 |
<table border="0" cellpadding="0" cellspacing="0">
|
6 |
<tr><td><h2>Wordfence Live Activity:</h2></td><td id="wfLiveStatus"></td></tr>
|
162 |
</div>
|
163 |
</div>
|
164 |
</script>
|
165 |
+
<script type="text/x-jquery-template" id="wfWelcomeContent3">
|
166 |
+
<div>
|
167 |
+
<h3>Welcome to ALL Your Site Visits, Live!</h3>
|
168 |
+
<strong><p>Traffic you've never seen before</p></strong>
|
169 |
+
<p>
|
170 |
+
Google Analytics and other Javascript analytics packages can't show you crawlers, RSS feed readers, hack attempts and other non-human traffic that hits your site.
|
171 |
+
Wordfence runs on your server and shows you, in real-time, all the traffic that is hitting your server right now, including those non-human crawlers, feed readers and hackers that Analytics can't track.
|
172 |
+
</p>
|
173 |
+
<strong><p>Separated into the important categories</p></strong>
|
174 |
+
<p>
|
175 |
+
You'll notice we have divided your traffic into tabs. These include an "All Hits" tab to simply view everything that is hitting your server right now.
|
176 |
+
We then sub-divide that into Human traffic, your site members, crawlers - which we further break down into Google crawlers.
|
177 |
+
</p>
|
178 |
+
<p>
|
179 |
+
<strong>How to use this page when your site is being attacked</strong>
|
180 |
+
</p>
|
181 |
+
<p>
|
182 |
+
Start by looking at "All Hits" because you may notice that a single IP address is generating most of your traffic.
|
183 |
+
This could be a denial of service attack, someone stealing your content or a hacker probing for weaknesses.
|
184 |
+
If you see a suspicious pattern, simply block that IP address.
|
185 |
+
</p>
|
186 |
+
<p>
|
187 |
+
If you don't see any clear patterns of attack, take a look at "Top 404s" which will show you IP addresses that are generating excessive page not found errors.
|
188 |
+
It's common for an attacker probing for weaknesses to generate a lot of page not found errors. If you see one IP
|
189 |
+
address that is generating many of these requests, and it's not Google or another trusted crawler, then you should consider
|
190 |
+
blocking them.
|
191 |
+
</p>
|
192 |
+
<p>
|
193 |
+
Next look at "Logins and Logouts". If you see a large number of failed logins from an IP address, block them if you don't recognize who they are.
|
194 |
+
</p>
|
195 |
+
<p>
|
196 |
+
Finally, take a look at "Top Consumers". These are the top IP addresses who are "consuming" or accessing most of your content.
|
197 |
+
If you're trying to protect yourself against a content thief, this is the first place to look.
|
198 |
+
</p>
|
199 |
+
|
200 |
+
</div>
|
201 |
+
</script>
|
lib/menu_blockedIPs.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_blockedIPs"></div>
|
2 |
<div class="wrap">
|
3 |
-
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2>Wordfence Blocked IP Addresses</h2>
|
4 |
<div class="wordfenceLive">
|
5 |
<table border="0" cellpadding="0" cellspacing="0">
|
6 |
<tr><td><h2>Wordfence Live Activity:</h2></td><td id="wfLiveStatus"></td></tr>
|
@@ -158,3 +158,23 @@
|
|
158 |
</div>
|
159 |
</script>
|
160 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_blockedIPs"></div>
|
2 |
<div class="wrap">
|
3 |
+
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Wordfence Blocked IP Addresses</h2>
|
4 |
<div class="wordfenceLive">
|
5 |
<table border="0" cellpadding="0" cellspacing="0">
|
6 |
<tr><td><h2>Wordfence Live Activity:</h2></td><td id="wfLiveStatus"></td></tr>
|
158 |
</div>
|
159 |
</script>
|
160 |
|
161 |
+
<script type="text/x-jquery-template" id="wfWelcomeContent4">
|
162 |
+
<div>
|
163 |
+
<h3>How to manage Blocked IP addresses</h3>
|
164 |
+
<strong><p>Block IP's temporarily or permanently</p></strong>
|
165 |
+
<p>
|
166 |
+
When you block an IP address, it will appear here with some additional information.
|
167 |
+
You will be able to see the geographic location of the IP, how many hits occured before
|
168 |
+
it was blocked and how many attempts it has made on your site since it was blocked.
|
169 |
+
</p>
|
170 |
+
<p>
|
171 |
+
You can also see how long until a blocked IP will be automatically unblocked.
|
172 |
+
You can also manually add IP addresses on this page to be blocked.
|
173 |
+
</p>
|
174 |
+
<p>
|
175 |
+
You also have the option to see IP addresses who have been locked out from the login system for too many login attempts.
|
176 |
+
And finally, when the firewall "throttles" someone's access for accessing the site too quickly, you can
|
177 |
+
see which IP addresses have been throttled.
|
178 |
+
</p>
|
179 |
+
</div>
|
180 |
+
</script>
|
lib/menu_countryBlocking.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_countryBlocking"></div>
|
2 |
<div class="wrap" id="paidWrap">
|
3 |
-
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2>Block specific countries from accessing your site</h2>
|
4 |
<div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
|
5 |
<table class="wfConfigForm">
|
6 |
<tr><td colspan="2"><h2>Country Blocking Options</h2></td></tr>
|
@@ -20,7 +20,7 @@
|
|
20 |
<?php require('wfCountrySelect.php'); ?>
|
21 |
</select><input type="button" name="but3" class="button-primary" value="Add Country" onclick="var cVal = jQuery('#wfBlockedCountry').val(); WFAD.addBlockedCountry(cVal, jQuery('#wfBlockedCountry option[value=\'' + cVal + '\']').text());" /></td></tr>
|
22 |
<tr><td colspan="2">
|
23 |
-
<div id="wfCountryList" style="width: 350px; height: 200px; border: 1px solid #999; padding: 5px; margin: 5px;">
|
24 |
</div>
|
25 |
<b>Changes to the country list will only take effect once you hit the save button below.</b>
|
26 |
</td></tr>
|
@@ -43,9 +43,34 @@ WFAD.loadBlockedCountries('<?php echo wfConfig::get('cbl_countries'); ?>');
|
|
43 |
}
|
44 |
?>
|
45 |
<?php
|
46 |
-
if(! wfConfig::get('isPaid')){
|
47 |
echo 'WFAD.paidUsersOnly("Country blocking is only available to paid members because we have licensed a commercial geolocation database to provide this feature.");';
|
48 |
}
|
49 |
?>
|
50 |
</script>
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_countryBlocking"></div>
|
2 |
<div class="wrap" id="paidWrap">
|
3 |
+
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Block specific countries from accessing your site</h2>
|
4 |
<div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
|
5 |
<table class="wfConfigForm">
|
6 |
<tr><td colspan="2"><h2>Country Blocking Options</h2></td></tr>
|
20 |
<?php require('wfCountrySelect.php'); ?>
|
21 |
</select><input type="button" name="but3" class="button-primary" value="Add Country" onclick="var cVal = jQuery('#wfBlockedCountry').val(); WFAD.addBlockedCountry(cVal, jQuery('#wfBlockedCountry option[value=\'' + cVal + '\']').text());" /></td></tr>
|
22 |
<tr><td colspan="2">
|
23 |
+
<div id="wfCountryList" style="width: 350px; height: 200px; border: 1px solid #999; padding: 5px; margin: 5px; overflow: auto;">
|
24 |
</div>
|
25 |
<b>Changes to the country list will only take effect once you hit the save button below.</b>
|
26 |
</td></tr>
|
43 |
}
|
44 |
?>
|
45 |
<?php
|
46 |
+
if( (! wfConfig::get('isPaid')) && (wfConfig::get('tourClosed', 0) == '1') ){
|
47 |
echo 'WFAD.paidUsersOnly("Country blocking is only available to paid members because we have licensed a commercial geolocation database to provide this feature.");';
|
48 |
}
|
49 |
?>
|
50 |
</script>
|
51 |
+
<script type="text/x-jquery-template" id="wfWelcomeContentCntBlk">
|
52 |
+
<div>
|
53 |
+
<h3>Premium Feature: Block or redirect countries</h3>
|
54 |
+
<strong><p>Being targeted by hackers in a specific country?</p></strong>
|
55 |
+
<p>
|
56 |
+
The premium version of Wordfence offers country blocking.
|
57 |
+
This uses a commercial geolocation database to block hackers, spammers
|
58 |
+
or other malicious traffic by country with a 99.5% accuracy rate.
|
59 |
+
</p>
|
60 |
+
<p>
|
61 |
+
<?php
|
62 |
+
if(wfConfig::get('isPaid')){
|
63 |
+
?>
|
64 |
+
You have upgraded to the premium version of Wordfence and have full access
|
65 |
+
to this feature along with our other premium features and priority support.
|
66 |
+
<?php
|
67 |
+
} else {
|
68 |
+
?>
|
69 |
+
If you would like access to this premium feature, please
|
70 |
+
<a href="https://www.wordfence.com/choose-a-wordfence-membership-type/?s2-ssl=yes" target="_blank">upgrade to our premium version</a>.
|
71 |
+
</p>
|
72 |
+
<?php
|
73 |
+
}
|
74 |
+
?>
|
75 |
+
</div>
|
76 |
+
</script>
|
lib/menu_options.php
CHANGED
@@ -6,7 +6,7 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
6 |
</script>
|
7 |
<div class="wordfenceModeElem" id="wordfenceMode_options"></div>
|
8 |
<div class="wrap">
|
9 |
-
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2>Wordfence Options</h2>
|
10 |
<div class="wordfenceLive">
|
11 |
<table border="0" cellpadding="0" cellspacing="0">
|
12 |
<tr><td><h2>Wordfence Live Activity:</h2></td><td id="wfLiveStatus"></td></tr>
|
@@ -39,6 +39,7 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
39 |
|
40 |
</table>
|
41 |
<p><table border="0" cellpadding="0" cellspacing="0"><tr><td><input type="button" id="button1" name="button1" class="button-primary" value="Save Changes" onclick="WFAD.saveConfig();" /></td><td style="height: 24px;"><div class="wfAjax24"></div><span class="wfSavedMsg"> Your changes have been saved!</span></td></tr></table></p>
|
|
|
42 |
<div style="margin-top: 25px;">
|
43 |
<h2>Advanced Options:</h2>
|
44 |
<p style="width: 600px;">
|
@@ -56,27 +57,23 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
56 |
<tr><th>Alert when the "lost password" form is used for a valid user</th><td><input type="checkbox" id="alertOn_lostPasswdForm" class="wfConfigElem" name="alertOn_lostPasswdForm" value="1" <?php $w->cb('alertOn_lostPasswdForm'); ?>/></td></tr>
|
57 |
<tr><th>Alert me when someone with administrator access signs in</th><td><input type="checkbox" id="alertOn_adminLogin" class="wfConfigElem" name="alertOn_adminLogin" value="1" <?php $w->cb('alertOn_adminLogin'); ?>/></td></tr>
|
58 |
<tr><th>Alert me when a non-admin user signs in</th><td><input type="checkbox" id="alertOn_nonAdminLogin" class="wfConfigElem" name="alertOn_nonAdminLogin" value="1" <?php $w->cb('alertOn_nonAdminLogin'); ?>/></td></tr>
|
59 |
-
<tr><td colspan="2"
|
|
|
|
|
|
|
60 |
<tr><th class="wfConfigEnable">Enable Live Traffic View</th><td><input type="checkbox" id="liveTrafficEnabled" class="wfConfigElem" name="liveTrafficEnabled" value="1" <?php $w->cb('liveTrafficEnabled'); ?> onclick="WFAD.reloadConfigPage = true; return true;" /></td></tr>
|
61 |
<tr><th>Don't log signed-in users with publishing access:</th><td><input type="checkbox" id="liveTraf_ignorePublishers" name="liveTraf_ignorePublishers" value="1" <?php $w->cb('liveTraf_ignorePublishers'); ?> /></td></tr>
|
62 |
<tr><th>List of comma separated usernames to ignore:</th><td><input type="text" name="liveTraf_ignoreUsers" id="liveTraf_ignoreUsers" value="<?php echo $w->getHTML('liveTraf_ignoreUsers'); ?>" /></td></tr>
|
63 |
<tr><th>List of comma separated IP addresses to ignore:</th><td><input type="text" name="liveTraf_ignoreIPs" id="liveTraf_ignoreIPs" value="<?php echo $w->getHTML('liveTraf_ignoreIPs'); ?>" /></td></tr>
|
64 |
<tr><th>Browser user-agent to ignore:</th><td><input type="text" name="liveTraf_ignoreUA" id="liveTraf_ignoreUA" value="<?php echo $w->getHTML('liveTraf_ignoreUA'); ?>" /></td></tr>
|
65 |
-
<tr><td colspan="2"
|
|
|
|
|
66 |
<tr><th class="wfConfigEnable">Enable automatic scheduled scans</th><td><input type="checkbox" id="scheduledScansEnabled" class="wfConfigElem" name="scheduledScansEnabled" value="1" <?php $w->cb('scheduledScansEnabled'); ?> /></td></tr>
|
67 |
<tr><th>Scan core files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_core" class="wfConfigElem" name="scansEnabled_core" value="1" <?php $w->cb('scansEnabled_core'); ?>/></td></tr>
|
68 |
|
69 |
-
<?php
|
70 |
-
<tr><th
|
71 |
-
<tr><th style="font-weight: bold;">Scan theme files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_themes" class="wfConfigElem" name="scansEnabled_themes" value="1" <?php $w->cb('scansEnabled_themes'); ?>/></td></tr>
|
72 |
-
<tr><th style="font-weight: bold;">Scan plugin files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_plugins" class="wfConfigElem" name="scansEnabled_plugins" value="1" <?php $w->cb('scansEnabled_plugins'); ?>/></td></tr>
|
73 |
-
<tr><td colspan="2"> </td></tr>
|
74 |
-
<?php } else { ?>
|
75 |
-
<tr><th style="color: #F00; padding-top: 10px;" colspan="2">Only available to Premium Members: <a href="https://www.wordfence.com/choose-a-wordfence-membership-type/" target="_blank">[click to upgrade]</a></th><td></td></tr>
|
76 |
-
<tr><th style="color: #999;">Scan theme files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_themes" class="wfConfigElem" name="scansEnabled_themes" value="1" DISABLED /></td></tr>
|
77 |
-
<tr><th style="color: #999;">Scan plugin files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_plugins" class="wfConfigElem" name="scansEnabled_plugins" value="1" DISABLED /></td></tr>
|
78 |
-
<tr><td colspan="2"> </td></tr>
|
79 |
-
<?php } ?>
|
80 |
<tr><th>Scan for signatures of known malicious files</th><td><input type="checkbox" id="scansEnabled_malware" class="wfConfigElem" name="scansEnabled_malware" value="1" <?php $w->cb('scansEnabled_malware'); ?>/></td></tr>
|
81 |
<tr><th>Scan file contents for backdoors, trojans and suspicious code</th><td><input type="checkbox" id="scansEnabled_fileContents" class="wfConfigElem" name="scansEnabled_fileContents" value="1" <?php $w->cb('scansEnabled_fileContents'); ?>/></td></tr>
|
82 |
<tr><th>Scan posts for known dangerous URLs and suspicious content</th><td><input type="checkbox" id="scansEnabled_posts" class="wfConfigElem" name="scansEnabled_posts" value="1" <?php $w->cb('scansEnabled_posts'); ?>/></td></tr>
|
@@ -87,6 +84,7 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
87 |
<tr><th>Scan for unauthorized DNS changes</th><td><input type="checkbox" id="scansEnabled_dns" class="wfConfigElem" name="scansEnabled_dns" value="1" <?php $w->cb('scansEnabled_dns'); ?>/></td></tr>
|
88 |
<tr><th>Scan files outside your WordPress installation</th><td><input type="checkbox" id="other_scanOutside" class="wfConfigElem" name="other_scanOutside" value="1" <?php $w->cb('other_scanOutside'); ?> /></td></tr>
|
89 |
<tr><td colspan="2">
|
|
|
90 |
<h3 class="wfConfigHeading">Firewall Rules</h3>
|
91 |
</td></tr>
|
92 |
|
@@ -120,7 +118,10 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
120 |
<option value="2592000"<?php $w->sel('blockedTime', '2592000'); ?>>1 month</option>
|
121 |
</select></td></tr>
|
122 |
|
123 |
-
<tr><td colspan="2"
|
|
|
|
|
|
|
124 |
<tr><th class="wfConfigEnable">Enable login security</th><td><input type="checkbox" id="loginSecurityEnabled" class="wfConfigElem" name="loginSecurityEnabled" value="1" <?php $w->cb('loginSecurityEnabled'); ?> /></td></tr>
|
125 |
<tr><th>Lock out after how many login failures</th><td>
|
126 |
<select id="loginSec_maxFailures" class="wfConfigElem" name="loginSec_maxFailures">
|
@@ -196,7 +197,10 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
196 |
</td></tr>
|
197 |
<tr><th>Immediately lock out invalid usernames</th><td><input type="checkbox" id="loginSec_lockInvalidUsers" class="wfConfigElem" name="loginSec_lockInvalidUsers" <?php $w->cb('loginSec_lockInvalidUsers'); ?> /></td></tr>
|
198 |
<tr><th>Don't let WordPress reveal valid users in login errors</th><td><input type="checkbox" id="loginSec_maskLoginErrors" class="wfConfigElem" name="loginSec_maskLoginErrors" <?php $w->cb('loginSec_maskLoginErrors'); ?> /></td></tr>
|
199 |
-
<tr><td colspan="2"
|
|
|
|
|
|
|
200 |
<tr><th>Whitelisted IP addresses that bypass all rules:</th><td><input type="text" name="whitelisted" id="whitelisted" value="<?php echo $w->getHTML('whitelisted'); ?>" size="40" /></td></tr>
|
201 |
<tr><th colspan="2" style="color: #999;">Whitelisted IP's must be separated by commas. You can specify ranges using the following format: 123.23.34.[1-50]<br />Wordfence automatically whitelists <a href="http://en.wikipedia.org/wiki/Private_network" target="_blank">private networks</a> because these are not routable on the public Internet.<br /><br /></th></tr>
|
202 |
<tr><th>Hide WordPress version</th><td><input type="checkbox" id="other_hideWPVersion" class="wfConfigElem" name="other_hideWPVersion" value="1" <?php $w->cb('other_hideWPVersion'); ?> /></td></tr>
|
@@ -214,3 +218,98 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
214 |
</div>
|
215 |
</form>
|
216 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
</script>
|
7 |
<div class="wordfenceModeElem" id="wordfenceMode_options"></div>
|
8 |
<div class="wrap">
|
9 |
+
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Wordfence Options</h2>
|
10 |
<div class="wordfenceLive">
|
11 |
<table border="0" cellpadding="0" cellspacing="0">
|
12 |
<tr><td><h2>Wordfence Live Activity:</h2></td><td id="wfLiveStatus"></td></tr>
|
39 |
|
40 |
</table>
|
41 |
<p><table border="0" cellpadding="0" cellspacing="0"><tr><td><input type="button" id="button1" name="button1" class="button-primary" value="Save Changes" onclick="WFAD.saveConfig();" /></td><td style="height: 24px;"><div class="wfAjax24"></div><span class="wfSavedMsg"> Your changes have been saved!</span></td></tr></table></p>
|
42 |
+
<div class="wfMarker" id="wfMarkerBasicOptions"></div>
|
43 |
<div style="margin-top: 25px;">
|
44 |
<h2>Advanced Options:</h2>
|
45 |
<p style="width: 600px;">
|
57 |
<tr><th>Alert when the "lost password" form is used for a valid user</th><td><input type="checkbox" id="alertOn_lostPasswdForm" class="wfConfigElem" name="alertOn_lostPasswdForm" value="1" <?php $w->cb('alertOn_lostPasswdForm'); ?>/></td></tr>
|
58 |
<tr><th>Alert me when someone with administrator access signs in</th><td><input type="checkbox" id="alertOn_adminLogin" class="wfConfigElem" name="alertOn_adminLogin" value="1" <?php $w->cb('alertOn_adminLogin'); ?>/></td></tr>
|
59 |
<tr><th>Alert me when a non-admin user signs in</th><td><input type="checkbox" id="alertOn_nonAdminLogin" class="wfConfigElem" name="alertOn_nonAdminLogin" value="1" <?php $w->cb('alertOn_nonAdminLogin'); ?>/></td></tr>
|
60 |
+
<tr><td colspan="2">
|
61 |
+
<div class="wfMarker" id="wfMarkerLiveTrafficOptions"></div>
|
62 |
+
<h3 class="wfConfigHeading">Live Traffic View</h3>
|
63 |
+
</td></tr>
|
64 |
<tr><th class="wfConfigEnable">Enable Live Traffic View</th><td><input type="checkbox" id="liveTrafficEnabled" class="wfConfigElem" name="liveTrafficEnabled" value="1" <?php $w->cb('liveTrafficEnabled'); ?> onclick="WFAD.reloadConfigPage = true; return true;" /></td></tr>
|
65 |
<tr><th>Don't log signed-in users with publishing access:</th><td><input type="checkbox" id="liveTraf_ignorePublishers" name="liveTraf_ignorePublishers" value="1" <?php $w->cb('liveTraf_ignorePublishers'); ?> /></td></tr>
|
66 |
<tr><th>List of comma separated usernames to ignore:</th><td><input type="text" name="liveTraf_ignoreUsers" id="liveTraf_ignoreUsers" value="<?php echo $w->getHTML('liveTraf_ignoreUsers'); ?>" /></td></tr>
|
67 |
<tr><th>List of comma separated IP addresses to ignore:</th><td><input type="text" name="liveTraf_ignoreIPs" id="liveTraf_ignoreIPs" value="<?php echo $w->getHTML('liveTraf_ignoreIPs'); ?>" /></td></tr>
|
68 |
<tr><th>Browser user-agent to ignore:</th><td><input type="text" name="liveTraf_ignoreUA" id="liveTraf_ignoreUA" value="<?php echo $w->getHTML('liveTraf_ignoreUA'); ?>" /></td></tr>
|
69 |
+
<tr><td colspan="2">
|
70 |
+
<div class="wfMarker" id="wfMarkerScansToInclude"></div>
|
71 |
+
<h3 class="wfConfigHeading">Scans to include</h3></td></tr>
|
72 |
<tr><th class="wfConfigEnable">Enable automatic scheduled scans</th><td><input type="checkbox" id="scheduledScansEnabled" class="wfConfigElem" name="scheduledScansEnabled" value="1" <?php $w->cb('scheduledScansEnabled'); ?> /></td></tr>
|
73 |
<tr><th>Scan core files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_core" class="wfConfigElem" name="scansEnabled_core" value="1" <?php $w->cb('scansEnabled_core'); ?>/></td></tr>
|
74 |
|
75 |
+
<tr><th>Scan theme files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_themes" class="wfConfigElem" name="scansEnabled_themes" value="1" <?php $w->cb('scansEnabled_themes'); ?>/></td></tr>
|
76 |
+
<tr><th>Scan plugin files against repository versions for changes</th><td><input type="checkbox" id="scansEnabled_plugins" class="wfConfigElem" name="scansEnabled_plugins" value="1" <?php $w->cb('scansEnabled_plugins'); ?>/></td></tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
<tr><th>Scan for signatures of known malicious files</th><td><input type="checkbox" id="scansEnabled_malware" class="wfConfigElem" name="scansEnabled_malware" value="1" <?php $w->cb('scansEnabled_malware'); ?>/></td></tr>
|
78 |
<tr><th>Scan file contents for backdoors, trojans and suspicious code</th><td><input type="checkbox" id="scansEnabled_fileContents" class="wfConfigElem" name="scansEnabled_fileContents" value="1" <?php $w->cb('scansEnabled_fileContents'); ?>/></td></tr>
|
79 |
<tr><th>Scan posts for known dangerous URLs and suspicious content</th><td><input type="checkbox" id="scansEnabled_posts" class="wfConfigElem" name="scansEnabled_posts" value="1" <?php $w->cb('scansEnabled_posts'); ?>/></td></tr>
|
84 |
<tr><th>Scan for unauthorized DNS changes</th><td><input type="checkbox" id="scansEnabled_dns" class="wfConfigElem" name="scansEnabled_dns" value="1" <?php $w->cb('scansEnabled_dns'); ?>/></td></tr>
|
85 |
<tr><th>Scan files outside your WordPress installation</th><td><input type="checkbox" id="other_scanOutside" class="wfConfigElem" name="other_scanOutside" value="1" <?php $w->cb('other_scanOutside'); ?> /></td></tr>
|
86 |
<tr><td colspan="2">
|
87 |
+
<div class="wfMarker" id="wfMarkerFirewallRules"></div>
|
88 |
<h3 class="wfConfigHeading">Firewall Rules</h3>
|
89 |
</td></tr>
|
90 |
|
118 |
<option value="2592000"<?php $w->sel('blockedTime', '2592000'); ?>>1 month</option>
|
119 |
</select></td></tr>
|
120 |
|
121 |
+
<tr><td colspan="2">
|
122 |
+
<div class="wfMarker" id="wfMarkerLoginSecurity"></div>
|
123 |
+
<h3 class="wfConfigHeading">Login Security Options</h3>
|
124 |
+
</td></tr>
|
125 |
<tr><th class="wfConfigEnable">Enable login security</th><td><input type="checkbox" id="loginSecurityEnabled" class="wfConfigElem" name="loginSecurityEnabled" value="1" <?php $w->cb('loginSecurityEnabled'); ?> /></td></tr>
|
126 |
<tr><th>Lock out after how many login failures</th><td>
|
127 |
<select id="loginSec_maxFailures" class="wfConfigElem" name="loginSec_maxFailures">
|
197 |
</td></tr>
|
198 |
<tr><th>Immediately lock out invalid usernames</th><td><input type="checkbox" id="loginSec_lockInvalidUsers" class="wfConfigElem" name="loginSec_lockInvalidUsers" <?php $w->cb('loginSec_lockInvalidUsers'); ?> /></td></tr>
|
199 |
<tr><th>Don't let WordPress reveal valid users in login errors</th><td><input type="checkbox" id="loginSec_maskLoginErrors" class="wfConfigElem" name="loginSec_maskLoginErrors" <?php $w->cb('loginSec_maskLoginErrors'); ?> /></td></tr>
|
200 |
+
<tr><td colspan="2">
|
201 |
+
<div class="wfMarker" id="wfMarkerOtherOptions"></div>
|
202 |
+
<h3 class="wfConfigHeading">Other Options</h3>
|
203 |
+
</td></tr>
|
204 |
<tr><th>Whitelisted IP addresses that bypass all rules:</th><td><input type="text" name="whitelisted" id="whitelisted" value="<?php echo $w->getHTML('whitelisted'); ?>" size="40" /></td></tr>
|
205 |
<tr><th colspan="2" style="color: #999;">Whitelisted IP's must be separated by commas. You can specify ranges using the following format: 123.23.34.[1-50]<br />Wordfence automatically whitelists <a href="http://en.wikipedia.org/wiki/Private_network" target="_blank">private networks</a> because these are not routable on the public Internet.<br /><br /></th></tr>
|
206 |
<tr><th>Hide WordPress version</th><td><input type="checkbox" id="other_hideWPVersion" class="wfConfigElem" name="other_hideWPVersion" value="1" <?php $w->cb('other_hideWPVersion'); ?> /></td></tr>
|
218 |
</div>
|
219 |
</form>
|
220 |
</div>
|
221 |
+
<script type="text/x-jquery-template" id="wfContentBasicOptions">
|
222 |
+
<div>
|
223 |
+
<h3>Basic Options</h3>
|
224 |
+
<p>
|
225 |
+
Using Wordfence is simple. Install Wordfence, enter an email address on this page to send alerts to, and then do your first scan and work through the security alerts we provide.
|
226 |
+
We give you a few basic security levels to choose from, depending on your needs. Remember to hit the "Save" button to save any changes you make.
|
227 |
+
</p>
|
228 |
+
<p>
|
229 |
+
If you use the free edition of Wordfence, you don't need to worry about entering an API key in the "API Key" field above. One is automatically created for you. If you choose to <a href="https://www.wordfence.com/choose-a-wordfence-membership-type/?s2-ssl=yes" target="_blank">upgrade to Wordfence premium edition</a>, you will receive an API key. You will need to copy and paste that key into the "API Key"
|
230 |
+
field above and hit "Save" to activate your key.
|
231 |
+
</p>
|
232 |
+
</div>
|
233 |
+
</script>
|
234 |
+
<script type="text/x-jquery-template" id="wfContentLiveTrafficOptions">
|
235 |
+
<div>
|
236 |
+
<h3>Live Traffic Options</h3>
|
237 |
+
<p>
|
238 |
+
These options let you ignore certain types of visitors, based on their level of access, usernames, IP address or browser type.
|
239 |
+
If you run a very high traffic website where it is not feasible to see your visitors in real-time, simply un-check the live traffic option and nothing will be written to the Wordfence tracking tables.
|
240 |
+
</p>
|
241 |
+
</div>
|
242 |
+
</script>
|
243 |
+
<script type="text/x-jquery-template" id="wfContentScansToInclude">
|
244 |
+
<div>
|
245 |
+
<h3>Scans to Include</h3>
|
246 |
+
<p>
|
247 |
+
This section gives you the ability to fine-tune what we scan.
|
248 |
+
If you use many themes or plugins from the public WordPress directory we recommend you
|
249 |
+
enable theme and plugin scanning. This will verify the integrity of all these themes and plugins and alert you of any changes.
|
250 |
+
<p>
|
251 |
+
<p>
|
252 |
+
The option to "scan files outside your WordPress installation" will cause Wordfence to do a much wider security scan
|
253 |
+
that is not limited to your base WordPress directory and known WordPress subdirectories. This scan may take longer
|
254 |
+
but can be very useful if you have other infected files outside this WordPress installation that you would like us to look for.
|
255 |
+
</p>
|
256 |
+
</div>
|
257 |
+
</script>
|
258 |
+
<script type="text/x-jquery-template" id="wfContentFirewallRules">
|
259 |
+
<div>
|
260 |
+
<h3>Firewall Rules</h3>
|
261 |
+
<p>
|
262 |
+
<strong>NOTE:</strong> Before modifying these rules, make sure you have access to the email address associated with this site's administrator account. If you accidentally lock yourself out, you will be given the option
|
263 |
+
to enter that email address and receive an "unlock email" which will allow you to regain access.
|
264 |
+
</p>
|
265 |
+
<p>
|
266 |
+
<strong>Tips:</strong>
|
267 |
+
<p>• If you choose to limit the rate at which your site can be accessed, you need to customize the settings for your site.</p>
|
268 |
+
<p>• If your users usually skip quickly between pages, you should set the values for human visitors to be high.</p>
|
269 |
+
<p>• If you are aggressively crawled by non-Google crawlers like Baidu, you should set the page view limit for crawlers to a high value.</p>
|
270 |
+
<p>• If you are currently under attack and want to aggressively protect your site or your content, you can set low values for most options.</p>
|
271 |
+
<p>• In general we recommend you don't block fake Google crawlers unless you have a specific problem with someone stealing your content.</p>
|
272 |
+
</p>
|
273 |
+
<p>
|
274 |
+
Remember that as long as you have your administrator email set correctly in this site's user administration, and you are able to receive email at that address,
|
275 |
+
you will be able to regain access if you are accidentally locked out because your rules are too strict.
|
276 |
+
</p>
|
277 |
+
</div>
|
278 |
+
</script>
|
279 |
+
<script type="text/x-jquery-template" id="wfContentLoginSecurity">
|
280 |
+
<div>
|
281 |
+
<h3>Login Security</h3>
|
282 |
+
<p>
|
283 |
+
We have found that real brute force login attacks make hundreds or thousands of requests trying to guess passwords or user login names.
|
284 |
+
So in general you can leave the number of failed logins before a user is locked out as a fairly high number.
|
285 |
+
We have found that blocking after 20 failed attempts is sufficient for most sites and it allows your real site users enough
|
286 |
+
attempts to guess their forgotten passwords without getting locked out.
|
287 |
+
</p>
|
288 |
+
</div>
|
289 |
+
</script>
|
290 |
+
<script type="text/x-jquery-template" id="wfContentOtherOptions">
|
291 |
+
<div>
|
292 |
+
<h3>Other Options</h3>
|
293 |
+
<p>
|
294 |
+
We have worked hard to make Wordfence memory efficient and much of the heavy lifting is done for your site by our cloud scanning servers in our Seattle data center.
|
295 |
+
On most sites Wordfence will only use about 8 megabytes of additional memory when doing a scan, even if you have large files or a large number of files.
|
296 |
+
You should not have to adjust the maximum memory that Wordfence can use, but we have provided the option. Remember that this does not affect the actual memory usage of Wordfence, simply the maximum Wordfence can use if it needs to.
|
297 |
+
</p>
|
298 |
+
<p>
|
299 |
+
You may find debugging mode helpful if Wordfence is not able to start a scan on your site or
|
300 |
+
if you are experiencing some other problem. Enable debugging by checking the box, save your options
|
301 |
+
and then try to do a scan. You will notice a lot more output on the "Scan" page.
|
302 |
+
</p>
|
303 |
+
<p>
|
304 |
+
If you decide to permanently remove Wordfence, you can choose the option to delete all data on deactivation.
|
305 |
+
We also provide helpful links at the bottom of this page which lets you see your systems configuration and test how
|
306 |
+
much memory your host really allows you to use.
|
307 |
+
</p>
|
308 |
+
<p>
|
309 |
+
Thanks for completing this tour and I'm very happy to have you as our newest Wordfence customer. Don't forget to <a href="http://wordpress.org/extend/plugins/wordfence/" target="_blank">rate us 5 stars if you love Wordfence</a>.<br />
|
310 |
+
<br />
|
311 |
+
<strong>Mark Maunder</strong> - Wordfence Creator.
|
312 |
+
</p>
|
313 |
+
</div>
|
314 |
+
</script>
|
315 |
+
|
lib/menu_scan.php
CHANGED
@@ -1,11 +1,21 @@
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_scan"></div>
|
2 |
<div class="wrap wordfence">
|
3 |
-
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2>Wordfence Scan</h2>
|
4 |
<div class="wordfenceWrap">
|
5 |
-
<div class="wordfenceScanButton"
|
6 |
-
|
7 |
-
|
8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
</div>
|
10 |
<div>
|
11 |
<div class="consoleHead">
|
@@ -28,7 +38,7 @@
|
|
28 |
</div>
|
29 |
<?php } else { ?>
|
30 |
<div style="margin: 0 0 20px 5px; width: 795px;">
|
31 |
-
<strong>How to upgrade:</strong> <a href="https://www.wordfence.com/choose-a-wordfence-membership-type/?s2-ssl=yes" target="_blank">
|
32 |
</div>
|
33 |
|
34 |
<?php } ?>
|
@@ -67,6 +77,12 @@
|
|
67 |
|
68 |
<a href="#" target="_blank" class="wfALogViewLink" id="wfALogViewLink">View activity log</a>
|
69 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
</div>
|
71 |
<div style="margin-top: 20px;">
|
72 |
<div id="wfTabs">
|
@@ -509,3 +525,67 @@
|
|
509 |
</script>
|
510 |
|
511 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_scan"></div>
|
2 |
<div class="wrap wordfence">
|
3 |
+
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Wordfence Scan</h2>
|
4 |
<div class="wordfenceWrap">
|
5 |
+
<div class="wordfenceScanButton">
|
6 |
+
<table border="0" cellpadding="0" cellspacing="0" style="width: 800px;">
|
7 |
+
<tr>
|
8 |
+
<td style="width: 250px; padding-top: 10px;">
|
9 |
+
<input type="button" value="Start a Wordfence Scan" id="wfStartScanButton1" class="wfStartScanButton button-primary" onclick="wordfenceAdmin.startScan();" /><br />
|
10 |
+
<a href="#" onclick="WFAD.killScan(); return false;" style="font-size: 10px; color: #AAA;">Click here to kill a running scan.</a>
|
11 |
+
</td>
|
12 |
+
<td>
|
13 |
+
<div style="border: 1px solid #CCC; padding: 4px;">
|
14 |
+
You can <a href="#" onclick="WFAD.startTourAgain(); return false;">start the tour again</a> or <a target="_blank" href="http://www.wordfence.com/forums/">visit our support forums for help.</a> Love Wordfence? You can help by doing two simple things: <a href="http://wordpress.org/extend/plugins/wordfence/" target="_blank">Go to WordPress.org now and give this plugin a 5★ rating</a>. Blog about Wordfence and link to the <a href="http://wordpress.org/extend/plugins/wordfence/" target="_blank">plugin page</a>. Spreading the word helps us keep the best features free.
|
15 |
+
</div>
|
16 |
+
</td>
|
17 |
+
</tr>
|
18 |
+
</table>
|
19 |
</div>
|
20 |
<div>
|
21 |
<div class="consoleHead">
|
38 |
</div>
|
39 |
<?php } else { ?>
|
40 |
<div style="margin: 0 0 20px 5px; width: 795px;">
|
41 |
+
<strong>How to upgrade:</strong> If you would like to control how often your site is checked for security vulnerabilities and infections, and you would like to be able to block countries, <a href="https://www.wordfence.com/choose-a-wordfence-membership-type/?s2-ssl=yes" target="_blank">visit www.wordfence.com</a> and sign up for our paid option. Then go to the Wordfence options page on this site and replace your free API key with your new premium key. You will then be able to activate the premium scanning options on the Wordfence options page.
|
42 |
</div>
|
43 |
|
44 |
<?php } ?>
|
77 |
|
78 |
<a href="#" target="_blank" class="wfALogViewLink" id="wfALogViewLink">View activity log</a>
|
79 |
</div>
|
80 |
+
<div style="margin: 0 0 20px 5px; width: 795px;">
|
81 |
+
<strong>Docs:</strong> Our <a href="http://www.wordfence.com/docs/" target="_blank">Wordfence Documentation</a> has tips on <a href="http://www.wordfence.com/docs/using-wordfence-to-analyze-changes-in-wordpress-files/" target="_blank">dealing with changed files</a>, <a href="http://www.wordfence.com/docs/how-to-clean-a-hacked-wordpress-site-using-wordfence/" target="_blank">how to clean a hacked site</a> and our <a href="http://www.wordfence.com/docs/frequently-asked-questions/" target="_blank">FAQ</a>.
|
82 |
+
<?php $unknownFilesLink = wfUtils::siteURLRelative() . '?_wfsf=unknownFiles&nonce=' . wp_create_nonce('wp-ajax'); ?>
|
83 |
+
<br /><strong>Tools:</strong> Cleaning a hacked system? See a <a href="<?php echo $unknownFilesLink ?>&sort=3&dir=rev" target="_blank">list of files that are not in the WordPress core, plugin or theme repositories</a> after your first scan.
|
84 |
+
</div>
|
85 |
+
|
86 |
</div>
|
87 |
<div style="margin-top: 20px;">
|
88 |
<div id="wfTabs">
|
525 |
</script>
|
526 |
|
527 |
|
528 |
+
<script type="text/x-jquery-template" id="wfWelcomeContent1">
|
529 |
+
<div>
|
530 |
+
<h3>Welcome to Wordfence</h3>
|
531 |
+
<p>
|
532 |
+
Wordfence is a robust and complete security system for WordPress. It protects your WordPress site
|
533 |
+
from security threats and keeps you off Google's SEO black-list by providing a firewall, brute force protection, continuous scanning and many other security enhancements.
|
534 |
+
</p>
|
535 |
+
<p>
|
536 |
+
Wordfence also detects if there are any security problems on
|
537 |
+
your site or if there has been an intrusion and will alert you via email.
|
538 |
+
Wordfence can also help repair hacked sites, even if you don't have a backup of your site.
|
539 |
+
</p>
|
540 |
+
</div>
|
541 |
+
</script>
|
542 |
+
<script type="text/x-jquery-template" id="wfWelcomeContent2">
|
543 |
+
<div>
|
544 |
+
<h3>How Wordfence is different</h3>
|
545 |
+
<p><strong>Powered by our Cloud Servers</strong></p>
|
546 |
+
<p>
|
547 |
+
Wordfence is not just a standalone plugin for WordPress. It is part of Feedjit Inc. and is powered by our cloud scanning servers based at our
|
548 |
+
data center in Seattle, Washington in the USA. On these servers we keep an updated mirror of every version of WordPress ever released
|
549 |
+
and every version of every plugin and theme ever released into the WordPress repository. That allows us to
|
550 |
+
do an integrity check on your core files, plugins and themes. It also means that when we detect they have changed, we can show you the
|
551 |
+
changes and we can give you the option to repair any corrupt files. Even if you don't have a backup of that file.
|
552 |
+
</p>
|
553 |
+
<p><strong>Keeping you off Google's SEO Black-List</strong></p>
|
554 |
+
<p>
|
555 |
+
We also maintain a real-time copy of the Google Safe Browsing list (the GSB) and use it to scan all your files, posts, pages and comments for dangerous URL's.
|
556 |
+
If you accidentally link to a URL on the GSB, your site is often black-listed by Google and removed from search results.
|
557 |
+
The GSB is constantly changing, so constant scanning of all your content is needed to keep you safe and off Google's SEO black-list.
|
558 |
+
</p>
|
559 |
+
<p><strong>Scans for back-doors, malware, viruses and other threats</strong></p>
|
560 |
+
<p>
|
561 |
+
Wordfence also maintains an updated threat and malware signature database which we use to scan your site for intrusions, malware, backdoors and more.
|
562 |
+
</p>
|
563 |
+
</div>
|
564 |
+
</script>
|
565 |
+
<script type="text/x-jquery-template" id="wfWelcomeContent3">
|
566 |
+
<div>
|
567 |
+
<h3>How to use Wordfence</h3>
|
568 |
+
<strong><p>Start with a Scan</p></strong>
|
569 |
+
<p>
|
570 |
+
Using Wordfence is simple. Start by doing a scan. One is probably already running if you just installed Wordfence.
|
571 |
+
Once the scan is complete, a list of issues will appear at the bottom of this page. Work through each issue one at a time. If you know an
|
572 |
+
issue is not a security problem, simply choose to ignore it. When you click "ignore" it will be moved to the list of ignored issues.
|
573 |
+
</p>
|
574 |
+
<strong><p>Use the tools we provide</p></strong>
|
575 |
+
<p>
|
576 |
+
You'll notice that with each issue we provide tools to help you repair problems you may find. For example, if a core file has been modified
|
577 |
+
you can view how it has been changed, view the whole file or repair the file. If we find a back-door a hacker has left behind, we give
|
578 |
+
you the option to delete the file. Using these tools is an essential part of the diagnostic and cleaning process if you have been hacked.
|
579 |
+
</p>
|
580 |
+
<p>
|
581 |
+
Repair each security problem that you find. You may have to fix a weak password that we detected, upgrade a theme or plugin, delete a comment that
|
582 |
+
contains an unsafe URL and so on. Once you're done, start another scan and your site should come back with no security issues.
|
583 |
+
</p>
|
584 |
+
<strong><p>Regular scheduled scans keep your site safe</p></strong>
|
585 |
+
<p>
|
586 |
+
Once you've done your initial scan and cleanup, Wordfence will automatically scan your site once a day.
|
587 |
+
If you would like to scan your site more frequently or control when Wordfence does a scan, upgrade to the
|
588 |
+
paid version of Wordfence which includes other features like country blocking.
|
589 |
+
</p>
|
590 |
+
</div>
|
591 |
+
</script>
|
lib/menu_scanSchedule.php
CHANGED
@@ -1,9 +1,18 @@
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_scanScheduling"></div>
|
2 |
<div class="wrap" id="paidWrap">
|
3 |
-
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2>Schedule Wordfence Scanning</h2>
|
4 |
<div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
|
5 |
<p>
|
6 |
-
<strong>Current time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
</p>
|
8 |
<p style="width: 600px;">
|
9 |
Wordfence provides continuous real-time security for your site. Occasionally we run a full scan of all files, posts, pages, comments, user password and other site components.
|
@@ -60,9 +69,40 @@
|
|
60 |
|
61 |
<script type="text/javascript">
|
62 |
<?php
|
63 |
-
if(! wfConfig::get('isPaid')){
|
64 |
echo 'WFAD.paidUsersOnly("Scan scheduling is only available to paid members because it puts significant additional load on our cloud scanning servers. As a free customer, Wordfence will automatically schedule scans to run approximately once daily.");';
|
65 |
}
|
66 |
?>
|
67 |
|
68 |
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="wordfenceModeElem" id="wordfenceMode_scanScheduling"></div>
|
2 |
<div class="wrap" id="paidWrap">
|
3 |
+
<div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Schedule Wordfence Scanning</h2>
|
4 |
<div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
|
5 |
<p>
|
6 |
+
<strong>Current time:</strong> <?php echo date('l jS \of F Y H:i:s A', current_time('timestamp')); ?>
|
7 |
+
<br /><strong>Next scan will start at:</strong>
|
8 |
+
<span id="wfScanStartTime">
|
9 |
+
<?php
|
10 |
+
$nextTime = wordfence::getNextScanStartTime();
|
11 |
+
if($nextTime){
|
12 |
+
echo $nextTime;
|
13 |
+
}
|
14 |
+
?>
|
15 |
+
</span>
|
16 |
</p>
|
17 |
<p style="width: 600px;">
|
18 |
Wordfence provides continuous real-time security for your site. Occasionally we run a full scan of all files, posts, pages, comments, user password and other site components.
|
69 |
|
70 |
<script type="text/javascript">
|
71 |
<?php
|
72 |
+
if( (! wfConfig::get('isPaid')) && (wfConfig::get('tourClosed', 0) == '1') ){
|
73 |
echo 'WFAD.paidUsersOnly("Scan scheduling is only available to paid members because it puts significant additional load on our cloud scanning servers. As a free customer, Wordfence will automatically schedule scans to run approximately once daily.");';
|
74 |
}
|
75 |
?>
|
76 |
|
77 |
</script>
|
78 |
+
<script type="text/x-jquery-template" id="wfWelcomeContentScanSched">
|
79 |
+
<div>
|
80 |
+
<h3>Premium Feature: Scan Scheduling</h3>
|
81 |
+
<strong><p>Want full control over when your scans run?</p></strong>
|
82 |
+
<p>
|
83 |
+
If you upgrade to our premium version you will have access to our scan scheduling feature.
|
84 |
+
This gives you full control over when and how frequently your site is scanned
|
85 |
+
for security vulnerabilities and intrusions.
|
86 |
+
</p>
|
87 |
+
<p>
|
88 |
+
If your site gets a surge of traffic in the mornings, you may choose to run
|
89 |
+
two scans in the late afternoon and at midnight, for example. Or if you
|
90 |
+
are experiencing an unusually high number of attacks, you might choose
|
91 |
+
to run scans once every two to four hours to be extra vigilant during the attack.
|
92 |
+
<p>
|
93 |
+
<?php
|
94 |
+
if(wfConfig::get('isPaid')){
|
95 |
+
?>
|
96 |
+
You have upgraded to the premium version of Wordfence and have full access
|
97 |
+
to this feature along with our other premium features and priority support.
|
98 |
+
<?php
|
99 |
+
} else {
|
100 |
+
?>
|
101 |
+
If you would like access to this premium feature, please
|
102 |
+
<a href="https://www.wordfence.com/choose-a-wordfence-membership-type/?s2-ssl=yes" target="_blank">upgrade to our premium version</a>.
|
103 |
+
</p>
|
104 |
+
<?php
|
105 |
+
}
|
106 |
+
?>
|
107 |
+
</div>
|
108 |
+
</script>
|
lib/unknownFiles.php
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if(! wfUtils::isAdmin()){ exit(); } ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2 |
+
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
|
3 |
+
<head>
|
4 |
+
<title>Files found that don't belong to WordPress Core or known Themes and Plugins</title>
|
5 |
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
6 |
+
<link rel='stylesheet' id='wordfence-main-style-css' href='<?php echo wfUtils::getBaseURL(); ?>/css/diff.css?ver=<?php echo WORDFENCE_VERSION; ?>' type='text/css' media='all' />
|
7 |
+
<body>
|
8 |
+
<h1>Wordfence: Files found that don't belong to WordPress Core or known Themes and Plugins.</h1>
|
9 |
+
<?php
|
10 |
+
$path = ABSPATH;
|
11 |
+
$fileList = wfConfig::get('lastUnknownFileList');
|
12 |
+
if($fileList){
|
13 |
+
?>
|
14 |
+
<p style="width: 700px; margin-top: 20px;">
|
15 |
+
<b>Please note:</b> To use this utility, you must enable scanning of Core, Theme and Plugin files on the Wordfence options page.
|
16 |
+
<?php if(! wfConfig::get('scansEnabled_themes')){ echo '<span style="color: #F00;">Theme scanning is currently disabled.</span> '; } ?>
|
17 |
+
<?php if(! wfConfig::get('scansEnabled_plugins')){ echo '<span style="color: #F00;">Plugin scanning is currently disabled.</span> '; } ?>
|
18 |
+
<?php if( (!wfConfig::get('scansEnabled_plugins')) || (!wfConfig::get('scansEnabled_themes')) ){ echo 'You can visit the Wordfence "options" page to enable theme or plugin scanning.'; } ?>
|
19 |
+
|
20 |
+
If you don't have core, theme and plugin scanning enabled, then the list below will not be very useful because Wordfence won't recognize known core, theme and plugin files.
|
21 |
+
If you have the option enabled to "Scan files outside your WordPress installation" enabled, then you may find that this list is very long because it will include files in all your directories.
|
22 |
+
<br /><br />
|
23 |
+
<b>What is in this list:</b>
|
24 |
+
When Wordfence does a scan, it separates files on your system into two lists. The first list is files that belong to WordPress Core or a known theme or plugin. The second list is all other files.
|
25 |
+
<br /><br />
|
26 |
+
If a <b>file belongs to WordPress Core or a known theme or plugin</b>, we do an integrity check and let you know if it has been modified.
|
27 |
+
The integrity check we do on known Core, theme and plugin files is a very reliable way to detect compromised files. It is impossible as far as we know for a hacker to fool this scan
|
28 |
+
because we are comparing your files to known originals on our secure scanning servers. If the file is modified, we let you know with a warning or critical alert in the scan results.
|
29 |
+
<br /><br />
|
30 |
+
If the file <b>does not belong to WordPress Core or a known theme or plugin</b>, we scan it for security problems.
|
31 |
+
We have a pretty good detection rate for this second scan, but for very advanced or sneaky attacks our admin's sometimes prefer to examine these files by hand.
|
32 |
+
If you would like to look at these non-integrity checked files, we provide you with the list below. You can click on any file to view the contents and see if it has been hacked.
|
33 |
+
<br /><br />
|
34 |
+
<b>Files that you will find in this list are:</b>
|
35 |
+
<ul>
|
36 |
+
<li>Files belonging to commercial themes that are not in the open source WordPress theme repository</li>
|
37 |
+
<li>Files belonging to commercial plugins that are not in the open source WordPress repository</li>
|
38 |
+
<li>Files created by themes or plugins</li>
|
39 |
+
<li>Files created by you on your WordPress installation by uploading them through WordPress or a utility like FTP or SFTP</li>
|
40 |
+
<li>Files that a hacker put on your system to create a back-door, distribute spam or for another nefarious purpose.</li>
|
41 |
+
</ul>
|
42 |
+
<b>How to use this list to clean your system if it is infected:</b>
|
43 |
+
<ul>
|
44 |
+
<li>First sort by most recently modified files by clicking the "Last Modified" column. You may have to click it twice.</li>
|
45 |
+
<li>Examine recently modified files by clicking them to view the file and check if it is infected. This is often the most reliable way to find an infection.</li>
|
46 |
+
<li>Then sort by "Full File Path" and look at files that aren't one of your custom themes or plugins.</li>
|
47 |
+
<li>Note that custom themes and plugins live in the /wp-content/themes/ and /wp-content/plugins directories.</li>
|
48 |
+
<li>Then start going through your themes and plugins to see if they are infected.</li>
|
49 |
+
</ul>
|
50 |
+
</p>
|
51 |
+
<h2 style="margin-top: 30px;">Files that don't belong to WordPress Core, or to a theme or plugin in the WordPress Repository:</h2>
|
52 |
+
|
53 |
+
|
54 |
+
<?php
|
55 |
+
$files = array();
|
56 |
+
while(strlen($fileList) > 0){
|
57 |
+
$filenameLen = unpack('n', substr($fileList, 0, 2));
|
58 |
+
$filenameLen = $filenameLen[1];
|
59 |
+
if($filenameLen > 1000 || $filenameLen < 1){
|
60 |
+
continue;
|
61 |
+
}
|
62 |
+
$file = substr($fileList, 2, $filenameLen);
|
63 |
+
$fileList = substr($fileList, 2 + $filenameLen);
|
64 |
+
$fullFile = $path . $file;
|
65 |
+
if(! file_exists($fullFile)){
|
66 |
+
continue;
|
67 |
+
}
|
68 |
+
$fileExt = '';
|
69 |
+
if(preg_match('/\.([a-zA-Z\d\-]{1,7})$/', $file, $matches)){
|
70 |
+
$fileExt = strtolower($matches[1]);
|
71 |
+
}
|
72 |
+
$isPHP = false;
|
73 |
+
if(preg_match('/^(?:php|phtml|php\d+)$/', $fileExt)){
|
74 |
+
$isPHP = true;
|
75 |
+
}
|
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 |
+
}
|
86 |
+
function wfUKFcmp($a, $b){
|
87 |
+
$idx = $_GET['sort'] ? $_GET['sort'] : 2;
|
88 |
+
if($_GET['dir'] == 'rev'){
|
89 |
+
$tmp = $a;
|
90 |
+
$a = $b;
|
91 |
+
$b = $tmp;
|
92 |
+
}
|
93 |
+
$type = 'num';
|
94 |
+
if($idx == 1 || $idx == 5 || $idx == 6 || $idx == 7){
|
95 |
+
$type = 'str';
|
96 |
+
}
|
97 |
+
|
98 |
+
if($a[$idx] == $b[$idx]){
|
99 |
+
return 0;
|
100 |
+
}
|
101 |
+
if($type == 'num'){
|
102 |
+
return ($a[$idx] < $b[$idx]) ? -1 : 1;
|
103 |
+
} else {
|
104 |
+
return strcmp($a[$idx], $b[$idx]);
|
105 |
+
}
|
106 |
+
}
|
107 |
+
usort($files, 'wfUKFcmp');
|
108 |
+
|
109 |
+
$sortLink = wfUtils::siteURLRelative() . '?_wfsf=unknownFiles&nonce=' . wp_create_nonce('wp-ajax') . '&sort=';
|
110 |
+
$sortIDX = $_GET['sort'];
|
111 |
+
if(! $sortIDX){
|
112 |
+
$sortIDX = 2;
|
113 |
+
}
|
114 |
+
$sortDir = $_GET['dir'];
|
115 |
+
if(! $sortDir){
|
116 |
+
$sortDir = 'fwd';
|
117 |
+
}
|
118 |
+
?>
|
119 |
+
<p>
|
120 |
+
All columns are sortable. Click the heading to sort a column. Click again to sort in reverse direction.<br />
|
121 |
+
If you are cleaning a hacked site, start by sorting files by most recently modified and view those files first.
|
122 |
+
</p>
|
123 |
+
<table border="1" cellpadding="2" cellspacing="0">
|
124 |
+
<tr>
|
125 |
+
<th><a href="<?php echo $sortLink; ?>2&dir=<?php echo ($sortIDX == 2 && $sortDir == 'fwd') ? 'rev' : 'fwd'; ?>">File Size in Bytes</a></th>
|
126 |
+
<th><a href="<?php echo $sortLink; ?>3&dir=<?php echo ($sortIDX == 3 && $sortDir == 'fwd') ? 'rev' : 'fwd'; ?>">Last modified</a></th>
|
127 |
+
<th><a href="<?php echo $sortLink; ?>5&dir=<?php echo ($sortIDX == 5 && $sortDir == 'fwd') ? 'rev' : 'fwd'; ?>">Owner<a></th>
|
128 |
+
<th><a href="<?php echo $sortLink; ?>6&dir=<?php echo ($sortIDX == 6 && $sortDir == 'fwd') ? 'rev' : 'fwd'; ?>">Group</a></th>
|
129 |
+
<th><a href="<?php echo $sortLink; ?>7&dir=<?php echo ($sortIDX == 7 && $sortDir == 'fwd') ? 'rev' : 'fwd'; ?>">Permissions</a></th>
|
130 |
+
<th><a href="<?php echo $sortLink; ?>1&dir=<?php echo ($sortIDX == 1 && $sortDir == 'fwd') ? 'rev' : 'fwd'; ?>">Full file path</a></th>
|
131 |
+
</tr>
|
132 |
+
<?php
|
133 |
+
for($i = 0; $i < sizeof($files); $i++){
|
134 |
+
echo '<tr><td>' . wfUtils::formatBytes($files[$i][2]) . '</td><td>' . wfUtils::makeTimeAgo(time() - $files[$i][3]) . ' ago.</td><td>' . $files[$i][5] . '</td><td>' . $files[$i][6] . '</td><td>' . $files[$i][7] . '</td><td><a href="' . $files[$i][4] . '" target="_blank">' . $files[$i][1] . '</a></td></tr>';
|
135 |
+
}
|
136 |
+
echo "</table>";
|
137 |
+
} else {
|
138 |
+
?>
|
139 |
+
<p style="margin: 40px; font-size: 20px;">
|
140 |
+
You either have not completed a scan recently, or there were no files found on your system that are not in the WordPress official repository for Core files, themes and plugins.
|
141 |
+
</p>
|
142 |
+
<?php
|
143 |
+
}
|
144 |
+
|
145 |
+
?>
|
146 |
+
|
147 |
+
<div class="diffFooter">© 2011 Wordfence — Visit <a href="http://wordfence.com/">Wordfence.com</a> for help, security updates and more.</a>
|
148 |
+
</body>
|
149 |
+
</html>
|
lib/wfDB.php
CHANGED
@@ -68,7 +68,7 @@ class wfDB {
|
|
68 |
}
|
69 |
}
|
70 |
public function reconnect(){
|
71 |
-
if(! mysql_ping($this->dbh)){
|
72 |
$this->connectHandle();
|
73 |
}
|
74 |
}
|
@@ -224,6 +224,10 @@ class wfDB {
|
|
224 |
public function getAffectedRows(){
|
225 |
return mysql_affected_rows($this->dbh);
|
226 |
}
|
|
|
|
|
|
|
|
|
227 |
}
|
228 |
|
229 |
?>
|
68 |
}
|
69 |
}
|
70 |
public function reconnect(){
|
71 |
+
if((! $this->dbh) || (! mysql_ping($this->dbh)) ){
|
72 |
$this->connectHandle();
|
73 |
}
|
74 |
}
|
224 |
public function getAffectedRows(){
|
225 |
return mysql_affected_rows($this->dbh);
|
226 |
}
|
227 |
+
public function truncate($table){ //Ensures everything is deleted if user is using MySQL >= 5.1.16 and does not have "drop" privileges
|
228 |
+
$this->query("truncate table $table");
|
229 |
+
$this->query("delete from $table");
|
230 |
+
}
|
231 |
}
|
232 |
|
233 |
?>
|
lib/wfScanEngine.php
CHANGED
@@ -136,27 +136,23 @@ class wfScanEngine {
|
|
136 |
} else {
|
137 |
wordfence::statusDisabled("Skipping core scan");
|
138 |
}
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
wordfence::statusDisabled("Skipping comparing plugin files against originals in repository");
|
145 |
-
}
|
146 |
} else {
|
147 |
-
wordfence::
|
148 |
}
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
} else {
|
154 |
-
wordfence::statusDisabled("Skipping comparing theme files against originals in repository");
|
155 |
-
}
|
156 |
} else {
|
157 |
-
wordfence::
|
158 |
}
|
159 |
-
|
|
|
160 |
if(wfConfig::get('scansEnabled_malware')){
|
161 |
$this->statusIDX['unknown'] = wordfence::statusStart("Scanning for known malware files");
|
162 |
$this->malwareScanEnabled = true;
|
@@ -259,6 +255,7 @@ class wfScanEngine {
|
|
259 |
$totalUStrLen = unpack('N', substr($dataArr['data'], 0, 4));
|
260 |
$totalUStrLen = $totalUStrLen[1];
|
261 |
$this->unknownFiles = substr($dataArr['data'], 4, ($totalUStrLen - 4)); //subtruct the first 4 bytes which is an INT that is the total length of unknown string including the 4 bytes
|
|
|
262 |
$resultArr = json_decode(substr($dataArr['data'], $totalUStrLen), true);
|
263 |
if(! (is_array($resultArr) && isset($resultArr['results'])) ){
|
264 |
wordfence::statusEndErr();
|
136 |
} else {
|
137 |
wordfence::statusDisabled("Skipping core scan");
|
138 |
}
|
139 |
+
|
140 |
+
//These are both now available to free customers
|
141 |
+
if(wfConfig::get('scansEnabled_plugins')){
|
142 |
+
$this->pluginScanEnabled = true;
|
143 |
+
$this->statusIDX['plugin'] = wordfence::statusStart("Comparing open source plugins against WordPress.org originals");
|
|
|
|
|
144 |
} else {
|
145 |
+
wordfence::statusDisabled("Skipping comparing plugin files against originals in repository");
|
146 |
}
|
147 |
+
|
148 |
+
if(wfConfig::get('scansEnabled_themes')){
|
149 |
+
$this->themeScanEnabled = true;
|
150 |
+
$this->statusIDX['theme'] = wordfence::statusStart("Comparing open source themes against WordPress.org originals");
|
|
|
|
|
|
|
151 |
} else {
|
152 |
+
wordfence::statusDisabled("Skipping comparing theme files against originals in repository");
|
153 |
}
|
154 |
+
//End new section available to free customers
|
155 |
+
|
156 |
if(wfConfig::get('scansEnabled_malware')){
|
157 |
$this->statusIDX['unknown'] = wordfence::statusStart("Scanning for known malware files");
|
158 |
$this->malwareScanEnabled = true;
|
255 |
$totalUStrLen = unpack('N', substr($dataArr['data'], 0, 4));
|
256 |
$totalUStrLen = $totalUStrLen[1];
|
257 |
$this->unknownFiles = substr($dataArr['data'], 4, ($totalUStrLen - 4)); //subtruct the first 4 bytes which is an INT that is the total length of unknown string including the 4 bytes
|
258 |
+
wfConfig::set('lastUnknownFileList', $this->unknownFiles);
|
259 |
$resultArr = json_decode(substr($dataArr['data'], $totalUStrLen), true);
|
260 |
if(! (is_array($resultArr) && isset($resultArr['results'])) ){
|
261 |
wordfence::statusEndErr();
|
lib/wordfenceClass.php
CHANGED
@@ -39,7 +39,7 @@ class wordfence {
|
|
39 |
wp_clear_scheduled_hook('wordfence_scheduled_scan');
|
40 |
|
41 |
//Remove all scheduled scans.
|
42 |
-
|
43 |
|
44 |
if(wfConfig::get('deleteTablesOnDeact')){
|
45 |
$schema = new wfSchema();
|
@@ -61,7 +61,7 @@ class wordfence {
|
|
61 |
while($rec = mysql_fetch_assoc($q1)){
|
62 |
array_push($URIs, $rec['URI']);
|
63 |
}
|
64 |
-
$wfdb->
|
65 |
if(sizeof($URIs) > 0){
|
66 |
try {
|
67 |
$api->call('send_net_404s', array(), array( 'URIs' => json_encode($URIs) ));
|
@@ -75,7 +75,7 @@ class wordfence {
|
|
75 |
while($rec = mysql_fetch_assoc($q2)){
|
76 |
$scanCont .= pack('N', ip2long($rec['IP']));
|
77 |
}
|
78 |
-
$wfdb->
|
79 |
|
80 |
$q3 = $wfdb->query("select INET_NTOA(IP) as IP from $p"."wfLockedOut where blockedTime > unix_timestamp() - 3600");
|
81 |
$lockCont = "";
|
@@ -120,7 +120,7 @@ class wordfence {
|
|
120 |
}
|
121 |
|
122 |
$wfdb->query("delete from $p"."wfLocs where ctime < unix_timestamp() - %d", WORDFENCE_MAX_IPLOC_AGE);
|
123 |
-
$wfdb->
|
124 |
$wfdb->query("delete from $p"."wfBlocks where (blockedTime + %s < unix_timestamp()) and permanent=0", wfConfig::get('blockedTime'));
|
125 |
$wfdb->query("delete from $p"."wfCrawlers where lastUpdate < unix_timestamp() - (86400 * 7)");
|
126 |
|
@@ -136,20 +136,20 @@ class wordfence {
|
|
136 |
$wfdb->query("delete from $p"."wfLockedOut where blockedTime + %s < unix_timestamp()", wfConfig::get('loginSec_lockoutMins') * 60);
|
137 |
$count2 = $wfdb->querySingle("select count(*) as cnt from $p"."wfLogins");
|
138 |
if($count2 > 20000){
|
139 |
-
$wfdb->
|
140 |
} else if($count2 > $maxRows){
|
141 |
$wfdb->query("delete from $p"."wfLogins order by ctime asc limit %d", ($count2 - $maxRows));
|
142 |
}
|
143 |
$wfdb->query("delete from $p"."wfReverseCache where unix_timestamp() - lastUpdate > 86400");
|
144 |
$count3 = $wfdb->querySingle("select count(*) as cnt from $p"."wfThrottleLog");
|
145 |
if($count3 > 20000){
|
146 |
-
$wfdb->
|
147 |
} else if($count3 > $maxRows){
|
148 |
$wfdb->query("delete from $p"."wfThrottleLog order by endTime asc limit %d", ($count3 - $maxRows));
|
149 |
}
|
150 |
$count4 = $wfdb->querySingle("select count(*) as cnt from $p"."wfStatus");
|
151 |
if($count4 > 100000){
|
152 |
-
$wfdb->
|
153 |
} else if($count4 > 1000){ //max status events we keep. This determines how much gets emailed to us when users sends us a debug report.
|
154 |
$wfdb->query("delete from $p"."wfStatus where level != 10 order by ctime asc limit %d", ($count4 - 1000));
|
155 |
$count5 = $wfdb->querySingle("select count(*) as cnt from $p"."wfStatus where level=10");
|
@@ -535,7 +535,22 @@ class wordfence {
|
|
535 |
wfConfig::set_ser('scanSched', $schedule);
|
536 |
wfConfig::set('schedMode', $schedMode);
|
537 |
wordfence::scheduleScans();
|
538 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
}
|
540 |
public static function wordfenceStartScheduledScan(){
|
541 |
//This prevents scheduled scans from piling up on low traffic blogs and all being run at once.
|
@@ -555,7 +570,7 @@ class wordfence {
|
|
555 |
wfScanEngine::startScan();
|
556 |
}
|
557 |
public static function scheduleScans(){ //Idempotent. Deschedules everything and schedules the following week.
|
558 |
-
|
559 |
$sched = wfConfig::get_ser('scanSched', array());
|
560 |
$mode = wfConfig::get('schedMode');
|
561 |
if($mode == 'manual' && is_array($sched) && is_array($sched[0]) ){
|
@@ -582,21 +597,38 @@ class wordfence {
|
|
582 |
$wpTime = current_time('timestamp');
|
583 |
$currentDayOfWeek = date('w', $wpTime);
|
584 |
$daysInFuture = $scheduledDay - $currentDayOfWeek; //It's monday and scheduledDay is Wed (3) then result is 2 days in future. It's Wed and sched day is monday, then result is 3 - 1 = -2
|
585 |
-
if($daysInFuture < 0){ $daysInFuture
|
586 |
$currentHour = date('G', $wpTime);
|
587 |
$secsOffset = ($scheduledHour - $currentHour) * 3600; //Offset from current hour, can be negative
|
588 |
$secondsInFuture = ($daysInFuture * 86400) + $secsOffset; //Can be negative, so we schedule those 1 week ahead
|
589 |
if($secondsInFuture < 1){
|
590 |
$secondsInFuture += (86400 * 7); //Add a week
|
591 |
}
|
592 |
-
$
|
593 |
-
$futureTime = $wpTimeRoundDownHour + $secondsInFuture;
|
594 |
wordfence::status(4, 'info', "Scheduled time for day $scheduledDay hour $scheduledHour is: " . date('l jS \of F Y h:i:s A', $futureTime));
|
595 |
-
|
596 |
}
|
597 |
}
|
598 |
}
|
599 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
600 |
public static function ajax_saveCountryBlocking_callback(){
|
601 |
if(! wfConfig::get('isPaid')){
|
602 |
return array('errorMsg' => "Sorry but this feature is only available for paid customers.");
|
@@ -632,6 +664,14 @@ class wordfence {
|
|
632 |
wp_mail($_POST['email'], "Wordfence Activity Log", $content);
|
633 |
return array('ok' => 1);
|
634 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
635 |
public static function ajax_saveConfig_callback(){
|
636 |
$opts = wfConfig::parseOptions();
|
637 |
$emails = array();
|
@@ -1027,7 +1067,7 @@ class wordfence {
|
|
1027 |
}
|
1028 |
}
|
1029 |
|
1030 |
-
if(! ($wfFunc == 'diff' || $wfFunc == 'view' || $wfFunc == 'sysinfo' || $wfFunc == 'IPTraf' || $wfFunc == 'viewActivityLog' || $wfFunc == 'testmem' || $wfFunc == 'testtime')){
|
1031 |
return;
|
1032 |
}
|
1033 |
if(! wfUtils::isAdmin()){
|
@@ -1036,7 +1076,7 @@ class wordfence {
|
|
1036 |
|
1037 |
$nonce = $_GET['nonce'];
|
1038 |
if(! wp_verify_nonce($nonce, 'wp-ajax')){
|
1039 |
-
echo "Bad security token.
|
1040 |
exit(0);
|
1041 |
}
|
1042 |
if($wfFunc == 'diff'){
|
@@ -1045,6 +1085,8 @@ class wordfence {
|
|
1045 |
self::wfFunc_view();
|
1046 |
} else if($wfFunc == 'sysinfo'){
|
1047 |
require('sysinfo.php');
|
|
|
|
|
1048 |
} else if($wfFunc == 'IPTraf'){
|
1049 |
self::wfFunc_IPTraf();
|
1050 |
} else if($wfFunc == 'viewActivityLog'){
|
@@ -1153,7 +1195,7 @@ class wordfence {
|
|
1153 |
return ($a['ctime'] < $b['ctime']) ? -1 : 1;
|
1154 |
}
|
1155 |
public static function wfFunc_view(){
|
1156 |
-
$localFile = ABSPATH . '/' . preg_replace('/^[
|
1157 |
if(strpos($localFile, '..') !== false){
|
1158 |
echo "Invalid file requested. (Relative paths not allowed)";
|
1159 |
exit();
|
@@ -1226,12 +1268,13 @@ class wordfence {
|
|
1226 |
}
|
1227 |
public static function admin_init(){
|
1228 |
if(! wfUtils::isAdmin()){ return; }
|
1229 |
-
foreach(array('activate', 'scan', 'sendActivityLog', 'restoreFile', 'deleteFile', 'removeExclusion', 'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues', 'reverseLookup', 'unlockOutIP', 'unblockIP', 'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule') as $func){
|
1230 |
add_action('wp_ajax_wordfence_' . $func, 'wordfence::ajaxReceiver');
|
1231 |
}
|
1232 |
|
1233 |
if(preg_match('/^Wordfence/', @$_GET['page'])){
|
1234 |
-
|
|
|
1235 |
wp_enqueue_style('wordfence-main-style', wfUtils::getBaseURL() . 'css/main.css', '', WORDFENCE_VERSION);
|
1236 |
wp_enqueue_style('wordfence-colorbox-style', wfUtils::getBaseURL() . 'css/colorbox.css', '', WORDFENCE_VERSION);
|
1237 |
wp_enqueue_style('wordfence-dttable-style', wfUtils::getBaseURL() . 'css/dt_table.css', '', WORDFENCE_VERSION);
|
@@ -1242,15 +1285,24 @@ class wordfence {
|
|
1242 |
wp_enqueue_script('jquery.dataTables', wfUtils::getBaseURL() . 'js/jquery.dataTables.min.js', array('jquery'), WORDFENCE_VERSION);
|
1243 |
//wp_enqueue_script('jquery.tools', wfUtils::getBaseURL() . 'js/jquery.tools.min.js', array('jquery'));
|
1244 |
wp_enqueue_script('wordfenceAdminjs', wfUtils::getBaseURL() . 'js/admin.js', array('jquery'), WORDFENCE_VERSION);
|
1245 |
-
|
1246 |
-
|
1247 |
-
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
}
|
1252 |
|
1253 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1254 |
public static function configure_warning(){
|
1255 |
if(! preg_match('/WordfenceSecOpt/', $_SERVER['REQUEST_URI'])){
|
1256 |
$numRun = wfConfig::get('alertEmailMsgCount', 0);
|
@@ -1266,6 +1318,7 @@ class wordfence {
|
|
1266 |
}
|
1267 |
public static function admin_menus(){
|
1268 |
if(! wfUtils::isAdmin()){ return; }
|
|
|
1269 |
if(! wfConfig::get('alertEmails')){
|
1270 |
if(wfUtils::isAdminPageMU()){
|
1271 |
add_action('network_admin_notices', 'wordfence::configure_warning');
|
@@ -1273,6 +1326,7 @@ class wordfence {
|
|
1273 |
add_action('admin_notices', 'wordfence::configure_warning');
|
1274 |
}
|
1275 |
}
|
|
|
1276 |
if(! wfConfig::get('apiKey')){
|
1277 |
if(wfUtils::isAdminPageMU()){
|
1278 |
add_action('network_admin_notices', 'wordfence::noKeyError');
|
39 |
wp_clear_scheduled_hook('wordfence_scheduled_scan');
|
40 |
|
41 |
//Remove all scheduled scans.
|
42 |
+
self::unscheduleAllScans();
|
43 |
|
44 |
if(wfConfig::get('deleteTablesOnDeact')){
|
45 |
$schema = new wfSchema();
|
61 |
while($rec = mysql_fetch_assoc($q1)){
|
62 |
array_push($URIs, $rec['URI']);
|
63 |
}
|
64 |
+
$wfdb->truncate($p . "wfNet404s");
|
65 |
if(sizeof($URIs) > 0){
|
66 |
try {
|
67 |
$api->call('send_net_404s', array(), array( 'URIs' => json_encode($URIs) ));
|
75 |
while($rec = mysql_fetch_assoc($q2)){
|
76 |
$scanCont .= pack('N', ip2long($rec['IP']));
|
77 |
}
|
78 |
+
$wfdb->truncate($p . "wfVulnScanners");
|
79 |
|
80 |
$q3 = $wfdb->query("select INET_NTOA(IP) as IP from $p"."wfLockedOut where blockedTime > unix_timestamp() - 3600");
|
81 |
$lockCont = "";
|
120 |
}
|
121 |
|
122 |
$wfdb->query("delete from $p"."wfLocs where ctime < unix_timestamp() - %d", WORDFENCE_MAX_IPLOC_AGE);
|
123 |
+
$wfdb->truncate($p . "wfBadLeechers"); //only uses date that's less than 1 minute old
|
124 |
$wfdb->query("delete from $p"."wfBlocks where (blockedTime + %s < unix_timestamp()) and permanent=0", wfConfig::get('blockedTime'));
|
125 |
$wfdb->query("delete from $p"."wfCrawlers where lastUpdate < unix_timestamp() - (86400 * 7)");
|
126 |
|
136 |
$wfdb->query("delete from $p"."wfLockedOut where blockedTime + %s < unix_timestamp()", wfConfig::get('loginSec_lockoutMins') * 60);
|
137 |
$count2 = $wfdb->querySingle("select count(*) as cnt from $p"."wfLogins");
|
138 |
if($count2 > 20000){
|
139 |
+
$wfdb->truncate($p . "wfLogins"); //in case of Dos
|
140 |
} else if($count2 > $maxRows){
|
141 |
$wfdb->query("delete from $p"."wfLogins order by ctime asc limit %d", ($count2 - $maxRows));
|
142 |
}
|
143 |
$wfdb->query("delete from $p"."wfReverseCache where unix_timestamp() - lastUpdate > 86400");
|
144 |
$count3 = $wfdb->querySingle("select count(*) as cnt from $p"."wfThrottleLog");
|
145 |
if($count3 > 20000){
|
146 |
+
$wfdb->truncate($p . "wfThrottleLog"); //in case of DoS
|
147 |
} else if($count3 > $maxRows){
|
148 |
$wfdb->query("delete from $p"."wfThrottleLog order by endTime asc limit %d", ($count3 - $maxRows));
|
149 |
}
|
150 |
$count4 = $wfdb->querySingle("select count(*) as cnt from $p"."wfStatus");
|
151 |
if($count4 > 100000){
|
152 |
+
$wfdb->truncate($p . "wfStatus");
|
153 |
} else if($count4 > 1000){ //max status events we keep. This determines how much gets emailed to us when users sends us a debug report.
|
154 |
$wfdb->query("delete from $p"."wfStatus where level != 10 order by ctime asc limit %d", ($count4 - 1000));
|
155 |
$count5 = $wfdb->querySingle("select count(*) as cnt from $p"."wfStatus where level=10");
|
535 |
wfConfig::set_ser('scanSched', $schedule);
|
536 |
wfConfig::set('schedMode', $schedMode);
|
537 |
wordfence::scheduleScans();
|
538 |
+
$nextTime = self::getNextScanStartTime();
|
539 |
+
return array(
|
540 |
+
'ok' => 1,
|
541 |
+
'nextStart' => ($nextTime ? $nextTime : '')
|
542 |
+
);
|
543 |
+
}
|
544 |
+
public static function getNextScanStartTime(){
|
545 |
+
$nextTime = false;
|
546 |
+
$cron = _get_cron_array();
|
547 |
+
foreach($cron as $key => $val){
|
548 |
+
if(isset($val['wordfence_start_scheduled_scan'])){
|
549 |
+
$nextTime = $key;
|
550 |
+
break;
|
551 |
+
}
|
552 |
+
}
|
553 |
+
return ($nextTime ? date('l jS \of F Y H:i:s A', $nextTime + (3600 * get_option('gmt_offset'))) : '');
|
554 |
}
|
555 |
public static function wordfenceStartScheduledScan(){
|
556 |
//This prevents scheduled scans from piling up on low traffic blogs and all being run at once.
|
570 |
wfScanEngine::startScan();
|
571 |
}
|
572 |
public static function scheduleScans(){ //Idempotent. Deschedules everything and schedules the following week.
|
573 |
+
self::unscheduleAllScans();
|
574 |
$sched = wfConfig::get_ser('scanSched', array());
|
575 |
$mode = wfConfig::get('schedMode');
|
576 |
if($mode == 'manual' && is_array($sched) && is_array($sched[0]) ){
|
597 |
$wpTime = current_time('timestamp');
|
598 |
$currentDayOfWeek = date('w', $wpTime);
|
599 |
$daysInFuture = $scheduledDay - $currentDayOfWeek; //It's monday and scheduledDay is Wed (3) then result is 2 days in future. It's Wed and sched day is monday, then result is 3 - 1 = -2
|
600 |
+
if($daysInFuture < 0){ $daysInFuture += 7; } //Turns -2 into 5 days in future
|
601 |
$currentHour = date('G', $wpTime);
|
602 |
$secsOffset = ($scheduledHour - $currentHour) * 3600; //Offset from current hour, can be negative
|
603 |
$secondsInFuture = ($daysInFuture * 86400) + $secsOffset; //Can be negative, so we schedule those 1 week ahead
|
604 |
if($secondsInFuture < 1){
|
605 |
$secondsInFuture += (86400 * 7); //Add a week
|
606 |
}
|
607 |
+
$futureTime = time() - (time() % 3600) + $secondsInFuture; //Modulo rounds down to top of the hour
|
|
|
608 |
wordfence::status(4, 'info', "Scheduled time for day $scheduledDay hour $scheduledHour is: " . date('l jS \of F Y h:i:s A', $futureTime));
|
609 |
+
self::scheduleSingleScan($futureTime);
|
610 |
}
|
611 |
}
|
612 |
}
|
613 |
}
|
614 |
+
private static function scheduleSingleScan($futureTime){
|
615 |
+
wp_schedule_single_event($futureTime, 'wordfence_start_scheduled_scan', array($futureTime));
|
616 |
+
$schedArgs = wfConfig::get_ser('schedScanArgs', array());
|
617 |
+
if(! is_array($schedArgs)){ //paranoia
|
618 |
+
$schedArgs = array();
|
619 |
+
}
|
620 |
+
$schedArgs[] = $futureTime;
|
621 |
+
wfConfig::set_ser('schedScanArgs', $schedArgs);
|
622 |
+
}
|
623 |
+
private static function unscheduleAllScans(){
|
624 |
+
wp_clear_scheduled_hook('wordfence_start_scheduled_scan'); //Unschedule legacy scans without args
|
625 |
+
|
626 |
+
$schedArgs = wfConfig::get_ser('schedScanArgs', array());
|
627 |
+
foreach($schedArgs as $futureTime){
|
628 |
+
wp_clear_scheduled_hook('wordfence_start_scheduled_scan', array($futureTime));
|
629 |
+
}
|
630 |
+
wfConfig::set_ser('schedScanArgs', array());
|
631 |
+
}
|
632 |
public static function ajax_saveCountryBlocking_callback(){
|
633 |
if(! wfConfig::get('isPaid')){
|
634 |
return array('errorMsg' => "Sorry but this feature is only available for paid customers.");
|
664 |
wp_mail($_POST['email'], "Wordfence Activity Log", $content);
|
665 |
return array('ok' => 1);
|
666 |
}
|
667 |
+
public static function ajax_startTourAgain_callback(){
|
668 |
+
wfConfig::set('tourClosed', 0);
|
669 |
+
return array('ok' => 1);
|
670 |
+
}
|
671 |
+
public static function ajax_tourClosed_callback(){
|
672 |
+
wfConfig::set('tourClosed', 1);
|
673 |
+
return array('ok' => 1);
|
674 |
+
}
|
675 |
public static function ajax_saveConfig_callback(){
|
676 |
$opts = wfConfig::parseOptions();
|
677 |
$emails = array();
|
1067 |
}
|
1068 |
}
|
1069 |
|
1070 |
+
if(! ($wfFunc == 'diff' || $wfFunc == 'view' || $wfFunc == 'sysinfo' || $wfFunc == 'unknownFiles' || $wfFunc == 'IPTraf' || $wfFunc == 'viewActivityLog' || $wfFunc == 'testmem' || $wfFunc == 'testtime')){
|
1071 |
return;
|
1072 |
}
|
1073 |
if(! wfUtils::isAdmin()){
|
1076 |
|
1077 |
$nonce = $_GET['nonce'];
|
1078 |
if(! wp_verify_nonce($nonce, 'wp-ajax')){
|
1079 |
+
echo "Bad security token. It may have been more than 12 hours since you reloaded the page you came from. Try reloading the page you came from. If that doesn't work, please sign out and sign-in again.";
|
1080 |
exit(0);
|
1081 |
}
|
1082 |
if($wfFunc == 'diff'){
|
1085 |
self::wfFunc_view();
|
1086 |
} else if($wfFunc == 'sysinfo'){
|
1087 |
require('sysinfo.php');
|
1088 |
+
} else if($wfFunc == 'unknownFiles'){
|
1089 |
+
require('unknownFiles.php');
|
1090 |
} else if($wfFunc == 'IPTraf'){
|
1091 |
self::wfFunc_IPTraf();
|
1092 |
} else if($wfFunc == 'viewActivityLog'){
|
1195 |
return ($a['ctime'] < $b['ctime']) ? -1 : 1;
|
1196 |
}
|
1197 |
public static function wfFunc_view(){
|
1198 |
+
$localFile = ABSPATH . '/' . preg_replace('/^(?:\.\.|[\/]+)/', '', $_GET['file']);
|
1199 |
if(strpos($localFile, '..') !== false){
|
1200 |
echo "Invalid file requested. (Relative paths not allowed)";
|
1201 |
exit();
|
1268 |
}
|
1269 |
public static function admin_init(){
|
1270 |
if(! wfUtils::isAdmin()){ return; }
|
1271 |
+
foreach(array('activate', 'scan', 'sendActivityLog', 'restoreFile', 'deleteFile', 'removeExclusion', 'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues', 'reverseLookup', 'unlockOutIP', 'unblockIP', 'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule', 'tourClosed', 'startTourAgain') as $func){
|
1272 |
add_action('wp_ajax_wordfence_' . $func, 'wordfence::ajaxReceiver');
|
1273 |
}
|
1274 |
|
1275 |
if(preg_match('/^Wordfence/', @$_GET['page'])){
|
1276 |
+
wp_enqueue_style('wp-pointer');
|
1277 |
+
wp_enqueue_script('wp-pointer');
|
1278 |
wp_enqueue_style('wordfence-main-style', wfUtils::getBaseURL() . 'css/main.css', '', WORDFENCE_VERSION);
|
1279 |
wp_enqueue_style('wordfence-colorbox-style', wfUtils::getBaseURL() . 'css/colorbox.css', '', WORDFENCE_VERSION);
|
1280 |
wp_enqueue_style('wordfence-dttable-style', wfUtils::getBaseURL() . 'css/dt_table.css', '', WORDFENCE_VERSION);
|
1285 |
wp_enqueue_script('jquery.dataTables', wfUtils::getBaseURL() . 'js/jquery.dataTables.min.js', array('jquery'), WORDFENCE_VERSION);
|
1286 |
//wp_enqueue_script('jquery.tools', wfUtils::getBaseURL() . 'js/jquery.tools.min.js', array('jquery'));
|
1287 |
wp_enqueue_script('wordfenceAdminjs', wfUtils::getBaseURL() . 'js/admin.js', array('jquery'), WORDFENCE_VERSION);
|
1288 |
+
self::setupAdminVars();
|
1289 |
+
} else {
|
1290 |
+
wp_enqueue_style('wp-pointer');
|
1291 |
+
wp_enqueue_script('wp-pointer');
|
1292 |
+
wp_enqueue_script('wordfenceAdminjs', wfUtils::getBaseURL() . 'js/tourTip.js', array('jquery'), WORDFENCE_VERSION);
|
1293 |
+
self::setupAdminVars();
|
1294 |
}
|
1295 |
|
1296 |
}
|
1297 |
+
private static function setupAdminVars(){
|
1298 |
+
wp_localize_script('wordfenceAdminjs', 'WordfenceAdminVars', array(
|
1299 |
+
'ajaxURL' => admin_url('admin-ajax.php'),
|
1300 |
+
'firstNonce' => wp_create_nonce('wp-ajax'),
|
1301 |
+
'siteBaseURL' => wfUtils::getSiteBaseURL(),
|
1302 |
+
'debugOn' => wfConfig::get('debugOn', 0),
|
1303 |
+
'tourClosed' => wfConfig::get('tourClosed', 0)
|
1304 |
+
));
|
1305 |
+
}
|
1306 |
public static function configure_warning(){
|
1307 |
if(! preg_match('/WordfenceSecOpt/', $_SERVER['REQUEST_URI'])){
|
1308 |
$numRun = wfConfig::get('alertEmailMsgCount', 0);
|
1318 |
}
|
1319 |
public static function admin_menus(){
|
1320 |
if(! wfUtils::isAdmin()){ return; }
|
1321 |
+
/* Removed this because we now have the tour.
|
1322 |
if(! wfConfig::get('alertEmails')){
|
1323 |
if(wfUtils::isAdminPageMU()){
|
1324 |
add_action('network_admin_notices', 'wordfence::configure_warning');
|
1326 |
add_action('admin_notices', 'wordfence::configure_warning');
|
1327 |
}
|
1328 |
}
|
1329 |
+
*/
|
1330 |
if(! wfConfig::get('apiKey')){
|
1331 |
if(wfUtils::isAdminPageMU()){
|
1332 |
add_action('network_admin_notices', 'wordfence::noKeyError');
|
lib/wordfenceConstants.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
-
define('WORDFENCE_API_VERSION',
|
3 |
-
define('WORDFENCE_API_URL_SEC', 'https://
|
4 |
-
define('WORDFENCE_API_URL_NONSEC', 'http://
|
5 |
define('WORDFENCE_MAX_SCAN_TIME', 600);
|
6 |
define('WORDFENCE_TRANSIENTS_TIMEOUT', 3600); //how long are items cached in seconds e.g. files downloaded for diffing
|
7 |
define('WORDFENCE_MAX_IPLOC_AGE', 604800); //1 week
|
1 |
<?php
|
2 |
+
define('WORDFENCE_API_VERSION', '2.0');
|
3 |
+
define('WORDFENCE_API_URL_SEC', 'https://noc1.wordfence.com/');
|
4 |
+
define('WORDFENCE_API_URL_NONSEC', 'http://noc1.wordfence.com/');
|
5 |
define('WORDFENCE_MAX_SCAN_TIME', 600);
|
6 |
define('WORDFENCE_TRANSIENTS_TIMEOUT', 3600); //how long are items cached in seconds e.g. files downloaded for diffing
|
7 |
define('WORDFENCE_MAX_IPLOC_AGE', 604800); //1 week
|
lib/wordfenceHash.php
CHANGED
@@ -42,7 +42,7 @@ class wordfenceHash {
|
|
42 |
$this->api = new wfAPI($this->apiKey, $this->wp_version);
|
43 |
}
|
44 |
public function buildFileQueue($path, $only = array()){ //base path and 'only' is a list of files and dirs in the bast that are the only ones that should be processed. Everything else in base is ignored. If only is empty then everything is processed.
|
45 |
-
$this->db->
|
46 |
if($path[strlen($path) - 1] != '/'){
|
47 |
$path .= '/';
|
48 |
}
|
@@ -72,7 +72,11 @@ class wordfenceHash {
|
|
72 |
$haveMoreInDB = true;
|
73 |
while($haveMoreInDB){
|
74 |
$haveMoreInDB = false;
|
75 |
-
|
|
|
|
|
|
|
|
|
76 |
$ids = array();
|
77 |
while($rec = mysql_fetch_row($res)){
|
78 |
$this->processFile($rec[1]);
|
@@ -86,7 +90,7 @@ class wordfenceHash {
|
|
86 |
}
|
87 |
//Will only reach here if we empty file queue. fork may cause exit
|
88 |
$this->sendHashPacket();
|
89 |
-
$this->db->
|
90 |
$this->writeHashingStatus();
|
91 |
}
|
92 |
private function writeHashingStatus(){
|
42 |
$this->api = new wfAPI($this->apiKey, $this->wp_version);
|
43 |
}
|
44 |
public function buildFileQueue($path, $only = array()){ //base path and 'only' is a list of files and dirs in the bast that are the only ones that should be processed. Everything else in base is ignored. If only is empty then everything is processed.
|
45 |
+
$this->db->truncate($this->table);
|
46 |
if($path[strlen($path) - 1] != '/'){
|
47 |
$path .= '/';
|
48 |
}
|
72 |
$haveMoreInDB = true;
|
73 |
while($haveMoreInDB){
|
74 |
$haveMoreInDB = false;
|
75 |
+
//This limit used to be 1000, but we changed it to 5 because forkIfNeeded needs to run frequently, but
|
76 |
+
// we still want to minimize the number of queries we do.
|
77 |
+
// So now we select, process and delete 5 from teh queue and then check forkIfNeeded()
|
78 |
+
// So this assumes that processing 5 files won't take longer than wfScanEngine::$maxExecTime (which was 10 at the time of writing, which is 2 secs per file)
|
79 |
+
$res = $this->db->query("select id, filename from " . $this->table . " limit 5");
|
80 |
$ids = array();
|
81 |
while($rec = mysql_fetch_row($res)){
|
82 |
$this->processFile($rec[1]);
|
90 |
}
|
91 |
//Will only reach here if we empty file queue. fork may cause exit
|
92 |
$this->sendHashPacket();
|
93 |
+
$this->db->truncate($this->table); //Also resets id autoincrement to 1
|
94 |
$this->writeHashingStatus();
|
95 |
}
|
96 |
private function writeHashingStatus(){
|
lib/wordfenceScanner.php
CHANGED
@@ -3,6 +3,8 @@ require_once('wordfenceConstants.php');
|
|
3 |
require_once('wordfenceClass.php');
|
4 |
require_once('wordfenceURLHoover.php');
|
5 |
class wordfenceScanner {
|
|
|
|
|
6 |
//serialized:
|
7 |
protected $path = '';
|
8 |
protected $fileList = array();
|
@@ -17,6 +19,7 @@ class wordfenceScanner {
|
|
17 |
return array('path', 'fileList', 'results', 'errorMsg', 'apiKey', 'wordpressVersion', 'urlHoover', 'totalFilesScanned', 'startTime', 'lastStatusTime');
|
18 |
}
|
19 |
public function __wakeup(){
|
|
|
20 |
}
|
21 |
public function __construct($apiKey, $wordpressVersion, $fileList, $path){
|
22 |
$this->apiKey = $apiKey;
|
@@ -26,10 +29,86 @@ class wordfenceScanner {
|
|
26 |
$path .= '/';
|
27 |
}
|
28 |
$this->path = $path;
|
|
|
|
|
29 |
$this->results = array();
|
30 |
$this->errorMsg = false;
|
31 |
//First extract hosts or IP's and their URL's into $this->hostsFound and URL's into $this->urlsFound
|
32 |
$this->urlHoover = new wordfenceURLHoover($this->apiKey, $this->wordpressVersion);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
}
|
34 |
public function scan($forkObj){
|
35 |
if(! $this->startTime){
|
@@ -116,6 +195,23 @@ class wordfenceScanner {
|
|
116 |
)
|
117 |
));
|
118 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
}
|
120 |
$longestNospace = wfUtils::longestNospace($data);
|
121 |
if($longestNospace > 1000 && (strpos($data, 'eval') !== false || preg_match('/preg_replace\([^\(]+\/[a-z]*e/', $data)) ){
|
3 |
require_once('wordfenceClass.php');
|
4 |
require_once('wordfenceURLHoover.php');
|
5 |
class wordfenceScanner {
|
6 |
+
protected $sigs = array();
|
7 |
+
protected $sigPattern = "";
|
8 |
//serialized:
|
9 |
protected $path = '';
|
10 |
protected $fileList = array();
|
19 |
return array('path', 'fileList', 'results', 'errorMsg', 'apiKey', 'wordpressVersion', 'urlHoover', 'totalFilesScanned', 'startTime', 'lastStatusTime');
|
20 |
}
|
21 |
public function __wakeup(){
|
22 |
+
$this->setupSigs();
|
23 |
}
|
24 |
public function __construct($apiKey, $wordpressVersion, $fileList, $path){
|
25 |
$this->apiKey = $apiKey;
|
29 |
$path .= '/';
|
30 |
}
|
31 |
$this->path = $path;
|
32 |
+
|
33 |
+
|
34 |
$this->results = array();
|
35 |
$this->errorMsg = false;
|
36 |
//First extract hosts or IP's and their URL's into $this->hostsFound and URL's into $this->urlsFound
|
37 |
$this->urlHoover = new wordfenceURLHoover($this->apiKey, $this->wordpressVersion);
|
38 |
+
$this->setupSigs();
|
39 |
+
}
|
40 |
+
private function setupSigs(){
|
41 |
+
//Set up sigs
|
42 |
+
$this->sigs = array(
|
43 |
+
array('\$QBDB51E25BF9A7F3D2475072803D1C36D', "antichat.php, cgi.php and possibly others, this is the var they assign the code to"),
|
44 |
+
array('\$login\s*=\s*"c99"|\$pass\s*=\s*"c99"|\$sess_cookie\s*=\s*"c9'.'9shvars"', "several lines of c99 decoded"),
|
45 |
+
array('C9'.'9Shell v\.', "c99.php"),
|
46 |
+
array('passthru\s*\(\s*getenv\s*\(\s*"HTTP_ACCEPT_LANGUAGE', "accept_language HTTP header backdoor"),
|
47 |
+
array('runcommand\s*\([\'"]etcpasswdfile', "Ajax_PHP Command Shell"),
|
48 |
+
array('exesysform', "AK-74 Security Team Web Shell"),
|
49 |
+
array('\$password\s*=\s*[\'"]antichat', "Antichat shell"),
|
50 |
+
array('if\s*\(\s*\$action\s*==\s*["\']phpeval', "Antichat shell"),
|
51 |
+
array('Can\'t open file, permission denide', "Antichat spelling error"),
|
52 |
+
array('tmp[\'"],\s*["\']phpshell', "Ayyildiz Tim -AYT- Shell v 2.1 Biz"),
|
53 |
+
array('\$this_file\?op=phpinfo', "aZRaiLPhp v1.0"),
|
54 |
+
array('\.\s*\$server_ip\s*=\s*gethostbyname\s*\(\$SERVER_NAME', "c0derz shell [csh] v. 0.1.1"),
|
55 |
+
array('dosyayicek', "c99_locus7s and c99_PSych0"),
|
56 |
+
array('c99_sess_put', "c99_locus7s, c99_PSych0, c99_w4cking, RedhatC99 "),
|
57 |
+
array('PHP Safe\-Mode Bypass', "c99_w4cking"),
|
58 |
+
array('fonksiyonlary_kapat', "CasuS"),
|
59 |
+
array('Dim szCMD, szTempFile', "CmdAsp.asp"),
|
60 |
+
array('Open base dir: \$hopenbasedir', "Crystal shell"),
|
61 |
+
array('find config.inc.php files', "Many c99 variants including NFM, Perl, Predator, CTT, r57, Redhatc99"),
|
62 |
+
array('find all .htpasswd files', "Many c99 variants including NFM, Perl, Predator, CTT, r57, Redhatc9"),
|
63 |
+
array('function anonim_mail', "Cybershell"),
|
64 |
+
array('\$_SESSION\[aupass\]=md5\(\$aupassword', "Cybershell"),
|
65 |
+
array('echo\s+htmlspecialchars\(\s*crypt\(\s*fread', "dC3 Security Crew Shell PRiV"),
|
66 |
+
array('proc_open\(\s*\$_REQUEST', "Dive Shell"),
|
67 |
+
array('file_exists\([\'"]\/usr\/bin\/gcc', "DTool Pro"),
|
68 |
+
array('find all \*\.php files with word [\'"]password', "Dx"),
|
69 |
+
array('WebShell::Configuration', "Gamma Web Shell (perl)"),
|
70 |
+
array('base64_decode\(\$prx', "GFS shell"),
|
71 |
+
array('icq, command\-n\-conquer and shell nfm', "Various GFS variants"),
|
72 |
+
array('open\(FILEHANDLE,\s*[\'"]cd\s+\$param\{dir\}', "go-shell (perl)"),
|
73 |
+
array('document.PostActForm\$', "GRP Webshell"),
|
74 |
+
array('\$cmd 1> \/tmp\/cmdtemp 2>\&1\; cat', "h4ntu shell"),
|
75 |
+
array('\$Düzenlecols, \$Düzenlerows', "iMHaBiRLiGi PHP FTP"),
|
76 |
+
array('get_execution_method\s*\(', "ironshell and many others"),
|
77 |
+
array('proc\s*=\s*runtime\.exec\(\s*cmd\s*\)', "JSP Web Shell"),
|
78 |
+
array('eval>PHP Eval Code', "KAdot Universal Shell"),
|
79 |
+
array('if\(\(\$_POST\[\'exe\'\]\) == "Execute"', "Lamashell"),
|
80 |
+
array('cat \/etc\/passwd', "Liz0ziM and many other malicious apps"),
|
81 |
+
array('exec\(\$com,\$arr\)', "Loaderz WEB Shell"),
|
82 |
+
array('\$SFileName=\$PHP_SELF', "Macker's Private PHPShell"),
|
83 |
+
array('if\s*\(isset\s*\(\$_POST\)\)\s*walkArray\(\s*\$_POST', "Macker's and some c99 variantes"),
|
84 |
+
array('define\(\s*["\']PHPSHELL_VERSION[\'"]\s*,\s*[\'"]\d+', "Matamu and others"),
|
85 |
+
array('If\s*\(\$file_name\)\s*\$header\s*\.=\s*"Content\-Transfer\-Encoding:\s*base64', "Moroccan Spamers Ma-EditioN By GhOsT"),
|
86 |
+
array('\$MyShellVersion', "MyShell"),
|
87 |
+
array('function viewSchema', "Mysql interface"),
|
88 |
+
array('global \$HTTP_GET_VARS, \$HTTP_COOKIE_VARS, \$password', "mysql_tool"),
|
89 |
+
array('\$file\s*=\s*[\'"]\/etc\/passwd[\'"];', "mysql.php"),
|
90 |
+
array('move_uploaded_file\(\$_FILES\[\'probe\'\]\[\'tmp_name\'\]', "NCC-Shell"),
|
91 |
+
array('["\']find all suid files[\'"]', "NetworkFileManager.php and variants"),
|
92 |
+
array('["\']find all sgid files[\'"]', "NetworkFileManager.php and variants"),
|
93 |
+
array('["\']find all config\.inc\.php files[\'"]', "NetworkFileManager.php and variants"),
|
94 |
+
array('["\']find writeable directories and files[\'"]', "NetworkFileManager.php and variants"),
|
95 |
+
array('xargs grep \-li password', "NetworkFileManager.php and variants"),
|
96 |
+
array('\$filename\s*=\s*[\'"]\/etc\/passwd["\']', 'NFM 1.8, NIX Remote Web Shell and others'),
|
97 |
+
array('function mvcp\(\$from', 'NGH, Webcommander'),
|
98 |
+
array('find \/ \-type f \-name \.ht', 'NIX Remote Web Shell, nsTView and other variants'),
|
99 |
+
array('passthru\(\$comd', 'NShell'),
|
100 |
+
array('find \/ \-type f \-perm \-04000', 'nsTView and others'),
|
101 |
+
array('bind\(S,sockaddr_in\(\$LISTEN_PORT,INADDR_ANY', 'Perl Web Shell by RST-GHC'),
|
102 |
+
array('jmp_buf jmp;', 'PHANTASMA'),
|
103 |
+
array('\b(?:system|exec|passthru|shell_exec|proc_open)[\r\n\s\t]*\([\r\n\s\t]*\$_(?:POST|GET|REQUEST|SERVER)', 'PHP Backdoor, many malicious apps and any badly written app')
|
104 |
+
|
105 |
+
|
106 |
+
); //End sigs
|
107 |
+
$sigArr = array();
|
108 |
+
foreach($this->sigs as $elem){
|
109 |
+
$sigArr[] = $elem[0];
|
110 |
+
}
|
111 |
+
$this->sigPattern = '/(' . implode('|', $sigArr) . ')/i';
|
112 |
}
|
113 |
public function scan($forkObj){
|
114 |
if(! $this->startTime){
|
195 |
)
|
196 |
));
|
197 |
break;
|
198 |
+
} else if(strpos($file, 'lib/wordfenceScanner.php') === false && preg_match($this->sigPattern, $data, $matches)){
|
199 |
+
$this->addResult(array(
|
200 |
+
'type' => 'file',
|
201 |
+
'severity' => 1,
|
202 |
+
'ignoreP' => $this->path . $file,
|
203 |
+
'ignoreC' => $fileSum,
|
204 |
+
'shortMsg' => "This file appears to be an attack shell",
|
205 |
+
'longMsg' => "This file appears to be an executable shell that allows hackers entry to your site via a backdoor. If you know about this file you can choose to ignore it to exclude it from future scans. The text we found in this file that matches a known malicious file is: <strong style=\"color: #F00;\">\"" . $matches[1] . "\"</strong>.",
|
206 |
+
'data' => array(
|
207 |
+
'file' => $file,
|
208 |
+
'canDiff' => false,
|
209 |
+
'canFix' => false,
|
210 |
+
'canDelete' => true
|
211 |
+
)
|
212 |
+
));
|
213 |
+
break;
|
214 |
+
|
215 |
}
|
216 |
$longestNospace = wfUtils::longestNospace($data);
|
217 |
if($longestNospace > 1000 && (strpos($data, 'eval') !== false || preg_match('/preg_replace\([^\(]+\/[a-z]*e/', $data)) ){
|
lib/wordfenceURLHoover.php
CHANGED
@@ -39,7 +39,7 @@ class wordfenceURLHoover {
|
|
39 |
} else {
|
40 |
$this->table = 'wp_wfHoover';
|
41 |
}
|
42 |
-
$this->db->
|
43 |
}
|
44 |
public function hoover($id, $data){
|
45 |
if(strpos($data, '.') === false){
|
39 |
} else {
|
40 |
$this->table = 'wp_wfHoover';
|
41 |
}
|
42 |
+
$this->db->truncate($this->table);
|
43 |
}
|
44 |
public function hoover($id, $data){
|
45 |
if(strpos($data, '.') === false){
|
readme.txt
CHANGED
@@ -3,29 +3,30 @@ 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.1
|
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 |
|
10 |
== Description ==
|
11 |
|
12 |
-
Wordfence Security is a free enterprise class security plugin that includes a firewall
|
13 |
|
14 |
-
Wordfence is now Multi-Site compatible.
|
15 |
|
16 |
[Remember to visit our support forums if you have questions or comments.](http://wordfence.com/forums/)
|
17 |
|
18 |
-
Wordfence is 100% free. We also offer a Premium API key that
|
19 |
|
20 |
Wordfence:
|
21 |
|
22 |
-
* Scans core files against repository versions to check their integrity.
|
23 |
-
* WordPress Multi-Site (or WordPress MU in the older parlance) compatible
|
24 |
* Wordfence Security for multi-site also scans all posts and comments across all blogs from one admin panel.
|
25 |
-
* Premium
|
26 |
* See how files have changed. Optionally repair changed files that are security threats.
|
27 |
* Scans for signatures of over 44,000 known malware variants that are known security threats.
|
28 |
-
*
|
|
|
29 |
* Scans for heuristics of backdoors, trojans, suspicious code and other security issues.
|
30 |
* Checks the strength of all user and admin passwords to enhance login security.
|
31 |
* Monitor your DNS security for unauthorized DNS changes.
|
@@ -152,8 +153,34 @@ or a theme, because often these have been updated to fix a security hole.
|
|
152 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
153 |
|
154 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
= 3.1.6 =
|
156 |
-
*
|
157 |
|
158 |
= 3.1.4 =
|
159 |
* Fixed SQL error in code that checks if IP blockedTime has expired. Changed column type to signed.
|
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.1
|
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 |
|
10 |
== Description ==
|
11 |
|
12 |
+
Wordfence Security is a free enterprise class security plugin that includes a firewall, anti-virus scanning, malicious URL scanning and live traffic including crawlers. Wordfence is the only WordPress security plugin that can verify and repair your core, theme and plugin files, even if you don't have backups.
|
13 |
|
14 |
+
Wordfence is now Multi-Site compatible.
|
15 |
|
16 |
[Remember to visit our support forums if you have questions or comments.](http://wordfence.com/forums/)
|
17 |
|
18 |
+
Wordfence is 100% free. We also offer a Premium API key that lets you block countries and schedule scans for specific times.
|
19 |
|
20 |
Wordfence:
|
21 |
|
22 |
+
* Scans core files, themes and plugins against WordPress.org repository versions to check their integrity.
|
23 |
+
* WordPress Multi-Site (or WordPress MU in the older parlance) compatible.
|
24 |
* Wordfence Security for multi-site also scans all posts and comments across all blogs from one admin panel.
|
25 |
+
* Premium users can also block countries and schedule scans for specific times and a higher frequency.
|
26 |
* See how files have changed. Optionally repair changed files that are security threats.
|
27 |
* Scans for signatures of over 44,000 known malware variants that are known security threats.
|
28 |
+
* Scans for many known backdoors including C99, R57, RootShell, Crystal Shell, Matamu, Cybershell, W4cking, Sniper, Predator, Jackal, Phantasma, GFS, Dive, Dx and many many more.
|
29 |
+
* Continuously scans for malware and phishing URL's including all URL's on the Google Safe Browsing List in all your comments, posts and files that are security threats.
|
30 |
* Scans for heuristics of backdoors, trojans, suspicious code and other security issues.
|
31 |
* Checks the strength of all user and admin passwords to enhance login security.
|
32 |
* Monitor your DNS security for unauthorized DNS changes.
|
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.1 =
|
157 |
+
* Theme and plugin scanning is now free. Woohoo!
|
158 |
+
* Added introductory tour for Wordfence.
|
159 |
+
* Upgraded to Wordfence scanning API version 2.0 to allow free theme and plugin scanning.
|
160 |
+
* Fixed two issue with scheduled scanning for premium users that would cause scans to not run or run at wrong times under certain conditions.
|
161 |
+
* Added feature to view unknown files on system to help clean badly infected systems. See on scanning page in "Tools" under yellow box.
|
162 |
+
* Fixed blocked countries overflowing their container in the user interface.
|
163 |
+
* Fixed case where if user is using MySQL >= 5.1.16 and doesn't have the "drop" privilege, they can't truncate the wfFileQueue table and it could grow uncontrollably.
|
164 |
+
* Updated to the new Libyan flag.
|
165 |
+
* Fixed mysql_ping() reconnection to DB generating warnings.
|
166 |
+
* Fixed issue that caused scans to hang. Wordfence now processes smaller batches of files before checking if it needs to fork.
|
167 |
+
* Security scan for backdoors: "s72 Shell", "r57 kartal", "r57shell", "rootshell", "r57", "r57 Mohajer22", "r57 iFX", "php backdoor", "phpRemoteView"
|
168 |
+
* Security scan for backdoors: "nstview", "nshell", "mysql tool", "nsTView", "matamu", "mysql shell", "load shell", "ironshell", "lamashell", "hiddens shell"
|
169 |
+
* Security scan for backdoors: "h4ntu shell", "go shell", "dC3 Shell", "gfs sh", "cybershell", "c99 w4cking", "ctt sh"
|
170 |
+
* Security scan for backdoors: "c99 madnet", "c99 locus7s", "c99 PSych0", "c99", "c0derz shell", "accept language", "Web shell"
|
171 |
+
* Security scan for backdoors: "aZRaiLPhp", "SnIpEr SA Shell", "Safe0ver Shell"
|
172 |
+
* Security scan for backdoors: "SimShell", "Rootshell", "Predator", "PhpSpy", "PHPJackal", "PHANTASMA", "PHP Shell"
|
173 |
+
* Security scan for backdoors: "NTDaddy", "NetworkFileManagerPHP", "NIX REMOTE WEB SHELL", "NGH"
|
174 |
+
* Security scan for backdoors: "NFM", "Mysql interface", "NCC Shell", "MySQL Web Interface", "MyShell", "Macker PHPShell"
|
175 |
+
* Security scan for backdoors: "Loaderz WEB Shell", "KA uShell", "KAdot Universal Shell", "Liz0ziM"
|
176 |
+
* Security scan for backdoors: "Gamma Web Shell", "JspWebshell", "GRP WebShell", "GFS web shell"
|
177 |
+
* Security scan for backdoors: "GFS Web Shell", "Dx", "DxShell, "Dive Shell", "DTool Pro"
|
178 |
+
* Security scan for backdoors: "Ajax PHP Command Shell", "Antichat Shell", "Ayyildiz Shell"
|
179 |
+
* Security scan for backdoors: "C99 Shell", "C99 madShell", "CTT Shell", "CasuS", "CmdAsp", "Crystal Shell", "Cyber Shell"
|
180 |
+
* DNS fix from previous release backed out because it's no longer needed. (We temporarily hardcoded an IP)
|
181 |
+
|
182 |
= 3.1.6 =
|
183 |
+
* Emergency release to deal with DNS issue.
|
184 |
|
185 |
= 3.1.4 =
|
186 |
* Fixed SQL error in code that checks if IP blockedTime has expired. Changed column type to signed.
|
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.1
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
-
define('WORDFENCE_VERSION', '3.1
|
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.1
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
+
define('WORDFENCE_VERSION', '3.2.1');
|
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.
|