Wordfence Security – Firewall & Malware Scan - Version 6.1.9

Version Description

  • Fix: Using WP-CLI causes error Undefined index: SERVER_NAME.
  • Improvement: Hooked up restore/delete file scan tools to Filesystem API.
  • Fix: Reworked country blocking authentication check for access to XMLRPC.
  • Improvement: Added option to require cellphone sign-in on all admin accounts.
  • Improvement: Updated IPv6 GeoIP lite data.
  • Fix: Removed suPHP_ConfigPath from WAF installation process.
  • Fix: Prevent author names from being found through /wp-json/oembed.
  • Improvement: Added better solutions for fixing wordfence-waf.php, .user.ini, or .htaccess in scan.
  • Improvement: Added a method to view which files are currently used for WAF and to remove without reinstalling Wordfence.
  • Improvement: Changed rule compilation to use atomic writes.
  • Improvement: Removed security levels from Options page.
  • Improvement: Added option to disable ajaxwatcher (for whitelisting only for Admins) on the front end.
Download this release

Release Info

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

Code changes from version 6.1.8 to 6.1.9

css/main.css CHANGED
@@ -579,8 +579,16 @@ table.block-ranges-table tr td {
579
  border: 1px solid #ffd975;
580
  border-width: 1px 1px 1px 10px;
581
  }
 
 
 
 
 
 
 
582
  .wf-success-text,
583
- .wf-notice-text {
 
584
  display: inline-block;
585
  vertical-align: middle;
586
  line-height: 1.3;
@@ -591,6 +599,9 @@ table.block-ranges-table tr td {
591
  .wf-notice-text {
592
  color: #6d798c;
593
  }
 
 
 
594
  .wf-success-text {
595
  color: #11967A;
596
  }
@@ -1008,6 +1019,15 @@ table.whitelist-table .edit-mode input.whitelist-edit {
1008
  font-size: 14px;
1009
  line-height: 1.3;
1010
  }
 
 
 
 
 
 
 
 
 
1011
 
1012
  pre.wf-pre {
1013
  margin:8px 0 20px;
579
  border: 1px solid #ffd975;
580
  border-width: 1px 1px 1px 10px;
581
  }
582
+ .wf-error {
583
+ margin: 12px 0;
584
+ padding: 8px;
585
+ background-color: #fff0f0;
586
+ border: 1px solid #dc3232;
587
+ border-width: 1px 1px 1px 10px;
588
+ }
589
  .wf-success-text,
590
+ .wf-notice-text,
591
+ .wf-error-text {
592
  display: inline-block;
593
  vertical-align: middle;
594
  line-height: 1.3;
599
  .wf-notice-text {
600
  color: #6d798c;
601
  }
602
+ .wf-error-text {
603
+ color: #6d798c;
604
+ }
605
  .wf-success-text {
606
  color: #11967A;
607
  }
1019
  font-size: 14px;
1020
  line-height: 1.3;
1021
  }
1022
+ .wordfence-waiting {
1023
+ line-height: 32px;
1024
+ }
1025
+ .wordfence-waiting img {
1026
+ vertical-align: middle;
1027
+ }
1028
+ .wordfence-waiting span {
1029
+
1030
+ }
1031
 
1032
  pre.wf-pre {
1033
  margin:8px 0 20px;
css/wordfenceBox.css ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ ColorBox Core Style:
3
+ The following CSS is consistent between example themes and should not be altered.
4
+ */
5
+ #wordfenceBox, #wfboxOverlay, #wfboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;}
6
+ #wfboxOverlay{position:fixed; width:100%; height:100%;}
7
+ #wfboxMiddleLeft, #wfboxBottomLeft{clear:left;}
8
+ #wfboxContent{position:relative;}
9
+ #wfboxLoadedContent{overflow:auto;}
10
+ #wfboxTitle{margin:0;}
11
+ #wfboxLoadingOverlay, #wfboxLoadingGraphic{position:absolute; top:0; left:0; width:100%;}
12
+ #wfboxPrevious, #wfboxNext, #wfboxClose, #wfboxSlideshow{cursor:pointer;}
13
+ .wfboxPhoto{float:left; margin:auto; border:0; display:block;}
14
+ .wfboxIframe{width:100%; height:100%; display:block; border:0;}
15
+
16
+ /*
17
+ User Style:
18
+ Change the following styles to modify the appearance of ColorBox. They are
19
+ ordered & tabbed in a way that represents the nesting of the generated HTML.
20
+ */
21
+ #wfboxOverlay{
22
+ background: #777;
23
+ background: -webkit-radial-gradient(rgba(120, 120, 120, 0.8), rgba(100, 100, 100, 0.8) 50%, rgba(70, 70, 70, 1));
24
+ background: -moz-radial-gradient(rgba(120, 120, 120, 0.6), rgba(100, 100, 100, 0.8) 20%, rgba(70, 70, 70, 1));
25
+ }
26
+ #wordfenceBox {
27
+ color: #444;
28
+ font-family: "Open Sans", sans-serif;
29
+ font-size: 13px;
30
+ line-height: 1.4em;
31
+ }
32
+ #wfboxContent { background:#fff; overflow:hidden; padding: 0 0 8px; margin: 20px;
33
+ -webkit-border-radius: 3px 3px 2px 2px; -moz-border-radius: 3px 3px 2px 2px; border-radius: 3px 3px 2px 2px; /* border radius */
34
+ -webkit-box-shadow: 0 2px 4px rgba(0,0,0,.4); -moz-box-shadow: 0 2px 4px rgba(0,0,0,.4); box-shadow: 0 2px 4px rgba(0,0,0,.4); /* box shadow */
35
+ -webkit-background-clip: padding-box; /* smoother borders with webkit */ }
36
+ #wfboxError{padding:50px; border:1px solid #ccc;}
37
+ #wfboxLoadedContent {
38
+ /* margin-bottom:28px; */
39
+ /* MDM added: */ margin: 10px 20px 28px 20px; font-family: Arial; color: #333;
40
+ -webkit-border-radius: 2px 2px 0 0; -moz-border-radius: 2px 2px 0 0; border-radius: 2px 2px 0 0; /* border radius */
41
+ }
42
+ #wfboxTitle{position:absolute; bottom:8px; left:5px; text-align:center; width:100%; color:#949494;}
43
+ #wfboxCurrent{position:absolute; bottom:8px; left:63px; color:#949494; text-indent: -9999px;}
44
+ #wfboxSlideshow{position:absolute; bottom:8px; right:35px; color:#0092ef;}
45
+ #wfboxPrevious{position:absolute; bottom:5px; left:5px; background:url(../images/lightbox-controls.png) no-repeat -75px 0; width:25px; height:25px; text-indent:-9999px;}
46
+ #wfboxPrevious.hover{background-position:-75px -25px;}
47
+ #wfboxNext{position:absolute; bottom:5px; left:32px; background:url(../images/lightbox-controls.png) no-repeat -50px 0; width:25px; height:25px; text-indent:-9999px;}
48
+ #wfboxNext.hover{background-position:-50px -25px;}
49
+ #wfboxLoadingOverlay{background:url(../images/loading_background.png) no-repeat center center;}
50
+ #wfboxLoadingGraphic{background:url(../images/loading.gif) no-repeat center center;}
51
+ #wfboxClose{position:absolute; bottom:5px; right:5px; background:url(../images/lightbox-controls.png) no-repeat -25px 0; width:25px; height:25px; text-indent:-9999px;}
52
+ #wfboxClose.hover{background-position:-25px -25px;}
53
+
54
+ /*
55
+ The following fixes a problem where IE7+ replaces a PNG's alpha transparency with a black fill
56
+ when an alpha filter (opacity change) is set on the element or ancestor element.
57
+ */
58
+ .wfboxIE #wfboxTopLeft,
59
+ .wfboxIE #wfboxTopCenter,
60
+ .wfboxIE #wfboxTopRight,
61
+ .wfboxIE #wfboxBottomLeft,
62
+ .wfboxIE #wfboxBottomCenter,
63
+ .wfboxIE #wfboxBottomRight,
64
+ .wfboxIE #wfboxMiddleLeft,
65
+ .wfboxIE #wfboxMiddleRight {
66
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF);
67
+ }
68
+
69
+ /*
70
+ Enforce our styles over any theme styling
71
+ */
72
+ #wordfenceBox, #wordfenceBox:before, #wordfenceBox:after {
73
+ -webkit-box-sizing: content-box;
74
+ -moz-box-sizing: content-box;
75
+ box-sizing: content-box;
76
+ }
77
+
78
+ #wordfenceBox h1, #wordfenceBox h2, #wordfenceBox h3, #wordfenceBox h4, #wordfenceBox h5, #wordfenceBox h6 {
79
+ display: block;
80
+ font-weight: 600
81
+ }
82
+
83
+ #wordfenceBox h1 {
84
+ font-size: 2em;
85
+ margin: .67em 0
86
+ }
87
+
88
+ #wordfenceBox h2, #wordfenceBox h3 {
89
+ font-size: 1.3em;
90
+ margin: 1em 0
91
+ }
92
+
93
+ #wordfenceBox h1, #wordfenceBox h2, #wordfenceBox h3 {
94
+ color: #23282d
95
+ }
96
+
97
+ #wordfenceBox p {
98
+ font-size: 13px;
99
+ line-height: 1.5;
100
+ margin: 1em 0;
101
+ }
102
+
103
+ #wordfenceBox .textright {
104
+ text-align: right;
105
+ }
106
+
107
+ #wordfenceBox .button, #wordfenceBox .button-primary, #wordfenceBox .button-secondary {
108
+ display: inline-block;
109
+ text-decoration: none;
110
+ font-size: 13px;
111
+ line-height: 26px;
112
+ height: 28px;
113
+ margin: 0;
114
+ padding: 0 10px 1px;
115
+ cursor: pointer;
116
+ border-width: 1px;
117
+ border-style: solid;
118
+ -webkit-appearance: none;
119
+ -webkit-border-radius: 3px;
120
+ border-radius: 3px;
121
+ white-space: nowrap;
122
+ -webkit-box-sizing: border-box;
123
+ -moz-box-sizing: border-box;
124
+ box-sizing: border-box
125
+ }
126
+
127
+ #wordfenceBox .button, #wordfenceBox .button-secondary {
128
+ color: #555;
129
+ border-color: #ccc;
130
+ background: #f7f7f7;
131
+ -webkit-box-shadow: 0 1px 0 #ccc;
132
+ box-shadow: 0 1px 0 #ccc;
133
+ vertical-align: top
134
+ }
135
+
136
+ #wordfenceBox p .button {
137
+ vertical-align: baseline;
138
+ font-family: Arial, san-serif;
139
+ font-weight: normal;
140
+ text-transform: none;
141
+ }
142
+
143
+ #wordfenceBox p code {
144
+ padding: 3px 5px 2px;
145
+ margin: 0 1px;
146
+ background: #eaeaea;
147
+ background: rgba(0,0,0,.07);
148
+ font-size: 13px;
149
+ }
150
+
151
+ #wordfenceBox .button-secondary:focus, #wordfenceBox .button-secondary:hover, #wordfenceBox .button.focus, #wordfenceBox .button.hover, #wordfenceBox .button:focus, #wordfenceBox .button:hover {
152
+ background: #fafafa;
153
+ border-color: #999;
154
+ color: #23282d
155
+ }
156
+
157
+ #wordfenceBox a.wfboxhelp {
158
+ float: left;
159
+ background-image: url(../images/help.png);
160
+ width: 12px;
161
+ height: 12px;
162
+ background-position: 0 0;
163
+ background-repeat: no-repeat;
164
+ padding: 0;
165
+ margin: 9px 0px;
166
+ text-decoration: none;
167
+ display: inline-block;
168
+ vertical-align: middle;
169
+ }
images/loading_large.gif ADDED
Binary file
js/admin.ajaxWatcher.js CHANGED
@@ -1,4 +1,4 @@
1
- (function($) {
2
  if (!window['wordfenceAJAXWatcher']) {
3
  window['wordfenceAJAXWatcher'] = {
4
  blockWarningOpen: false,
@@ -27,15 +27,15 @@
27
  }
28
 
29
  wordfenceAJAXWatcher.blockWarningOpen = true;
30
- $.colorbox({
31
  closeButton: false,
32
  width: '400px',
33
- html: "<h3>Background Request Blocked</h3><p>A background request to WordPress was just blocked for the URL <code>" + requestURLEscaped + "</code>. If this occurred as a result of an intentional action, you may consider whitelisting the request to allow it in the future.</p><p class=\"textright\"><a href=\"#\" class=\"button\" id=\"background-block-whitelist\">Whitelist this action</a> <a href=\"#\" class=\"button\" id=\"background-block-dismiss\">Dismiss</a></p>",
34
  onComplete: function() {
35
  $('#background-block-dismiss').click(function(event) {
36
  event.preventDefault();
37
  event.stopPropagation();
38
- $.colorbox.close();
39
  });
40
 
41
  $('#background-block-whitelist').click(function(event) {
@@ -50,11 +50,11 @@
50
  global: false,
51
  success: function() {
52
  alert('The request has been whitelisted. Please try it again.');
53
- $.colorbox.close();
54
  },
55
  error: function() {
56
  alert('An error occurred when adding the request to the whitelist.');
57
- $.colorbox.close();
58
  }
59
  });
60
  }
@@ -71,4 +71,7 @@
71
  $(function() {
72
  wordfenceAJAXWatcher.init();
73
  });
74
- })(jQuery);
 
 
 
1
+ (function($, document, window) {
2
  if (!window['wordfenceAJAXWatcher']) {
3
  window['wordfenceAJAXWatcher'] = {
4
  blockWarningOpen: false,
27
  }
28
 
29
  wordfenceAJAXWatcher.blockWarningOpen = true;
30
+ $.wordfenceBox({
31
  closeButton: false,
32
  width: '400px',
33
+ html: "<h3>Background Request Blocked</h3><p>Wordfence Firewall blocked a background request to WordPress for the URL <code>" + requestURLEscaped + "</code>. If this occurred as a result of an intentional action, you may consider whitelisting the request to allow it in the future.</p><p class=\"textright\"><a href=\"https://docs.wordfence.com/en/Web_Application_Firewall_-_Blocked_Ajax_Requests\" target=\"_blank\" class=\"wfboxhelp\"></a><a href=\"#\" class=\"button\" id=\"background-block-whitelist\">Whitelist this action</a> <a href=\"#\" class=\"button\" id=\"background-block-dismiss\">Dismiss</a></p>",
34
  onComplete: function() {
35
  $('#background-block-dismiss').click(function(event) {
36
  event.preventDefault();
37
  event.stopPropagation();
38
+ $.wordfenceBox.close();
39
  });
40
 
41
  $('#background-block-whitelist').click(function(event) {
50
  global: false,
51
  success: function() {
52
  alert('The request has been whitelisted. Please try it again.');
53
+ $.wordfenceBox.close();
54
  },
55
  error: function() {
56
  alert('An error occurred when adding the request to the whitelist.');
57
+ $.wordfenceBox.close();
58
  }
59
  });
60
  }
71
  $(function() {
72
  wordfenceAJAXWatcher.init();
73
  });
74
+
75
+ }(jQuery, document, window));
76
+
77
+ !function(t,e,i){function n(i,n,o){var r=e.createElement(i);return n&&(r.id=Z+n),o&&(r.style.cssText=o),t(r)}function o(){return i.innerHeight?i.innerHeight:t(i).height()}function r(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return void 0===this.cache[e]&&(n=t(this.el).attr("data-wfbox-"+e),void 0!==n?this.cache[e]=n:void 0!==i[e]?this.cache[e]=i[e]:void 0!==X[e]&&(this.cache[e]=X[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function h(t){var e=W.length,i=(A+t)%e;return 0>i?e+i:i}function a(t,e){return Math.round((/%/.test(t)?("x"===e?E.width():o())/100:1)*parseInt(t,10))}function s(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function l(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function d(t){"contains"in x[0]&&!x[0].contains(t.target)&&t.target!==v[0]&&(t.stopPropagation(),x.focus())}function c(t){c.str!==t&&(x.add(v).removeClass(c.str).addClass(t),c.str=t)}function g(e){A=0,e&&e!==!1&&"nofollow"!==e?(W=t("."+tt).filter(function(){var i=t.data(this,Y),n=new r(this,i);return n.get("rel")===e}),A=W.index(_.el),-1===A&&(W=W.add(_.el),A=W.length-1)):W=t(_.el)}function u(i){t(e).trigger(i),at.triggerHandler(i)}function f(i){var o;if(!G){if(o=t(i).data(Y),_=new r(i,o),g(_.get("rel")),!U){U=$=!0,c(_.get("className")),x.css({visibility:"hidden",display:"block",opacity:""}),I=n(st,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),b.css({width:"",height:""}).append(I),j=T.height()+k.height()+b.outerHeight(!0)-b.height(),D=C.width()+H.width()+b.outerWidth(!0)-b.width(),N=I.outerHeight(!0),z=I.outerWidth(!0);var h=a(_.get("initialWidth"),"x"),s=a(_.get("initialHeight"),"y"),l=_.get("maxWidth"),f=_.get("maxHeight");_.w=Math.max((l!==!1?Math.min(h,a(l,"x")):h)-z-D,0),_.h=Math.max((f!==!1?Math.min(s,a(f,"y")):s)-N-j,0),I.css({width:"",height:_.h}),J.position(),u(et),_.get("onOpen"),O.add(F).hide(),x.focus(),_.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",d,!0),at.one(rt,function(){e.removeEventListener("focus",d,!0)})),_.get("returnFocus")&&at.one(rt,function(){t(_.el).focus()})}var p=parseFloat(_.get("opacity"));v.css({opacity:p===p?p:"",cursor:_.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),_.get("closeButton")?P.html(_.get("close")).appendTo(b):P.appendTo("<div/>"),w()}}function p(){x||(V=!1,E=t(i),x=n(st).attr({id:Y,"class":t.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),v=n(st,"Overlay").hide(),L=t([n(st,"LoadingOverlay")[0],n(st,"LoadingGraphic")[0]]),y=n(st,"Wrapper"),b=n(st,"Content").append(F=n(st,"Title"),R=n(st,"Current"),K=t('<button type="button"/>').attr({id:Z+"Previous"}),B=t('<button type="button"/>').attr({id:Z+"Next"}),S=t('<button type="button"/>').attr({id:Z+"Slideshow"}),L),P=t('<button type="button"/>').attr({id:Z+"Close"}),y.append(n(st).append(n(st,"TopLeft"),T=n(st,"TopCenter"),n(st,"TopRight")),n(st,!1,"clear:left").append(C=n(st,"MiddleLeft"),b,H=n(st,"MiddleRight")),n(st,!1,"clear:left").append(n(st,"BottomLeft"),k=n(st,"BottomCenter"),n(st,"BottomRight"))).find("div div").css({"float":"left"}),M=n(st,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),O=B.add(K).add(R).add(S)),e.body&&!x.parent().length&&t(e.body).append(v,x.append(y,M))}function m(){function i(t){t.which>1||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),f(this))}return x?(V||(V=!0,B.click(function(){J.next()}),K.click(function(){J.prev()}),P.click(function(){J.close()}),v.click(function(){_.get("overlayClose")&&J.close()}),t(e).bind("keydown."+Z,function(t){var e=t.keyCode;U&&_.get("escKey")&&27===e&&(t.preventDefault(),J.close()),U&&_.get("arrowKey")&&W[1]&&!t.altKey&&(37===e?(t.preventDefault(),K.click()):39===e&&(t.preventDefault(),B.click()))}),t.isFunction(t.fn.on)?t(e).on("click."+Z,"."+tt,i):t("."+tt).live("click."+Z,i)),!0):!1}function w(){var e,o,r,h=J.prep,d=++lt;if($=!0,q=!1,u(ht),u(it),_.get("onLoad"),_.h=_.get("height")?a(_.get("height"),"y")-N-j:_.get("innerHeight")&&a(_.get("innerHeight"),"y"),_.w=_.get("width")?a(_.get("width"),"x")-z-D:_.get("innerWidth")&&a(_.get("innerWidth"),"x"),_.mw=_.w,_.mh=_.h,_.get("maxWidth")&&(_.mw=a(_.get("maxWidth"),"x")-z-D,_.mw=_.w&&_.w<_.mw?_.w:_.mw),_.get("maxHeight")&&(_.mh=a(_.get("maxHeight"),"y")-N-j,_.mh=_.h&&_.h<_.mh?_.h:_.mh),e=_.get("href"),Q=setTimeout(function(){L.show()},100),_.get("inline")){var c=t(e).eq(0);r=t("<div>").hide().insertBefore(c),at.one(ht,function(){r.replaceWith(c)}),h(c)}else _.get("iframe")?h(" "):_.get("html")?h(_.get("html")):s(_,e)?(e=l(_,e),q=_.get("createImg"),t(q).addClass(Z+"Photo").bind("error."+Z,function(){h(n(st,"Error").html(_.get("imgError")))}).one("load",function(){d===lt&&setTimeout(function(){var e;_.get("retinaImage")&&i.devicePixelRatio>1&&(q.height=q.height/i.devicePixelRatio,q.width=q.width/i.devicePixelRatio),_.get("scalePhotos")&&(o=function(){q.height-=q.height*e,q.width-=q.width*e},_.mw&&q.width>_.mw&&(e=(q.width-_.mw)/q.width,o()),_.mh&&q.height>_.mh&&(e=(q.height-_.mh)/q.height,o())),_.h&&(q.style.marginTop=Math.max(_.mh-q.height,0)/2+"px"),W[1]&&(_.get("loop")||W[A+1])&&(q.style.cursor="pointer",t(q).bind("click."+Z,function(){J.next()})),q.style.width=q.width+"px",q.style.height=q.height+"px",h(q)},1)}),q.src=e):e&&M.load(e,_.get("data"),function(e,i){d===lt&&h("error"===i?n(st,"Error").html(_.get("xhrError")):t(this).contents())})}var v,x,y,b,T,C,H,k,W,E,I,M,L,F,R,S,B,K,P,O,_,j,D,N,z,A,q,U,$,G,Q,J,V,X={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,rel:function(){return this.rel},href:function(){return t(this).attr("href")},title:function(){return this.title},createImg:function(){var e=new Image,i=t(this).data("cbox-img-attrs");return"object"==typeof i&&t.each(i,function(t,i){e[t]=i}),e},createIframe:function(){var i=e.createElement("iframe"),n=t(this).data("cbox-iframe-attrs");return"object"==typeof n&&t.each(n,function(t,e){i[t]=e}),"frameBorder"in i&&(i.frameBorder=0),"allowTransparency"in i&&(i.allowTransparency="true"),i.name=(new Date).getTime(),i.allowFullscreen=!0,i}},Y="wordfenceBox",Z="wfbox",tt=Z+"Element",et=Z+"_open",it=Z+"_load",nt=Z+"_complete",ot=Z+"_cleanup",rt=Z+"_closed",ht=Z+"_purge",at=t("<a/>"),st="div",lt=0,dt={},ct=function(){function t(){clearTimeout(h)}function e(){(_.get("loop")||W[A+1])&&(t(),h=setTimeout(J.next,_.get("slideshowSpeed")))}function i(){S.html(_.get("slideshowStop")).unbind(s).one(s,n),at.bind(nt,e).bind(it,t),x.removeClass(a+"off").addClass(a+"on")}function n(){t(),at.unbind(nt,e).unbind(it,t),S.html(_.get("slideshowStart")).unbind(s).one(s,function(){J.next(),i()}),x.removeClass(a+"on").addClass(a+"off")}function o(){r=!1,S.hide(),t(),at.unbind(nt,e).unbind(it,t),x.removeClass(a+"off "+a+"on")}var r,h,a=Z+"Slideshow_",s="click."+Z;return function(){r?_.get("slideshow")||(at.unbind(ot,o),o()):_.get("slideshow")&&W[1]&&(r=!0,at.one(ot,o),_.get("slideshowAuto")?i():n(),S.show())}}();t[Y]||(t(p),J=t.fn[Y]=t[Y]=function(e,i){var n,o=this;return e=e||{},t.isFunction(o)&&(o=t("<a/>"),e.open=!0),o[0]?(p(),m()&&(i&&(e.onComplete=i),o.each(function(){var i=t.data(this,Y)||{};t.data(this,Y,t.extend(i,e))}).addClass(tt),n=new r(o[0],e),n.get("open")&&f(o[0])),o):o},J.position=function(e,i){function n(){T[0].style.width=k[0].style.width=b[0].style.width=parseInt(x[0].style.width,10)-D+"px",b[0].style.height=C[0].style.height=H[0].style.height=parseInt(x[0].style.height,10)-j+"px"}var r,h,s,l=0,d=0,c=x.offset();if(E.unbind("resize."+Z),x.css({top:-9e4,left:-9e4}),h=E.scrollTop(),s=E.scrollLeft(),_.get("fixed")?(c.top-=h,c.left-=s,x.css({position:"fixed"})):(l=h,d=s,x.css({position:"absolute"})),d+=_.get("right")!==!1?Math.max(E.width()-_.w-z-D-a(_.get("right"),"x"),0):_.get("left")!==!1?a(_.get("left"),"x"):Math.round(Math.max(E.width()-_.w-z-D,0)/2),l+=_.get("bottom")!==!1?Math.max(o()-_.h-N-j-a(_.get("bottom"),"y"),0):_.get("top")!==!1?a(_.get("top"),"y"):Math.round(Math.max(o()-_.h-N-j,0)/2),x.css({top:c.top,left:c.left,visibility:"visible"}),y[0].style.width=y[0].style.height="9999px",r={width:_.w+z+D,height:_.h+N+j,top:l,left:d},e){var g=0;t.each(r,function(t){return r[t]!==dt[t]?void(g=e):void 0}),e=g}dt=r,e||x.css(r),x.dequeue().animate(r,{duration:e||0,complete:function(){n(),$=!1,y[0].style.width=_.w+z+D+"px",y[0].style.height=_.h+N+j+"px",_.get("reposition")&&setTimeout(function(){E.bind("resize."+Z,J.position)},1),t.isFunction(i)&&i()},step:n})},J.resize=function(t){var e;U&&(t=t||{},t.width&&(_.w=a(t.width,"x")-z-D),t.innerWidth&&(_.w=a(t.innerWidth,"x")),I.css({width:_.w}),t.height&&(_.h=a(t.height,"y")-N-j),t.innerHeight&&(_.h=a(t.innerHeight,"y")),t.innerHeight||t.height||(e=I.scrollTop(),I.css({height:"auto"}),_.h=I.height()),I.css({height:_.h}),e&&I.scrollTop(e),J.position("none"===_.get("transition")?0:_.get("speed")))},J.prep=function(i){function o(){return _.w=_.w||I.width(),_.w=_.mw&&_.mw<_.w?_.mw:_.w,_.w}function a(){return _.h=_.h||I.height(),_.h=_.mh&&_.mh<_.h?_.mh:_.h,_.h}if(U){var d,g="none"===_.get("transition")?0:_.get("speed");I.remove(),I=n(st,"LoadedContent").append(i),I.hide().appendTo(M.show()).css({width:o(),overflow:_.get("scrolling")?"auto":"hidden"}).css({height:a()}).prependTo(b),M.hide(),t(q).css({"float":"none"}),c(_.get("className")),d=function(){function i(){t.support.opacity===!1&&x[0].style.removeAttribute("filter")}var n,o,a=W.length;U&&(o=function(){clearTimeout(Q),L.hide(),u(nt),_.get("onComplete")},F.html(_.get("title")).show(),I.show(),a>1?("string"==typeof _.get("current")&&R.html(_.get("current").replace("{current}",A+1).replace("{total}",a)).show(),B[_.get("loop")||a-1>A?"show":"hide"]().html(_.get("next")),K[_.get("loop")||A?"show":"hide"]().html(_.get("previous")),ct(),_.get("preloading")&&t.each([h(-1),h(1)],function(){var i,n=W[this],o=new r(n,t.data(n,Y)),h=o.get("href");h&&s(o,h)&&(h=l(o,h),i=e.createElement("img"),i.src=h)})):O.hide(),_.get("iframe")?(n=_.get("createIframe"),_.get("scrolling")||(n.scrolling="no"),t(n).attr({src:_.get("href"),"class":Z+"Iframe"}).one("load",o).appendTo(I),at.one(ht,function(){n.src="//about:blank"}),_.get("fastIframe")&&t(n).trigger("load")):o(),"fade"===_.get("transition")?x.fadeTo(g,1,i):i())},"fade"===_.get("transition")?x.fadeTo(g,0,function(){J.position(0,d)}):J.position(g,d)}},J.next=function(){!$&&W[1]&&(_.get("loop")||W[A+1])&&(A=h(1),f(W[A]))},J.prev=function(){!$&&W[1]&&(_.get("loop")||A)&&(A=h(-1),f(W[A]))},J.close=function(){U&&!G&&(G=!0,U=!1,u(ot),_.get("onCleanup"),E.unbind("."+Z),v.fadeTo(_.get("fadeOut")||0,0),x.stop().fadeTo(_.get("fadeOut")||0,0,function(){x.hide(),v.hide(),u(ht),I.remove(),setTimeout(function(){G=!1,u(rt),_.get("onClosed")},1)}))},J.remove=function(){x&&(x.stop(),t[Y].close(),x.stop(!1,!0).remove(),v.remove(),G=!1,x=null,t("."+tt).removeData(Y).removeClass(tt),t(e).unbind("click."+Z).unbind("keydown."+Z))},J.element=function(){return t(_.el)},J.settings=X)}(jQuery,document,window);
js/admin.js CHANGED
@@ -153,9 +153,6 @@
153
  }
154
  } else if (jQuery('#wordfenceMode_options').length > 0) {
155
  this.mode = 'options';
156
- jQuery('.wfConfigElem').change(function() {
157
- jQuery('#securityLevel').val('CUSTOM');
158
- });
159
  this.updateTicker(true);
160
  startTicker = true;
161
  if (this.needTour()) {
@@ -1030,7 +1027,11 @@
1030
  issueID: issueID,
1031
  forceDelete: force
1032
  }, function(res) {
1033
- self.doneDeleteFile(res);
 
 
 
 
1034
  });
1035
  },
1036
  doneDeleteFile: function(res) {
@@ -1154,7 +1155,11 @@
1154
  this.ajax('wordfence_restoreFile', {
1155
  issueID: issueID
1156
  }, function(res) {
1157
- self.doneRestoreFile(res);
 
 
 
 
1158
  });
1159
  },
1160
  doneRestoreFile: function(res) {
@@ -2102,7 +2107,9 @@
2102
  }, function(res) {
2103
  if (res.ok) {
2104
  self.twoFacStatus('User added! Check the user\'s phone to get the activation code.');
2105
- jQuery('<div id="twoFacCont_' + res.userID + '">' + jQuery('#wfTwoFacUserTmpl').tmpl(res).html() + '</div>').prependTo(jQuery('#wfTwoFacUsers'));
 
 
2106
  }
2107
  });
2108
  },
@@ -2113,9 +2120,10 @@
2113
  code: code
2114
  }, function(res) {
2115
  if (res.ok) {
2116
- jQuery('#twoFacCont_' + res.userID).html(
2117
- jQuery('#wfTwoFacUserTmpl').tmpl(res)
2118
- );
 
2119
  self.twoFacStatus('Cellphone Sign-in activated for user.');
2120
  }
2121
  });
@@ -2125,20 +2133,19 @@
2125
  userID: userID
2126
  }, function(res) {
2127
  if (res.ok) {
2128
- jQuery('#twoFacCont_' + res.userID).fadeOut(function() {
2129
  jQuery(this).remove();
 
 
 
 
2130
  });
2131
  }
2132
  });
2133
  },
2134
  loadTwoFactor: function() {
2135
  this.ajax('wordfence_loadTwoFactor', {}, function(res) {
2136
- if (res.users && res.users.length > 0) {
2137
- for (var i = 0; i < res.users.length; i++) {
2138
- jQuery('<div id="twoFacCont_' + res.users[i].userID + '">' +
2139
- jQuery('#wfTwoFacUserTmpl').tmpl(res.users[i]).html() + '</div>').appendTo(jQuery('#wfTwoFacUsers'));
2140
- }
2141
- }
2142
  });
2143
  },
2144
  getQueryParam: function(name) {
@@ -2544,7 +2551,7 @@
2544
 
2545
  wafConfigureAutoPrepend: function() {
2546
  var self = this;
2547
- self.colorbox("400px", 'Backup .htaccess before continuing', 'We are about to change your <em>.htaccess</em> file. Please make a backup of this file proceeding'
2548
  + '<br/>'
2549
  + '<a href="' + WordfenceAdminVars.ajaxURL + '?action=wordfence_downloadHtaccess&nonce=' + self.nonce + '" onclick="jQuery(\'#wf-htaccess-confirm\').prop(\'disabled\', false); return true;">Click here to download a backup copy of your .htaccess file now</a>' +
2550
  '<br /><br />' +
153
  }
154
  } else if (jQuery('#wordfenceMode_options').length > 0) {
155
  this.mode = 'options';
 
 
 
156
  this.updateTicker(true);
157
  startTicker = true;
158
  if (this.needTour()) {
1027
  issueID: issueID,
1028
  forceDelete: force
1029
  }, function(res) {
1030
+ if (res.needsCredentials) {
1031
+ document.location.href = res.redirect;
1032
+ } else {
1033
+ self.doneDeleteFile(res);
1034
+ }
1035
  });
1036
  },
1037
  doneDeleteFile: function(res) {
1155
  this.ajax('wordfence_restoreFile', {
1156
  issueID: issueID
1157
  }, function(res) {
1158
+ if (res.needsCredentials) {
1159
+ document.location.href = res.redirect;
1160
+ } else {
1161
+ self.doneRestoreFile(res);
1162
+ }
1163
  });
1164
  },
1165
  doneRestoreFile: function(res) {
2107
  }, function(res) {
2108
  if (res.ok) {
2109
  self.twoFacStatus('User added! Check the user\'s phone to get the activation code.');
2110
+ var updatedTwoFac = jQuery('#wfTwoFacUserTmpl').tmpl({users: [res]});
2111
+ jQuery('#twoFactorUser-none').remove();
2112
+ jQuery('#wfTwoFacUsers > table > tbody:last-child').append(updatedTwoFac.find('tbody > tr'));
2113
  }
2114
  });
2115
  },
2120
  code: code
2121
  }, function(res) {
2122
  if (res.ok) {
2123
+ var updatedTwoFac = jQuery('#wfTwoFacUserTmpl').tmpl({users: [res]});
2124
+ updatedTwoFac.find('tbody > tr').each(function(index, element) {
2125
+ jQuery('#' + jQuery(element).attr('id')).replaceWith(element);
2126
+ });
2127
  self.twoFacStatus('Cellphone Sign-in activated for user.');
2128
  }
2129
  });
2133
  userID: userID
2134
  }, function(res) {
2135
  if (res.ok) {
2136
+ jQuery('#twoFactorUser-' + res.userID).fadeOut(function() {
2137
  jQuery(this).remove();
2138
+
2139
+ if (jQuery('#wfTwoFacUsers > table > tbody:last-child').children().length == 0) {
2140
+ jQuery('#wfTwoFacUsers').html(jQuery('#wfTwoFacUserTmpl').tmpl({users: []}));
2141
+ }
2142
  });
2143
  }
2144
  });
2145
  },
2146
  loadTwoFactor: function() {
2147
  this.ajax('wordfence_loadTwoFactor', {}, function(res) {
2148
+ jQuery('#wfTwoFacUsers').html(jQuery('#wfTwoFacUserTmpl').tmpl(res));
 
 
 
 
 
2149
  });
2150
  },
2151
  getQueryParam: function(name) {
2551
 
2552
  wafConfigureAutoPrepend: function() {
2553
  var self = this;
2554
+ self.colorbox("400px", 'Backup .htaccess before continuing', 'We are about to change your <em>.htaccess</em> file. Please make a backup of this file before proceeding.'
2555
  + '<br/>'
2556
  + '<a href="' + WordfenceAdminVars.ajaxURL + '?action=wordfence_downloadHtaccess&nonce=' + self.nonce + '" onclick="jQuery(\'#wf-htaccess-confirm\').prop(\'disabled\', false); return true;">Click here to download a backup copy of your .htaccess file now</a>' +
2557
  '<br /><br />' +
lib/GeoIPv6.dat ADDED
Binary file
lib/menu_options.php CHANGED
@@ -1,9 +1,6 @@
1
  <?php
2
  $w = new wfConfig();
3
  ?>
4
- <script type="text/javascript">
5
- var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
6
- </script>
7
  <div class="wordfenceModeElem" id="wordfenceMode_options"></div>
8
  <div class="wrap">
9
  <?php require( 'menuHeader.php' ); ?>
@@ -198,30 +195,6 @@ $w = new wfConfig();
198
  <tr>
199
  <th colspan="2">&nbsp;</th>
200
  </tr>
201
- <tr>
202
- <th>Security Level:<a href="http://docs.wordfence.com/en/Wordfence_options#Security_Level"
203
- target="_blank" class="wfhelp"></a></th>
204
- <td>
205
- <select id="securityLevel" name="securityLevel" onchange="WFAD.changeSecurityLevel(); return true;">
206
- <option value="0"<?php $w->sel( 'securityLevel', '0' ); ?>>Level 0: Disable all Wordfence
207
- security measures
208
- </option>
209
- <option value="1"<?php $w->sel( 'securityLevel', '1' ); ?>>Level 1: Light protection. Just the
210
- basics
211
- </option>
212
- <option value="2"<?php $w->sel( 'securityLevel', '2' ); ?>>Level 2: Medium protection. Suitable
213
- for most sites
214
- </option>
215
- <option value="3"<?php $w->sel( 'securityLevel', '3' ); ?>>Level 3: High security. Use this when
216
- an attack is imminent
217
- </option>
218
- <option value="4"<?php $w->sel( 'securityLevel', '4' ); ?>>Level 4: Lockdown. Protect the site
219
- against an attack in progress at the cost of inconveniencing some users
220
- </option>
221
- <option value="CUSTOM"<?php $w->sel( 'securityLevel', 'CUSTOM' ); ?>>Custom settings</option>
222
- </select>
223
- </td>
224
- </tr>
225
  <tr>
226
  <th>How does Wordfence get IPs:<a
227
  href="http://docs.wordfence.com/en/Wordfence_options#How_does_Wordfence_get_IPs" target="_blank"
@@ -836,7 +809,7 @@ $w = new wfConfig();
836
  name="loginSec_blockAdminReg" <?php $w->cb( 'loginSec_blockAdminReg' ); ?> /></td>
837
  </tr>
838
  <tr>
839
- <th>Prevent discovery of usernames through '/?author=N' scans<a
840
  href="http://docs.wordfence.com/en/Wordfence_options#Prevent_discovery_of_usernames_through_.27.3F.2Fauthor.3DN.27_scans"
841
  target="_blank" class="wfhelp"></a></th>
842
  <td><input type="checkbox" id="loginSec_disableAuthorScan" class="wfConfigElem"
1
  <?php
2
  $w = new wfConfig();
3
  ?>
 
 
 
4
  <div class="wordfenceModeElem" id="wordfenceMode_options"></div>
5
  <div class="wrap">
6
  <?php require( 'menuHeader.php' ); ?>
195
  <tr>
196
  <th colspan="2">&nbsp;</th>
197
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  <tr>
199
  <th>How does Wordfence get IPs:<a
200
  href="http://docs.wordfence.com/en/Wordfence_options#How_does_Wordfence_get_IPs" target="_blank"
809
  name="loginSec_blockAdminReg" <?php $w->cb( 'loginSec_blockAdminReg' ); ?> /></td>
810
  </tr>
811
  <tr>
812
+ <th>Prevent discovery of usernames through '/?author=N' scans and the oEmbed API<a
813
  href="http://docs.wordfence.com/en/Wordfence_options#Prevent_discovery_of_usernames_through_.27.3F.2Fauthor.3DN.27_scans"
814
  target="_blank" class="wfhelp"></a></th>
815
  <td><input type="checkbox" id="loginSec_disableAuthorScan" class="wfConfigElem"
lib/menu_scan.php CHANGED
@@ -3,6 +3,29 @@ $sigUpdateTime = wfConfig::get('signatureUpdateTime');
3
  ?>
4
  <div class="wordfenceModeElem" id="wordfenceMode_scan"></div>
5
  <div class="wrap wordfence">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  <?php require('menuHeader.php'); ?>
7
  <?php $pageTitle = "Wordfence Scan"; $helpLink="http://docs.wordfence.com/en/Wordfence_scanning"; $helpLabel="Learn more about scanning"; include('pageTitle.php'); ?>
8
  <div class="wordfenceWrap">
@@ -171,6 +194,8 @@ $sigUpdateTime = wfConfig::get('signatureUpdateTime');
171
  </div>
172
  </div>
173
  </div>
 
 
174
  </div>
175
  <script type="text/x-jquery-template" id="issueTmpl_configReadable">
176
  <div>
@@ -912,6 +937,40 @@ $sigUpdateTime = wfConfig::get('signatureUpdateTime');
912
  </div>
913
  </div>
914
  </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
915
 
916
  <script type="text/x-jquery-template" id="issueTmpl_spamvertizeCheck">
917
  <div>
3
  ?>
4
  <div class="wordfenceModeElem" id="wordfenceMode_scan"></div>
5
  <div class="wrap wordfence">
6
+
7
+ <?php
8
+ $nonce = filter_input(INPUT_GET, 'nonce', FILTER_SANITIZE_STRING);
9
+ if (!empty($promptForCredentials) && !empty($wpFilesystemActionCallback) && is_callable($wpFilesystemActionCallback)):
10
+ if (wp_verify_nonce($nonce, 'wp-ajax')) {
11
+ $relaxedOwnership = true;
12
+ $homePath = get_home_path();
13
+
14
+ if (!wordfence::requestFilesystemCredentials($filesystemCredentialsAdminURL, $homePath, $relaxedOwnership, true)) {
15
+ echo '</div>';
16
+ return;
17
+ }
18
+
19
+ call_user_func_array($wpFilesystemActionCallback,
20
+ !empty($wpFilesystemActionCallbackArgs) && is_array($wpFilesystemActionCallbackArgs) ? $wpFilesystemActionCallbackArgs : array());
21
+ } else {
22
+ printf("Security token has expired. Click <a href='%s'>here</a> to return to the scan page.", esc_url(network_admin_url('admin.php?page=Wordfence')));
23
+ }
24
+
25
+ ?>
26
+
27
+ <?php else: ?>
28
+
29
  <?php require('menuHeader.php'); ?>
30
  <?php $pageTitle = "Wordfence Scan"; $helpLink="http://docs.wordfence.com/en/Wordfence_scanning"; $helpLabel="Learn more about scanning"; include('pageTitle.php'); ?>
31
  <div class="wordfenceWrap">
194
  </div>
195
  </div>
196
  </div>
197
+ <?php endif ?>
198
+
199
  </div>
200
  <script type="text/x-jquery-template" id="issueTmpl_configReadable">
201
  <div>
937
  </div>
938
  </div>
939
  </script>
940
+ <script type="text/x-jquery-template" id="issueTmpl_checkGSB">
941
+ <div>
942
+ <div class="wfIssue">
943
+ <h2>${shortMsg}</h2>
944
+ <p>
945
+ <table border="0" class="wfIssue" cellspacing="0" cellpadding="0">
946
+ {{if ((typeof data.badURL !== 'undefined') && data.badURL)}}
947
+ <tr><th>Bad URL:</th><td><strong class="wfWarn">${data.badURL}</strong></td></tr>
948
+ {{/if}}
949
+ <tr><th>Issue first detected:</th><td>${timeAgo} ago.</td></tr>
950
+ <tr><th>Severity:</th><td>{{if severity == '1'}}Critical{{else}}Warning{{/if}}</td></tr>
951
+ <tr><th>Status</th><td>
952
+ {{if status == 'new' }}New{{/if}}
953
+ {{if status == 'ignoreC' }}This issue will be ignored until it changes.{{/if}}
954
+ {{if status == 'ignoreP' }}This issue is permanently ignored.{{/if}}
955
+ </td></tr>
956
+ </table>
957
+ </p>
958
+ <p>
959
+ {{html longMsg}}
960
+ </p>
961
+ <div class="wfIssueOptions">
962
+ {{if status == 'new'}}
963
+ <strong>Resolve:</strong>
964
+ <a href="#" onclick="WFAD.updateIssueStatus('${id}', 'delete'); return false;">I have fixed this issue</a>
965
+ <a href="#" onclick="WFAD.updateIssueStatus('${id}', 'ignoreP'); return false;">Ignore this problem</a>
966
+ {{/if}}
967
+ {{if status == 'ignoreP' || status == 'ignoreC'}}
968
+ <a href="#" onclick="WFAD.updateIssueStatus('${id}', 'delete'); return false;">Stop ignoring this issue</a>
969
+ {{/if}}
970
+ </div>
971
+ </div>
972
+ </div>
973
+ </script>
974
 
975
  <script type="text/x-jquery-template" id="issueTmpl_spamvertizeCheck">
976
  <div>
lib/menu_twoFactor.php CHANGED
@@ -27,42 +27,75 @@
27
  <?php } ?>
28
 
29
  <div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
30
- <p style="width: 500px;">
31
- </p>
32
- <p>
33
- <table border="0">
34
  <tr><td>Enter a username to enable Cellphone Sign-in:</td><td><input type="text" id="wfUsername" value="" size="20" /></td></tr>
35
- <tr><td>Enter a phone number where the code will be sent:</td><td><input type="text" id="wfPhone" value="" size="20" />Format: +1-123-555-5034</td></tr>
36
- <tr><td colspan="2"><input type="button" value="Enable Cellphone Sign-in" onclick="WFAD.addTwoFactor(jQuery('#wfUsername').val(), jQuery('#wfPhone').val());" /></td></tr>
37
- </table>
38
- </p>
39
  <div style="height: 20px;">
40
  <div id="wfTwoFacMsg" style="color: #F00;">
41
  &nbsp;
42
  </div>
43
  </div>
 
 
44
  <div id="wfTwoFacUsers">
45
 
46
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  </div>
48
  </div>
49
 
50
  <script type="text/x-jquery-template" id="wfTwoFacUserTmpl">
51
- <div>
52
- <table border="0"><tr>
53
- <td style="width: 100px;">${username}</td>
54
- <td style="width: 150px;">${phone}</td>
55
- <td>
56
- {{if status == 'activated'}}
57
- <span style="color: #0A0;">Cellphone Sign-in Enabled</span>
58
- {{else}}
59
- Enter activation code:<input type="text" id="wfActivate" size="4" /><input type="button" value="Activate" onclick="WFAD.twoFacActivate('${userID}', jQuery('#wfActivate').val());" />
60
- {{/if}}
61
- </td>
62
- <td>&nbsp;&nbsp;&nbsp;<a href="#" onclick="WFAD.delTwoFac('${userID}'); return false;">[Delete]</a></td>
63
- </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  </table>
65
- </div>
66
  </script>
67
  <script type="text/x-jquery-template" id="wfWelcomeTwoFactor">
68
  <div>
27
  <?php } ?>
28
 
29
  <div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
30
+ <h2>Enable Cellphone Sign-in</h2>
31
+ <p><em>Our Cellphone Sign-in uses a technique called "Two Factor Authentication" which is used by banks, government agencies and military world-wide as one of the most secure forms of remote system authentication. We recommend you enable Cellphone Sign-in for all Administrator level accounts.</em></p>
32
+ <table class="wfConfigForm">
 
33
  <tr><td>Enter a username to enable Cellphone Sign-in:</td><td><input type="text" id="wfUsername" value="" size="20" /></td></tr>
34
+ <tr><td>Enter a phone number where the code will be sent:</td><td><input type="text" id="wfPhone" value="" size="20" /> Format: +1-123-555-5034</td></tr>
35
+ <tr><td colspan="2"><input type="button" class="button button-primary" value="Enable Cellphone Sign-in" onclick="WFAD.addTwoFactor(jQuery('#wfUsername').val(), jQuery('#wfPhone').val());" /></td></tr>
36
+ </table>
 
37
  <div style="height: 20px;">
38
  <div id="wfTwoFacMsg" style="color: #F00;">
39
  &nbsp;
40
  </div>
41
  </div>
42
+
43
+ <h2>Cellphone Sign-in Users</h2>
44
  <div id="wfTwoFacUsers">
45
 
46
  </div>
47
+
48
+ <br>
49
+
50
+ <h2>Security Options</h2>
51
+ <table class="wfConfigForm">
52
+ <tr>
53
+ <td><input type="checkbox" id="loginSec_requireAdminTwoFactor" name="loginSec_requireAdminTwoFactor"<?php echo wfConfig::get('loginSec_requireAdminTwoFactor') ? ' checked' : ''; ?>></td>
54
+ <th>Require Cellphone Sign-in for all Administrators<a href="<?php echo $helpLink; ?>" target="_blank" class="wfhelp"></a><br>
55
+ <em>This setting requires at least one administrator to have Cellphone Sign-in enabled. On multisite, this option applies only to super admins.</em></th>
56
+ </tr>
57
+ </table>
58
+
59
+ <script type="text/javascript">
60
+ jQuery('#loginSec_requireAdminTwoFactor').on('click', function() {
61
+ WFAD.updateConfig('loginSec_requireAdminTwoFactor', jQuery('#loginSec_requireAdminTwoFactor').is(':checked') ? 1 : 0, function() {});
62
+ })
63
+ </script>
64
  </div>
65
  </div>
66
 
67
  <script type="text/x-jquery-template" id="wfTwoFacUserTmpl">
68
+ <table class="wf-table">
69
+ <thead>
70
+ <tr>
71
+ <th style="width: 80px;"></th>
72
+ <th style="width: 100px;">User</th>
73
+ <th style="width: 150px;">Phone Number</th>
74
+ <th>Status</th>
75
+ </tr>
76
+ </thead>
77
+ <tbody>
78
+ {{each(idx, user) users}}
79
+ <tr id="twoFactorUser-${user.userID}">
80
+ <td style="white-space: nowrap; text-align: center;"><a href="#" class="button" onclick="WFAD.delTwoFac('${user.userID}'); return false;">Delete</a></td>
81
+ <td style="white-space: nowrap;">${user.username}</td>
82
+ <td style="white-space: nowrap;">${user.phone}</td>
83
+ <td style="white-space: nowrap;">
84
+ {{if user.status == 'activated'}}
85
+ <span style="color: #0A0;">Cellphone Sign-in Enabled</span>
86
+ {{else}}
87
+ Enter activation code: <input type="text" id="wfActivate-${user.userID}" size="6" /><input type="button" value="Activate" onclick="WFAD.twoFacActivate('${user.userID}', jQuery('#wfActivate-${user.userID}').val());" />
88
+ {{/if}}
89
+ </td>
90
+ </tr>
91
+ {{/each}}
92
+ {{if (users.length == 0)}}
93
+ <tr id="twoFactorUser-none">
94
+ <td colspan="4">No users currently have cellphone sign-in enabled.</td>
95
+ </tr>
96
+ {{/if}}
97
+ </tbody>
98
  </table>
 
99
  </script>
100
  <script type="text/x-jquery-template" id="wfWelcomeTwoFactor">
101
  <div>
lib/menu_waf.php CHANGED
@@ -2,6 +2,7 @@
2
  $waf = wfWAF::getInstance();
3
  $config = $waf->getStorageEngine();
4
  $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configureAutoPrepend');
 
5
  /** @var array $wafData */
6
  ?>
7
  <div class="wrap" id="paidWrap">
@@ -47,9 +48,15 @@ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configu
47
  <?php elseif (!empty($wafActionContent)): ?>
48
  <?php echo $wafActionContent ?>
49
 
50
- <p class="wf-notice"><em>If you cannot complete the setup process,
 
 
 
 
 
51
  <a target="_blank" href="https://docs.wordfence.com/en/Web_Application_Firewall_Setup">click here for
52
  help</a>.</em></p>
 
53
 
54
  <?php else: ?>
55
 
@@ -246,6 +253,23 @@ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configu
246
  </p>
247
 
248
  <div id="waf-whitelisted-urls-wrapper"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  </div>
250
  <?php endif ?>
251
  <?php endif ?>
@@ -703,7 +727,16 @@ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configu
703
  ruleEnabled: enabled
704
  });
705
  });
706
-
 
 
 
 
 
 
 
 
 
707
  })(jQuery);
708
  </script>
709
 
2
  $waf = wfWAF::getInstance();
3
  $config = $waf->getStorageEngine();
4
  $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configureAutoPrepend');
5
+ $wafRemoveURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeAutoPrepend');
6
  /** @var array $wafData */
7
  ?>
8
  <div class="wrap" id="paidWrap">
48
  <?php elseif (!empty($wafActionContent)): ?>
49
  <?php echo $wafActionContent ?>
50
 
51
+ <?php if (!empty($_REQUEST['wafAction']) && $_REQUEST['wafAction'] == 'removeAutoPrepend'): ?>
52
+ <p class="wf-notice"><em>If you cannot complete the uninstallation process,
53
+ <a target="_blank" href="https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F">click here for
54
+ help</a>.</em></p>
55
+ <?php else: ?>
56
+ <p class="wf-notice"><em>If you cannot complete the setup process,
57
  <a target="_blank" href="https://docs.wordfence.com/en/Web_Application_Firewall_Setup">click here for
58
  help</a>.</em></p>
59
+ <?php endif ?>
60
 
61
  <?php else: ?>
62
 
253
  </p>
254
 
255
  <div id="waf-whitelisted-urls-wrapper"></div>
256
+
257
+ <p id="whitelist-monitor">
258
+ <strong>Monitor Background Requests for False Positives:</strong><br>
259
+ <label><input type="checkbox" id="monitor-front" name="monitor-front" value="1"<?php echo wfConfig::get('ajaxWatcherDisabled_front') ? '' : ' checked'; ?>>Front</label> &nbsp; <label><input type="checkbox" id="monitor-admin" name="monitor-admin" value="1"<?php echo wfConfig::get('ajaxWatcherDisabled_admin') ? '' : ' checked'; ?>>Admin Panel</label>
260
+ </p>
261
+ <br>
262
+
263
+ <?php if (WFWAF_AUTO_PREPEND) : ?>
264
+ <h2>Advanced Configuration</h2>
265
+
266
+ <p><strong>Remove Extended Protection<a href="https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F" target="_blank"
267
+ class="wfhelp"></a></strong><br>
268
+
269
+ <em>If you're moving to a new host or a new installation location, you may need to temporarily disable extended protection to avoid any file not found errors. Use this action to remove the configuration changes that enable extended protection mode or you can <a href="https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F" target="_blank">remove them manually</a>.</em></p>
270
+
271
+ <p><a href="<?php echo $wafRemoveURL; ?>" class="button button-small" id="waf-remove-extended">Remove Extended Protection</a></p>
272
+ <?php endif ?>
273
  </div>
274
  <?php endif ?>
275
  <?php endif ?>
727
  ruleEnabled: enabled
728
  });
729
  });
730
+
731
+ $('#monitor-front').on('click', function() {
732
+ var disabled = this.checked ? 0 : 1;
733
+ WFAD.updateConfig('ajaxWatcherDisabled_front', disabled);
734
+ })
735
+
736
+ $('#monitor-admin').on('click', function() {
737
+ var disabled = this.checked ? 0 : 1;
738
+ WFAD.updateConfig('ajaxWatcherDisabled_admin', disabled);
739
+ })
740
  })(jQuery);
741
  </script>
742
 
lib/wfAPI.php CHANGED
@@ -118,12 +118,13 @@ class wfAPI {
118
  }
119
  }
120
  return self::buildQuery(array(
121
- 'v' => $this->wordpressVersion,
122
- 's' => $siteurl,
123
- 'k' => $this->APIKey,
124
- 'openssl' => function_exists('openssl_verify') && defined('OPENSSL_VERSION_NUMBER') ? OPENSSL_VERSION_NUMBER : '0.0.0',
125
- 'phpv' => phpversion(),
126
- 'betaFeed' => (int) wfConfig::get('betaThreatDefenseFeed'),
 
127
  ));
128
  }
129
 
118
  }
119
  }
120
  return self::buildQuery(array(
121
+ 'v' => $this->wordpressVersion,
122
+ 's' => $siteurl,
123
+ 'k' => $this->APIKey,
124
+ 'openssl' => function_exists('openssl_verify') && defined('OPENSSL_VERSION_NUMBER') ? OPENSSL_VERSION_NUMBER : '0.0.0',
125
+ 'phpv' => phpversion(),
126
+ 'betaFeed' => (int) wfConfig::get('betaThreatDefenseFeed'),
127
+ 'cacheType' => wfConfig::get('cacheType'),
128
  ));
129
  }
130
 
lib/wfConfig.php CHANGED
@@ -8,482 +8,111 @@ class wfConfig {
8
  private static $DB = false;
9
  private static $tmpFileHeader = "<?php\n/* Wordfence temporary file security header */\necho \"Nothing to see here!\\n\"; exit(0);\n?>";
10
  private static $tmpDirCache = false;
11
- public static $securityLevels = array(
12
- array( //level 0
13
- "checkboxes" => array(
14
- "alertOn_critical" => false,
15
- "alertOn_update" => false,
16
- "alertOn_warnings" => false,
17
- "alertOn_throttle" => false,
18
- "alertOn_block" => false,
19
- "alertOn_loginLockout" => false,
20
- "alertOn_lostPasswdForm" => false,
21
- "alertOn_adminLogin" => false,
22
- "alertOn_nonAdminLogin" => false,
23
- "liveTrafficEnabled" => true,
24
- "advancedCommentScanning" => false,
25
- "checkSpamIP" => false,
26
- "spamvertizeCheck" => false,
27
- "liveTraf_ignorePublishers" => true,
28
- //"perfLoggingEnabled" => false,
29
- "scheduledScansEnabled" => false,
30
- "scansEnabled_public" => false,
31
- "scansEnabled_heartbleed" => true,
32
- "scansEnabled_core" => false,
33
- "scansEnabled_themes" => false,
34
- "scansEnabled_plugins" => false,
35
- "scansEnabled_malware" => false,
36
- "scansEnabled_fileContents" => false,
37
- "scansEnabled_posts" => false,
38
- "scansEnabled_comments" => false,
39
- "scansEnabled_passwds" => false,
40
- "scansEnabled_diskSpace" => false,
41
- "scansEnabled_options" => false,
42
- "scansEnabled_wpscan_fullPathDisclosure" => true,
43
- "scansEnabled_wpscan_directoryListingEnabled" => true,
44
- "scansEnabled_dns" => false,
45
- "scansEnabled_scanImages" => false,
46
- "scansEnabled_highSense" => false,
47
- "scansEnabled_oldVersions" => false,
48
- "scansEnabled_suspiciousAdminUsers" => false,
49
- "firewallEnabled" => false,
50
- "blockFakeBots" => false,
51
- "autoBlockScanners" => false,
52
- "loginSecurityEnabled" => false,
53
- "loginSec_lockInvalidUsers" => false,
54
- "loginSec_maskLoginErrors" => false,
55
- "loginSec_blockAdminReg" => false,
56
- "loginSec_disableAuthorScan" => false,
57
- "other_hideWPVersion" => false,
58
- "other_noAnonMemberComments" => false,
59
- "other_blockBadPOST" => false,
60
- "other_scanComments" => false,
61
- "other_pwStrengthOnUpdate" => false,
62
- "other_WFNet" => true,
63
- "other_scanOutside" => false,
64
- "deleteTablesOnDeact" => false,
65
- "autoUpdate" => false,
66
- "disableCookies" => false,
67
- "startScansRemotely" => false,
68
- "disableConfigCaching" => false,
69
- "addCacheComment" => false,
70
- "disableCodeExecutionUploads" => false,
71
- "allowHTTPSCaching" => false,
72
- "debugOn" => false,
73
- 'email_summary_enabled' => true,
74
- 'email_summary_dashboard_widget_enabled' => true,
75
- 'ssl_verify' => true,
76
- ),
77
- "otherParams" => array(
78
- 'securityLevel' => '0',
79
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
80
- 'liveTraf_maxRows' => 2000,
81
- "neverBlockBG" => "neverBlockVerified",
82
- "loginSec_countFailMins" => "5",
83
- "loginSec_lockoutMins" => "5",
84
- 'loginSec_strongPasswds' => '',
85
- 'loginSec_maxFailures' => "500",
86
- 'loginSec_maxForgotPasswd' => "500",
87
- 'maxGlobalRequests' => "DISABLED",
88
- 'maxGlobalRequests_action' => "throttle",
89
- 'maxRequestsCrawlers' => "DISABLED",
90
- 'maxRequestsCrawlers_action' => "throttle",
91
- 'maxRequestsHumans' => "DISABLED",
92
- 'maxRequestsHumans_action' => "throttle",
93
- 'max404Crawlers' => "DISABLED",
94
- 'max404Crawlers_action' => "throttle",
95
- 'max404Humans' => "DISABLED",
96
- 'max404Humans_action' => "throttle",
97
- 'maxScanHits' => "DISABLED",
98
- 'maxScanHits_action' => "throttle",
99
- 'blockedTime' => "300",
100
- 'email_summary_interval' => 'biweekly',
101
- 'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
102
- 'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png",
103
- )
104
  ),
105
- array( //level 1
106
- "checkboxes" => array(
107
- "alertOn_critical" => true,
108
- "alertOn_update" => false,
109
- "alertOn_warnings" => false,
110
- "alertOn_throttle" => false,
111
- "alertOn_block" => true,
112
- "alertOn_loginLockout" => true,
113
- "alertOn_lostPasswdForm" => false,
114
- "alertOn_adminLogin" => true,
115
- "alertOn_nonAdminLogin" => false,
116
- "liveTrafficEnabled" => true,
117
- "advancedCommentScanning" => false,
118
- "checkSpamIP" => false,
119
- "spamvertizeCheck" => false,
120
- "liveTraf_ignorePublishers" => true,
121
- //"perfLoggingEnabled" => false,
122
- "scheduledScansEnabled" => true,
123
- "scansEnabled_public" => false,
124
- "scansEnabled_heartbleed" => true,
125
- "scansEnabled_core" => true,
126
- "scansEnabled_themes" => false,
127
- "scansEnabled_plugins" => false,
128
- "scansEnabled_malware" => true,
129
- "scansEnabled_fileContents" => true,
130
- "scansEnabled_posts" => true,
131
- "scansEnabled_comments" => true,
132
- "scansEnabled_passwds" => true,
133
- "scansEnabled_diskSpace" => true,
134
- "scansEnabled_options" => true,
135
- "scansEnabled_wpscan_fullPathDisclosure" => true,
136
- "scansEnabled_wpscan_directoryListingEnabled" => true,
137
- "scansEnabled_dns" => true,
138
- "scansEnabled_scanImages" => false,
139
- "scansEnabled_highSense" => false,
140
- "scansEnabled_oldVersions" => true,
141
- "scansEnabled_suspiciousAdminUsers" => true,
142
- "firewallEnabled" => true,
143
- "blockFakeBots" => false,
144
- "autoBlockScanners" => true,
145
- "loginSecurityEnabled" => true,
146
- "loginSec_lockInvalidUsers" => false,
147
- "loginSec_maskLoginErrors" => true,
148
- "loginSec_blockAdminReg" => true,
149
- "loginSec_disableAuthorScan" => true,
150
- "other_hideWPVersion" => true,
151
- "other_noAnonMemberComments" => true,
152
- "other_blockBadPOST" => false,
153
- "other_scanComments" => true,
154
- "other_pwStrengthOnUpdate" => true,
155
- "other_WFNet" => true,
156
- "other_scanOutside" => false,
157
- "deleteTablesOnDeact" => false,
158
- "autoUpdate" => false,
159
- "disableCookies" => false,
160
- "startScansRemotely" => false,
161
- "disableConfigCaching" => false,
162
- "addCacheComment" => false,
163
- "disableCodeExecutionUploads" => false,
164
- "allowHTTPSCaching" => false,
165
- "debugOn" => false,
166
- 'email_summary_enabled' => true,
167
- 'email_summary_dashboard_widget_enabled' => true,
168
- 'ssl_verify' => true,
169
- ),
170
- "otherParams" => array(
171
- 'securityLevel' => '1',
172
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
173
- 'liveTraf_maxRows' => 2000,
174
- "neverBlockBG" => "neverBlockVerified",
175
- "loginSec_countFailMins" => "5",
176
- "loginSec_lockoutMins" => "5",
177
- 'loginSec_strongPasswds' => 'pubs',
178
- 'loginSec_maxFailures' => "50",
179
- 'loginSec_maxForgotPasswd' => "50",
180
- 'maxGlobalRequests' => "DISABLED",
181
- 'maxGlobalRequests_action' => "throttle",
182
- 'maxRequestsCrawlers' => "DISABLED",
183
- 'maxRequestsCrawlers_action' => "throttle",
184
- 'maxRequestsHumans' => "DISABLED",
185
- 'maxRequestsHumans_action' => "throttle",
186
- 'max404Crawlers' => "DISABLED",
187
- 'max404Crawlers_action' => "throttle",
188
- 'max404Humans' => "DISABLED",
189
- 'max404Humans_action' => "throttle",
190
- 'maxScanHits' => "DISABLED",
191
- 'maxScanHits_action' => "throttle",
192
- 'blockedTime' => "300",
193
- 'email_summary_interval' => 'biweekly',
194
- 'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
195
- 'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png",
196
- )
197
- ),
198
- array( //level 2
199
- "checkboxes" => array(
200
- "alertOn_critical" => true,
201
- "alertOn_update" => false,
202
- "alertOn_warnings" => true,
203
- "alertOn_throttle" => false,
204
- "alertOn_block" => true,
205
- "alertOn_loginLockout" => true,
206
- "alertOn_lostPasswdForm" => true,
207
- "alertOn_adminLogin" => true,
208
- "alertOn_nonAdminLogin" => false,
209
- "liveTrafficEnabled" => true,
210
- "scansEnabled_checkReadableConfig" => true,
211
- "advancedCommentScanning" => false,
212
- "checkSpamIP" => false,
213
- "spamvertizeCheck" => false,
214
- "liveTraf_ignorePublishers" => true,
215
- //"perfLoggingEnabled" => false,
216
- "scheduledScansEnabled" => true,
217
- "scansEnabled_public" => false,
218
- "scansEnabled_heartbleed" => true,
219
- "scansEnabled_core" => true,
220
- "scansEnabled_themes" => false,
221
- "scansEnabled_plugins" => false,
222
- "scansEnabled_malware" => true,
223
- "scansEnabled_fileContents" => true,
224
- "scansEnabled_posts" => true,
225
- "scansEnabled_comments" => true,
226
- "scansEnabled_passwds" => true,
227
- "scansEnabled_diskSpace" => true,
228
- "scansEnabled_options" => true,
229
- "scansEnabled_wpscan_fullPathDisclosure" => true,
230
- "scansEnabled_wpscan_directoryListingEnabled" => true,
231
- "scansEnabled_dns" => true,
232
- "scansEnabled_scanImages" => false,
233
- "scansEnabled_highSense" => false,
234
- "scansEnabled_oldVersions" => true,
235
- "scansEnabled_suspiciousAdminUsers" => true,
236
- "firewallEnabled" => true,
237
- "blockFakeBots" => false,
238
- "autoBlockScanners" => true,
239
- "loginSecurityEnabled" => true,
240
- "loginSec_lockInvalidUsers" => false,
241
- "loginSec_maskLoginErrors" => true,
242
- "loginSec_blockAdminReg" => true,
243
- "loginSec_disableAuthorScan" => true,
244
- "other_hideWPVersion" => true,
245
- "other_noAnonMemberComments" => true,
246
- "other_blockBadPOST" => false,
247
- "other_scanComments" => true,
248
- "other_pwStrengthOnUpdate" => true,
249
- "other_WFNet" => true,
250
- "other_scanOutside" => false,
251
- "deleteTablesOnDeact" => false,
252
- "autoUpdate" => false,
253
- "disableCookies" => false,
254
- "startScansRemotely" => false,
255
- "disableConfigCaching" => false,
256
- "addCacheComment" => false,
257
- "disableCodeExecutionUploads" => false,
258
- "allowHTTPSCaching" => false,
259
- "debugOn" => false,
260
- 'email_summary_enabled' => true,
261
- 'email_summary_dashboard_widget_enabled' => true,
262
- 'ssl_verify' => true,
263
- ),
264
- "otherParams" => array(
265
- "scan_include_extra" => "",
266
- 'securityLevel' => '2',
267
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
268
- 'liveTraf_maxRows' => 2000,
269
- "neverBlockBG" => "neverBlockVerified",
270
- "loginSec_countFailMins" => "240",
271
- "loginSec_lockoutMins" => "240",
272
- 'loginSec_strongPasswds' => 'pubs',
273
- 'loginSec_maxFailures' => "20",
274
- 'loginSec_maxForgotPasswd' => "20",
275
- 'maxGlobalRequests' => "DISABLED",
276
- 'maxGlobalRequests_action' => "throttle",
277
- 'maxRequestsCrawlers' => "DISABLED",
278
- 'maxRequestsCrawlers_action' => "throttle",
279
- 'maxRequestsHumans' => "DISABLED",
280
- 'maxRequestsHumans_action' => "throttle",
281
- 'max404Crawlers' => "DISABLED",
282
- 'max404Crawlers_action' => "throttle",
283
- 'max404Humans' => "DISABLED",
284
- 'max404Humans_action' => "throttle",
285
- 'maxScanHits' => "DISABLED",
286
- 'maxScanHits_action' => "throttle",
287
- 'blockedTime' => "300",
288
- 'email_summary_interval' => 'biweekly',
289
- 'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
290
- 'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png",
291
- )
292
- ),
293
- array( //level 3
294
- "checkboxes" => array(
295
- "alertOn_critical" => true,
296
- "alertOn_update" => false,
297
- "alertOn_warnings" => true,
298
- "alertOn_throttle" => false,
299
- "alertOn_block" => true,
300
- "alertOn_loginLockout" => true,
301
- "alertOn_lostPasswdForm" => true,
302
- "alertOn_adminLogin" => true,
303
- "alertOn_nonAdminLogin" => false,
304
- "liveTrafficEnabled" => true,
305
- "advancedCommentScanning" => false,
306
- "checkSpamIP" => false,
307
- "spamvertizeCheck" => false,
308
- "liveTraf_ignorePublishers" => true,
309
- //"perfLoggingEnabled" => false,
310
- "scheduledScansEnabled" => true,
311
- "scansEnabled_public" => false,
312
- "scansEnabled_heartbleed" => true,
313
- "scansEnabled_core" => true,
314
- "scansEnabled_themes" => false,
315
- "scansEnabled_plugins" => false,
316
- "scansEnabled_malware" => true,
317
- "scansEnabled_fileContents" => true,
318
- "scansEnabled_posts" => true,
319
- "scansEnabled_comments" => true,
320
- "scansEnabled_passwds" => true,
321
- "scansEnabled_diskSpace" => true,
322
- "scansEnabled_options" => true,
323
- "scansEnabled_wpscan_fullPathDisclosure" => true,
324
- "scansEnabled_wpscan_directoryListingEnabled" => true,
325
- "scansEnabled_dns" => true,
326
- "scansEnabled_scanImages" => false,
327
- "scansEnabled_highSense" => false,
328
- "scansEnabled_oldVersions" => true,
329
- "scansEnabled_suspiciousAdminUsers" => true,
330
- "firewallEnabled" => true,
331
- "blockFakeBots" => false,
332
- "autoBlockScanners" => true,
333
- "loginSecurityEnabled" => true,
334
- "loginSec_lockInvalidUsers" => false,
335
- "loginSec_maskLoginErrors" => true,
336
- "loginSec_blockAdminReg" => true,
337
- "loginSec_disableAuthorScan" => true,
338
- "other_hideWPVersion" => true,
339
- "other_noAnonMemberComments" => true,
340
- "other_blockBadPOST" => false,
341
- "other_scanComments" => true,
342
- "other_pwStrengthOnUpdate" => true,
343
- "other_WFNet" => true,
344
- "other_scanOutside" => false,
345
- "deleteTablesOnDeact" => false,
346
- "autoUpdate" => false,
347
- "disableCookies" => false,
348
- "startScansRemotely" => false,
349
- "disableConfigCaching" => false,
350
- "addCacheComment" => false,
351
- "disableCodeExecutionUploads" => false,
352
- "allowHTTPSCaching" => false,
353
- "debugOn" => false,
354
- 'email_summary_enabled' => true,
355
- 'email_summary_dashboard_widget_enabled' => true,
356
- 'ssl_verify' => true,
357
- ),
358
- "otherParams" => array(
359
- 'securityLevel' => '3',
360
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
361
- 'liveTraf_maxRows' => 2000,
362
- "neverBlockBG" => "neverBlockVerified",
363
- "loginSec_countFailMins" => "1440",
364
- "loginSec_lockoutMins" => "1440",
365
- 'loginSec_strongPasswds' => 'all',
366
- 'loginSec_maxFailures' => "10",
367
- 'loginSec_maxForgotPasswd' => "10",
368
- 'maxGlobalRequests' => "960",
369
- 'maxGlobalRequests_action' => "throttle",
370
- 'maxRequestsCrawlers' => "960",
371
- 'maxRequestsCrawlers_action' => "throttle",
372
- 'maxRequestsHumans' => "60",
373
- 'maxRequestsHumans_action' => "throttle",
374
- 'max404Crawlers' => "60",
375
- 'max404Crawlers_action' => "throttle",
376
- 'max404Humans' => "60",
377
- 'max404Humans_action' => "throttle",
378
- 'maxScanHits' => "30",
379
- 'maxScanHits_action' => "throttle",
380
- 'blockedTime' => "1800",
381
- 'email_summary_interval' => 'biweekly',
382
- 'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
383
- 'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png",
384
- )
385
- ),
386
- array( //level 4
387
- "checkboxes" => array(
388
- "alertOn_critical" => true,
389
- "alertOn_update" => false,
390
- "alertOn_warnings" => true,
391
- "alertOn_throttle" => false,
392
- "alertOn_block" => true,
393
- "alertOn_loginLockout" => true,
394
- "alertOn_lostPasswdForm" => true,
395
- "alertOn_adminLogin" => true,
396
- "alertOn_nonAdminLogin" => false,
397
- "liveTrafficEnabled" => true,
398
- "advancedCommentScanning" => false,
399
- "checkSpamIP" => false,
400
- "spamvertizeCheck" => false,
401
- "liveTraf_ignorePublishers" => true,
402
- //"perfLoggingEnabled" => false,
403
- "scheduledScansEnabled" => true,
404
- "scansEnabled_public" => false,
405
- "scansEnabled_heartbleed" => true,
406
- "scansEnabled_core" => true,
407
- "scansEnabled_themes" => false,
408
- "scansEnabled_plugins" => false,
409
- "scansEnabled_malware" => true,
410
- "scansEnabled_fileContents" => true,
411
- "scansEnabled_posts" => true,
412
- "scansEnabled_comments" => true,
413
- "scansEnabled_passwds" => true,
414
- "scansEnabled_diskSpace" => true,
415
- "scansEnabled_options" => true,
416
- "scansEnabled_wpscan_fullPathDisclosure" => true,
417
- "scansEnabled_wpscan_directoryListingEnabled" => true,
418
- "scansEnabled_dns" => true,
419
- "scansEnabled_scanImages" => false,
420
- "scansEnabled_highSense" => false,
421
- "scansEnabled_oldVersions" => true,
422
- "scansEnabled_suspiciousAdminUsers" => true,
423
- "firewallEnabled" => true,
424
- "blockFakeBots" => true,
425
- "autoBlockScanners" => true,
426
- "loginSecurityEnabled" => true,
427
- "loginSec_lockInvalidUsers" => true,
428
- "loginSec_maskLoginErrors" => true,
429
- "loginSec_blockAdminReg" => true,
430
- "loginSec_disableAuthorScan" => true,
431
- "other_hideWPVersion" => true,
432
- "other_noAnonMemberComments" => true,
433
- "other_blockBadPOST" => false,
434
- "other_scanComments" => true,
435
- "other_pwStrengthOnUpdate" => true,
436
- "other_WFNet" => true,
437
- "other_scanOutside" => false,
438
- "deleteTablesOnDeact" => false,
439
- "autoUpdate" => false,
440
- "disableCookies" => false,
441
- "startScansRemotely" => false,
442
- "disableConfigCaching" => false,
443
- "addCacheComment" => false,
444
- "disableCodeExecutionUploads" => false,
445
- "allowHTTPSCaching" => false,
446
- "debugOn" => false,
447
- 'email_summary_enabled' => true,
448
- 'email_summary_dashboard_widget_enabled' => true,
449
- 'ssl_verify' => true,
450
- ),
451
- "otherParams" => array(
452
- 'securityLevel' => '4',
453
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
454
- 'liveTraf_maxRows' => 2000,
455
- "neverBlockBG" => "neverBlockVerified",
456
- "loginSec_countFailMins" => "1440",
457
- "loginSec_lockoutMins" => "1440",
458
- 'loginSec_strongPasswds' => 'all',
459
- 'loginSec_maxFailures' => "5",
460
- 'loginSec_maxForgotPasswd' => "5",
461
- 'maxGlobalRequests' => "960",
462
- 'maxGlobalRequests_action' => "throttle",
463
- 'maxRequestsCrawlers' => "960",
464
- 'maxRequestsCrawlers_action' => "throttle",
465
- 'maxRequestsHumans' => "30",
466
- 'maxRequestsHumans_action' => "block",
467
- 'max404Crawlers' => "30",
468
- 'max404Crawlers_action' => "block",
469
- 'max404Humans' => "60",
470
- 'max404Humans_action' => "block",
471
- 'maxScanHits' => "10",
472
- 'maxScanHits_action' => "block",
473
- 'blockedTime' => "7200",
474
- 'email_summary_interval' => 'biweekly',
475
- 'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
476
- 'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png",
477
- )
478
  )
479
  );
480
  public static function setDefaults(){
481
- foreach(self::$securityLevels[2]['checkboxes'] as $key => $val){
482
  if(self::get($key) === false){
483
  self::set($key, $val ? '1' : '0');
484
  }
485
  }
486
- foreach(self::$securityLevels[2]['otherParams'] as $key => $val){
487
  if(self::get($key) === false){
488
  self::set($key, $val);
489
  }
@@ -504,10 +133,10 @@ class wfConfig {
504
  }
505
  public static function getExportableOptionsKeys(){
506
  $ret = array();
507
- foreach(self::$securityLevels[2]['checkboxes'] as $key => $val){
508
  $ret[] = $key;
509
  }
510
- foreach(self::$securityLevels[2]['otherParams'] as $key => $val){
511
  if($key != 'apiKey'){
512
  $ret[] = $key;
513
  }
@@ -519,10 +148,10 @@ class wfConfig {
519
  }
520
  public static function parseOptions(){
521
  $ret = array();
522
- foreach(self::$securityLevels[2]['checkboxes'] as $key => $val){ //value is not used. We just need the keys for validation
523
  $ret[$key] = isset($_POST[$key]) ? '1' : '0';
524
  }
525
- foreach(self::$securityLevels[2]['otherParams'] as $key => $val){
526
  if(isset($_POST[$key])){
527
  $ret[$key] = stripslashes($_POST[$key]);
528
  } else {
8
  private static $DB = false;
9
  private static $tmpFileHeader = "<?php\n/* Wordfence temporary file security header */\necho \"Nothing to see here!\\n\"; exit(0);\n?>";
10
  private static $tmpDirCache = false;
11
+ public static $defaultConfig = array(
12
+ "checkboxes" => array(
13
+ "alertOn_critical" => true,
14
+ "alertOn_update" => false,
15
+ "alertOn_warnings" => true,
16
+ "alertOn_throttle" => false,
17
+ "alertOn_block" => true,
18
+ "alertOn_loginLockout" => true,
19
+ "alertOn_lostPasswdForm" => true,
20
+ "alertOn_adminLogin" => true,
21
+ "alertOn_nonAdminLogin" => false,
22
+ "liveTrafficEnabled" => true,
23
+ "scansEnabled_checkReadableConfig" => true,
24
+ "advancedCommentScanning" => false,
25
+ "checkSpamIP" => false,
26
+ "spamvertizeCheck" => false,
27
+ "liveTraf_ignorePublishers" => true,
28
+ //"perfLoggingEnabled" => false,
29
+ "scheduledScansEnabled" => true,
30
+ "scansEnabled_public" => false,
31
+ "scansEnabled_heartbleed" => true,
32
+ "scansEnabled_core" => true,
33
+ "scansEnabled_themes" => false,
34
+ "scansEnabled_plugins" => false,
35
+ "scansEnabled_malware" => true,
36
+ "scansEnabled_fileContents" => true,
37
+ "scansEnabled_posts" => true,
38
+ "scansEnabled_comments" => true,
39
+ "scansEnabled_passwds" => true,
40
+ "scansEnabled_diskSpace" => true,
41
+ "scansEnabled_options" => true,
42
+ "scansEnabled_wpscan_fullPathDisclosure" => true,
43
+ "scansEnabled_wpscan_directoryListingEnabled" => true,
44
+ "scansEnabled_dns" => true,
45
+ "scansEnabled_scanImages" => false,
46
+ "scansEnabled_highSense" => false,
47
+ "scansEnabled_oldVersions" => true,
48
+ "scansEnabled_suspiciousAdminUsers" => true,
49
+ "firewallEnabled" => true,
50
+ "blockFakeBots" => false,
51
+ "autoBlockScanners" => true,
52
+ "loginSecurityEnabled" => true,
53
+ "loginSec_lockInvalidUsers" => false,
54
+ "loginSec_maskLoginErrors" => true,
55
+ "loginSec_blockAdminReg" => true,
56
+ "loginSec_disableAuthorScan" => true,
57
+ "loginSec_disableOEmbedAuthor" => false,
58
+ "other_hideWPVersion" => true,
59
+ "other_noAnonMemberComments" => true,
60
+ "other_blockBadPOST" => false,
61
+ "other_scanComments" => true,
62
+ "other_pwStrengthOnUpdate" => true,
63
+ "other_WFNet" => true,
64
+ "other_scanOutside" => false,
65
+ "deleteTablesOnDeact" => false,
66
+ "autoUpdate" => false,
67
+ "disableCookies" => false,
68
+ "startScansRemotely" => false,
69
+ "disableConfigCaching" => false,
70
+ "addCacheComment" => false,
71
+ "disableCodeExecutionUploads" => false,
72
+ "allowHTTPSCaching" => false,
73
+ "debugOn" => false,
74
+ 'email_summary_enabled' => true,
75
+ 'email_summary_dashboard_widget_enabled' => true,
76
+ 'ssl_verify' => true,
77
+ 'ajaxWatcherDisabled_front' => false,
78
+ 'ajaxWatcherDisabled_admin' => false,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  ),
80
+ "otherParams" => array(
81
+ "scan_include_extra" => "",
82
+ // 'securityLevel' => '2',
83
+ "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'bannedURLs' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
84
+ 'liveTraf_maxRows' => 2000,
85
+ "neverBlockBG" => "neverBlockVerified",
86
+ "loginSec_countFailMins" => "240",
87
+ "loginSec_lockoutMins" => "240",
88
+ 'loginSec_strongPasswds' => 'pubs',
89
+ 'loginSec_maxFailures' => "20",
90
+ 'loginSec_maxForgotPasswd' => "20",
91
+ 'maxGlobalRequests' => "DISABLED",
92
+ 'maxGlobalRequests_action' => "throttle",
93
+ 'maxRequestsCrawlers' => "DISABLED",
94
+ 'maxRequestsCrawlers_action' => "throttle",
95
+ 'maxRequestsHumans' => "DISABLED",
96
+ 'maxRequestsHumans_action' => "throttle",
97
+ 'max404Crawlers' => "DISABLED",
98
+ 'max404Crawlers_action' => "throttle",
99
+ 'max404Humans' => "DISABLED",
100
+ 'max404Humans_action' => "throttle",
101
+ 'maxScanHits' => "DISABLED",
102
+ 'maxScanHits_action' => "throttle",
103
+ 'blockedTime' => "300",
104
+ 'email_summary_interval' => 'biweekly',
105
+ 'email_summary_excluded_directories' => 'wp-content/cache,wp-content/wfcache,wp-content/plugins/wordfence/tmp',
106
+ 'allowed404s' => "/favicon.ico\n/apple-touch-icon*.png\n/*@2x.png",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  )
108
  );
109
  public static function setDefaults(){
110
+ foreach(self::$defaultConfig['checkboxes'] as $key => $val){
111
  if(self::get($key) === false){
112
  self::set($key, $val ? '1' : '0');
113
  }
114
  }
115
+ foreach(self::$defaultConfig['otherParams'] as $key => $val){
116
  if(self::get($key) === false){
117
  self::set($key, $val);
118
  }
133
  }
134
  public static function getExportableOptionsKeys(){
135
  $ret = array();
136
+ foreach(self::$defaultConfig['checkboxes'] as $key => $val){
137
  $ret[] = $key;
138
  }
139
+ foreach(self::$defaultConfig['otherParams'] as $key => $val){
140
  if($key != 'apiKey'){
141
  $ret[] = $key;
142
  }
148
  }
149
  public static function parseOptions(){
150
  $ret = array();
151
+ foreach(self::$defaultConfig['checkboxes'] as $key => $val){ //value is not used. We just need the keys for validation
152
  $ret[$key] = isset($_POST[$key]) ? '1' : '0';
153
  }
154
+ foreach(self::$defaultConfig['otherParams'] as $key => $val){
155
  if(isset($_POST[$key])){
156
  $ret[$key] = stripslashes($_POST[$key]);
157
  } else {
lib/wfIssues.php CHANGED
@@ -153,6 +153,7 @@ class wfIssues {
153
  'new' => array(),
154
  'ignored' => array()
155
  );
 
156
  $q1 = $this->getDB()->querySelect("select * from " . $this->issuesTable . " order by time desc");
157
  foreach($q1 as $i){
158
  $i['data'] = unserialize($i['data']);
@@ -170,7 +171,14 @@ class wfIssues {
170
  foreach($ret as $status => &$issueList){
171
  for($i = 0; $i < sizeof($issueList); $i++){
172
  if($issueList[$i]['type'] == 'file'){
173
- $localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $issueList[$i]['data']['file']);
 
 
 
 
 
 
 
174
  if(file_exists($localFile)){
175
  $issueList[$i]['data']['fileExists'] = true;
176
  } else {
153
  'new' => array(),
154
  'ignored' => array()
155
  );
156
+ $userIni = ini_get('user_ini.filename');
157
  $q1 = $this->getDB()->querySelect("select * from " . $this->issuesTable . " order by time desc");
158
  foreach($q1 as $i){
159
  $i['data'] = unserialize($i['data']);
171
  foreach($ret as $status => &$issueList){
172
  for($i = 0; $i < sizeof($issueList); $i++){
173
  if($issueList[$i]['type'] == 'file'){
174
+ $localFile = $issueList[$i]['data']['file'];
175
+ if ($localFile != '.htaccess' && $localFile != $userIni) {
176
+ $localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $localFile);
177
+ }
178
+ else {
179
+ $localFile = ABSPATH . '/' . $localFile;
180
+ }
181
+
182
  if(file_exists($localFile)){
183
  $issueList[$i]['data']['fileExists'] = true;
184
  } else {
lib/wfLog.php CHANGED
@@ -952,44 +952,34 @@ class wfLog {
952
  $skipCountryBlocking = true;
953
  }
954
 
955
- if((! $skipCountryBlocking) && $blockedCountries && (! self::isCBLBypassCookieSet()) ){
956
- if(is_user_logged_in() && (! wfConfig::get('cbl_loggedInBlocked', false)) ){ //User is logged in and we're allowing logins
957
- //Do nothing
958
- } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') !== false && (! wfConfig::get('cbl_loginFormBlocked', false)) ){ //It's the login form and we're allowing that
959
- //Do nothing
960
- } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') === false && (! wfConfig::get('cbl_restOfSiteBlocked', false)) ){ //It's the rest of the site and we're allowing that
961
- //Do nothing
962
- } else {
963
- if($country = wfUtils::IP2Country($IP) ){
964
- foreach(explode(',', $blockedCountries) as $blocked){
965
- if(strtoupper($blocked) == strtoupper($country)){ //At this point we know the user has been blocked
966
- if(wfConfig::get('cbl_action') == 'redir'){
967
- $redirURL = wfConfig::get('cbl_redirURL');
968
- $eRedirHost = wfUtils::extractHostname($redirURL);
969
- $isExternalRedir = false;
970
- if($eRedirHost && $eRedirHost != wfUtils::extractHostname(home_url())){ //It's an external redirect...
971
- $isExternalRedir = true;
972
- }
973
- if( (! $isExternalRedir) && wfUtils::extractBareURI($redirURL) == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it
974
- //Do nothing
975
- /* Uncomment the following if page components aren't loading for the page we redirect to.
976
- Uncommenting is not recommended because it means that anyone from a blocked country
977
- can crawl your site by sending the page blocked users are redirected to as the referer for every request.
978
- But it's your call.
979
- } else if(wfUtils::extractBareURI($_SERVER['HTTP_REFERER']) == $redirURL){ //If the referer the page we want to redirect to? Then this might be loading as a component so don't block.
980
- //Do nothing
981
- */
982
- } else {
983
- $this->redirect(wfConfig::get('cbl_redirURL'));
984
- }
985
- } else {
986
- $this->currentRequest->actionDescription = 'blocked access via country blocking';
987
- $this->do503(3600, "Access from your area has been temporarily limited for security reasons");
988
- wfConfig::inc('totalCountryBlocked');
989
- }
990
- }
991
- }
992
  }
 
 
 
 
 
 
 
 
 
 
 
 
993
  }
994
  }
995
  }
@@ -998,7 +988,7 @@ class wfLog {
998
  $this->getDB()->queryWrite("update " . $this->blocksTable . " set lastAttempt=unix_timestamp(), blockedHits = blockedHits + 1 where IP=%s", $IPnum);
999
  $now = $this->getDB()->querySingle("select unix_timestamp()");
1000
  $secsToGo = ($rec['blockedTime'] + wfConfig::get('blockedTime')) - $now;
1001
- if(wfConfig::get('other_WFNet') && strpos($_SERVER['REQUEST_URI'], '/wp-login.php') !== false){ //We're on the login page and this IP has been blocked
1002
  wordfence::wfsnReportBlockedAttempt($IP, 'login');
1003
  }
1004
  $this->do503($secsToGo, $rec['reason']);
@@ -1021,6 +1011,49 @@ class wfLog {
1021
  }
1022
  return false;
1023
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1024
  private function takeBlockingAction($configVar, $reason){
1025
  if($this->googleSafetyCheckOK()){
1026
  $action = wfConfig::get($configVar . '_action');
@@ -1050,6 +1083,19 @@ class wfLog {
1050
  return;
1051
  }
1052
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1053
  public function do503($secsToGo, $reason){
1054
  $this->initLogRequest();
1055
  $this->currentRequest->statusCode = 403;
952
  $skipCountryBlocking = true;
953
  }
954
 
955
+ if (!$skipCountryBlocking && $blockedCountries && !self::isCBLBypassCookieSet()) {
956
+ // If everything is checked, make sure this always runs.
957
+ if (wfConfig::get('cbl_loggedInBlocked', false) &&
958
+ wfConfig::get('cbl_loginFormBlocked', false) &&
959
+ wfConfig::get('cbl_restOfSiteBlocked', false)) {
960
+ $this->checkForBlockedCountry();
961
+ }
962
+ // Block logged in users.
963
+ if (wfConfig::get('cbl_loggedInBlocked', false) && is_user_logged_in()) {
964
+ $this->checkForBlockedCountry();
965
+ }
966
+ // Block the login form itself and any attempt to authenticate.
967
+ if (wfConfig::get('cbl_loginFormBlocked', false)) {
968
+ if (self::isAuthRequest()) {
969
+ $this->checkForBlockedCountry();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970
  }
971
+ add_filter('authenticate', array($this, 'checkForBlockedCountry'), 1, 0);
972
+ }
973
+ // Block requests that aren't to the login page, xmlrpc.php, or a user already logged in.
974
+ if (wfConfig::get('cbl_restOfSiteBlocked', false) &&
975
+ !self::isAuthRequest() && !defined('XMLRPC_REQUEST') && !is_user_logged_in()) {
976
+ $this->checkForBlockedCountry();
977
+ }
978
+ // XMLRPC is inaccesible when public portion of the site and auth is disabled.
979
+ if (wfConfig::get('cbl_loginFormBlocked', false) &&
980
+ wfConfig::get('cbl_restOfSiteBlocked', false) &&
981
+ defined('XMLRPC_REQUEST')) {
982
+ $this->checkForBlockedCountry();
983
  }
984
  }
985
  }
988
  $this->getDB()->queryWrite("update " . $this->blocksTable . " set lastAttempt=unix_timestamp(), blockedHits = blockedHits + 1 where IP=%s", $IPnum);
989
  $now = $this->getDB()->querySingle("select unix_timestamp()");
990
  $secsToGo = ($rec['blockedTime'] + wfConfig::get('blockedTime')) - $now;
991
+ if(wfConfig::get('other_WFNet') && self::isAuthRequest()){ //It's an auth request and this IP has been blocked
992
  wordfence::wfsnReportBlockedAttempt($IP, 'login');
993
  }
994
  $this->do503($secsToGo, $rec['reason']);
1011
  }
1012
  return false;
1013
  }
1014
+
1015
+ public function checkForBlockedCountry() {
1016
+ static $hasRun;
1017
+ if (isset($hasRun)) {
1018
+ return;
1019
+ }
1020
+ $hasRun = true;
1021
+
1022
+ $blockedCountries = wfConfig::get('cbl_countries', false);
1023
+ $bareRequestURI = wfUtils::extractBareURI($_SERVER['REQUEST_URI']);
1024
+ $IP = wfUtils::getIP();
1025
+ if($country = wfUtils::IP2Country($IP) ){
1026
+ foreach(explode(',', $blockedCountries) as $blocked){
1027
+ if(strtoupper($blocked) == strtoupper($country)){ //At this point we know the user has been blocked
1028
+ if(wfConfig::get('cbl_action') == 'redir'){
1029
+ $redirURL = wfConfig::get('cbl_redirURL');
1030
+ $eRedirHost = wfUtils::extractHostname($redirURL);
1031
+ $isExternalRedir = false;
1032
+ if($eRedirHost && $eRedirHost != wfUtils::extractHostname(home_url())){ //It's an external redirect...
1033
+ $isExternalRedir = true;
1034
+ }
1035
+ if( (! $isExternalRedir) && wfUtils::extractBareURI($redirURL) == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it
1036
+ //Do nothing
1037
+ /* Uncomment the following if page components aren't loading for the page we redirect to.
1038
+ Uncommenting is not recommended because it means that anyone from a blocked country
1039
+ can crawl your site by sending the page blocked users are redirected to as the referer for every request.
1040
+ But it's your call.
1041
+ } else if(wfUtils::extractBareURI($_SERVER['HTTP_REFERER']) == $redirURL){ //If the referer the page we want to redirect to? Then this might be loading as a component so don't block.
1042
+ //Do nothing
1043
+ */
1044
+ } else {
1045
+ $this->redirect(wfConfig::get('cbl_redirURL'));
1046
+ }
1047
+ } else {
1048
+ $this->currentRequest->actionDescription = 'blocked access via country blocking';
1049
+ wfConfig::inc('totalCountryBlocked');
1050
+ $this->do503(3600, "Access from your area has been temporarily limited for security reasons");
1051
+ }
1052
+ }
1053
+ }
1054
+ }
1055
+ }
1056
+
1057
  private function takeBlockingAction($configVar, $reason){
1058
  if($this->googleSafetyCheckOK()){
1059
  $action = wfConfig::get($configVar . '_action');
1083
  return;
1084
  }
1085
  }
1086
+
1087
+ /**
1088
+ * Test if the current request is for wp-login.php or xmlrpc.php
1089
+ *
1090
+ * @return boolean
1091
+ */
1092
+ private static function isAuthRequest() {
1093
+ if ((strpos($_SERVER['REQUEST_URI'], '/wp-login.php') !== false)) {
1094
+ return true;
1095
+ }
1096
+ return false;
1097
+ }
1098
+
1099
  public function do503($secsToGo, $reason){
1100
  $this->initLogRequest();
1101
  $this->currentRequest->statusCode = 403;
lib/wfScanEngine.php CHANGED
@@ -86,6 +86,7 @@ class wfScanEngine {
86
  $this->jobList[] = 'publicSite';
87
  $this->jobList[] = 'checkSpamvertized';
88
  $this->jobList[] = 'checkSpamIP';
 
89
  $this->jobList[] = 'heartbleed';
90
  $this->jobList[] = 'knownFiles_init';
91
  $this->jobList[] = 'knownFiles_main';
@@ -241,6 +242,48 @@ class wfScanEngine {
241
  sleep(2);
242
  }
243
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
 
245
  private function scan_checkReadableConfig() {
246
  $haveIssues = false;
@@ -466,7 +509,7 @@ class wfScanEngine {
466
 
467
 
468
  private function scan_posts_init(){
469
- $this->statusIDX['posts'] = wordfence::statusStart('Scanning posts for URL\'s in Google\'s Safe Browsing List');
470
  $blogsToScan = self::getBlogsToScan('posts');
471
  $wfdb = new wfDB();
472
  $this->hoover = new wordfenceURLHoover($this->apiKey, $this->wp_version);
@@ -573,7 +616,7 @@ class wfScanEngine {
573
  wordfence::statusEnd($this->statusIDX['posts'], $haveIssues);
574
  }
575
  private function scan_comments_init(){
576
- $this->statusIDX['comments'] = wordfence::statusStart('Scanning comments for URL\'s in Google\'s Safe Browsing List');
577
  $this->scanData = array();
578
  $this->scanQueue = array();
579
  $this->hoover = new wordfenceURLHoover($this->apiKey, $this->wp_version);
@@ -767,7 +810,7 @@ class wfScanEngine {
767
  $this->userPasswdQueue = substr($this->userPasswdQueue, 4);
768
  $userLogin = $wfdb->querySingle("select user_login from $wpdb->users where ID=%s", $userID);
769
  if(! $userLogin){
770
- wordfence::status(2, 'error', "Could not get username for user with ID $userID when checking password strenght.");
771
  continue;
772
  }
773
  wordfence::status(4, 'info', "Checking password strength for user $userLogin with ID $userID");
86
  $this->jobList[] = 'publicSite';
87
  $this->jobList[] = 'checkSpamvertized';
88
  $this->jobList[] = 'checkSpamIP';
89
+ $this->jobList[] = 'checkGSB';
90
  $this->jobList[] = 'heartbleed';
91
  $this->jobList[] = 'knownFiles_init';
92
  $this->jobList[] = 'knownFiles_main';
242
  sleep(2);
243
  }
244
  }
245
+
246
+ private function scan_checkGSB(){
247
+ if(wfConfig::get('isPaid')){
248
+ $this->statusIDX['checkGSB'] = wordfence::statusStart("Checking if your site is on the Google Safe Browsing list");
249
+
250
+ $urlsToCheck = array(array(get_site_url()));
251
+ $haveIssues = false;
252
+ $badURLs = $this->api->call('check_bad_urls', array(), array( 'toCheck' => json_encode($urlsToCheck)) );
253
+ if (is_array($badURLs) && sizeof($badURLs) > 0) {
254
+ foreach ($badURLs as $id => $badSiteList) {
255
+ foreach ($badSiteList as $badSite) {
256
+ $url = $badSite[0];
257
+ $badList = $badSite[1];
258
+
259
+ if ($badList == 'goog-malware-shavar') {
260
+ $shortMsg = 'Your site is listed on Google\'s Safe Browsing malware list.';
261
+ $longMsg = "The URL " . esc_html($url) . " is on the malware list. More info available at <a href=\"http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=" . urlencode($url) . "&client=googlechrome&hl=en-US\" target=\"_blank\">Google Safe Browsing diagnostic page</a>.";
262
+ $gsb = $badList;
263
+ }
264
+ else if ($badList == 'googpub-phish-shavar') {
265
+ $shortMsg = 'Your site is listed on Google\'s Safe Browsing phishing list.';
266
+ $longMsg = "The URL " . esc_html($url) . " is on the phishing list. More info available at <a href=\"http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=" . urlencode($url) . "&client=googlechrome&hl=en-US\" target=\"_blank\">Google Safe Browsing diagnostic page</a>.";
267
+ $gsb = $badList;
268
+ }
269
+ else {
270
+ $shortMsg = 'Your site is listed on Google\'s Safe Browsing list.';
271
+ $longMsg = "The URL is: " . esc_html($url) . ". More info available at <a href=\"http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=" . urlencode($url) . "&client=googlechrome&hl=en-US\" target=\"_blank\">Google Safe Browsing diagnostic page</a>.";
272
+ $gsb = 'unknown';
273
+ }
274
+
275
+ $this->addIssue('checkGSB', 1, 'checkGSB', 'checkGSB' . $url, $shortMsg, $longMsg, array('badURL' => $url, 'gsb' => $gsb));
276
+ $haveIssues = true;
277
+ }
278
+ }
279
+ }
280
+
281
+ wordfence::statusEnd($this->statusIDX['checkGSB'], $haveIssues);
282
+ } else {
283
+ wordfence::statusPaidOnly("Checking if your site is on the Google Safe Browsing list is for paid members only");
284
+ sleep(2);
285
+ }
286
+ }
287
 
288
  private function scan_checkReadableConfig() {
289
  $haveIssues = false;
509
 
510
 
511
  private function scan_posts_init(){
512
+ $this->statusIDX['posts'] = wordfence::statusStart('Scanning posts for URLs in Google\'s Safe Browsing List');
513
  $blogsToScan = self::getBlogsToScan('posts');
514
  $wfdb = new wfDB();
515
  $this->hoover = new wordfenceURLHoover($this->apiKey, $this->wp_version);
616
  wordfence::statusEnd($this->statusIDX['posts'], $haveIssues);
617
  }
618
  private function scan_comments_init(){
619
+ $this->statusIDX['comments'] = wordfence::statusStart('Scanning comments for URLs in Google\'s Safe Browsing List');
620
  $this->scanData = array();
621
  $this->scanQueue = array();
622
  $this->hoover = new wordfenceURLHoover($this->apiKey, $this->wp_version);
810
  $this->userPasswdQueue = substr($this->userPasswdQueue, 4);
811
  $userLogin = $wfdb->querySingle("select user_login from $wpdb->users where ID=%s", $userID);
812
  if(! $userLogin){
813
+ wordfence::status(2, 'error', "Could not get username for user with ID $userID when checking password strength.");
814
  continue;
815
  }
816
  wordfence::status(4, 'info', "Checking password strength for user $userLogin with ID $userID");
lib/wfUtils.php CHANGED
@@ -634,14 +634,17 @@ class wfUtils {
634
  public static function isValidIP($IP){
635
  return filter_var($IP, FILTER_VALIDATE_IP) !== false;
636
  }
637
- public static function getRequestedURL(){
638
- if(isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST']){
639
  $host = $_SERVER['HTTP_HOST'];
640
- } else {
641
  $host = $_SERVER['SERVER_NAME'];
642
  }
 
 
 
643
  $prefix = 'http';
644
- if( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] ){
645
  $prefix = 'https';
646
  }
647
  return $prefix . '://' . $host . $_SERVER['REQUEST_URI'];
@@ -1008,10 +1011,11 @@ class wfUtils {
1008
  if(! (function_exists('geoip_open') && function_exists('geoip_country_code_by_addr') && function_exists('geoip_country_code_by_addr_v6'))){
1009
  require_once('wfGeoIP.php');
1010
  }
1011
- $gi = geoip_open(dirname(__FILE__) . "/GeoIP.dat",GEOIP_STANDARD);
1012
  if (filter_var($IP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
 
1013
  $country = geoip_country_code_by_addr_v6($gi, $IP);
1014
  } else {
 
1015
  $country = geoip_country_code_by_addr($gi, $IP);
1016
  }
1017
  geoip_close($gi);
634
  public static function isValidIP($IP){
635
  return filter_var($IP, FILTER_VALIDATE_IP) !== false;
636
  }
637
+ public static function getRequestedURL() {
638
+ if (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST']) {
639
  $host = $_SERVER['HTTP_HOST'];
640
+ } else if (isset($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME']) {
641
  $host = $_SERVER['SERVER_NAME'];
642
  }
643
+ else {
644
+ return null;
645
+ }
646
  $prefix = 'http';
647
+ if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) {
648
  $prefix = 'https';
649
  }
650
  return $prefix . '://' . $host . $_SERVER['REQUEST_URI'];
1011
  if(! (function_exists('geoip_open') && function_exists('geoip_country_code_by_addr') && function_exists('geoip_country_code_by_addr_v6'))){
1012
  require_once('wfGeoIP.php');
1013
  }
 
1014
  if (filter_var($IP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
1015
+ $gi = geoip_open(dirname(__FILE__) . "/GeoIPv6.dat", GEOIP_STANDARD);
1016
  $country = geoip_country_code_by_addr_v6($gi, $IP);
1017
  } else {
1018
+ $gi = geoip_open(dirname(__FILE__) . "/GeoIP.dat", GEOIP_STANDARD);
1019
  $country = geoip_country_code_by_addr($gi, $IP);
1020
  }
1021
  geoip_close($gi);
lib/wordfenceClass.php CHANGED
@@ -588,8 +588,13 @@ SQL
588
  add_action('init', 'wordfence::initAction');
589
  add_action('template_redirect', 'wordfence::templateRedir', 1001);
590
  add_action('shutdown', 'wordfence::shutdownAction');
591
- add_action('wp_enqueue_scripts', 'wordfence::enqueueAJAXWatcher');
592
- add_action('admin_enqueue_scripts', 'wordfence::enqueueAJAXWatcher');
 
 
 
 
 
593
 
594
  if(version_compare(PHP_VERSION, '5.4.0') >= 0){
595
  add_action('wp_authenticate','wordfence::authActionNew', 1, 2);
@@ -636,6 +641,10 @@ SQL
636
  add_filter('get_the_generator_comment', 'wordfence::genFilter', 99, 2);
637
  add_filter('get_the_generator_export', 'wordfence::genFilter', 99, 2);
638
  add_filter('registration_errors', 'wordfence::registrationFilter', 99, 3);
 
 
 
 
639
 
640
  // Change GoDaddy's limit login mu-plugin since it can interfere with the two factor auth message.
641
  if (self::hasGDLimitLoginsMUPlugin()) {
@@ -715,9 +724,11 @@ SQL
715
  return $URL;
716
  }
717
  public static function enqueueAJAXWatcher() {
718
- if (wfUtils::isAdmin()) {
719
- wp_enqueue_style('wordfence-colorbox-style', wfUtils::getBaseURL() . 'css/colorbox.css', '', WORDFENCE_VERSION);
720
- wp_enqueue_script('jquery.wfcolorbox', wfUtils::getBaseURL() . 'js/jquery.colorbox-min.js', array('jquery'), WORDFENCE_VERSION);
 
 
721
  wp_enqueue_script('wordfenceAJAXjs', wfUtils::getBaseURL() . 'js/admin.ajaxWatcher.js', array('jquery'), WORDFENCE_VERSION);
722
  }
723
  }
@@ -1157,6 +1168,11 @@ SQL
1157
  }
1158
  return $errors;
1159
  }
 
 
 
 
 
1160
  public static function authenticateFilter($authUser, $username, $passwd){
1161
  wfConfig::inc('totalLoginHits'); //The total hits to wp-login.php including logins, logouts and just hits.
1162
  $IP = wfUtils::getIP();
@@ -1203,7 +1219,19 @@ SQL
1203
  } //No user matches and has TF activated so let user sign in.
1204
  }
1205
  } else { //valid login with no code entered
1206
- foreach($twoFactorUsers as &$t){
 
 
 
 
 
 
 
 
 
 
 
 
1207
  if($t[0] == $userDat->ID && $t[3] == 'activated'){ //Yup, enabled, so lets send the code
1208
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
1209
  try {
@@ -1240,8 +1268,18 @@ SQL
1240
  } else { //oops, our API returned an error.
1241
  break; //Let them sign in without two factor because the API is broken and we don't want to lock users out of their own systems.
1242
  }
1243
- } //User is not present in two factor list or is not activated. Sign in without twofactor.
1244
- } //Two facto users is empty. Sign in without two factor.
 
 
 
 
 
 
 
 
 
 
1245
  }
1246
  }
1247
  }
@@ -2644,8 +2682,10 @@ SQL
2644
  return array('errorMsg' => "Invalid bulk operation selected");
2645
  }
2646
  }
2647
- public static function ajax_deleteFile_callback(){
2648
- $issueID = intval($_POST['issueID']);
 
 
2649
  $wfIssues = new wfIssues();
2650
  $issue = $wfIssues->getIssueByID($issueID);
2651
  if(! $issue){
@@ -2671,7 +2711,27 @@ SQL
2671
  </p>",
2672
  );
2673
  }
2674
- if(@unlink($localFile)){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2675
  $wfIssues->updateIssue($issueID, 'delete');
2676
  return array(
2677
  'ok' => 1,
@@ -2736,13 +2796,35 @@ SQL
2736
  $issues->updateIssue($_POST['issueID'], 'delete');
2737
  return array('ok' => 1);
2738
  }
2739
- public static function ajax_restoreFile_callback(){
2740
- $issueID = intval($_POST['issueID']);
 
 
2741
  $wfIssues = new wfIssues();
2742
  $issue = $wfIssues->getIssueByID($issueID);
2743
  if(! $issue){
2744
  return array('cerrorMsg' => "We could not find that issue in our database.");
2745
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2746
  $dat = $issue['data'];
2747
  $result = self::getWPFileContent($dat['file'], $dat['cType'], (isset($dat['cName']) ? $dat['cName'] : ''), (isset($dat['cVersion']) ? $dat['cVersion'] : ''));
2748
  $file = $dat['file'];
@@ -2756,28 +2838,16 @@ SQL
2756
  return array('cerrorMsg' => "An invalid file was specified for repair.");
2757
  }
2758
  $localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $file);
2759
- $fh = fopen($localFile, 'w');
2760
- if(! $fh){
2761
- $err = error_get_last();
2762
- if(preg_match('/Permission denied/i', $err['message'])){
2763
- $errMsg = "You don't have permission to repair that file. You need to either fix the file manually using FTP or change the file permissions and ownership so that your web server has write access to repair the file.";
2764
- } else {
2765
- $errMsg = "We could not write to that file. The error was: " . $err['message'];
2766
- }
2767
- return array('cerrorMsg' => $errMsg);
2768
- }
2769
- flock($fh, LOCK_EX);
2770
- $bytes = fwrite($fh, $result['fileContent']);
2771
- flock($fh, LOCK_UN);
2772
- fclose($fh);
2773
- if($bytes < 1){
2774
- return array('cerrorMsg' => "We could not write to that file. ($bytes bytes written) You may not have permission to modify files on your WordPress server.");
2775
  }
2776
- $wfIssues->updateIssue($issueID, 'delete');
2777
  return array(
2778
- 'ok' => 1,
2779
- 'file' => $localFile
2780
- );
2781
  }
2782
  public static function ajax_scan_callback(){
2783
  self::status(4, 'info', "Ajax request received to start scan.");
@@ -3563,6 +3633,21 @@ HTML;
3563
  }
3564
  }
3565
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3566
 
3567
  if (!empty($_REQUEST['wafVerify']) && wp_verify_nonce($_REQUEST['wafVerify'], 'wfWAFAutoPrepend')) {
3568
  if (is_multisite()) {
@@ -3571,6 +3656,14 @@ HTML;
3571
  add_action('admin_notices', 'wordfence::wafAutoPrependVerify');
3572
  }
3573
  }
 
 
 
 
 
 
 
 
3574
  }
3575
  private static function setupAdminVars(){
3576
  $updateInt = wfConfig::get('actUpdateInterval', 2);
@@ -3985,6 +4078,243 @@ $nginxIniWarning
3985
 
3986
  $wafActionContent = sprintf('<div style="margin: 20px 0;">%s</div>', $wafActionContent);
3987
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3988
 
3989
  case '':
3990
  break;
@@ -4019,8 +4349,75 @@ $nginxIniWarning
4019
  require 'menu_activity.php';
4020
  }
4021
  public static function menu_scan(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4022
  require 'menu_scan.php';
4023
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4024
  public static function status($level /* 1 has highest visibility */, $type /* info|error */, $msg){
4025
  if($level > 3 && $level < 10 && (! self::isDebugOn())){ //level 10 and higher is for summary messages
4026
  return false;
@@ -5152,6 +5549,21 @@ LIMIT %d", $lastSendTime, $limit));
5152
  echo '<div class="notice notice-error"><p>The changes have not yet taken effect. If you are using LiteSpeed or IIS
5153
  as your web server or CGI/FastCGI interface, you may need to wait a few minutes for the changes to take effect since the
5154
  configuration files are sometimes cached. You also may need to select a different server configuration in order to
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5155
  complete this step, but wait for a few minutes before trying. You can try refreshing this page. </p></div>';
5156
  }
5157
  }
@@ -5226,6 +5638,44 @@ if (file_exists(%1$s)) {
5226
  }
5227
  wfWAF::getInstance()->getStorageEngine()->setConfig('cron', $cron);
5228
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5229
  }
5230
 
5231
  class wfWAFAutoPrependHelper {
@@ -5364,9 +5814,6 @@ $userIniHtaccessDirectives
5364
 
5365
  case 'apache-suphp':
5366
  $autoPrependDirective = sprintf("# Wordfence WAF
5367
- <IfModule mod_suphp.c>
5368
- suPHP_ConfigPath '%s'
5369
- </IfModule>
5370
  $userIniHtaccessDirectives
5371
  # END Wordfence WAF
5372
  ", addcslashes($homePath, "'"));
@@ -5450,6 +5897,75 @@ auto_prepend_file = '%s'
5450
  }
5451
  }
5452
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5453
 
5454
  public function getHtaccessPath() {
5455
  return get_home_path() . '.htaccess';
@@ -5462,6 +5978,22 @@ auto_prepend_file = '%s'
5462
  }
5463
  return false;
5464
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5465
 
5466
  public function uninstall() {
5467
  /** @var WP_Filesystem_Base $wp_filesystem */
588
  add_action('init', 'wordfence::initAction');
589
  add_action('template_redirect', 'wordfence::templateRedir', 1001);
590
  add_action('shutdown', 'wordfence::shutdownAction');
591
+
592
+ if (!wfConfig::get('ajaxWatcherDisabled_front')) {
593
+ add_action('wp_enqueue_scripts', 'wordfence::enqueueAJAXWatcher');
594
+ }
595
+ if (!wfConfig::get('ajaxWatcherDisabled_admin')) {
596
+ add_action('admin_enqueue_scripts', 'wordfence::enqueueAJAXWatcher');
597
+ }
598
 
599
  if(version_compare(PHP_VERSION, '5.4.0') >= 0){
600
  add_action('wp_authenticate','wordfence::authActionNew', 1, 2);
641
  add_filter('get_the_generator_comment', 'wordfence::genFilter', 99, 2);
642
  add_filter('get_the_generator_export', 'wordfence::genFilter', 99, 2);
643
  add_filter('registration_errors', 'wordfence::registrationFilter', 99, 3);
644
+
645
+ if (wfConfig::get('loginSec_disableAuthorScan')) {
646
+ add_filter('oembed_response_data', 'wordfence::oembedAuthorFilter', 99, 4);
647
+ }
648
 
649
  // Change GoDaddy's limit login mu-plugin since it can interfere with the two factor auth message.
650
  if (self::hasGDLimitLoginsMUPlugin()) {
724
  return $URL;
725
  }
726
  public static function enqueueAJAXWatcher() {
727
+ $waf = wfWAF::getInstance();
728
+ $config = $waf->getStorageEngine();
729
+ $wafStatus = (!WFWAF_ENABLED ? 'disabled' : $config->getConfig('wafStatus'));
730
+ if (wfUtils::isAdmin() && $wafStatus != 'disabled') {
731
+ wp_enqueue_style('wordfenceAJAXcss', wfUtils::getBaseURL() . 'css/wordfenceBox.css', '', WORDFENCE_VERSION);
732
  wp_enqueue_script('wordfenceAJAXjs', wfUtils::getBaseURL() . 'js/admin.ajaxWatcher.js', array('jquery'), WORDFENCE_VERSION);
733
  }
734
  }
1168
  }
1169
  return $errors;
1170
  }
1171
+ public static function oembedAuthorFilter($data, $post, $width, $height) {
1172
+ unset($data['author_name']);
1173
+ unset($data['author_url']);
1174
+ return $data;
1175
+ }
1176
  public static function authenticateFilter($authUser, $username, $passwd){
1177
  wfConfig::inc('totalLoginHits'); //The total hits to wp-login.php including logins, logouts and just hits.
1178
  $IP = wfUtils::getIP();
1219
  } //No user matches and has TF activated so let user sign in.
1220
  }
1221
  } else { //valid login with no code entered
1222
+ //Verify at least one administrator has 2FA enabled
1223
+ $requireAdminTwoFactor = false;
1224
+ foreach($twoFactorUsers as &$t) {
1225
+ $userID = $t[0];
1226
+ $testUser = get_user_by('ID', $userID);
1227
+ if (is_object($testUser) && wfUtils::isAdmin($testUser) && $t[3] == 'activated') {
1228
+ $requireAdminTwoFactor = true;
1229
+ break;
1230
+ }
1231
+ }
1232
+ $requireAdminTwoFactor = $requireAdminTwoFactor && wfConfig::get('loginSec_requireAdminTwoFactor');
1233
+
1234
+ foreach($twoFactorUsers as &$t) {
1235
  if($t[0] == $userDat->ID && $t[3] == 'activated'){ //Yup, enabled, so lets send the code
1236
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
1237
  try {
1268
  } else { //oops, our API returned an error.
1269
  break; //Let them sign in without two factor because the API is broken and we don't want to lock users out of their own systems.
1270
  }
1271
+ }
1272
+ }
1273
+
1274
+ if ($requireAdminTwoFactor && wfUtils::isAdmin($authUser)) {
1275
+ $username = $authUser->user_login;
1276
+ self::getLog()->logLogin('loginFailValidUsername', 1, $username);
1277
+ wordfence::alert("Admin Login Blocked", "A user with username \"$username\" who has administrator access tried to sign in to your WordPress site. Access was denied because all administrator accounts are required to have Cellphone Sign-in enabled but this account does not.", wfUtils::getIP());
1278
+ self::$authError = new WP_Error( 'twofactor_disabled_required', __( '<strong>Cellphone Sign-in Required</strong>: Cellphone Sign-in is required for all administrator accounts. Please contact the site administrator to enable it for your account.' ) );
1279
+ return self::$authError;
1280
+ }
1281
+
1282
+ //User is not configured for two factor. Sign in without two factor.
1283
  }
1284
  }
1285
  }
2682
  return array('errorMsg' => "Invalid bulk operation selected");
2683
  }
2684
  }
2685
+ public static function ajax_deleteFile_callback($issueID = null){
2686
+ if ($issueID === null) {
2687
+ $issueID = intval($_POST['issueID']);
2688
+ }
2689
  $wfIssues = new wfIssues();
2690
  $issue = $wfIssues->getIssueByID($issueID);
2691
  if(! $issue){
2711
  </p>",
2712
  );
2713
  }
2714
+
2715
+ /** @var WP_Filesystem_Base $wp_filesystem */
2716
+ global $wp_filesystem;
2717
+
2718
+ $adminURL = network_admin_url('admin.php?' . http_build_query(array(
2719
+ 'page' => 'Wordfence',
2720
+ 'wfScanAction' => 'promptForCredentials',
2721
+ 'wfFilesystemAction' => 'deleteFile',
2722
+ 'issueID' => $issueID,
2723
+ 'nonce' => wp_create_nonce('wp-ajax'),
2724
+ )));
2725
+
2726
+ if (!self::requestFilesystemCredentials($adminURL, null, true, false)) {
2727
+ return array(
2728
+ 'ok' => 1,
2729
+ 'needsCredentials' => true,
2730
+ 'redirect' => $adminURL,
2731
+ );
2732
+ }
2733
+
2734
+ if($wp_filesystem->delete($localFile)){
2735
  $wfIssues->updateIssue($issueID, 'delete');
2736
  return array(
2737
  'ok' => 1,
2796
  $issues->updateIssue($_POST['issueID'], 'delete');
2797
  return array('ok' => 1);
2798
  }
2799
+ public static function ajax_restoreFile_callback($issueID = null){
2800
+ if ($issueID === null) {
2801
+ $issueID = intval($_POST['issueID']);
2802
+ }
2803
  $wfIssues = new wfIssues();
2804
  $issue = $wfIssues->getIssueByID($issueID);
2805
  if(! $issue){
2806
  return array('cerrorMsg' => "We could not find that issue in our database.");
2807
  }
2808
+
2809
+ /** @var WP_Filesystem_Base $wp_filesystem */
2810
+ global $wp_filesystem;
2811
+
2812
+ $adminURL = network_admin_url('admin.php?' . http_build_query(array(
2813
+ 'page' => 'Wordfence',
2814
+ 'wfScanAction' => 'promptForCredentials',
2815
+ 'wfFilesystemAction' => 'restoreFile',
2816
+ 'issueID' => $issueID,
2817
+ 'nonce' => wp_create_nonce('wp-ajax'),
2818
+ )));
2819
+
2820
+ if (!self::requestFilesystemCredentials($adminURL, null, true, false)) {
2821
+ return array(
2822
+ 'ok' => 1,
2823
+ 'needsCredentials' => true,
2824
+ 'redirect' => $adminURL,
2825
+ );
2826
+ }
2827
+
2828
  $dat = $issue['data'];
2829
  $result = self::getWPFileContent($dat['file'], $dat['cType'], (isset($dat['cName']) ? $dat['cName'] : ''), (isset($dat['cVersion']) ? $dat['cVersion'] : ''));
2830
  $file = $dat['file'];
2838
  return array('cerrorMsg' => "An invalid file was specified for repair.");
2839
  }
2840
  $localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $file);
2841
+ if ($wp_filesystem->put_contents($localFile, $result['fileContent'])) {
2842
+ $wfIssues->updateIssue($issueID, 'delete');
2843
+ return array(
2844
+ 'ok' => 1,
2845
+ 'file' => $localFile,
2846
+ );
 
 
 
 
 
 
 
 
 
 
2847
  }
 
2848
  return array(
2849
+ 'cerrorMsg' => "We could not write to that file. You may not have permission to modify files on your WordPress server.",
2850
+ );
 
2851
  }
2852
  public static function ajax_scan_callback(){
2853
  self::status(4, 'info', "Ajax request received to start scan.");
3633
  }
3634
  }
3635
  }
3636
+ else {
3637
+ if (!empty($_GET['wafAction'])) {
3638
+ switch ($_GET['wafAction']) {
3639
+ case 'removeAutoPrepend':
3640
+ if (isset($_REQUEST['serverConfiguration'])) {
3641
+ check_admin_referer('wfWAFRemoveAutoPrepend', 'wfnonce');
3642
+ $helper = new wfWAFAutoPrependHelper($_REQUEST['serverConfiguration']);
3643
+ if (!empty($_REQUEST['downloadBackup'])) {
3644
+ $helper->downloadBackups(!empty($_REQUEST['backupIndex']) ? absint($_REQUEST['backupIndex']) : 0);
3645
+ }
3646
+ }
3647
+ break;
3648
+ }
3649
+ }
3650
+ }
3651
 
3652
  if (!empty($_REQUEST['wafVerify']) && wp_verify_nonce($_REQUEST['wafVerify'], 'wfWAFAutoPrepend')) {
3653
  if (is_multisite()) {
3656
  add_action('admin_notices', 'wordfence::wafAutoPrependVerify');
3657
  }
3658
  }
3659
+
3660
+ if (!empty($_REQUEST['wafRemoved']) && wp_verify_nonce($_REQUEST['wafRemoved'], 'wfWAFRemoveAutoPrepend')) {
3661
+ if (is_multisite()) {
3662
+ add_action('network_admin_notices', 'wordfence::wafAutoPrependRemoved');
3663
+ } else {
3664
+ add_action('admin_notices', 'wordfence::wafAutoPrependRemoved');
3665
+ }
3666
+ }
3667
  }
3668
  private static function setupAdminVars(){
3669
  $updateInt = wfConfig::get('actUpdateInterval', 2);
4078
 
4079
  $wafActionContent = sprintf('<div style="margin: 20px 0;">%s</div>', $wafActionContent);
4080
  break;
4081
+
4082
+ case 'removeAutoPrepend':
4083
+ $installedHere = !(!WFWAF_AUTO_PREPEND && !WFWAF_SUBDIRECTORY_INSTALL);
4084
+ $wfnonce = wp_create_nonce('wfWAFRemoveAutoPrepend');
4085
+
4086
+ $currentAutoPrependFile = ini_get('auto_prepend_file');
4087
+ $adminURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeAutoPrepend');
4088
+ if (!$currentAutoPrependFile && $installedHere) {
4089
+ //This should never happen but covering the possibility anyway
4090
+ $wafActionContent = "<p>Extended Protection Mode of the Wordfence Web Application Firewall uses the PHP ini setting called <code>auto_prepend_file</code> in order to ensure it runs before any potentially
4091
+ vulnerable code runs. This PHP setting is not currently configured.</p>";
4092
+ break;
4093
+ }
4094
+ else if ($currentAutoPrependFile &&
4095
+ is_file($currentAutoPrependFile) &&
4096
+ !isset($_REQUEST['serverConfiguration']) &&
4097
+ !isset($_REQUEST['iniModified']) &&
4098
+ $installedHere &&
4099
+ !WFWAF_SUBDIRECTORY_INSTALL
4100
+ ) {
4101
+ $contents = file_get_contents($currentAutoPrependFile);
4102
+ $refersToWAF = preg_match('/define\s*\(\s*(["\'])WFWAF_LOG_PATH\1\s*,\s*(["\']).+?\2\s*\)\s*/', $contents);
4103
+
4104
+ if ($refersToWAF) {
4105
+ $wafActionContent = sprintf("<p>Extended Protection Mode of the Wordfence Web Application Firewall uses the PHP ini setting called <code>auto_prepend_file</code> in order to ensure it runs before any potentially
4106
+ vulnerable code runs. This PHP setting currently refers to the Wordfence file at:</p>
4107
+
4108
+ <pre class='wf-pre'>%s</pre>
4109
+
4110
+ <p>Before this file can be deleted, the configuration for the <code>auto_prepend_file</code> setting needs to be removed.</p>
4111
+ ",
4112
+ esc_html($currentAutoPrependFile)
4113
+ );
4114
+
4115
+ // Auto populate drop down with server configuration
4116
+ // If no preconfiguration routine exists, output instructions for manual configuration
4117
+ $serverInfo = wfWebServerInfo::createFromEnvironment();
4118
+
4119
+ $dropdown = array(
4120
+ array("apache-mod_php", 'Apache + mod_php', $serverInfo->isApacheModPHP()),
4121
+ array("apache-suphp", 'Apache + suPHP', $serverInfo->isApacheSuPHP()),
4122
+ array("cgi", 'Apache + CGI/FastCGI', $serverInfo->isApache() &&
4123
+ !$serverInfo->isApacheSuPHP() &&
4124
+ ($serverInfo->isCGI() || $serverInfo->isFastCGI())),
4125
+ array("litespeed", 'LiteSpeed', $serverInfo->isLiteSpeed()),
4126
+ array("nginx", 'NGINX', $serverInfo->isNGINX()),
4127
+ array("iis", 'Windows (IIS)', $serverInfo->isIIS()),
4128
+ );
4129
+
4130
+ $hasRecommendedOption = false;
4131
+ $wafPrependOptions = '';
4132
+ foreach ($dropdown as $option) {
4133
+ list($optionValue, $optionText, $selected) = $option;
4134
+ $wafPrependOptions .= "<option value=\"$optionValue\"" . ($selected ? ' selected' : '')
4135
+ . ">$optionText" . ($selected ? ' (recommended based on our tests)' : '') . "</option>\n";
4136
+ if ($selected) {
4137
+ $hasRecommendedOption = true;
4138
+ }
4139
+ }
4140
+
4141
+ if (!$hasRecommendedOption) {
4142
+ $wafActionContent .= "<p>If you know your web server's configuration, please select it from the
4143
+ list below:</p>";
4144
+ }
4145
+ else {
4146
+ $wafActionContent .= "<p>We've preselected your server configuration based on our tests, but if
4147
+ you know your web server's configuration, please select it now.</p>";
4148
+ }
4149
+
4150
+ $adminURL = esc_url($adminURL);
4151
+ $wafActionContent .= "
4152
+ <form action='$adminURL' method='post'>
4153
+ <input type='hidden' name='wfnonce' value='$wfnonce'>
4154
+ <select name='serverConfiguration' id='wf-waf-server-config'>
4155
+ $wafPrependOptions
4156
+ </select>
4157
+ <button class='button button-primary' type='submit'>Continue</button>
4158
+ </form>
4159
+ </div>
4160
+ ";
4161
+ }
4162
+ else {
4163
+ //This point should only be reached if the wordfence-waf.php file format changes enough for the detection to fail and this isn't updated to match
4164
+ $wafActionContent = sprintf("<p>Extended Protection Mode of the Wordfence Web Application Firewall uses the PHP ini setting called <code>auto_prepend_file</code> in order to ensure it runs before any potentially
4165
+ vulnerable code runs. This PHP setting currently refers to an unknown file at:</p>
4166
+
4167
+ <pre class='wf-pre'>%s</pre>
4168
+
4169
+ <p>Automatic uninstallation cannot be completed, but you may still be able to <a href='%s' target='_blank'>manually uninstall extended protection</a>.</p>
4170
+ ",
4171
+ esc_html($currentAutoPrependFile),
4172
+ esc_url('https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#How_can_I_remove_the_firewall_setup_manually.3F')
4173
+ );
4174
+ break;
4175
+ }
4176
+ }
4177
+ else if (isset($_REQUEST['serverConfiguration'])) {
4178
+ check_admin_referer('wfWAFRemoveAutoPrepend', 'wfnonce');
4179
+ $allow_relaxed_file_ownership = true;
4180
+ $helper = new wfWAFAutoPrependHelper($_REQUEST['serverConfiguration'], null);
4181
+ $serverConfig = esc_attr($helper->getServerConfig());
4182
+ if ($installedHere && empty($_REQUEST['iniModified']) && ($backups = $helper->getFilesNeededForBackup()) && empty($_REQUEST['confirmedBackup'])) {
4183
+ $wafActionContent = '<p>Please download a backup copy of the following files before we make the necessary changes:</p>';
4184
+ $wafActionContent .= '<ul>';
4185
+ foreach ($backups as $index => $backup) {
4186
+ $wafActionContent .= '<li><a class="button" onclick="wfWAFConfirmBackup(' . $index . ');" href="' .
4187
+ esc_url(add_query_arg(array(
4188
+ 'downloadBackup' => 1,
4189
+ 'backupIndex' => $index,
4190
+ 'serverConfiguration' => $helper->getServerConfig(),
4191
+ 'wfnonce' => $wfnonce,
4192
+ ), $adminURL)) . '">Download ' . esc_html(basename($backup)) . '</a></li>';
4193
+ }
4194
+ $jsonBackups = json_encode(array_map('basename', $backups));
4195
+ $adminURL = esc_url($adminURL);
4196
+ $wafActionContent .= "</ul>
4197
+ <form action='$adminURL' method='post'>
4198
+ <input type='hidden' name='wfnonce' value='$wfnonce'>
4199
+ <input type='hidden' value='$serverConfig' name='serverConfiguration'>
4200
+ <input type='hidden' value='1' name='confirmedBackup'>
4201
+ <button id='confirmed-backups' disabled class='button button-primary' type='submit'>Continue</button>
4202
+ </form>
4203
+ <script>
4204
+ var wfWAFBackups = $jsonBackups;
4205
+ var wfWAFConfirmedBackups = [];
4206
+ function wfWAFConfirmBackup(index) {
4207
+ wfWAFBackups[index] = false;
4208
+ var confirmed = true;
4209
+ for (var i = 0; i < wfWAFBackups.length; i++) {
4210
+ if (wfWAFBackups[i] !== false) {
4211
+ confirmed = false;
4212
+ }
4213
+ }
4214
+ if (confirmed) {
4215
+ document.getElementById('confirmed-backups').disabled = false;
4216
+ }
4217
+ }
4218
+ </script>";
4219
+ break;
4220
+ }
4221
+
4222
+ ob_start();
4223
+ if (false === ($credentials = request_filesystem_credentials($adminURL, '', false, ABSPATH,
4224
+ array('version', 'locale'), $allow_relaxed_file_ownership))
4225
+ ) {
4226
+ $wafActionContent = ob_get_clean();
4227
+ break;
4228
+ }
4229
+
4230
+ if (!WP_Filesystem($credentials, ABSPATH, $allow_relaxed_file_ownership)) {
4231
+ // Failed to connect, Error and request again
4232
+ request_filesystem_credentials($adminURL, '', true, ABSPATH, array('version', 'locale'),
4233
+ $allow_relaxed_file_ownership);
4234
+ $wafActionContent = ob_get_clean();
4235
+ break;
4236
+ }
4237
+
4238
+ if ($wp_filesystem->errors->get_error_code()) {
4239
+ foreach ($wp_filesystem->errors->get_error_messages() as $message)
4240
+ show_message($message);
4241
+ $wafActionContent = ob_get_clean();
4242
+ break;
4243
+ }
4244
+ ob_end_clean();
4245
+
4246
+ try {
4247
+ if (isset($_REQUEST['iniModified'])) {
4248
+ $usesUserIni = $helper->usesUserIni();
4249
+ if ((!WFWAF_AUTO_PREPEND || WFWAF_SUBDIRECTORY_INSTALL) && (!$usesUserIni || ($usesUserIni && isset($_REQUEST['iniTTLWaited'])))) { //WFWAF_AUTO_PREPEND can be false for a brief time when using .user.ini, so make sure we've waited the TTL before removing the wordfence-waf.php file
4250
+ $helper->performAutoPrependFileRemoval($wp_filesystem);
4251
+
4252
+ $adminURL = json_encode(esc_url_raw(network_admin_url('admin.php?page=WordfenceWAF&wafRemoved=' . $wfnonce)));
4253
+ $wafActionContent = "<p>Removing firewall files...</p><script>
4254
+ document.location.href=$adminURL;
4255
+ </script>";
4256
+ }
4257
+ else { //Using a .user.ini where there's a delay before taking effect
4258
+ $iniTTL = intval(ini_get('user_ini.cache_ttl'));
4259
+ if ($iniTTL == 0) {
4260
+ $iniTTL = 300; //The PHP default
4261
+ }
4262
+ $timeout = max(30000, ($iniTTL + 1) * 1000);
4263
+
4264
+ if ($timeout < 60000) { $timeoutString = floor($timeout / 1000) . ' second' . ($timeout == 1000 ? '' : 's'); }
4265
+ else { $timeoutString = floor($timeout / 60000) . ' minute' . (floor($timeout / 60000) == 1 ? '' : 's'); }
4266
+
4267
+ $wafActionContent = "<h3>Finishing Removal</h3>";
4268
+
4269
+ if (isset($_REQUEST['iniTTLWaited'])) {
4270
+ $wafActionContent .= "<p class='wf-error'>Extended Protection Mode has not been disabled. This may be because <code>auto_prepend_file</code> is configured somewhere else or the value is still cached by PHP.</p>";
4271
+ }
4272
+ else {
4273
+ $wafActionContent .= "<p>The <code>auto_prepend_file</code> setting has been successfully removed from <code>.htaccess</code> and <code>.user.ini</code>. Once this change takes effect, Extended Protection Mode will be disabled.</p>\n";
4274
+ if ($_REQUEST['manualAutoPrependReenable']) {
4275
+ $wafActionContent .= "<p>Any previous value for <code>auto_prepend_file</code> will need to be re-enabled manually if needed.</p>";
4276
+ }
4277
+ $wafActionContent .= "<p class='wordfence-waiting'><img src='" . wfUtils::getBaseURL() . "images/loading_large.gif' alt='Loading indicator'>&nbsp;&nbsp;<span>Waiting for it to take effect. This may take up to {$timeoutString}.</span></p>";
4278
+ }
4279
+
4280
+ $adminURL = json_encode(esc_url_raw(network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeAutoPrepend&wfnonce='
4281
+ . $wfnonce . '&serverConfiguration=' . $serverConfig . '&iniModified=1&iniTTLWaited=1')));
4282
+ $wafActionContent .= "<script>
4283
+ setTimeout(function() { document.location.href={$adminURL}; }, {$timeout});
4284
+ </script>";
4285
+ }
4286
+ }
4287
+ else if ($installedHere) {
4288
+ $hasCommentedAutoPrepend = $helper->performIniRemoval($wp_filesystem);
4289
+
4290
+ $adminURL = json_encode(esc_url_raw(network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeAutoPrepend&wfnonce='
4291
+ . $wfnonce . '&serverConfiguration=' . $serverConfig . '&iniModified=1&manualAutoPrependReenable=' . ($hasCommentedAutoPrepend ? 1 : 0))));
4292
+ $wafActionContent = "<script>
4293
+ document.location.href={$adminURL};
4294
+ </script>";
4295
+ }
4296
+ break;
4297
+ }
4298
+ catch (wfWAFAutoPrependHelperException $e) {
4299
+ $wafActionContent = "<p>" . $e->getMessage() . "</p>";
4300
+ break;
4301
+ }
4302
+ }
4303
+
4304
+ $bootstrap = self::getWAFBootstrapPath();
4305
+
4306
+ $wafActionContent .= "<br>
4307
+ <h3>Alternate method:</h3>
4308
+ <p>We've also included instructions to manually perform the change if you are using a web server other than what is listed in the drop-down, or if file permissions prevent this change.</p>";
4309
+
4310
+
4311
+ $wafActionContent .= "<p>You will need to remove the following code from your <code>php.ini</code>, <code>.user.ini</code>, or <code>.htaccess</code> file:</p>
4312
+ <pre class='wf-pre'>auto_prepend_file = '" . esc_textarea($currentAutoPrependFile) . "'</pre>
4313
+ <p>Once the change takes effect, you will need remove the following file in your WordPress root:</p>
4314
+ <pre class='wf-pre'>" . esc_html(self::getWAFBootstrapPath()) . "</pre>";
4315
+
4316
+ $wafActionContent = sprintf('<div style="margin: 20px 0;">%s</div>', $wafActionContent);
4317
+ break;
4318
 
4319
  case '':
4320
  break;
4349
  require 'menu_activity.php';
4350
  }
4351
  public static function menu_scan(){
4352
+ $scanAction = filter_input(INPUT_GET, 'wfScanAction', FILTER_SANITIZE_STRING);
4353
+ if ($scanAction == 'promptForCredentials') {
4354
+ $fsAction = filter_input(INPUT_GET, 'wfFilesystemAction', FILTER_SANITIZE_STRING);
4355
+ $promptForCredentials = true;
4356
+ $filesystemCredentialsAdminURL = network_admin_url('admin.php?' . http_build_query(array(
4357
+ 'page' => 'Wordfence',
4358
+ 'wfScanAction' => 'promptForCredentials',
4359
+ 'wfFilesystemAction' => $fsAction,
4360
+ 'issueID' => filter_input(INPUT_GET, 'issueID', FILTER_SANITIZE_NUMBER_INT),
4361
+ 'nonce' => wp_create_nonce('wp-ajax'),
4362
+ )));
4363
+
4364
+ switch ($fsAction) {
4365
+ case 'restoreFile':
4366
+ $wpFilesystemActionCallback = array('wordfence', 'fsActionRestoreFileCallback');
4367
+ break;
4368
+ case 'deleteFile':
4369
+ $wpFilesystemActionCallback = array('wordfence', 'fsActionDeleteFileCallback');
4370
+ break;
4371
+ }
4372
+ }
4373
+
4374
  require 'menu_scan.php';
4375
  }
4376
+
4377
+ public static function fsActionRestoreFileCallback() {
4378
+ $issueID = filter_input(INPUT_GET, 'issueID', FILTER_SANITIZE_NUMBER_INT);
4379
+ $response = self::ajax_restoreFile_callback($issueID);
4380
+ if (!empty($response['ok'])) {
4381
+ $result = sprintf('<p>The file <code>%s</code> was restored successfully.</p>',
4382
+ esc_html(strpos($response['file'], ABSPATH) === 0 ? substr($response['file'], strlen(ABSPATH) + 1) : $response['file']));
4383
+ } else if (!empty($response['cerrorMessage'])) {
4384
+ $result = sprintf('<div class="wfSummaryErr">%s</div>', esc_html($response['cerrorMessage']));
4385
+ } else {
4386
+ $result = '<div class="wfSummaryErr">There was an error restoring the file.</div>';
4387
+ }
4388
+ printf(<<<HTML
4389
+ <br>
4390
+ %s
4391
+ <p><a href="%s">Return to scan results</a></p>
4392
+ HTML
4393
+ ,
4394
+ $result,
4395
+ esc_url(network_admin_url('admin.php?page=Wordfence'))
4396
+ );
4397
+
4398
+ }
4399
+
4400
+ public static function fsActionDeleteFileCallback() {
4401
+ $issueID = filter_input(INPUT_GET, 'issueID', FILTER_SANITIZE_NUMBER_INT);
4402
+ $response = self::ajax_deleteFile_callback($issueID);
4403
+ if (!empty($response['ok'])) {
4404
+ $result = sprintf('<p>The file <code>%s</code> was deleted successfully.</p>', esc_html($response['file']));
4405
+ } else if (!empty($response['errorMessage'])) {
4406
+ $result = sprintf('<div class="wfSummaryErr">%s</div>', esc_html($response['errorMessage']));
4407
+ } else {
4408
+ $result = '<div class="wfSummaryErr">There was an error deleting the file.</div>';
4409
+ }
4410
+ printf(<<<HTML
4411
+ <br>
4412
+ %s
4413
+ <p><a href="%s">Return to scan results</a></p>
4414
+ HTML
4415
+ ,
4416
+ $result,
4417
+ esc_url(network_admin_url('admin.php?page=Wordfence'))
4418
+ );
4419
+ }
4420
+
4421
  public static function status($level /* 1 has highest visibility */, $type /* info|error */, $msg){
4422
  if($level > 3 && $level < 10 && (! self::isDebugOn())){ //level 10 and higher is for summary messages
4423
  return false;
5549
  echo '<div class="notice notice-error"><p>The changes have not yet taken effect. If you are using LiteSpeed or IIS
5550
  as your web server or CGI/FastCGI interface, you may need to wait a few minutes for the changes to take effect since the
5551
  configuration files are sometimes cached. You also may need to select a different server configuration in order to
5552
+ complete this step, but wait for a few minutes before trying. You can try refreshing this page. </p></div>';
5553
+ }
5554
+ }
5555
+
5556
+ public static function wafAutoPrependRemoved() {
5557
+ if (!WFWAF_AUTO_PREPEND) {
5558
+ echo '<div class="updated is-dismissible"><p>Uninstallation was successful!</p></div>';
5559
+ }
5560
+ else if (WFWAF_SUBDIRECTORY_INSTALL) {
5561
+ echo '<div class="notice notice-warning"><p>Uninstallation from this site was successful! The Wordfence Firewall is still active because it is installed in another WordPress installation.</p></div>';
5562
+ }
5563
+ else {
5564
+ echo '<div class="notice notice-error"><p>The changes have not yet taken effect. If you are using LiteSpeed or IIS
5565
+ as your web server or CGI/FastCGI interface, you may need to wait a few minutes for the changes to take effect since the
5566
+ configuration files are sometimes cached. You also may need to select a different server configuration in order to
5567
  complete this step, but wait for a few minutes before trying. You can try refreshing this page. </p></div>';
5568
  }
5569
  }
5638
  }
5639
  wfWAF::getInstance()->getStorageEngine()->setConfig('cron', $cron);
5640
  }
5641
+
5642
+ /**
5643
+ * @param string $adminURL
5644
+ * @param string $homePath
5645
+ * @param bool $relaxedFileOwnership
5646
+ * @param bool $output
5647
+ * @return bool
5648
+ */
5649
+ public static function requestFilesystemCredentials($adminURL, $homePath = null, $relaxedFileOwnership = true, $output = true) {
5650
+ if ($homePath === null) {
5651
+ $homePath = get_home_path();
5652
+ }
5653
+
5654
+ global $wp_filesystem;
5655
+
5656
+ !$output && ob_start();
5657
+ if (false === ($credentials = request_filesystem_credentials($adminURL, '', false, $homePath,
5658
+ array('version', 'locale'), $relaxedFileOwnership))
5659
+ ) {
5660
+ !$output && ob_end_clean();
5661
+ return false;
5662
+ }
5663
+
5664
+ if (!WP_Filesystem($credentials, $homePath, $relaxedFileOwnership)) {
5665
+ // Failed to connect, Error and request again
5666
+ request_filesystem_credentials($adminURL, '', true, ABSPATH, array('version', 'locale'),
5667
+ $relaxedFileOwnership);
5668
+ !$output && ob_end_clean();
5669
+ return false;
5670
+ }
5671
+
5672
+ if ($wp_filesystem->errors->get_error_code()) {
5673
+ !$output && ob_end_clean();
5674
+ return false;
5675
+ }
5676
+ !$output && ob_end_clean();
5677
+ return true;
5678
+ }
5679
  }
5680
 
5681
  class wfWAFAutoPrependHelper {
5814
 
5815
  case 'apache-suphp':
5816
  $autoPrependDirective = sprintf("# Wordfence WAF
 
 
 
5817
  $userIniHtaccessDirectives
5818
  # END Wordfence WAF
5819
  ", addcslashes($homePath, "'"));
5897
  }
5898
  }
5899
  }
5900
+
5901
+ /**
5902
+ * @param WP_Filesystem_Base $wp_filesystem
5903
+ * @throws wfWAFAutoPrependHelperException
5904
+ *
5905
+ * @return bool Whether or not the .user.ini still has a commented-out auto_prepend_file setting
5906
+ */
5907
+ public function performIniRemoval($wp_filesystem) {
5908
+ $serverConfig = $this->getServerConfig();
5909
+
5910
+ $htaccessPath = $this->getHtaccessPath();
5911
+
5912
+ $userIniPath = $this->getUserIniPath();
5913
+ $userIni = ini_get('user_ini.filename');
5914
+
5915
+ // Modify .htaccess
5916
+ $htaccessContent = $wp_filesystem->get_contents($htaccessPath);
5917
+
5918
+ if (is_string($htaccessContent)) {
5919
+ $htaccessContent = preg_replace('/# Wordfence WAF.*?# END Wordfence WAF/is', '', $htaccessContent);
5920
+ } else {
5921
+ $htaccessContent = '';
5922
+ }
5923
+
5924
+ if (!$wp_filesystem->put_contents($htaccessPath, $htaccessContent)) {
5925
+ throw new wfWAFAutoPrependHelperException('We were unable to make changes to the .htaccess file. It\'s
5926
+ possible WordPress cannot write to the .htaccess file because of file permissions, which may have been
5927
+ set by another security plugin, or you may have set them manually. Please verify the permissions allow
5928
+ the web server to write to the file, and retry the installation.');
5929
+ }
5930
+ if ($serverConfig == 'litespeed') {
5931
+ // sleep(2);
5932
+ $wp_filesystem->touch($htaccessPath);
5933
+ }
5934
+
5935
+ if ($userIni) {
5936
+ // Modify .user.ini
5937
+ $userIniContent = $wp_filesystem->get_contents($userIniPath);
5938
+ if (is_string($userIniContent)) {
5939
+ $userIniContent = preg_replace('/; Wordfence WAF.*?; END Wordfence WAF/is', '', $userIniContent);
5940
+ $userIniContent = str_replace('auto_prepend_file', ';auto_prepend_file', $userIniContent);
5941
+ } else {
5942
+ $userIniContent = '';
5943
+ }
5944
+
5945
+ if (!$wp_filesystem->put_contents($userIniPath, $userIniContent)) {
5946
+ throw new wfWAFAutoPrependHelperException(sprintf('We were unable to make changes to the %1$s file.
5947
+ It\'s possible WordPress cannot write to the %1$s file because of file permissions.
5948
+ Please verify the permissions are correct and retry the installation.', basename($userIniPath)));
5949
+ }
5950
+
5951
+ return strpos($userIniContent, 'auto_prepend_file') !== false;
5952
+ }
5953
+
5954
+ return false;
5955
+ }
5956
+
5957
+ /**
5958
+ * @param WP_Filesystem_Base $wp_filesystem
5959
+ * @throws wfWAFAutoPrependHelperException
5960
+ */
5961
+ public function performAutoPrependFileRemoval($wp_filesystem) {
5962
+ $bootstrapPath = wordfence::getWAFBootstrapPath();
5963
+ if (!$wp_filesystem->delete($bootstrapPath)) {
5964
+ throw new wfWAFAutoPrependHelperException('We were unable to remove the <code>wordfence-waf.php</code> file
5965
+ in the root of the WordPress installation. It\'s possible WordPress cannot remove the <code>wordfence-waf.php</code>
5966
+ file because of file permissions. Please verify the permissions are correct and retry the removal.');
5967
+ }
5968
+ }
5969
 
5970
  public function getHtaccessPath() {
5971
  return get_home_path() . '.htaccess';
5978
  }
5979
  return false;
5980
  }
5981
+
5982
+ public function usesUserIni() {
5983
+ $userIni = ini_get('user_ini.filename');
5984
+ if (!$userIni) {
5985
+ return false;
5986
+ }
5987
+ switch ($this->getServerConfig()) {
5988
+ case 'cgi':
5989
+ case 'apache-suphp':
5990
+ case 'nginx':
5991
+ case 'litespeed':
5992
+ case 'iis':
5993
+ return true;
5994
+ }
5995
+ return false;
5996
+ }
5997
 
5998
  public function uninstall() {
5999
  /** @var WP_Filesystem_Base $wp_filesystem */
lib/wordfenceScanner.php CHANGED
@@ -75,14 +75,12 @@ class wordfenceScanner {
75
  }
76
 
77
  if (is_array($sigData['rules'])) {
78
- $finalPattern = '/';
79
- foreach ($sigData['rules'] as $signatureRow) {
80
- list($id, $timeAdded, $pattern, $description) = $signatureRow;
81
- $finalPattern .= ($pattern . '|');
82
- }
83
- $finalPattern = substr($finalPattern, 0, -1) . '/i';
84
- if(@preg_match($finalPattern, null) === false){
85
- throw new Exception("The regex Wordfence received from it's servers is invalid. The pattern is: " . $finalPattern);
86
  }
87
  }
88
 
@@ -197,7 +195,7 @@ class wordfenceScanner {
197
  $isPHP = true;
198
  }
199
  $dontScanForURLs = false;
200
- if( (! wfConfig::get('scansEnabled_highSense')) && preg_match('/^(?:\.htaccess|wp\-config\.php)$/', $file)) {
201
  $dontScanForURLs = true;
202
  }
203
 
@@ -359,13 +357,25 @@ class wordfenceScanner {
359
  return false;
360
  }
361
  $this->urlHoover->cleanup();
 
 
362
  foreach($hooverResults as $file => $hresults){
363
- $dataForFile = $this->dataForFile($file);
364
 
365
  foreach($hresults as $result){
366
  if(preg_match('/wfBrowscapCache\.php$/', $file)){
367
  continue;
368
  }
 
 
 
 
 
 
 
 
 
 
369
  if($result['badList'] == 'goog-malware-shavar'){
370
  if(! $this->isSafeFile($this->path . $file)){
371
  $this->addResult(array(
@@ -439,7 +449,7 @@ class wordfenceScanner {
439
  * @param string $file
440
  * @return array
441
  */
442
- private function dataForFile($file) {
443
  $loader = $this->scanEngine->getKnownFilesLoader();
444
  $data = array();
445
  if ($isKnownFile = $loader->isKnownFile($file)) {
@@ -465,10 +475,34 @@ class wordfenceScanner {
465
  ));
466
  }
467
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
 
469
  $data['canDiff'] = $isKnownFile;
470
  $data['canFix'] = $isKnownFile;
471
- $data['canDelete'] = !$isKnownFile;
 
472
 
473
  return $data;
474
  }
75
  }
76
 
77
  if (is_array($sigData['rules'])) {
78
+ foreach ($sigData['rules'] as $key => $signatureRow) {
79
+ list(, , $pattern) = $signatureRow;
80
+ if (@preg_match('/' . $pattern . '/i', null) === false) {
81
+ wordfence::status(1, 'error', "A regex Wordfence received from it's servers is invalid. The pattern is: " . esc_html($pattern));
82
+ unset($sigData['rules'][$key]);
83
+ }
 
 
84
  }
85
  }
86
 
195
  $isPHP = true;
196
  }
197
  $dontScanForURLs = false;
198
+ if( (! wfConfig::get('scansEnabled_highSense')) && (preg_match('/^(?:\.htaccess|wp\-config\.php)$/', $file) || $file === ini_get('user_ini.filename'))) {
199
  $dontScanForURLs = true;
200
  }
201
 
357
  return false;
358
  }
359
  $this->urlHoover->cleanup();
360
+ $siteURL = get_site_url();
361
+ $siteHost = parse_url($siteURL, PHP_URL_HOST);
362
  foreach($hooverResults as $file => $hresults){
363
+ $dataForFile = $this->dataForFile($file, $this->path . $file);
364
 
365
  foreach($hresults as $result){
366
  if(preg_match('/wfBrowscapCache\.php$/', $file)){
367
  continue;
368
  }
369
+
370
+ if (empty($result['URL'])) {
371
+ continue;
372
+ }
373
+ $url = $result['URL'];
374
+ $urlHost = parse_url($url, PHP_URL_HOST);
375
+ if (strcasecmp($siteHost, $urlHost) === 0) {
376
+ continue;
377
+ }
378
+
379
  if($result['badList'] == 'goog-malware-shavar'){
380
  if(! $this->isSafeFile($this->path . $file)){
381
  $this->addResult(array(
449
  * @param string $file
450
  * @return array
451
  */
452
+ private function dataForFile($file, $fullPath = null) {
453
  $loader = $this->scanEngine->getKnownFilesLoader();
454
  $data = array();
455
  if ($isKnownFile = $loader->isKnownFile($file)) {
475
  ));
476
  }
477
  }
478
+
479
+ $suppressDelete = false;
480
+ $canRegenerate = false;
481
+ if ($fullPath !== null) {
482
+ $bootstrapPath = wordfence::getWAFBootstrapPath();
483
+ $htaccessPath = get_home_path() . '.htaccess';
484
+ $userIni = ini_get('user_ini.filename');
485
+ $userIniPath = false;
486
+ if ($userIni) {
487
+ $userIniPath = get_home_path() . $userIni;
488
+ }
489
+
490
+ if ($fullPath == $htaccessPath) {
491
+ $suppressDelete = true;
492
+ }
493
+ else if ($userIniPath !== false && $fullPath == $userIniPath) {
494
+ $suppressDelete = true;
495
+ }
496
+ else if ($fullPath == $bootstrapPath) {
497
+ $suppressDelete = true;
498
+ $canRegenerate = true;
499
+ }
500
+ }
501
 
502
  $data['canDiff'] = $isKnownFile;
503
  $data['canFix'] = $isKnownFile;
504
+ $data['canDelete'] = !$isKnownFile && !$canRegenerate && !$suppressDelete;
505
+ $data['canRegenerate'] = $canRegenerate;
506
 
507
  return $data;
508
  }
lib/wordfenceURLHoover.php CHANGED
@@ -12,7 +12,7 @@ class wordfenceURLHoover {
12
  private $hostKeys = array();
13
  private $hostList = array();
14
  public $currentHooverID = false;
15
- private $dRegex = 'aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|xn--lgbbat1ad8j|xn--fiqs8s|xn--fiqz9s|xn--wgbh1c|xn--j6w193g|xn--h2brj9c|xn--mgbbh1a71e|xn--fpcrj9c3d|xn--gecrj9c|xn--s9brj9c|xn--xkc2dl3a5ee0h|xn--45brj9c|xn--mgba3a4f16a|xn--mgbayh7gpa|xn--mgbc0a9azcg|xn--ygbi2ammx|xn--wgbl6a|xn--p1ai|xn--mgberp4a5d4ar|xn--90a3ac|xn--yfro4i67o|xn--clchc0ea0b2g2a9gcd|xn--3e0b707e|xn--fzc2c9e2c|xn--xkc2al3hye2a|xn--mgbtf8fl|xn--kprw13d|xn--kpry57d|xn--o3cw4h|xn--pgbs0dh|xn--mgbaam7a8h|xn--54b7fta0cc|xn--90ae|xn--node|xn--4dbrk0ce|xn--80ao21a|xn--mgb9awbf|xn--mgbai9azgqp6j|xn--j1amh|xn--mgb2ddes|xn--kgbechtv|xn--hgbk6aj7f53bba|xn--0zwm56d|xn--g6w251d|xn--80akhbyknj4f|xn--11b5bs3a9aj6g|xn--jxalpdlp|xn--9t4b11yi5a|xn--deba0ad|xn--zckzah|xn--hlcj6aya9esc7a';
16
  private $api = false;
17
  private $db = false;
18
  public function __sleep(){
@@ -51,7 +51,7 @@ class wordfenceURLHoover {
51
  }
52
  $this->currentHooverID = $id;
53
  try {
54
- @preg_replace_callback("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")($|[\r\n\s\t]|\/[^\r\n\s\t\"\'\$\{\}<>]*)/i", array($this, 'addHost'), $data);
55
  //((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)
56
  //"\$this->" . "addHost(\$id, '$1$2', '$3')", $data);
57
  } catch(Exception $e){
12
  private $hostKeys = array();
13
  private $hostList = array();
14
  public $currentHooverID = false;
15
+ private $dRegex = 'AAA|AARP|ABB|ABBOTT|ABBVIE|ABOGADO|ABUDHABI|AC|ACADEMY|ACCENTURE|ACCOUNTANT|ACCOUNTANTS|ACO|ACTIVE|ACTOR|AD|ADAC|ADS|ADULT|AE|AEG|AERO|AETNA|AF|AFL|AG|AGAKHAN|AGENCY|AI|AIG|AIRFORCE|AIRTEL|AKDN|AL|ALIBABA|ALIPAY|ALLFINANZ|ALLY|ALSACE|AM|AMICA|AMSTERDAM|ANALYTICS|ANDROID|ANQUAN|AO|APARTMENTS|APP|APPLE|AQ|AQUARELLE|AR|ARAMCO|ARCHI|ARMY|ARPA|ARTE|AS|ASIA|ASSOCIATES|AT|ATTORNEY|AU|AUCTION|AUDI|AUDIO|AUTHOR|AUTO|AUTOS|AVIANCA|AW|AWS|AX|AXA|AZ|AZURE|BA|BABY|BAIDU|BAND|BANK|BAR|BARCELONA|BARCLAYCARD|BARCLAYS|BAREFOOT|BARGAINS|BAUHAUS|BAYERN|BB|BBC|BBVA|BCG|BCN|BD|BE|BEATS|BEER|BENTLEY|BERLIN|BEST|BET|BF|BG|BH|BHARTI|BI|BIBLE|BID|BIKE|BING|BINGO|BIO|BIZ|BJ|BLACK|BLACKFRIDAY|BLOG|BLOOMBERG|BLUE|BM|BMS|BMW|BN|BNL|BNPPARIBAS|BO|BOATS|BOEHRINGER|BOM|BOND|BOO|BOOK|BOOTS|BOSCH|BOSTIK|BOT|BOUTIQUE|BR|BRADESCO|BRIDGESTONE|BROADWAY|BROKER|BROTHER|BRUSSELS|BS|BT|BUDAPEST|BUGATTI|BUILD|BUILDERS|BUSINESS|BUY|BUZZ|BV|BW|BY|BZ|BZH|CA|CAB|CAFE|CAL|CALL|CAMERA|CAMP|CANCERRESEARCH|CANON|CAPETOWN|CAPITAL|CAR|CARAVAN|CARDS|CARE|CAREER|CAREERS|CARS|CARTIER|CASA|CASH|CASINO|CAT|CATERING|CBA|CBN|CC|CD|CEB|CENTER|CEO|CERN|CF|CFA|CFD|CG|CH|CHANEL|CHANNEL|CHASE|CHAT|CHEAP|CHLOE|CHRISTMAS|CHROME|CHURCH|CI|CIPRIANI|CIRCLE|CISCO|CITIC|CITY|CITYEATS|CK|CL|CLAIMS|CLEANING|CLICK|CLINIC|CLINIQUE|CLOTHING|CLOUD|CLUB|CLUBMED|CM|CN|CO|COACH|CODES|COFFEE|COLLEGE|COLOGNE|COM|COMMBANK|COMMUNITY|COMPANY|COMPARE|COMPUTER|COMSEC|CONDOS|CONSTRUCTION|CONSULTING|CONTACT|CONTRACTORS|COOKING|COOL|COOP|CORSICA|COUNTRY|COUPON|COUPONS|COURSES|CR|CREDIT|CREDITCARD|CREDITUNION|CRICKET|CROWN|CRS|CRUISES|CSC|CU|CUISINELLA|CV|CW|CX|CY|CYMRU|CYOU|CZ|DABUR|DAD|DANCE|DATE|DATING|DATSUN|DAY|DCLK|DDS|DE|DEALER|DEALS|DEGREE|DELIVERY|DELL|DELOITTE|DELTA|DEMOCRAT|DENTAL|DENTIST|DESI|DESIGN|DEV|DHL|DIAMONDS|DIET|DIGITAL|DIRECT|DIRECTORY|DISCOUNT|DJ|DK|DM|DNP|DO|DOCS|DOG|DOHA|DOMAINS|DOT|DOWNLOAD|DRIVE|DTV|DUBAI|DURBAN|DVAG|DZ|EARTH|EAT|EC|EDEKA|EDU|EDUCATION|EE|EG|EMAIL|EMERCK|ENERGY|ENGINEER|ENGINEERING|ENTERPRISES|EPSON|EQUIPMENT|ER|ERNI|ES|ESQ|ESTATE|ET|EU|EUROVISION|EUS|EVENTS|EVERBANK|EXCHANGE|EXPERT|EXPOSED|EXPRESS|EXTRASPACE|FAGE|FAIL|FAIRWINDS|FAITH|FAMILY|FAN|FANS|FARM|FASHION|FAST|FEEDBACK|FERRERO|FI|FILM|FINAL|FINANCE|FINANCIAL|FIRESTONE|FIRMDALE|FISH|FISHING|FIT|FITNESS|FJ|FK|FLICKR|FLIGHTS|FLIR|FLORIST|FLOWERS|FLSMIDTH|FLY|FM|FO|FOO|FOOTBALL|FORD|FOREX|FORSALE|FORUM|FOUNDATION|FOX|FR|FRESENIUS|FRL|FROGANS|FRONTIER|FTR|FUND|FURNITURE|FUTBOL|FYI|GA|GAL|GALLERY|GALLO|GALLUP|GAME|GAMES|GARDEN|GB|GBIZ|GD|GDN|GE|GEA|GENT|GENTING|GF|GG|GGEE|GH|GI|GIFT|GIFTS|GIVES|GIVING|GL|GLASS|GLE|GLOBAL|GLOBO|GM|GMAIL|GMBH|GMO|GMX|GN|GOLD|GOLDPOINT|GOLF|GOO|GOOG|GOOGLE|GOP|GOT|GOV|GP|GQ|GR|GRAINGER|GRAPHICS|GRATIS|GREEN|GRIPE|GROUP|GS|GT|GU|GUARDIAN|GUCCI|GUGE|GUIDE|GUITARS|GURU|GW|GY|HAMBURG|HANGOUT|HAUS|HDFCBANK|HEALTH|HEALTHCARE|HELP|HELSINKI|HERE|HERMES|HIPHOP|HISAMITSU|HITACHI|HIV|HK|HKT|HM|HN|HOCKEY|HOLDINGS|HOLIDAY|HOMEDEPOT|HOMES|HONDA|HORSE|HOST|HOSTING|HOTELES|HOTMAIL|HOUSE|HOW|HR|HSBC|HT|HTC|HU|HYUNDAI|IBM|ICBC|ICE|ICU|ID|IE|IFM|IINET|IL|IM|IMAMAT|IMMO|IMMOBILIEN|IN|INDUSTRIES|INFINITI|INFO|ING|INK|INSTITUTE|INSURANCE|INSURE|INT|INTERNATIONAL|INVESTMENTS|IO|IPIRANGA|IQ|IR|IRISH|IS|ISELECT|ISMAILI|IST|ISTANBUL|IT|ITAU|IWC|JAGUAR|JAVA|JCB|JCP|JE|JETZT|JEWELRY|JLC|JLL|JM|JMP|JNJ|JO|JOBS|JOBURG|JOT|JOY|JP|JPMORGAN|JPRS|JUEGOS|KAUFEN|KDDI|KE|KERRYHOTELS|KERRYLOGISTICS|KERRYPROPERTIES|KFH|KG|KH|KI|KIA|KIM|KINDER|KITCHEN|KIWI|KM|KN|KOELN|KOMATSU|KP|KPMG|KPN|KR|KRD|KRED|KUOKGROUP|KW|KY|KYOTO|KZ|LA|LACAIXA|LAMBORGHINI|LAMER|LANCASTER|LAND|LANDROVER|LANXESS|LASALLE|LAT|LATROBE|LAW|LAWYER|LB|LC|LDS|LEASE|LECLERC|LEGAL|LEXUS|LGBT|LI|LIAISON|LIDL|LIFE|LIFEINSURANCE|LIFESTYLE|LIGHTING|LIKE|LIMITED|LIMO|LINCOLN|LINDE|LINK|LIPSY|LIVE|LIVING|LIXIL|LK|LOAN|LOANS|LOCKER|LOCUS|LOL|LONDON|LOTTE|LOTTO|LOVE|LR|LS|LT|LTD|LTDA|LU|LUPIN|LUXE|LUXURY|LV|LY|MA|MADRID|MAIF|MAISON|MAKEUP|MAN|MANAGEMENT|MANGO|MARKET|MARKETING|MARKETS|MARRIOTT|MATTEL|MBA|MC|MD|ME|MED|MEDIA|MEET|MELBOURNE|MEME|MEMORIAL|MEN|MENU|MEO|METLIFE|MG|MH|MIAMI|MICROSOFT|MIL|MINI|MK|ML|MLB|MLS|MM|MMA|MN|MO|MOBI|MOBILY|MODA|MOE|MOI|MOM|MONASH|MONEY|MONTBLANC|MORMON|MORTGAGE|MOSCOW|MOTORCYCLES|MOV|MOVIE|MOVISTAR|MP|MQ|MR|MS|MT|MTN|MTPC|MTR|MU|MUSEUM|MUTUAL|MUTUELLE|MV|MW|MX|MY|MZ|NA|NADEX|NAGOYA|NAME|NATURA|NAVY|NC|NE|NEC|NET|NETBANK|NETFLIX|NETWORK|NEUSTAR|NEW|NEWS|NEXT|NEXTDIRECT|NEXUS|NF|NG|NGO|NHK|NI|NICO|NIKON|NINJA|NISSAN|NISSAY|NL|NO|NOKIA|NORTHWESTERNMUTUAL|NORTON|NOWRUZ|NOWTV|NP|NR|NRA|NRW|NTT|NU|NYC|NZ|OBI|OFFICE|OKINAWA|OLAYAN|OLAYANGROUP|OLLO|OM|OMEGA|ONE|ONG|ONL|ONLINE|OOO|ORACLE|ORANGE|ORG|ORGANIC|ORIGINS|OSAKA|OTSUKA|OTT|OVH|PA|PAGE|PAMPEREDCHEF|PANERAI|PARIS|PARS|PARTNERS|PARTS|PARTY|PASSAGENS|PCCW|PE|PET|PF|PG|PH|PHARMACY|PHILIPS|PHOTO|PHOTOGRAPHY|PHOTOS|PHYSIO|PIAGET|PICS|PICTET|PICTURES|PID|PIN|PING|PINK|PIONEER|PIZZA|PK|PL|PLACE|PLAY|PLAYSTATION|PLUMBING|PLUS|PM|PN|POHL|POKER|PORN|POST|PR|PRAXI|PRESS|PRO|PROD|PRODUCTIONS|PROF|PROGRESSIVE|PROMO|PROPERTIES|PROPERTY|PROTECTION|PS|PT|PUB|PW|PWC|PY|QA|QPON|QUEBEC|QUEST|RACING|RE|READ|REALESTATE|REALTOR|REALTY|RECIPES|RED|REDSTONE|REDUMBRELLA|REHAB|REISE|REISEN|REIT|REN|RENT|RENTALS|REPAIR|REPORT|REPUBLICAN|REST|RESTAURANT|REVIEW|REVIEWS|REXROTH|RICH|RICHARDLI|RICOH|RIO|RIP|RO|ROCHER|ROCKS|RODEO|ROOM|RS|RSVP|RU|RUHR|RUN|RW|RWE|RYUKYU|SA|SAARLAND|SAFE|SAFETY|SAKURA|SALE|SALON|SAMSUNG|SANDVIK|SANDVIKCOROMANT|SANOFI|SAP|SAPO|SARL|SAS|SAXO|SB|SBI|SBS|SC|SCA|SCB|SCHAEFFLER|SCHMIDT|SCHOLARSHIPS|SCHOOL|SCHULE|SCHWARZ|SCIENCE|SCOR|SCOT|SD|SE|SEAT|SECURITY|SEEK|SELECT|SENER|SERVICES|SEVEN|SEW|SEX|SEXY|SFR|SG|SH|SHARP|SHAW|SHELL|SHIA|SHIKSHA|SHOES|SHOP|SHOUJI|SHOW|SHRIRAM|SI|SINA|SINGLES|SITE|SJ|SK|SKI|SKIN|SKY|SKYPE|SL|SM|SMILE|SN|SNCF|SO|SOCCER|SOCIAL|SOFTBANK|SOFTWARE|SOHU|SOLAR|SOLUTIONS|SONG|SONY|SOY|SPACE|SPIEGEL|SPOT|SPREADBETTING|SR|SRL|ST|STADA|STAR|STARHUB|STATEBANK|STATEFARM|STATOIL|STC|STCGROUP|STOCKHOLM|STORAGE|STORE|STREAM|STUDIO|STUDY|STYLE|SU|SUCKS|SUPPLIES|SUPPLY|SUPPORT|SURF|SURGERY|SUZUKI|SV|SWATCH|SWISS|SX|SY|SYDNEY|SYMANTEC|SYSTEMS|SZ|TAB|TAIPEI|TALK|TAOBAO|TATAMOTORS|TATAR|TATTOO|TAX|TAXI|TC|TCI|TD|TEAM|TECH|TECHNOLOGY|TEL|TELECITY|TELEFONICA|TEMASEK|TENNIS|TEST|TEVA|TF|TG|TH|THD|THEATER|THEATRE|TICKETS|TIENDA|TIFFANY|TIPS|TIRES|TIROL|TJ|TK|TL|TM|TMALL|TN|TO|TODAY|TOKYO|TOOLS|TOP|TORAY|TOSHIBA|TOTAL|TOURS|TOWN|TOYOTA|TOYS|TR|TRADE|TRADING|TRAINING|TRAVEL|TRAVELERS|TRAVELERSINSURANCE|TRUST|TRV|TT|TUBE|TUI|TUNES|TUSHU|TV|TVS|TW|TZ|UA|UBS|UG|UK|UNICOM|UNIVERSITY|UNO|UOL|UPS|US|UY|UZ|VA|VACATIONS|VANA|VC|VE|VEGAS|VENTURES|VERISIGN|VERSICHERUNG|VET|VG|VI|VIAJES|VIDEO|VIG|VIKING|VILLAS|VIN|VIP|VIRGIN|VISION|VISTA|VISTAPRINT|VIVA|VLAANDEREN|VN|VODKA|VOLKSWAGEN|VOTE|VOTING|VOTO|VOYAGE|VU|VUELOS|WALES|WALTER|WANG|WANGGOU|WARMAN|WATCH|WATCHES|WEATHER|WEATHERCHANNEL|WEBCAM|WEBER|WEBSITE|WED|WEDDING|WEIBO|WEIR|WF|WHOSWHO|WIEN|WIKI|WILLIAMHILL|WIN|WINDOWS|WINE|WME|WOLTERSKLUWER|WORK|WORKS|WORLD|WS|WTC|WTF|XBOX|XEROX|XIHUAN|XIN|XN--11B4C3D|XN--1CK2E1B|XN--1QQW23A|XN--30RR7Y|XN--3BST00M|XN--3DS443G|XN--3E0B707E|XN--3PXU8K|XN--42C2D9A|XN--45BRJ9C|XN--45Q11C|XN--4GBRIM|XN--55QW42G|XN--55QX5D|XN--5TZM5G|XN--6FRZ82G|XN--6QQ986B3XL|XN--80ADXHKS|XN--80AO21A|XN--80ASEHDB|XN--80ASWG|XN--8Y0A063A|XN--90A3AC|XN--90AIS|XN--9DBQ2A|XN--9ET52U|XN--9KRT00A|XN--B4W605FERD|XN--BCK1B9A5DRE4C|XN--C1AVG|XN--C2BR7G|XN--CCK2B3B|XN--CG4BKI|XN--CLCHC0EA0B2G2A9GCD|XN--CZR694B|XN--CZRS0T|XN--CZRU2D|XN--D1ACJ3B|XN--D1ALF|XN--E1A4C|XN--ECKVDTC9D|XN--EFVY88H|XN--ESTV75G|XN--FCT429K|XN--FHBEI|XN--FIQ228C5HS|XN--FIQ64B|XN--FIQS8S|XN--FIQZ9S|XN--FJQ720A|XN--FLW351E|XN--FPCRJ9C3D|XN--FZC2C9E2C|XN--FZYS8D69UVGM|XN--G2XX48C|XN--GCKR3F0F|XN--GECRJ9C|XN--H2BRJ9C|XN--HXT814E|XN--I1B6B1A6A2E|XN--IMR513N|XN--IO0A7I|XN--J1AEF|XN--J1AMH|XN--J6W193G|XN--JLQ61U9W7B|XN--JVR189M|XN--KCRX77D1X4A|XN--KPRW13D|XN--KPRY57D|XN--KPU716F|XN--KPUT3I|XN--L1ACC|XN--LGBBAT1AD8J|XN--MGB9AWBF|XN--MGBA3A3EJT|XN--MGBA3A4F16A|XN--MGBA7C0BBN0A|XN--MGBAAM7A8H|XN--MGBAB2BD|XN--MGBAYH7GPA|XN--MGBB9FBPOB|XN--MGBBH1A71E|XN--MGBC0A9AZCG|XN--MGBCA7DZDO|XN--MGBERP4A5D4AR|XN--MGBPL2FH|XN--MGBT3DHD|XN--MGBTX2B|XN--MGBX4CD0AB|XN--MIX891F|XN--MK1BU44C|XN--MXTQ1M|XN--NGBC5AZD|XN--NGBE9E0A|XN--NODE|XN--NQV7F|XN--NQV7FS00EMA|XN--NYQY26A|XN--O3CW4H|XN--OGBPF8FL|XN--P1ACF|XN--P1AI|XN--PBT977C|XN--PGBS0DH|XN--PSSY2U|XN--Q9JYB4C|XN--QCKA1PMC|XN--QXAM|XN--RHQV96G|XN--ROVU88B|XN--S9BRJ9C|XN--SES554G|XN--T60B56A|XN--TCKWE|XN--UNUP4Y|XN--VERMGENSBERATER-CTB|XN--VERMGENSBERATUNG-PWB|XN--VHQUV|XN--VUQ861B|XN--W4R85EL8FHU5DNRA|XN--W4RS40L|XN--WGBH1C|XN--WGBL6A|XN--XHQ521B|XN--XKC2AL3HYE2A|XN--XKC2DL3A5EE0H|XN--Y9A3AQ|XN--YFRO4I67O|XN--YGBI2AMMX|XN--ZFR164B|XPERIA|XXX|XYZ|YACHTS|YAHOO|YAMAXUN|YANDEX|YE|YODOBASHI|YOGA|YOKOHAMA|YOU|YOUTUBE|YT|YUN|ZA|ZAPPOS|ZARA|ZERO|ZIP|ZM|ZONE|ZUERICH|ZW';
16
  private $api = false;
17
  private $db = false;
18
  public function __sleep(){
51
  }
52
  $this->currentHooverID = $id;
53
  try {
54
+ @preg_replace_callback("/(?<=^|[^a-zA-Z0-9\-])(?:[a-z][a-z0-9\-\+\.]*\:)?\/\/((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")($|[\r\n\s\t]|[\/\?][^\r\n\s\t\"\'\$\{\}<>]*)/i", array($this, 'addHost'), $data);
55
  //((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)
56
  //"\$this->" . "addHost(\$id, '$1$2', '$3')", $data);
57
  } catch(Exception $e){
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
  Tags: wordpress, security, web application firewall, waf, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, two factor authentication, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
  Tested up to: 4.5.2
6
- Stable tag: 6.1.8
7
 
8
  The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
9
  == Description ==
@@ -195,6 +195,20 @@ Designed for every skill level, [The WordPress Security Learning Center](https:/
195
 
196
  == Changelog ==
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  = 6.1.8 =
199
  * Fix: Change wfConfig::set_ser to split large objects into multiple queries.
200
  * Fix: Fixed bug in multisite with "You do not have sufficient permissions to access this page" error after logging in.
3
  Tags: wordpress, security, web application firewall, waf, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, two factor authentication, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
  Tested up to: 4.5.2
6
+ Stable tag: 6.1.9
7
 
8
  The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
9
  == Description ==
195
 
196
  == Changelog ==
197
 
198
+ = 6.1.9 =
199
+ * Fix: Using WP-CLI causes error Undefined index: SERVER_NAME.
200
+ * Improvement: Hooked up restore/delete file scan tools to Filesystem API.
201
+ * Fix: Reworked country blocking authentication check for access to XMLRPC.
202
+ * Improvement: Added option to require cellphone sign-in on all admin accounts.
203
+ * Improvement: Updated IPv6 GeoIP lite data.
204
+ * Fix: Removed suPHP_ConfigPath from WAF installation process.
205
+ * Fix: Prevent author names from being found through /wp-json/oembed.
206
+ * Improvement: Added better solutions for fixing wordfence-waf.php, .user.ini, or .htaccess in scan.
207
+ * Improvement: Added a method to view which files are currently used for WAF and to remove without reinstalling Wordfence.
208
+ * Improvement: Changed rule compilation to use atomic writes.
209
+ * Improvement: Removed security levels from Options page.
210
+ * Improvement: Added option to disable ajaxwatcher (for whitelisting only for Admins) on the front end.
211
+
212
  = 6.1.8 =
213
  * Fix: Change wfConfig::set_ser to split large objects into multiple queries.
214
  * Fix: Fixed bug in multisite with "You do not have sufficient permissions to access this page" error after logging in.
vendor/wordfence/wf-waf/src/lib/rules.php CHANGED
@@ -1223,7 +1223,21 @@ class wfWAFRuleComparisonSubject {
1223
  * @return string
1224
  */
1225
  public function renderRule() {
1226
- $rule = is_array($this->getSubject()) ? join('.', $this->getSubject()) : $this->getSubject();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1227
  foreach ($this->getFilters() as $filter) {
1228
  $rule = $filter . '(' . $rule . ')';
1229
  }
1223
  * @return string
1224
  */
1225
  public function renderRule() {
1226
+ if (is_array($this->getSubject())) {
1227
+ $rule = '';
1228
+ foreach ($this->getSubject() as $subject) {
1229
+ if (preg_match("/^[a-zA-Z_][\\w_]*/", $subject)) {
1230
+ $rule .= "$subject.";
1231
+ } else {
1232
+ $rule = rtrim($rule, '.');
1233
+ $rule .= sprintf("['%s']", str_replace("'", "\\'", $subject));
1234
+ }
1235
+ }
1236
+ $rule = rtrim($rule, '.');
1237
+ } else {
1238
+ $rule = $this->getSubject();
1239
+ }
1240
+
1241
  foreach ($this->getFilters() as $filter) {
1242
  $rule = $filter . '(' . $rule . ')';
1243
  }
vendor/wordfence/wf-waf/src/lib/waf.php CHANGED
@@ -421,8 +421,8 @@ auEa+7b+FGTKs7dUo2BNGR7OVifK4GZ8w/ajS0TelhrSRi3BBQCGXLzUO/UURUAh
421
  if (!is_writable($this->getCompiledRulesFile())) {
422
  throw new wfWAFBuildRulesException('Rules file not writable.');
423
  }
424
-
425
- file_put_contents($this->getCompiledRulesFile(), sprintf(<<<PHP
426
  <?php
427
  if (!defined('WFWAF_VERSION')) {
428
  exit('Access denied');
@@ -433,9 +433,9 @@ if (!defined('WFWAF_VERSION')) {
433
 
434
  %s?>
435
  PHP
436
- , $this->buildRuleSet($rules)), LOCK_EX);
437
  if (!empty($ruleString) && !WFWAF_DEBUG) {
438
- file_put_contents($this->getStorageEngine()->getRulesDSLCacheFile(), $ruleString, LOCK_EX);
439
  }
440
 
441
  if ($updateLastUpdatedTimestamp) {
421
  if (!is_writable($this->getCompiledRulesFile())) {
422
  throw new wfWAFBuildRulesException('Rules file not writable.');
423
  }
424
+
425
+ wfWAFStorageFile::atomicFilePutContents($this->getCompiledRulesFile(), sprintf(<<<PHP
426
  <?php
427
  if (!defined('WFWAF_VERSION')) {
428
  exit('Access denied');
433
 
434
  %s?>
435
  PHP
436
+ , $this->buildRuleSet($rules)), 'rules');
437
  if (!empty($ruleString) && !WFWAF_DEBUG) {
438
+ wfWAFStorageFile::atomicFilePutContents($this->getStorageEngine()->getRulesDSLCacheFile(), $ruleString, 'rules');
439
  }
440
 
441
  if ($updateLastUpdatedTimestamp) {
wordfence.php CHANGED
@@ -4,14 +4,14 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
  Author: Wordfence
7
- Version: 6.1.8
8
  Author URI: http://www.wordfence.com/
9
  Network: true
10
  */
11
  if(defined('WP_INSTALLING') && WP_INSTALLING){
12
  return;
13
  }
14
- define('WORDFENCE_VERSION', '6.1.8');
15
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17
 
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
  Author: Wordfence
7
+ Version: 6.1.9
8
  Author URI: http://www.wordfence.com/
9
  Network: true
10
  */
11
  if(defined('WP_INSTALLING') && WP_INSTALLING){
12
  return;
13
  }
14
+ define('WORDFENCE_VERSION', '6.1.9');
15
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17