Version Description
( 2022-05-11) =
- Enhance: PHP upgrade notice
- Fix: Defender column country_iso_code missing from Lockout table
- Fix: Defender sets all country iso codes as NULL
Download this release
Release Info
Developer | BigTonny |
Plugin | Defender Security – Malware Scanner, Login Security & Firewall |
Version | 2.8.3 |
Comparing to | |
See all releases |
Code changes from version 2.8.2 to 2.8.3
- assets/img/modal/google-recaptcha@2x.png +0 -0
- assets/img/modal/new-256@2x.png +0 -0
- assets/img/modal/new-262@2x.png +0 -0
- assets/img/modal/user-agent@2x.png +0 -0
- assets/img/modal/woo-recaptcha@2x.png +0 -0
- assets/img/tab-tutorial1@1x.png +0 -0
- assets/img/tab-tutorial1@2x.png +0 -0
- assets/img/tab-tutorial2@1x.png +0 -0
- assets/img/tab-tutorial2@2x.png +0 -0
- assets/img/tab-tutorial3@1x.png +0 -0
- assets/img/tab-tutorial3@2x.png +0 -0
- assets/img/tab-tutorial4@1x.png +0 -0
- assets/img/tab-tutorial4@2x.png +0 -0
- assets/img/tutorial1@2x.png +0 -0
- assets/img/tutorial2@2x.png +0 -0
- assets/img/tutorial3@2x.png +0 -0
- assets/img/tutorial4@2x.png +0 -0
- languages/wpdef-default.pot +54 -44
- readme.txt +11 -5
- src/bootstrap.php +5 -5
- src/class-admin.php +57 -0
- src/component/login-lockout.php +17 -10
- src/component/notfound-lockout.php +14 -8
- src/component/security-tweaks/servers/apache.php +106 -92
- src/component/user-agent-lockout.php +14 -8
- src/traits/country.php +6 -0
- src/upgrader.php +5 -5
- wp-defender.php +3 -3
assets/img/modal/google-recaptcha@2x.png
DELETED
Binary file
|
assets/img/modal/new-256@2x.png
DELETED
Binary file
|
assets/img/modal/new-262@2x.png
DELETED
Binary file
|
assets/img/modal/user-agent@2x.png
DELETED
Binary file
|
assets/img/modal/woo-recaptcha@2x.png
DELETED
Binary file
|
assets/img/tab-tutorial1@1x.png
DELETED
Binary file
|
assets/img/tab-tutorial1@2x.png
DELETED
Binary file
|
assets/img/tab-tutorial2@1x.png
DELETED
Binary file
|
assets/img/tab-tutorial2@2x.png
DELETED
Binary file
|
assets/img/tab-tutorial3@1x.png
DELETED
Binary file
|
assets/img/tab-tutorial3@2x.png
DELETED
Binary file
|
assets/img/tab-tutorial4@1x.png
DELETED
Binary file
|
assets/img/tab-tutorial4@2x.png
DELETED
Binary file
|
assets/img/tutorial1@2x.png
DELETED
Binary file
|
assets/img/tutorial2@2x.png
DELETED
Binary file
|
assets/img/tutorial3@2x.png
DELETED
Binary file
|
assets/img/tutorial4@2x.png
DELETED
Binary file
|
languages/wpdef-default.pot
CHANGED
@@ -6,9 +6,9 @@
|
|
6 |
#, fuzzy
|
7 |
msgid ""
|
8 |
msgstr ""
|
9 |
-
"Project-Id-Version: wp-defender 2.8.
|
10 |
"Report-Msgid-Bugs-To: \n"
|
11 |
-
"POT-Creation-Date: 2022-
|
12 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
@@ -194,11 +194,11 @@ msgstr ""
|
|
194 |
msgid "Generate leads with pop-ups, slide-ins and email opt-ins."
|
195 |
msgstr ""
|
196 |
|
197 |
-
#: free/bootstrap.php:
|
198 |
msgid "Get Secure!"
|
199 |
msgstr ""
|
200 |
|
201 |
-
#: free/bootstrap.php:
|
202 |
msgid ""
|
203 |
"You're awesome for installing Defender! Are you interested in how to make "
|
204 |
"the most of this plugin? We've collected all the best security resources we "
|
@@ -434,11 +434,11 @@ msgstr ""
|
|
434 |
msgid "%s is disabled. Please contact your hosting provider to enable it."
|
435 |
msgstr ""
|
436 |
|
437 |
-
#: src/class-admin.php:
|
438 |
msgid "Go to Defender Settings"
|
439 |
msgstr ""
|
440 |
|
441 |
-
#: src/class-admin.php:
|
442 |
#: src/component/backup-settings.php:1173 src/controller/main-setting.php:27
|
443 |
#: front/src/module/advanced-tools/screen/password-reset.vue:41
|
444 |
#: front/src/module/audit/audit.vue:42 front/src/module/audit/audit.vue:49
|
@@ -459,15 +459,15 @@ msgstr ""
|
|
459 |
msgid "Settings"
|
460 |
msgstr ""
|
461 |
|
462 |
-
#: src/class-admin.php:
|
463 |
msgid "Docs"
|
464 |
msgstr ""
|
465 |
|
466 |
-
#: src/class-admin.php:
|
467 |
msgid "Upgrade to Defender Pro"
|
468 |
msgstr ""
|
469 |
|
470 |
-
#: src/class-admin.php:
|
471 |
#: front/src/module/dashboard/component/file-scanning-free.vue:75
|
472 |
#: front/src/module/dashboard/component/file-scanning-free.vue:90
|
473 |
#: front/src/module/scan/screen/scan-result.vue:54
|
@@ -476,72 +476,89 @@ msgstr ""
|
|
476 |
msgid "Upgrade"
|
477 |
msgstr ""
|
478 |
|
479 |
-
#: src/class-admin.php:
|
480 |
msgid "Renew Your Membership"
|
481 |
msgstr ""
|
482 |
|
483 |
-
#: src/class-admin.php:
|
484 |
msgid "Renew Membership"
|
485 |
msgstr ""
|
486 |
|
487 |
-
#: src/class-admin.php:
|
488 |
msgid "WPMU DEV"
|
489 |
msgstr ""
|
490 |
|
491 |
-
#: src/class-admin.php:
|
492 |
#, php-format
|
493 |
msgid "By %s"
|
494 |
msgstr ""
|
495 |
|
496 |
-
#: src/class-admin.php:
|
497 |
#, php-format
|
498 |
msgid "More information about %s"
|
499 |
msgstr ""
|
500 |
|
501 |
-
#: src/class-admin.php:
|
502 |
msgid "View details"
|
503 |
msgstr ""
|
504 |
|
505 |
-
#: src/class-admin.php:
|
506 |
msgid "Rate Defender"
|
507 |
msgstr ""
|
508 |
|
509 |
-
#: src/class-admin.php:
|
510 |
msgid "Support"
|
511 |
msgstr ""
|
512 |
|
513 |
-
#: src/class-admin.php:
|
514 |
msgid "Premium Support"
|
515 |
msgstr ""
|
516 |
|
517 |
-
#: src/class-admin.php:
|
518 |
msgid "Roadmap"
|
519 |
msgstr ""
|
520 |
|
521 |
-
#: src/class-admin.php:
|
522 |
msgid "Invalid request, you are not allowed to do that action."
|
523 |
msgstr ""
|
524 |
|
525 |
-
#: src/class-admin.php:
|
526 |
msgid "Invalid request, allowed data not provided."
|
527 |
msgstr ""
|
528 |
|
529 |
#. //wordpress.org
|
530 |
#. 4 Email Button CTA
|
531 |
-
#: src/class-admin.php:
|
532 |
msgid "Get Fast!"
|
533 |
msgstr ""
|
534 |
|
535 |
-
#: src/class-admin.php:
|
536 |
msgid ""
|
537 |
"We've spent countless hours developing Defender and making it free for you "
|
538 |
"to use. We would really appreciate it if you dropped us a quick rating!"
|
539 |
msgstr ""
|
540 |
|
541 |
-
#: src/class-admin.php:
|
542 |
msgid "Maybe later"
|
543 |
msgstr ""
|
544 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
545 |
#: src/component.php:19
|
546 |
msgid "daily"
|
547 |
msgstr ""
|
@@ -1488,38 +1505,38 @@ msgid ""
|
|
1488 |
"page as a third AUTH method."
|
1489 |
msgstr ""
|
1490 |
|
1491 |
-
#: src/component/login-lockout.php:
|
1492 |
msgid ""
|
1493 |
"You have been locked out by the administrator for attempting to login with a "
|
1494 |
"banned username"
|
1495 |
msgstr ""
|
1496 |
|
1497 |
-
#: src/component/login-lockout.php:
|
1498 |
#, php-format
|
1499 |
msgid "%d login attempts remaining"
|
1500 |
msgstr ""
|
1501 |
|
1502 |
-
#: src/component/login-lockout.php:
|
1503 |
#, php-format
|
1504 |
msgid "Failed login attempt with username %s"
|
1505 |
msgstr ""
|
1506 |
|
1507 |
-
#: src/component/login-lockout.php:
|
1508 |
#, php-format
|
1509 |
msgid "Failed login attempt with a ban username %s"
|
1510 |
msgstr ""
|
1511 |
|
1512 |
-
#: src/component/login-lockout.php:
|
1513 |
msgid "Lockout occurred: Too many failed login attempts"
|
1514 |
msgstr ""
|
1515 |
|
1516 |
-
#: src/component/notfound-lockout.php:
|
1517 |
-
#: src/component/notfound-lockout.php:
|
1518 |
#, php-format
|
1519 |
msgid "Request for file %s which doesn't exist"
|
1520 |
msgstr ""
|
1521 |
|
1522 |
-
#: src/component/notfound-lockout.php:
|
1523 |
#, php-format
|
1524 |
msgid "Lockout occurred: Too many 404 requests for %s"
|
1525 |
msgstr ""
|
@@ -1939,14 +1956,7 @@ msgid "Information Disclosure"
|
|
1939 |
msgstr ""
|
1940 |
|
1941 |
#: src/component/security-tweaks/security-key.php:94
|
1942 |
-
#: src/component/security-tweaks/servers/apache.php:
|
1943 |
-
#: src/component/security-tweaks/servers/apache.php:160
|
1944 |
-
#: src/component/security-tweaks/servers/apache.php:378
|
1945 |
-
#: src/component/security-tweaks/servers/apache.php:383
|
1946 |
-
#: src/component/security-tweaks/servers/apache.php:414
|
1947 |
-
#: src/component/security-tweaks/servers/apache.php:419
|
1948 |
-
#: src/component/security-tweaks/servers/apache.php:495
|
1949 |
-
#: src/component/security-tweaks/servers/apache.php:513
|
1950 |
#, php-format
|
1951 |
msgid "The file %s is not writable"
|
1952 |
msgstr ""
|
@@ -2003,7 +2013,7 @@ msgstr ""
|
|
2003 |
msgid "Security Keys"
|
2004 |
msgstr ""
|
2005 |
|
2006 |
-
#: src/component/security-tweaks/servers/apache.php:
|
2007 |
msgid ""
|
2008 |
"The rules can't be applied. This can be either because your host doesn't "
|
2009 |
"allow editing the file, or you've selected the wrong server type."
|
@@ -2263,15 +2273,15 @@ msgstr ""
|
|
2263 |
msgid "Whoops, the passcode you entered was incorrect or expired."
|
2264 |
msgstr ""
|
2265 |
|
2266 |
-
#: src/component/user-agent-lockout.php:
|
2267 |
msgid "Locked out due to empty User-Agent and Referer headers"
|
2268 |
msgstr ""
|
2269 |
|
2270 |
-
#: src/component/user-agent-lockout.php:
|
2271 |
msgid "Locked out due to attempted login with banned user agent"
|
2272 |
msgstr ""
|
2273 |
|
2274 |
-
#: src/component/user-agent-lockout.php:
|
2275 |
#: src/model/setting/user-agent-lockout.php:56
|
2276 |
msgid "You have been blocked from accessing this website."
|
2277 |
msgstr ""
|
6 |
#, fuzzy
|
7 |
msgid ""
|
8 |
msgstr ""
|
9 |
+
"Project-Id-Version: wp-defender 2.8.3\n"
|
10 |
"Report-Msgid-Bugs-To: \n"
|
11 |
+
"POT-Creation-Date: 2022-05-10 14:27+0300\n"
|
12 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
194 |
msgid "Generate leads with pop-ups, slide-ins and email opt-ins."
|
195 |
msgstr ""
|
196 |
|
197 |
+
#: free/bootstrap.php:270
|
198 |
msgid "Get Secure!"
|
199 |
msgstr ""
|
200 |
|
201 |
+
#: free/bootstrap.php:282
|
202 |
msgid ""
|
203 |
"You're awesome for installing Defender! Are you interested in how to make "
|
204 |
"the most of this plugin? We've collected all the best security resources we "
|
434 |
msgid "%s is disabled. Please contact your hosting provider to enable it."
|
435 |
msgstr ""
|
436 |
|
437 |
+
#: src/class-admin.php:110
|
438 |
msgid "Go to Defender Settings"
|
439 |
msgstr ""
|
440 |
|
441 |
+
#: src/class-admin.php:110 src/component/audit/options-audit.php:227
|
442 |
#: src/component/backup-settings.php:1173 src/controller/main-setting.php:27
|
443 |
#: front/src/module/advanced-tools/screen/password-reset.vue:41
|
444 |
#: front/src/module/audit/audit.vue:42 front/src/module/audit/audit.vue:49
|
459 |
msgid "Settings"
|
460 |
msgstr ""
|
461 |
|
462 |
+
#: src/class-admin.php:112
|
463 |
msgid "Docs"
|
464 |
msgstr ""
|
465 |
|
466 |
+
#: src/class-admin.php:115
|
467 |
msgid "Upgrade to Defender Pro"
|
468 |
msgstr ""
|
469 |
|
470 |
+
#: src/class-admin.php:115
|
471 |
#: front/src/module/dashboard/component/file-scanning-free.vue:75
|
472 |
#: front/src/module/dashboard/component/file-scanning-free.vue:90
|
473 |
#: front/src/module/scan/screen/scan-result.vue:54
|
476 |
msgid "Upgrade"
|
477 |
msgstr ""
|
478 |
|
479 |
+
#: src/class-admin.php:117
|
480 |
msgid "Renew Your Membership"
|
481 |
msgstr ""
|
482 |
|
483 |
+
#: src/class-admin.php:117
|
484 |
msgid "Renew Membership"
|
485 |
msgstr ""
|
486 |
|
487 |
+
#: src/class-admin.php:144
|
488 |
msgid "WPMU DEV"
|
489 |
msgstr ""
|
490 |
|
491 |
+
#: src/class-admin.php:146
|
492 |
#, php-format
|
493 |
msgid "By %s"
|
494 |
msgstr ""
|
495 |
|
496 |
+
#: src/class-admin.php:162
|
497 |
#, php-format
|
498 |
msgid "More information about %s"
|
499 |
msgstr ""
|
500 |
|
501 |
+
#: src/class-admin.php:164 src/class-admin.php:178
|
502 |
msgid "View details"
|
503 |
msgstr ""
|
504 |
|
505 |
+
#: src/class-admin.php:170 src/class-admin.php:278
|
506 |
msgid "Rate Defender"
|
507 |
msgstr ""
|
508 |
|
509 |
+
#: src/class-admin.php:171
|
510 |
msgid "Support"
|
511 |
msgstr ""
|
512 |
|
513 |
+
#: src/class-admin.php:181
|
514 |
msgid "Premium Support"
|
515 |
msgstr ""
|
516 |
|
517 |
+
#: src/class-admin.php:183
|
518 |
msgid "Roadmap"
|
519 |
msgstr ""
|
520 |
|
521 |
+
#: src/class-admin.php:195
|
522 |
msgid "Invalid request, you are not allowed to do that action."
|
523 |
msgstr ""
|
524 |
|
525 |
+
#: src/class-admin.php:204
|
526 |
msgid "Invalid request, allowed data not provided."
|
527 |
msgstr ""
|
528 |
|
529 |
#. //wordpress.org
|
530 |
#. 4 Email Button CTA
|
531 |
+
#: src/class-admin.php:234
|
532 |
msgid "Get Fast!"
|
533 |
msgstr ""
|
534 |
|
535 |
+
#: src/class-admin.php:274
|
536 |
msgid ""
|
537 |
"We've spent countless hours developing Defender and making it free for you "
|
538 |
"to use. We would really appreciate it if you dropped us a quick rating!"
|
539 |
msgstr ""
|
540 |
|
541 |
+
#: src/class-admin.php:281
|
542 |
msgid "Maybe later"
|
543 |
msgstr ""
|
544 |
|
545 |
+
#: src/class-admin.php:337
|
546 |
+
msgid ""
|
547 |
+
"There is a new version of Defender available - Deprecating PHP version 7.1. "
|
548 |
+
"and lower."
|
549 |
+
msgstr ""
|
550 |
+
|
551 |
+
#: src/class-admin.php:340
|
552 |
+
msgid "Important Upgrade Notice:"
|
553 |
+
msgstr ""
|
554 |
+
|
555 |
+
#: src/class-admin.php:344
|
556 |
+
#, php-format
|
557 |
+
msgid ""
|
558 |
+
"The upcoming version %s is compatible only with PHP 7.2.0 and higher. Please "
|
559 |
+
"make sure to upgrade your PHP version."
|
560 |
+
msgstr ""
|
561 |
+
|
562 |
#: src/component.php:19
|
563 |
msgid "daily"
|
564 |
msgstr ""
|
1505 |
"page as a third AUTH method."
|
1506 |
msgstr ""
|
1507 |
|
1508 |
+
#: src/component/login-lockout.php:81
|
1509 |
msgid ""
|
1510 |
"You have been locked out by the administrator for attempting to login with a "
|
1511 |
"banned username"
|
1512 |
msgstr ""
|
1513 |
|
1514 |
+
#: src/component/login-lockout.php:100
|
1515 |
#, php-format
|
1516 |
msgid "%d login attempts remaining"
|
1517 |
msgstr ""
|
1518 |
|
1519 |
+
#: src/component/login-lockout.php:221
|
1520 |
#, php-format
|
1521 |
msgid "Failed login attempt with username %s"
|
1522 |
msgstr ""
|
1523 |
|
1524 |
+
#: src/component/login-lockout.php:226
|
1525 |
#, php-format
|
1526 |
msgid "Failed login attempt with a ban username %s"
|
1527 |
msgstr ""
|
1528 |
|
1529 |
+
#: src/component/login-lockout.php:233
|
1530 |
msgid "Lockout occurred: Too many failed login attempts"
|
1531 |
msgstr ""
|
1532 |
|
1533 |
+
#: src/component/notfound-lockout.php:317
|
1534 |
+
#: src/component/notfound-lockout.php:321
|
1535 |
#, php-format
|
1536 |
msgid "Request for file %s which doesn't exist"
|
1537 |
msgstr ""
|
1538 |
|
1539 |
+
#: src/component/notfound-lockout.php:326
|
1540 |
#, php-format
|
1541 |
msgid "Lockout occurred: Too many 404 requests for %s"
|
1542 |
msgstr ""
|
1956 |
msgstr ""
|
1957 |
|
1958 |
#: src/component/security-tweaks/security-key.php:94
|
1959 |
+
#: src/component/security-tweaks/servers/apache.php:72
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1960 |
#, php-format
|
1961 |
msgid "The file %s is not writable"
|
1962 |
msgstr ""
|
2013 |
msgid "Security Keys"
|
2014 |
msgstr ""
|
2015 |
|
2016 |
+
#: src/component/security-tweaks/servers/apache.php:128
|
2017 |
msgid ""
|
2018 |
"The rules can't be applied. This can be either because your host doesn't "
|
2019 |
"allow editing the file, or you've selected the wrong server type."
|
2273 |
msgid "Whoops, the passcode you entered was incorrect or expired."
|
2274 |
msgstr ""
|
2275 |
|
2276 |
+
#: src/component/user-agent-lockout.php:75
|
2277 |
msgid "Locked out due to empty User-Agent and Referer headers"
|
2278 |
msgstr ""
|
2279 |
|
2280 |
+
#: src/component/user-agent-lockout.php:80
|
2281 |
msgid "Locked out due to attempted login with banned user agent"
|
2282 |
msgstr ""
|
2283 |
|
2284 |
+
#: src/component/user-agent-lockout.php:139
|
2285 |
#: src/model/setting/user-agent-lockout.php:56
|
2286 |
msgid "You have been blocked from accessing this website."
|
2287 |
msgstr ""
|
readme.txt
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
=== Defender Security - Malware Scanner, Login Security & Firewall ===
|
2 |
Plugin Name: Defender Security - Malware Scanner, Login Security & Firewall
|
3 |
-
Version: 2.8.
|
4 |
Author: WPMU DEV
|
5 |
Author URI: https://wpmudev.com/
|
6 |
Contributors: WPMUDEV
|
7 |
Tags: security plugin, security, firewall, malware, malware scanner, antivirus, ip blocking, login security, brute force attacks, two-factor authentication, activity log, audit logs, block hackers, 2fa, hack
|
8 |
Requires at least: 5.2
|
9 |
-
Tested up to:
|
10 |
-
Stable tag: 2.8.
|
11 |
Requires PHP: 5.6.20
|
12 |
License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
13 |
|
@@ -244,11 +244,17 @@ Please open a new thread in Defender’s [support forum](https://wordpress.org/s
|
|
244 |
|
245 |
== Changelog ==
|
246 |
|
247 |
-
= 2.8.
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
|
249 |
- Fix: All site visitors are blocked
|
250 |
|
251 |
-
= 2.8.1 ( 2022-04-
|
252 |
|
253 |
- Enhance: Hide write permissions error notices for Tweaks while applying config
|
254 |
- Enhance: Update the default Auth method on the Users page
|
1 |
=== Defender Security - Malware Scanner, Login Security & Firewall ===
|
2 |
Plugin Name: Defender Security - Malware Scanner, Login Security & Firewall
|
3 |
+
Version: 2.8.3
|
4 |
Author: WPMU DEV
|
5 |
Author URI: https://wpmudev.com/
|
6 |
Contributors: WPMUDEV
|
7 |
Tags: security plugin, security, firewall, malware, malware scanner, antivirus, ip blocking, login security, brute force attacks, two-factor authentication, activity log, audit logs, block hackers, 2fa, hack
|
8 |
Requires at least: 5.2
|
9 |
+
Tested up to: 6.0
|
10 |
+
Stable tag: 2.8.3
|
11 |
Requires PHP: 5.6.20
|
12 |
License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
13 |
|
244 |
|
245 |
== Changelog ==
|
246 |
|
247 |
+
= 2.8.3 ( 2022-05-11) =
|
248 |
+
|
249 |
+
- Enhance: PHP upgrade notice
|
250 |
+
- Fix: Defender column country_iso_code missing from Lockout table
|
251 |
+
- Fix: Defender sets all country iso codes as NULL
|
252 |
+
|
253 |
+
= 2.8.2 ( 2022-04-08 ) =
|
254 |
|
255 |
- Fix: All site visitors are blocked
|
256 |
|
257 |
+
= 2.8.1 ( 2022-04-07 ) =
|
258 |
|
259 |
- Enhance: Hide write permissions error notices for Tweaks while applying config
|
260 |
- Enhance: Update the default Auth method on the Users page
|
src/bootstrap.php
CHANGED
@@ -150,10 +150,12 @@ class Bootstrap {
|
|
150 |
`user_agent` varchar(255) DEFAULT NULL,
|
151 |
`blog_id` int(11) DEFAULT NULL,
|
152 |
`tried` varchar(255),
|
|
|
153 |
PRIMARY KEY (`id`),
|
154 |
KEY `ip` (`ip`),
|
155 |
KEY `type` (`type`),
|
156 |
-
KEY `tried` (`tried`)
|
|
|
157 |
) $charset_collate;";
|
158 |
$wpdb->query( $sql );
|
159 |
}
|
@@ -479,10 +481,8 @@ class Bootstrap {
|
|
479 |
add_action( 'init', function () {
|
480 |
require_once WP_DEFENDER_DIR . 'src/routes.php';
|
481 |
}, 9 );
|
482 |
-
// Include admin class.
|
483 |
-
|
484 |
-
( new \WP_Defender\Admin() )->init();
|
485 |
-
}
|
486 |
// Add WP-CLI commands.
|
487 |
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
488 |
\WP_CLI::add_command( 'defender', Cli::class );
|
150 |
`user_agent` varchar(255) DEFAULT NULL,
|
151 |
`blog_id` int(11) DEFAULT NULL,
|
152 |
`tried` varchar(255),
|
153 |
+
`country_iso_code` char(2) DEFAULT NULL,
|
154 |
PRIMARY KEY (`id`),
|
155 |
KEY `ip` (`ip`),
|
156 |
KEY `type` (`type`),
|
157 |
+
KEY `tried` (`tried`),
|
158 |
+
KEY `country_iso_code` (`country_iso_code`)
|
159 |
) $charset_collate;";
|
160 |
$wpdb->query( $sql );
|
161 |
}
|
481 |
add_action( 'init', function () {
|
482 |
require_once WP_DEFENDER_DIR . 'src/routes.php';
|
483 |
}, 9 );
|
484 |
+
// Include admin class. Don't use is_admin().
|
485 |
+
add_action( 'admin_init', [ ( new \WP_Defender\Admin() ), 'init' ] );
|
|
|
|
|
486 |
// Add WP-CLI commands.
|
487 |
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
488 |
\WP_CLI::add_command( 'defender', Cli::class );
|
src/class-admin.php
CHANGED
@@ -32,6 +32,8 @@ class Admin {
|
|
32 |
add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 3 );
|
33 |
// Only for wordpress.org members.
|
34 |
if ( ! $this->is_pro ) {
|
|
|
|
|
35 |
if ( $is_def_page && ! is_multisite() ) {
|
36 |
add_action( 'admin_notices', array( $this, 'show_rating_notice' ) );
|
37 |
} elseif ( $is_def_page && is_multisite() && is_main_site() ) {
|
@@ -39,6 +41,18 @@ class Admin {
|
|
39 |
}
|
40 |
add_action( 'wp_ajax_defender_dismiss_notification', array( $this, 'dismiss_notice' ) );
|
41 |
add_action( 'admin_init', array( $this, 'register_free_modules' ), 20 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
43 |
}
|
44 |
|
@@ -298,4 +312,47 @@ class Admin {
|
|
298 |
|
299 |
<?php
|
300 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
}
|
32 |
add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 3 );
|
33 |
// Only for wordpress.org members.
|
34 |
if ( ! $this->is_pro ) {
|
35 |
+
// Add plugin upgrade notification.
|
36 |
+
add_action( 'in_plugin_update_message-' . DEFENDER_PLUGIN_BASENAME, array( $this, 'show_upgrade_notice' ), 10, 2 );
|
37 |
if ( $is_def_page && ! is_multisite() ) {
|
38 |
add_action( 'admin_notices', array( $this, 'show_rating_notice' ) );
|
39 |
} elseif ( $is_def_page && is_multisite() && is_main_site() ) {
|
41 |
}
|
42 |
add_action( 'wp_ajax_defender_dismiss_notification', array( $this, 'dismiss_notice' ) );
|
43 |
add_action( 'admin_init', array( $this, 'register_free_modules' ), 20 );
|
44 |
+
} else {
|
45 |
+
// For Pro version.
|
46 |
+
add_action(
|
47 |
+
'load-plugins.php',
|
48 |
+
function () {
|
49 |
+
add_action( 'after_plugin_row_' . DEFENDER_PLUGIN_BASENAME, array(
|
50 |
+
$this,
|
51 |
+
'show_upgrade_notice'
|
52 |
+
), 10, 2 );
|
53 |
+
},
|
54 |
+
22
|
55 |
+
);
|
56 |
}
|
57 |
}
|
58 |
|
312 |
|
313 |
<?php
|
314 |
}
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Show plugin update notice.
|
318 |
+
*
|
319 |
+
* @param string $plugin_file
|
320 |
+
* @param array $response
|
321 |
+
*
|
322 |
+
* @since 2.8.3
|
323 |
+
*/
|
324 |
+
public function show_upgrade_notice( $plugin_file, $response ) {
|
325 |
+
if ( version_compare( PHP_VERSION, '7.2', '>=' ) ) {
|
326 |
+
return;
|
327 |
+
}
|
328 |
+
$plugin_data = (object) $response;
|
329 |
+
// Preparing for the next major plugin v3.0.0 and subsequent versions.
|
330 |
+
if ( isset( $plugin_data->new_version )
|
331 |
+
&& '3' === substr( trim( $plugin_data->new_version ), 0, 1 )
|
332 |
+
&& version_compare( DEFENDER_VERSION, '3', '<' )
|
333 |
+
){
|
334 |
+
// Major plugin version or subsequent versions.
|
335 |
+
$new_version = ( '3' === $plugin_data->new_version ) ? '3.0.0' : $plugin_data->new_version;
|
336 |
+
// Collect notice.
|
337 |
+
$notice = '<p>' . esc_html__( 'There is a new version of Defender available - Deprecating PHP version 7.1. and lower.', 'wpdef' ) . '</p>';
|
338 |
+
$notice .= '<span style="display: inherit;background: #D63638;color: #FFFFFF;margin-top: 12px;padding: 10px 12px;border-radius: 2px;">';
|
339 |
+
$notice .= '<strong>';
|
340 |
+
$notice .= esc_html__( 'Important Upgrade Notice:', 'wpdef' );
|
341 |
+
$notice .= '</strong> ';
|
342 |
+
$notice .= sprintf(
|
343 |
+
/* translators: %s: Version number. */
|
344 |
+
esc_html__( 'The upcoming version %s is compatible only with PHP 7.2.0 and higher. Please make sure to upgrade your PHP version.', 'wpdef' ),
|
345 |
+
$new_version
|
346 |
+
);
|
347 |
+
$notice .= '</span>';
|
348 |
+
|
349 |
+
echo "<script type='text/javascript'>
|
350 |
+
(function ($) {
|
351 |
+
$(document).ready(function () {
|
352 |
+
$( '.wp-list-table tr[data-plugin=\"" . esc_attr( $plugin_data->plugin ) . "\"] .notice-warning' ).html( '" . addslashes( $notice ) . "' ).css('padding-bottom', '10px');
|
353 |
+
});
|
354 |
+
})(jQuery);
|
355 |
+
</script>";
|
356 |
+
}
|
357 |
+
}
|
358 |
}
|
src/component/login-lockout.php
CHANGED
@@ -65,13 +65,14 @@ class Login_Lockout extends \WP_Defender\Component {
|
|
65 |
*/
|
66 |
public function show_attempt_left( $user, $username, $password ) {
|
67 |
if ( is_wp_error( $user )
|
68 |
-
|
69 |
&& ! in_array(
|
70 |
$user->get_error_code(),
|
71 |
array(
|
72 |
'empty_username',
|
73 |
'empty_password',
|
74 |
-
)
|
|
|
75 |
)
|
76 |
) {
|
77 |
$model = Lockout_Ip::get( $this->get_user_ip() );
|
@@ -199,15 +200,21 @@ class Login_Lockout extends \WP_Defender\Component {
|
|
199 |
* @param $scenario
|
200 |
*/
|
201 |
public function log_event( $ip, $username, $scenario ) {
|
202 |
-
$model
|
203 |
-
$model->ip
|
204 |
-
$model->user_agent
|
205 |
? User_Agent::fast_cleaning( $_SERVER['HTTP_USER_AGENT'] )
|
206 |
: null;
|
207 |
-
$model->date
|
208 |
-
$model->tried
|
209 |
-
$model->blog_id
|
210 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
switch ( $scenario ) {
|
212 |
case self::SCENARIO_LOGIN_FAIL:
|
213 |
$model->type = Lockout_Log::AUTH_FAIL;
|
@@ -227,7 +234,7 @@ class Login_Lockout extends \WP_Defender\Component {
|
|
227 |
break;
|
228 |
}
|
229 |
$model->save();
|
230 |
-
if ( $model->type
|
231 |
do_action( 'defender_notify', 'firewall-notification', $model );
|
232 |
}
|
233 |
}
|
65 |
*/
|
66 |
public function show_attempt_left( $user, $username, $password ) {
|
67 |
if ( is_wp_error( $user )
|
68 |
+
&& 'POST' === $_SERVER['REQUEST_METHOD']
|
69 |
&& ! in_array(
|
70 |
$user->get_error_code(),
|
71 |
array(
|
72 |
'empty_username',
|
73 |
'empty_password',
|
74 |
+
),
|
75 |
+
true
|
76 |
)
|
77 |
) {
|
78 |
$model = Lockout_Ip::get( $this->get_user_ip() );
|
200 |
* @param $scenario
|
201 |
*/
|
202 |
public function log_event( $ip, $username, $scenario ) {
|
203 |
+
$model = new Lockout_Log();
|
204 |
+
$model->ip = $ip;
|
205 |
+
$model->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] )
|
206 |
? User_Agent::fast_cleaning( $_SERVER['HTTP_USER_AGENT'] )
|
207 |
: null;
|
208 |
+
$model->date = time();
|
209 |
+
$model->tried = $username;
|
210 |
+
$model->blog_id = get_current_blog_id();
|
211 |
+
|
212 |
+
$ip_to_country = $this->ip_to_country( $ip );
|
213 |
+
|
214 |
+
if ( ! empty( $ip_to_country ) && isset( $ip_to_country['iso'] ) ) {
|
215 |
+
$model->country_iso_code = $ip_to_country['iso'];
|
216 |
+
}
|
217 |
+
|
218 |
switch ( $scenario ) {
|
219 |
case self::SCENARIO_LOGIN_FAIL:
|
220 |
$model->type = Lockout_Log::AUTH_FAIL;
|
234 |
break;
|
235 |
}
|
236 |
$model->save();
|
237 |
+
if ( Lockout_Log::AUTH_LOCK === $model->type ) {
|
238 |
do_action( 'defender_notify', 'firewall-notification', $model );
|
239 |
}
|
240 |
}
|
src/component/notfound-lockout.php
CHANGED
@@ -296,15 +296,21 @@ class Notfound_Lockout extends Component {
|
|
296 |
* @param string $scenario
|
297 |
*/
|
298 |
public function log_event( $ip, $uri, $scenario ) {
|
299 |
-
$model
|
300 |
-
$model->ip
|
301 |
-
$model->user_agent
|
302 |
? User_Agent::fast_cleaning( $_SERVER['HTTP_USER_AGENT'] )
|
303 |
: null;
|
304 |
-
$model->date
|
305 |
-
$model->tried
|
306 |
-
$model->blog_id
|
307 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
308 |
switch ( $scenario ) {
|
309 |
case self::SCENARIO_ERROR_404:
|
310 |
$model->type = Lockout_Log::ERROR_404;
|
@@ -321,7 +327,7 @@ class Notfound_Lockout extends Component {
|
|
321 |
break;
|
322 |
}
|
323 |
$model->save();
|
324 |
-
if ( $model->type
|
325 |
do_action( 'defender_notify', 'firewall-notification', $model );
|
326 |
}
|
327 |
}
|
296 |
* @param string $scenario
|
297 |
*/
|
298 |
public function log_event( $ip, $uri, $scenario ) {
|
299 |
+
$model = new Lockout_Log();
|
300 |
+
$model->ip = $ip;
|
301 |
+
$model->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] )
|
302 |
? User_Agent::fast_cleaning( $_SERVER['HTTP_USER_AGENT'] )
|
303 |
: null;
|
304 |
+
$model->date = time();
|
305 |
+
$model->tried = $uri;
|
306 |
+
$model->blog_id = get_current_blog_id();
|
307 |
+
|
308 |
+
$ip_to_country = $this->ip_to_country( $ip );
|
309 |
+
|
310 |
+
if ( ! empty( $ip_to_country ) && isset( $ip_to_country['iso'] ) ) {
|
311 |
+
$model->country_iso_code = $ip_to_country['iso'];
|
312 |
+
}
|
313 |
+
|
314 |
switch ( $scenario ) {
|
315 |
case self::SCENARIO_ERROR_404:
|
316 |
$model->type = Lockout_Log::ERROR_404;
|
327 |
break;
|
328 |
}
|
329 |
$model->save();
|
330 |
+
if ( Lockout_Log::LOCKOUT_404 === $model->type ) {
|
331 |
do_action( 'defender_notify', 'firewall-notification', $model );
|
332 |
}
|
333 |
}
|
src/component/security-tweaks/servers/apache.php
CHANGED
@@ -11,7 +11,7 @@ class Apache {
|
|
11 |
*
|
12 |
* @var array
|
13 |
*/
|
14 |
-
public $new_htaccess_config =
|
15 |
|
16 |
/**
|
17 |
* The htaccess inside wp-content.
|
@@ -58,6 +58,23 @@ class Apache {
|
|
58 |
return Server::ping_test_failed( $url );
|
59 |
}
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
/**
|
62 |
* Process the rule.
|
63 |
*
|
@@ -66,19 +83,15 @@ class Apache {
|
|
66 |
public function process() {
|
67 |
if ( 'protect-information' === $this->type ) {
|
68 |
$ht_access_path = ABSPATH . '.htaccess';
|
69 |
-
|
70 |
-
if ( ! is_file( $ht_access_path )
|
71 |
-
file_put_contents( $ht_access_path, '', LOCK_EX )
|
|
|
|
|
72 |
}
|
73 |
-
|
74 |
if ( ! is_writable( $ht_access_path ) ) {
|
75 |
-
return
|
76 |
-
'defender_file_not_editable',
|
77 |
-
sprintf(
|
78 |
-
__( 'The file %s is not writable', 'wpdef' ),
|
79 |
-
$ht_access_path
|
80 |
-
)
|
81 |
-
);
|
82 |
}
|
83 |
|
84 |
$ht_access_config = file( $ht_access_path );
|
@@ -87,12 +100,12 @@ class Apache {
|
|
87 |
$contains_search = array_diff( array_map( 'trim', $rules ), $ht_access_config );
|
88 |
|
89 |
if ( count( $contains_search ) < count( $rules ) ) {
|
90 |
-
//
|
91 |
$ht_access_content = file_get_contents( $ht_access_path );
|
92 |
preg_match( '/## WP Defender(.*?)## WP Defender - End ##/s', $ht_access_content, $matches );
|
93 |
|
94 |
if ( count( $matches ) ) {
|
95 |
-
//
|
96 |
$ht_access_content = str_replace( $matches[0], '', $ht_access_content );
|
97 |
$ht_access_config = explode( PHP_EOL, $ht_access_content );
|
98 |
$ht_access_config = array_merge( $ht_access_config, $rules );
|
@@ -152,15 +165,13 @@ class Apache {
|
|
152 |
public function revert() {
|
153 |
if ( 'protect-information' === $this->type ) {
|
154 |
$ht_access_path = ABSPATH . '.htaccess';
|
|
|
|
|
|
|
|
|
155 |
|
156 |
if ( ! is_writable( $ht_access_path ) ) {
|
157 |
-
return
|
158 |
-
'defender_file_not_editable',
|
159 |
-
sprintf(
|
160 |
-
__( "The file %s is not writable", 'wpdef' ),
|
161 |
-
$ht_access_path
|
162 |
-
)
|
163 |
-
);
|
164 |
}
|
165 |
|
166 |
$ht_access_config = file_get_contents( $ht_access_path );
|
@@ -180,28 +191,26 @@ class Apache {
|
|
180 |
}
|
181 |
|
182 |
if ( 'prevent-php-executed' === $this->type ) {
|
|
|
183 |
$response = $this->unprotect_content_directory();
|
184 |
-
|
185 |
if ( is_wp_error( $response ) ) {
|
186 |
-
return wp_send_json_error(
|
187 |
-
'message' => $response->get_error_message()
|
188 |
-
)
|
189 |
}
|
190 |
-
|
191 |
$response = $this->unprotect_includes_directory();
|
192 |
-
|
193 |
if ( is_wp_error( $response ) ) {
|
194 |
-
return wp_send_json_error(
|
195 |
-
'message' => $response->get_error_message()
|
196 |
-
)
|
197 |
}
|
198 |
-
|
199 |
$response = $this->unprotect_upload_directory();
|
200 |
-
|
201 |
if ( is_wp_error( $response ) ) {
|
202 |
-
return wp_send_json_error(
|
203 |
-
'message' => $response->get_error_message()
|
204 |
-
)
|
205 |
}
|
206 |
|
207 |
return delete_site_option( "defender_security_tweeks_{$this->type}" );
|
@@ -214,7 +223,7 @@ class Apache {
|
|
214 |
* @return array
|
215 |
*/
|
216 |
public function get_rules() {
|
217 |
-
$rules
|
218 |
PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
|
219 |
'<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
|
220 |
'Require all denied' . PHP_EOL .
|
@@ -225,11 +234,11 @@ class Apache {
|
|
225 |
'<Files ads.txt>' . PHP_EOL .
|
226 |
'Require all granted' . PHP_EOL .
|
227 |
'</Files>' . PHP_EOL,
|
228 |
-
'## WP Defender - End ##'
|
229 |
-
|
230 |
|
231 |
if ( version_compare( $this->get_version(), '2.4', '<' ) ) {
|
232 |
-
$rules =
|
233 |
PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
|
234 |
'<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
|
235 |
'Order allow,deny' . PHP_EOL .
|
@@ -241,8 +250,8 @@ class Apache {
|
|
241 |
'<Files ads.txt>' . PHP_EOL .
|
242 |
'Allow from all' . PHP_EOL .
|
243 |
'</Files>' . PHP_EOL,
|
244 |
-
'## WP Defender - End ##'
|
245 |
-
|
246 |
}
|
247 |
|
248 |
return $rules;
|
@@ -257,7 +266,7 @@ class Apache {
|
|
257 |
$rules = '';
|
258 |
|
259 |
if ( 'prevent-php-executed' === $this->type ) {
|
260 |
-
$rules
|
261 |
$rules .= PHP_EOL;
|
262 |
$rules .= '<Files *.php>' . PHP_EOL;
|
263 |
$rules .= 'Require all denied' . PHP_EOL;
|
@@ -266,7 +275,7 @@ class Apache {
|
|
266 |
$rules .= '## WP Defender - End ##' . PHP_EOL;
|
267 |
|
268 |
if ( version_compare( $this->get_version(), '2.4', '<' ) ) {
|
269 |
-
$rules
|
270 |
$rules .= PHP_EOL;
|
271 |
$rules .= '<Files *.php>' . PHP_EOL;
|
272 |
$rules .= 'Order allow,deny' . PHP_EOL;
|
@@ -278,7 +287,7 @@ class Apache {
|
|
278 |
}
|
279 |
|
280 |
if ( 'protect-information' === $this->type ) {
|
281 |
-
$rules
|
282 |
$rules .= PHP_EOL;
|
283 |
$rules .= '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
|
284 |
$rules .= 'Require all denied' . PHP_EOL;
|
@@ -295,7 +304,7 @@ class Apache {
|
|
295 |
$rules .= '## WP Defender - End ##';
|
296 |
|
297 |
if ( version_compare( $this->get_version(), '2.4', '>' ) ) {
|
298 |
-
$rules
|
299 |
$rules .= PHP_EOL;
|
300 |
$rules .= '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
|
301 |
$rules .= 'Order allow,deny' . PHP_EOL;
|
@@ -325,7 +334,8 @@ class Apache {
|
|
325 |
*/
|
326 |
public function get_version() {
|
327 |
if ( ! function_exists( 'apache_get_version' ) ) {
|
328 |
-
|
|
|
329 |
$url = home_url();
|
330 |
$apache_version = get_site_transient( 'defender_apache_version' );
|
331 |
|
@@ -336,14 +346,14 @@ class Apache {
|
|
336 |
if ( isset( $apache_version[ $url ] ) && ! empty( $apache_version[ $url ] ) ) {
|
337 |
return strtolower( $apache_version[ $url ] );
|
338 |
}
|
339 |
-
|
340 |
-
$apache_version[ $url ] = $version;
|
341 |
|
342 |
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
|
343 |
-
$server = explode(
|
344 |
if ( is_array( $server ) && count( $server ) > 1 ) {
|
345 |
$server = $server[0];
|
346 |
-
$server = explode(
|
347 |
if ( is_array( $server ) && count( $server ) > 1 ) {
|
348 |
$version = $server[1];
|
349 |
$apache_version[ $url ] = $version;
|
@@ -368,29 +378,27 @@ class Apache {
|
|
368 |
public function protect_content_directory() {
|
369 |
$ht_access_path = $this->contentdir_path;
|
370 |
|
371 |
-
if ( $ht_access_path
|
372 |
$ht_access_path = WP_CONTENT_DIR . '/' . '.htaccess';
|
373 |
}
|
374 |
-
|
375 |
-
if ( !
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
return
|
383 |
-
sprintf( __( 'The file %s is not writable', 'wpdef' ), $ht_access_path )
|
384 |
-
);
|
385 |
}
|
386 |
|
387 |
$exists_rules = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
388 |
-
$rule =
|
389 |
'## WP Defender - Protect PHP Executed ##',
|
390 |
'<Files *.php>',
|
391 |
$this->generate_htaccess_rule( false ),
|
392 |
'</Files>',
|
393 |
-
|
394 |
|
395 |
$rule[] = '## WP Defender - End ##';
|
396 |
file_put_contents( $ht_access_path, $exists_rules . implode( PHP_EOL, $rule ), LOCK_EX );
|
@@ -404,25 +412,23 @@ class Apache {
|
|
404 |
public function protect_includes_directory() {
|
405 |
$ht_access_path = $this->includedir_path;
|
406 |
|
407 |
-
if ( $ht_access_path
|
408 |
$ht_access_path = ABSPATH . WPINC . '/' . '.htaccess';
|
409 |
}
|
410 |
-
|
411 |
-
if ( ! is_file( $ht_access_path )
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
return
|
419 |
-
sprintf( __( 'The file %s is not writable', 'wpdef' ), $ht_access_path )
|
420 |
-
);
|
421 |
}
|
422 |
|
423 |
$exists_rules = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
424 |
|
425 |
-
$rule =
|
426 |
'## WP Defender - Protect PHP Executed ##',
|
427 |
'<Files *.php>',
|
428 |
$this->generate_htaccess_rule( false ),
|
@@ -434,7 +440,7 @@ class Apache {
|
|
434 |
$this->generate_htaccess_rule( true ),
|
435 |
'</Files>',
|
436 |
'## WP Defender - End ##',
|
437 |
-
|
438 |
|
439 |
file_put_contents( $ht_access_path, $exists_rules . implode( PHP_EOL, $rule ), LOCK_EX );
|
440 |
}
|
@@ -470,29 +476,29 @@ class Apache {
|
|
470 |
public function protect_uploads_directory() {
|
471 |
if ( defined( 'UPLOADS' ) ) {
|
472 |
$this->contentdir_path = ABSPATH . UPLOADS . '/' . '.htaccess';
|
|
|
473 |
return $this->protect_content_directory();
|
474 |
}
|
475 |
}
|
476 |
|
477 |
/**
|
478 |
-
*
|
479 |
*
|
480 |
* @return void|WP_Error
|
481 |
*/
|
482 |
public function unprotect_content_directory() {
|
483 |
$ht_access_path = $this->contentdir_path;
|
484 |
|
485 |
-
if ( $ht_access_path
|
486 |
$ht_access_path = WP_CONTENT_DIR . '/' . '.htaccess';
|
487 |
}
|
488 |
-
|
489 |
-
if ( !
|
490 |
return;
|
491 |
}
|
492 |
-
|
493 |
if ( ! is_writable( $ht_access_path ) ) {
|
494 |
-
return
|
495 |
-
sprintf( __( "The file %s is not writable", 'wpdef' ), $ht_access_path ) );
|
496 |
}
|
497 |
|
498 |
$ht_config = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
@@ -501,17 +507,25 @@ class Apache {
|
|
501 |
file_put_contents( $ht_access_path, trim( $ht_config ), LOCK_EX );
|
502 |
}
|
503 |
|
|
|
|
|
|
|
|
|
|
|
|
|
504 |
public function unprotect_includes_directory() {
|
505 |
$ht_access_path = $this->includedir_path;
|
506 |
|
507 |
-
if ( $ht_access_path
|
508 |
$ht_access_path = ABSPATH . WPINC . '/' . '.htaccess';
|
509 |
}
|
510 |
-
|
|
|
|
|
|
|
|
|
511 |
if ( ! is_writable( $ht_access_path ) ) {
|
512 |
-
return
|
513 |
-
sprintf( __( 'The file %s is not writable', 'wpdef' ), $ht_access_path )
|
514 |
-
);
|
515 |
}
|
516 |
|
517 |
$ht_config = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
@@ -519,7 +533,7 @@ class Apache {
|
|
519 |
}
|
520 |
|
521 |
/**
|
522 |
-
*
|
523 |
*
|
524 |
* @return void
|
525 |
*/
|
@@ -535,7 +549,7 @@ class Apache {
|
|
535 |
*
|
536 |
* @param array $config
|
537 |
*/
|
538 |
-
public function set_new_htaccess_config( $config =
|
539 |
if ( ! empty( $config ) ) {
|
540 |
$this->new_htaccess_config = $config;
|
541 |
}
|
11 |
*
|
12 |
* @var array
|
13 |
*/
|
14 |
+
public $new_htaccess_config = array();
|
15 |
|
16 |
/**
|
17 |
* The htaccess inside wp-content.
|
58 |
return Server::ping_test_failed( $url );
|
59 |
}
|
60 |
|
61 |
+
/**
|
62 |
+
* @param string $file_path
|
63 |
+
*
|
64 |
+
* @return WP_Error
|
65 |
+
* @since 2.8.3
|
66 |
+
*/
|
67 |
+
public function get_error_by_file_path( $file_path ) {
|
68 |
+
return new WP_Error(
|
69 |
+
'defender_file_not_writable',
|
70 |
+
sprintf(
|
71 |
+
/* translators: %s - file path */
|
72 |
+
__( 'The file %s is not writable', 'wpdef' ),
|
73 |
+
$file_path
|
74 |
+
)
|
75 |
+
);
|
76 |
+
}
|
77 |
+
|
78 |
/**
|
79 |
* Process the rule.
|
80 |
*
|
83 |
public function process() {
|
84 |
if ( 'protect-information' === $this->type ) {
|
85 |
$ht_access_path = ABSPATH . '.htaccess';
|
86 |
+
// Create a htaccess-file if it doesn't exist.
|
87 |
+
if ( ! is_file( $ht_access_path )
|
88 |
+
&& false === (bool) file_put_contents( $ht_access_path, '', LOCK_EX )
|
89 |
+
) {
|
90 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
91 |
}
|
92 |
+
// If the htaccess-file is existed.
|
93 |
if ( ! is_writable( $ht_access_path ) ) {
|
94 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
96 |
|
97 |
$ht_access_config = file( $ht_access_path );
|
100 |
$contains_search = array_diff( array_map( 'trim', $rules ), $ht_access_config );
|
101 |
|
102 |
if ( count( $contains_search ) < count( $rules ) ) {
|
103 |
+
// Search the wrapper block.
|
104 |
$ht_access_content = file_get_contents( $ht_access_path );
|
105 |
preg_match( '/## WP Defender(.*?)## WP Defender - End ##/s', $ht_access_content, $matches );
|
106 |
|
107 |
if ( count( $matches ) ) {
|
108 |
+
// Remove the whole parts as its partial done.
|
109 |
$ht_access_content = str_replace( $matches[0], '', $ht_access_content );
|
110 |
$ht_access_config = explode( PHP_EOL, $ht_access_content );
|
111 |
$ht_access_config = array_merge( $ht_access_config, $rules );
|
165 |
public function revert() {
|
166 |
if ( 'protect-information' === $this->type ) {
|
167 |
$ht_access_path = ABSPATH . '.htaccess';
|
168 |
+
// Quick exit if the file does not exist.
|
169 |
+
if ( ! is_file( $ht_access_path ) ) {
|
170 |
+
return true;
|
171 |
+
}
|
172 |
|
173 |
if ( ! is_writable( $ht_access_path ) ) {
|
174 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
}
|
176 |
|
177 |
$ht_access_config = file_get_contents( $ht_access_path );
|
191 |
}
|
192 |
|
193 |
if ( 'prevent-php-executed' === $this->type ) {
|
194 |
+
// Content-folder.
|
195 |
$response = $this->unprotect_content_directory();
|
|
|
196 |
if ( is_wp_error( $response ) ) {
|
197 |
+
return wp_send_json_error(
|
198 |
+
array( 'message' => $response->get_error_message() )
|
199 |
+
);
|
200 |
}
|
201 |
+
// Includes-folder.
|
202 |
$response = $this->unprotect_includes_directory();
|
|
|
203 |
if ( is_wp_error( $response ) ) {
|
204 |
+
return wp_send_json_error(
|
205 |
+
array( 'message' => $response->get_error_message() )
|
206 |
+
);
|
207 |
}
|
208 |
+
// Uploads-folder.
|
209 |
$response = $this->unprotect_upload_directory();
|
|
|
210 |
if ( is_wp_error( $response ) ) {
|
211 |
+
return wp_send_json_error(
|
212 |
+
array( 'message' => $response->get_error_message() )
|
213 |
+
);
|
214 |
}
|
215 |
|
216 |
return delete_site_option( "defender_security_tweeks_{$this->type}" );
|
223 |
* @return array
|
224 |
*/
|
225 |
public function get_rules() {
|
226 |
+
$rules = array(
|
227 |
PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
|
228 |
'<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
|
229 |
'Require all denied' . PHP_EOL .
|
234 |
'<Files ads.txt>' . PHP_EOL .
|
235 |
'Require all granted' . PHP_EOL .
|
236 |
'</Files>' . PHP_EOL,
|
237 |
+
'## WP Defender - End ##',
|
238 |
+
);
|
239 |
|
240 |
if ( version_compare( $this->get_version(), '2.4', '<' ) ) {
|
241 |
+
$rules = array(
|
242 |
PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
|
243 |
'<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
|
244 |
'Order allow,deny' . PHP_EOL .
|
250 |
'<Files ads.txt>' . PHP_EOL .
|
251 |
'Allow from all' . PHP_EOL .
|
252 |
'</Files>' . PHP_EOL,
|
253 |
+
'## WP Defender - End ##',
|
254 |
+
);
|
255 |
}
|
256 |
|
257 |
return $rules;
|
266 |
$rules = '';
|
267 |
|
268 |
if ( 'prevent-php-executed' === $this->type ) {
|
269 |
+
$rules = '## WP Defender - Protect PHP Executed ##' . PHP_EOL;
|
270 |
$rules .= PHP_EOL;
|
271 |
$rules .= '<Files *.php>' . PHP_EOL;
|
272 |
$rules .= 'Require all denied' . PHP_EOL;
|
275 |
$rules .= '## WP Defender - End ##' . PHP_EOL;
|
276 |
|
277 |
if ( version_compare( $this->get_version(), '2.4', '<' ) ) {
|
278 |
+
$rules = '## WP Defender - Protect PHP Executed ##' . PHP_EOL;
|
279 |
$rules .= PHP_EOL;
|
280 |
$rules .= '<Files *.php>' . PHP_EOL;
|
281 |
$rules .= 'Order allow,deny' . PHP_EOL;
|
287 |
}
|
288 |
|
289 |
if ( 'protect-information' === $this->type ) {
|
290 |
+
$rules = '## WP Defender - Prevent information disclosure ##' . PHP_EOL;
|
291 |
$rules .= PHP_EOL;
|
292 |
$rules .= '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
|
293 |
$rules .= 'Require all denied' . PHP_EOL;
|
304 |
$rules .= '## WP Defender - End ##';
|
305 |
|
306 |
if ( version_compare( $this->get_version(), '2.4', '>' ) ) {
|
307 |
+
$rules = '## WP Defender - Prevent information disclosure ##' . PHP_EOL;
|
308 |
$rules .= PHP_EOL;
|
309 |
$rules .= '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
|
310 |
$rules .= 'Order allow,deny' . PHP_EOL;
|
334 |
*/
|
335 |
public function get_version() {
|
336 |
if ( ! function_exists( 'apache_get_version' ) ) {
|
337 |
+
// The default support is 2.2.
|
338 |
+
$version = '2.2';
|
339 |
$url = home_url();
|
340 |
$apache_version = get_site_transient( 'defender_apache_version' );
|
341 |
|
346 |
if ( isset( $apache_version[ $url ] ) && ! empty( $apache_version[ $url ] ) ) {
|
347 |
return strtolower( $apache_version[ $url ] );
|
348 |
}
|
349 |
+
// The default support is 2.2.
|
350 |
+
$apache_version[ $url ] = $version;
|
351 |
|
352 |
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
|
353 |
+
$server = explode( ' ', $_SERVER['SERVER_SOFTWARE'] );
|
354 |
if ( is_array( $server ) && count( $server ) > 1 ) {
|
355 |
$server = $server[0];
|
356 |
+
$server = explode( '/', $server );
|
357 |
if ( is_array( $server ) && count( $server ) > 1 ) {
|
358 |
$version = $server[1];
|
359 |
$apache_version[ $url ] = $version;
|
378 |
public function protect_content_directory() {
|
379 |
$ht_access_path = $this->contentdir_path;
|
380 |
|
381 |
+
if ( empty( $ht_access_path ) ) {
|
382 |
$ht_access_path = WP_CONTENT_DIR . '/' . '.htaccess';
|
383 |
}
|
384 |
+
// Create a htaccess-file if it doesn't exist.
|
385 |
+
if ( ! is_file( $ht_access_path )
|
386 |
+
&& false === (bool) file_put_contents( $ht_access_path, '', LOCK_EX )
|
387 |
+
) {
|
388 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
389 |
+
}
|
390 |
+
// If the htaccess-file is existed.
|
391 |
+
if ( ! is_writable( $ht_access_path ) ) {
|
392 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
|
|
|
|
393 |
}
|
394 |
|
395 |
$exists_rules = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
396 |
+
$rule = array(
|
397 |
'## WP Defender - Protect PHP Executed ##',
|
398 |
'<Files *.php>',
|
399 |
$this->generate_htaccess_rule( false ),
|
400 |
'</Files>',
|
401 |
+
);
|
402 |
|
403 |
$rule[] = '## WP Defender - End ##';
|
404 |
file_put_contents( $ht_access_path, $exists_rules . implode( PHP_EOL, $rule ), LOCK_EX );
|
412 |
public function protect_includes_directory() {
|
413 |
$ht_access_path = $this->includedir_path;
|
414 |
|
415 |
+
if ( empty( $ht_access_path ) ) {
|
416 |
$ht_access_path = ABSPATH . WPINC . '/' . '.htaccess';
|
417 |
}
|
418 |
+
// Create a htaccess-file if it doesn't exist.
|
419 |
+
if ( ! is_file( $ht_access_path )
|
420 |
+
&& false === (bool) file_put_contents( $ht_access_path, '', LOCK_EX )
|
421 |
+
) {
|
422 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
423 |
+
}
|
424 |
+
// If the htaccess-file is existed.
|
425 |
+
if ( ! is_writable( $ht_access_path ) ) {
|
426 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
|
|
|
|
427 |
}
|
428 |
|
429 |
$exists_rules = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
430 |
|
431 |
+
$rule = array(
|
432 |
'## WP Defender - Protect PHP Executed ##',
|
433 |
'<Files *.php>',
|
434 |
$this->generate_htaccess_rule( false ),
|
440 |
$this->generate_htaccess_rule( true ),
|
441 |
'</Files>',
|
442 |
'## WP Defender - End ##',
|
443 |
+
);
|
444 |
|
445 |
file_put_contents( $ht_access_path, $exists_rules . implode( PHP_EOL, $rule ), LOCK_EX );
|
446 |
}
|
476 |
public function protect_uploads_directory() {
|
477 |
if ( defined( 'UPLOADS' ) ) {
|
478 |
$this->contentdir_path = ABSPATH . UPLOADS . '/' . '.htaccess';
|
479 |
+
|
480 |
return $this->protect_content_directory();
|
481 |
}
|
482 |
}
|
483 |
|
484 |
/**
|
485 |
+
* Unprotect content directory.
|
486 |
*
|
487 |
* @return void|WP_Error
|
488 |
*/
|
489 |
public function unprotect_content_directory() {
|
490 |
$ht_access_path = $this->contentdir_path;
|
491 |
|
492 |
+
if ( empty( $ht_access_path ) ) {
|
493 |
$ht_access_path = WP_CONTENT_DIR . '/' . '.htaccess';
|
494 |
}
|
495 |
+
// Quick exit if the file does not exist.
|
496 |
+
if ( ! is_file( $ht_access_path ) ) {
|
497 |
return;
|
498 |
}
|
499 |
+
// If the htaccess-file is existed.
|
500 |
if ( ! is_writable( $ht_access_path ) ) {
|
501 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
|
|
502 |
}
|
503 |
|
504 |
$ht_config = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
507 |
file_put_contents( $ht_access_path, trim( $ht_config ), LOCK_EX );
|
508 |
}
|
509 |
|
510 |
+
/**
|
511 |
+
* Unprotect includes-directory.
|
512 |
+
* Todo: can be combined with unprotect_content_directory()?
|
513 |
+
*
|
514 |
+
* @return void|WP_Error
|
515 |
+
*/
|
516 |
public function unprotect_includes_directory() {
|
517 |
$ht_access_path = $this->includedir_path;
|
518 |
|
519 |
+
if ( empty( $ht_access_path ) ) {
|
520 |
$ht_access_path = ABSPATH . WPINC . '/' . '.htaccess';
|
521 |
}
|
522 |
+
// Quick exit if the file does not exist.
|
523 |
+
if ( ! is_file( $ht_access_path ) ) {
|
524 |
+
return;
|
525 |
+
}
|
526 |
+
// If the htaccess-file is existed.
|
527 |
if ( ! is_writable( $ht_access_path ) ) {
|
528 |
+
return $this->get_error_by_file_path( $ht_access_path );
|
|
|
|
|
529 |
}
|
530 |
|
531 |
$ht_config = $this->cleanup_old_rules( file_get_contents( $ht_access_path ) );
|
533 |
}
|
534 |
|
535 |
/**
|
536 |
+
* Unprotect upload directory.
|
537 |
*
|
538 |
* @return void
|
539 |
*/
|
549 |
*
|
550 |
* @param array $config
|
551 |
*/
|
552 |
+
public function set_new_htaccess_config( $config = array() ) {
|
553 |
if ( ! empty( $config ) ) {
|
554 |
$this->new_htaccess_config = $config;
|
555 |
}
|
src/component/user-agent-lockout.php
CHANGED
@@ -54,14 +54,20 @@ class User_Agent extends Component {
|
|
54 |
* @param string $reason
|
55 |
*/
|
56 |
private function log_event( $ip, $user_agent, $reason ) {
|
57 |
-
$model
|
58 |
-
$model->ip
|
59 |
-
$model->user_agent
|
60 |
-
$model->date
|
61 |
-
$model->tried
|
62 |
-
$model->blog_id
|
63 |
-
$model->type
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
switch ( $reason ) {
|
66 |
case self::REASON_BAD_POST:
|
67 |
// Distinguish between different block cases of User agent lockouts.
|
54 |
* @param string $reason
|
55 |
*/
|
56 |
private function log_event( $ip, $user_agent, $reason ) {
|
57 |
+
$model = new Lockout_Log();
|
58 |
+
$model->ip = $ip;
|
59 |
+
$model->user_agent = $user_agent;
|
60 |
+
$model->date = time();
|
61 |
+
$model->tried = $user_agent;
|
62 |
+
$model->blog_id = get_current_blog_id();
|
63 |
+
$model->type = Lockout_Log::LOCKOUT_UA;
|
64 |
+
|
65 |
+
$ip_to_country = $this->ip_to_country( $ip );
|
66 |
+
|
67 |
+
if ( ! empty( $ip_to_country ) && isset( $ip_to_country['iso'] ) ) {
|
68 |
+
$model->country_iso_code = $ip_to_country['iso'];
|
69 |
+
}
|
70 |
+
|
71 |
switch ( $reason ) {
|
72 |
case self::REASON_BAD_POST:
|
73 |
// Distinguish between different block cases of User agent lockouts.
|
src/traits/country.php
CHANGED
@@ -339,6 +339,12 @@ trait Country {
|
|
339 |
|
340 |
if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
|
341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
return false;
|
343 |
|
344 |
}
|
339 |
|
340 |
if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
|
341 |
|
342 |
+
$log_message = 'HTTP Status Code: ' . wp_remote_retrieve_response_code( $response ) . PHP_EOL;
|
343 |
+
$log_message .= 'HTTP Response Message: ' . wp_remote_retrieve_response_message( $response ) . PHP_EOL;
|
344 |
+
$log_message .= 'API URL: ' . $url . PHP_EOL;
|
345 |
+
|
346 |
+
$this->log( $log_message, 'firewall.log' );
|
347 |
+
|
348 |
return false;
|
349 |
|
350 |
}
|
src/upgrader.php
CHANGED
@@ -311,8 +311,8 @@ class Upgrader {
|
|
311 |
if ( version_compare( $db_version, '2.8.0', '<' ) ) {
|
312 |
$this->upgrade_2_8_0();
|
313 |
}
|
314 |
-
if ( version_compare( $db_version, '2.8.
|
315 |
-
$this->
|
316 |
}
|
317 |
|
318 |
defender_no_fresh_install();
|
@@ -941,12 +941,12 @@ Your temporary password is {{passcode}}. To finish logging in, copy and paste th
|
|
941 |
}
|
942 |
|
943 |
/**
|
944 |
-
* Upgrade to 2.8.
|
945 |
*
|
946 |
-
* @since 2.8.
|
947 |
* @return void
|
948 |
*/
|
949 |
-
private function
|
950 |
$this->add_country_iso_code_column();
|
951 |
}
|
952 |
}
|
311 |
if ( version_compare( $db_version, '2.8.0', '<' ) ) {
|
312 |
$this->upgrade_2_8_0();
|
313 |
}
|
314 |
+
if ( version_compare( $db_version, '2.8.3', '<' ) ) {
|
315 |
+
$this->upgrade_2_8_3();
|
316 |
}
|
317 |
|
318 |
defender_no_fresh_install();
|
941 |
}
|
942 |
|
943 |
/**
|
944 |
+
* Upgrade to 2.8.3.
|
945 |
*
|
946 |
+
* @since 2.8.3
|
947 |
* @return void
|
948 |
*/
|
949 |
+
private function upgrade_2_8_3() {
|
950 |
$this->add_country_iso_code_column();
|
951 |
}
|
952 |
}
|
wp-defender.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/**
|
3 |
* Plugin Name: Defender
|
4 |
* Plugin URI: https://wpmudev.com/project/wp-defender/
|
5 |
-
* Version: 2.8.
|
6 |
* Description: Get regular security scans, vulnerability reports, safety recommendations and customized hardening for your site in just a few clicks. Defender is the analyst and enforcer who never sleeps.
|
7 |
* Author: WPMU DEV
|
8 |
* Author URI: https://wpmudev.com/
|
@@ -33,10 +33,10 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
33 |
die;
|
34 |
}
|
35 |
if ( ! defined( 'DEFENDER_VERSION' ) ) {
|
36 |
-
define( 'DEFENDER_VERSION', '2.8.
|
37 |
}
|
38 |
if ( ! defined( 'DEFENDER_DB_VERSION' ) ) {
|
39 |
-
define( 'DEFENDER_DB_VERSION', '2.8.
|
40 |
}
|
41 |
if ( ! defined( 'DEFENDER_SUI' ) ) {
|
42 |
define( 'DEFENDER_SUI', '2-12-2' );
|
2 |
/**
|
3 |
* Plugin Name: Defender
|
4 |
* Plugin URI: https://wpmudev.com/project/wp-defender/
|
5 |
+
* Version: 2.8.3
|
6 |
* Description: Get regular security scans, vulnerability reports, safety recommendations and customized hardening for your site in just a few clicks. Defender is the analyst and enforcer who never sleeps.
|
7 |
* Author: WPMU DEV
|
8 |
* Author URI: https://wpmudev.com/
|
33 |
die;
|
34 |
}
|
35 |
if ( ! defined( 'DEFENDER_VERSION' ) ) {
|
36 |
+
define( 'DEFENDER_VERSION', '2.8.3' );
|
37 |
}
|
38 |
if ( ! defined( 'DEFENDER_DB_VERSION' ) ) {
|
39 |
+
define( 'DEFENDER_DB_VERSION', '2.8.3' );
|
40 |
}
|
41 |
if ( ! defined( 'DEFENDER_SUI' ) ) {
|
42 |
define( 'DEFENDER_SUI', '2-12-2' );
|