Version Description
= 1.8.8 = This version adds support for the latest version of WordPress. Introduces new features and fixes some bugs reported by the WordPress community as well as bugs found by our automated testing system.
Download this release
Release Info
Developer | yorman |
Plugin | ![]() |
Version | 1.8.9 |
Comparing to | |
See all releases |
Code changes from version 1.8.8 to 1.8.9
- inc/css/styles.css +48 -0
- inc/tpl/auditlogs.html.tpl +8 -8
- inc/tpl/base.html.tpl +6 -6
- inc/tpl/dashboard.html.tpl +3 -3
- inc/tpl/firewall-auditlogs.html.tpl +9 -9
- inc/tpl/firewall-clearcache.html.tpl +10 -12
- inc/tpl/firewall-ipaccess.html.tpl +11 -11
- inc/tpl/firewall-settings.html.tpl +11 -11
- inc/tpl/firewall.html.tpl +4 -4
- inc/tpl/integrity-correct.html.tpl +5 -5
- inc/tpl/integrity-diff-utility.html.tpl +10 -2
- inc/tpl/integrity-incorrect.html.tpl +17 -17
- inc/tpl/integrity-notification.html.tpl +7 -7
- inc/tpl/integrity.html.tpl +4 -4
- inc/tpl/lastlogins-admins.html.tpl +5 -5
- inc/tpl/lastlogins-admins.snippet.tpl +4 -4
- inc/tpl/lastlogins-all.html.tpl +8 -8
- inc/tpl/lastlogins-all.snippet.tpl +1 -1
- inc/tpl/lastlogins-blockedusers.html.tpl +10 -10
- inc/tpl/lastlogins-failedlogins.html.tpl +9 -9
- inc/tpl/lastlogins-loggedin.html.tpl +7 -7
- inc/tpl/lastlogins-loggedin.snippet.tpl +1 -1
- inc/tpl/lastlogins.html.tpl +5 -5
- inc/tpl/notification-pretty.html.tpl +5 -5
- inc/tpl/notification-simple.html.tpl +5 -5
- inc/tpl/register-site.html.tpl +7 -7
- inc/tpl/settings-alerts-bruteforce.html.tpl +4 -4
- inc/tpl/settings-alerts-events.html.tpl +4 -4
- inc/tpl/settings-alerts-ignore-posts.html.tpl +30 -22
- inc/tpl/settings-alerts-ignore-posts.snippet.tpl +9 -10
- inc/tpl/settings-alerts-perhour.html.tpl +4 -4
- inc/tpl/settings-alerts-recipients.html.tpl +7 -7
- inc/tpl/settings-alerts-subject.html.tpl +4 -4
- inc/tpl/settings-alerts-trustedips.html.tpl +9 -9
- inc/tpl/settings-apirecovery.html.tpl +4 -4
- inc/tpl/settings-apiregistered.html.tpl +4 -4
- inc/tpl/settings-apiservice-checksums.html.tpl +5 -5
- inc/tpl/settings-apiservice-proxy.html.tpl +6 -6
- inc/tpl/settings-apiservice-status.html.tpl +4 -4
- inc/tpl/settings-general-apikey.html.tpl +9 -9
- inc/tpl/settings-general-datastorage.html.tpl +7 -7
- inc/tpl/settings-general-importexport.html.tpl +4 -4
- inc/tpl/settings-general-ipdiscoverer.html.tpl +8 -8
- inc/tpl/settings-general-resetoptions.html.tpl +4 -4
- inc/tpl/settings-general-reverseproxy.html.tpl +3 -3
- inc/tpl/settings-general-selfhosting.html.tpl +5 -5
- inc/tpl/settings-general-timezone.html.tpl +4 -4
- inc/tpl/settings-hardening-whitelist-phpfiles.html.tpl +9 -9
- inc/tpl/settings-posthack-available-updates-alert.html.tpl +5 -5
- inc/tpl/settings-posthack-available-updates.html.tpl +8 -8
- inc/tpl/settings-posthack-available-updates.snippet.tpl +2 -2
- inc/tpl/settings-posthack-reset-password-alert.html.tpl +1 -1
- inc/tpl/settings-posthack-reset-password.html.tpl +10 -10
- inc/tpl/settings-posthack-reset-plugins.html.tpl +12 -12
- inc/tpl/settings-posthack-reset-plugins.snippet.tpl +1 -1
- inc/tpl/settings-posthack-security-keys.html.tpl +8 -8
- inc/tpl/settings-scanner-cronjobs.html.tpl +10 -10
- inc/tpl/settings-scanner-ignore-folders.html.tpl +9 -36
- inc/tpl/settings-scanner-ignore-folders.snippet.tpl +3 -3
- inc/tpl/settings-scanner-integrity-cache.html.tpl +7 -7
- inc/tpl/settings-scanner-integrity-diff-utility.html.tpl +3 -3
- inc/tpl/settings-scanner-integrity-language.html.tpl +0 -24
- inc/tpl/settings-webinfo-details.html.tpl +1 -1
- inc/tpl/settings-webinfo-htaccess.html.tpl +5 -5
- inc/tpl/settings.html.tpl +7 -9
- inc/tpl/sitecheck-blacklist.html.tpl +1 -3
- inc/tpl/sitecheck-blacklist.snippet.tpl +1 -3
- inc/tpl/sitecheck-malware.html.tpl +1 -1
- inc/tpl/sitecheck-malware.snippet.tpl +3 -3
- inc/tpl/sitecheck-recommendations.html.tpl +1 -1
- inc/tpl/sitecheck-recommendations.snippet.tpl +1 -1
- inc/tpl/sitecheck-target.html.tpl +5 -8
- languages/index.html +0 -1
- languages/sucuri-scanner-en_US.mo +0 -0
- languages/sucuri-scanner-en_US.po +0 -1512
- languages/sucuri-scanner-es_ES.mo +0 -0
- languages/sucuri-scanner-es_ES.po +0 -1513
- readme.txt +1 -1
- src/api.lib.php +149 -205
- src/auditlogs.lib.php +120 -89
- src/cache.lib.php +70 -53
- src/command.lib.php +39 -20
- src/event.lib.php +108 -100
- src/fileinfo.lib.php +53 -37
- src/firewall.lib.php +110 -77
- src/fsscanner.lib.php +35 -69
- src/globals.php +19 -97
- src/hardening.lib.php +40 -26
- src/hook.lib.php +173 -98
- src/installer-skin.lib.php +21 -8
- src/integrity.lib.php +100 -78
- src/interface.lib.php +72 -34
- src/lastlogins-blocked.php +64 -42
- src/lastlogins-failed.php +105 -84
- src/lastlogins-loggedin.php +30 -19
- src/lastlogins.php +117 -77
- src/mail.lib.php +32 -18
- src/option.lib.php +82 -102
- src/pagehandler.php +27 -13
- src/request.lib.php +29 -15
- src/settings-alerts.php +179 -155
- src/settings-apiservice.php +19 -11
- src/settings-general.php +78 -64
- src/settings-hardening.php +210 -100
- src/settings-integrity.php +47 -58
- src/settings-posthack.php +110 -77
- src/settings-scanner.php +108 -130
- src/settings-webinfo.php +26 -31
- src/settings.php +17 -3
- src/sitecheck.lib.php +71 -55
- src/sucuriscan.lib.php +148 -309
- src/template.lib.php +81 -93
- sucuri.php +56 -58
inc/css/styles.css
CHANGED
@@ -863,3 +863,51 @@ body.sucuri-security_page_sucuriscan_hardening {
|
|
863 |
.sucuriscan-firewall-accesslog {
|
864 |
word-break: break-all;
|
865 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
863 |
.sucuriscan-firewall-accesslog {
|
864 |
word-break: break-all;
|
865 |
}
|
866 |
+
.rtl .sucuriscan-header .sucuriscan-pull-left {
|
867 |
+
float: right;
|
868 |
+
}
|
869 |
+
.rtl .sucuriscan-header .sucuriscan-pull-right {
|
870 |
+
float: left;
|
871 |
+
}
|
872 |
+
.rtl .sucuriscan-header .sucuriscan-navbar li {
|
873 |
+
float: right;
|
874 |
+
}
|
875 |
+
.rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li {
|
876 |
+
float: right;
|
877 |
+
}
|
878 |
+
.rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li:first-child {
|
879 |
+
margin-left: 0;
|
880 |
+
margin-right: 12px;
|
881 |
+
}
|
882 |
+
.rtl .sucuriscan-tabs .sucuriscan-tabs-buttons a {
|
883 |
+
border-right: 1px solid #dfdfdf;
|
884 |
+
border-left: 0;
|
885 |
+
}
|
886 |
+
.rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li:first-child a {
|
887 |
+
border-top-right-radius: 6px;
|
888 |
+
}
|
889 |
+
.rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li:last-child a {
|
890 |
+
border-left: 1px solid #ccc;
|
891 |
+
border-top-left-radius: 6px;
|
892 |
+
}
|
893 |
+
.rtl .sucuriscan-hstatus form {
|
894 |
+
left: 20px;
|
895 |
+
right: initial;
|
896 |
+
}
|
897 |
+
.rtl .sucuriscan-container fieldset span,
|
898 |
+
.rtl .sucuriscan-container fieldset label,
|
899 |
+
.rtl .sucuriscan-container fieldset select,
|
900 |
+
.rtl .sucuriscan-container fieldset button,
|
901 |
+
.rtl .sucuriscan-container fieldset input[type=text],
|
902 |
+
.rtl .sucuriscan-container fieldset input[type=checkbox],
|
903 |
+
.rtl .wp-core-ui .sucuriscan-container fieldset .button,
|
904 |
+
.rtl .wp-core-ui .sucuriscan-container fieldset .button-primary,
|
905 |
+
.rtl .wp-core-ui .sucuriscan-container fieldset .button-secondary {
|
906 |
+
float: right !important;
|
907 |
+
margin-left: 0;
|
908 |
+
margin-right: 5px;
|
909 |
+
}
|
910 |
+
.rtl .wrap .sucuriscan-alert > .close {
|
911 |
+
right: initial;
|
912 |
+
left: 20px;
|
913 |
+
}
|
inc/tpl/auditlogs.html.tpl
CHANGED
@@ -2,13 +2,13 @@
|
|
2 |
<script type="text/javascript">
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase:false */
|
5 |
-
jQuery(function ($) {
|
6 |
var writeQueueSize = function (queueSize) {
|
7 |
if (queueSize === 0) {
|
8 |
$('.sucuriscan-auditlogs-sendlogs-response').html('');
|
9 |
$('.sucuriscan-sendlogs-panel').addClass('sucuriscan-hidden');
|
10 |
} else {
|
11 |
-
var msg = '\x20
|
12 |
$('.sucuriscan-auditlogs-sendlogs-response').html((queueSize).toString() + msg);
|
13 |
$('.sucuriscan-sendlogs-panel').removeClass('sucuriscan-hidden');
|
14 |
}
|
@@ -21,9 +21,9 @@ jQuery(function ($) {
|
|
21 |
url += '&paged=' + page;
|
22 |
}
|
23 |
|
24 |
-
$('.sucuriscan-auditlog-response').html('<em
|
25 |
-
$('.sucuriscan-auditlog-status').html('
|
26 |
-
$('.sucuriscan-pagination-loading').html('
|
27 |
$('.sucuriscan-pagination-panel').addClass('sucuriscan-hidden');
|
28 |
$('.sucuriscan-auditlog-footer').addClass('sucuriscan-hidden');
|
29 |
|
@@ -72,7 +72,7 @@ jQuery(function ($) {
|
|
72 |
event.preventDefault();
|
73 |
|
74 |
$('.sucuriscan-sendlogs-panel').attr('content', '');
|
75 |
-
$('.sucuriscan-auditlogs-sendlogs-response').html('
|
76 |
|
77 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
78 |
action: 'sucuriscan_ajax',
|
@@ -104,7 +104,7 @@ jQuery(function ($) {
|
|
104 |
|
105 |
<div class="sucuriscan-auditlog-table">
|
106 |
<div class="sucuriscan-auditlog-response">
|
107 |
-
<em
|
108 |
</div>
|
109 |
|
110 |
<div class="sucuriscan-clearfix sucuriscan-pagination-panel">
|
@@ -121,7 +121,7 @@ jQuery(function ($) {
|
|
121 |
<div class="sucuriscan-pull-left sucuriscan-hidden sucuriscan-tooltip
|
122 |
sucuriscan-sendlogs-panel" tooltip-width="250" tooltip-html="true">
|
123 |
<small class="sucuriscan-auditlogs-sendlogs-response"></small>
|
124 |
-
<small><a href="#" class="sucuriscan-auditlogs-sendlogs"
|
125 |
</div>
|
126 |
|
127 |
<div class="sucuriscan-pull-right">
|
2 |
<script type="text/javascript">
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase:false */
|
5 |
+
jQuery(document).ready(function ($) {
|
6 |
var writeQueueSize = function (queueSize) {
|
7 |
if (queueSize === 0) {
|
8 |
$('.sucuriscan-auditlogs-sendlogs-response').html('');
|
9 |
$('.sucuriscan-sendlogs-panel').addClass('sucuriscan-hidden');
|
10 |
} else {
|
11 |
+
var msg = '\x20logs in the queue\x20—\x20';
|
12 |
$('.sucuriscan-auditlogs-sendlogs-response').html((queueSize).toString() + msg);
|
13 |
$('.sucuriscan-sendlogs-panel').removeClass('sucuriscan-hidden');
|
14 |
}
|
21 |
url += '&paged=' + page;
|
22 |
}
|
23 |
|
24 |
+
$('.sucuriscan-auditlog-response').html('<em>Loading...</em>');
|
25 |
+
$('.sucuriscan-auditlog-status').html('Loading...');
|
26 |
+
$('.sucuriscan-pagination-loading').html('Loading...');
|
27 |
$('.sucuriscan-pagination-panel').addClass('sucuriscan-hidden');
|
28 |
$('.sucuriscan-auditlog-footer').addClass('sucuriscan-hidden');
|
29 |
|
72 |
event.preventDefault();
|
73 |
|
74 |
$('.sucuriscan-sendlogs-panel').attr('content', '');
|
75 |
+
$('.sucuriscan-auditlogs-sendlogs-response').html('Loading...');
|
76 |
|
77 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
78 |
action: 'sucuriscan_ajax',
|
104 |
|
105 |
<div class="sucuriscan-auditlog-table">
|
106 |
<div class="sucuriscan-auditlog-response">
|
107 |
+
<em>Loading...</em>
|
108 |
</div>
|
109 |
|
110 |
<div class="sucuriscan-clearfix sucuriscan-pagination-panel">
|
121 |
<div class="sucuriscan-pull-left sucuriscan-hidden sucuriscan-tooltip
|
122 |
sucuriscan-sendlogs-panel" tooltip-width="250" tooltip-html="true">
|
123 |
<small class="sucuriscan-auditlogs-sendlogs-response"></small>
|
124 |
+
<small><a href="#" class="sucuriscan-auditlogs-sendlogs">Send Logs</a></small>
|
125 |
</div>
|
126 |
|
127 |
<div class="sucuriscan-pull-right">
|
inc/tpl/base.html.tpl
CHANGED
@@ -17,18 +17,18 @@
|
|
17 |
|
18 |
<div class="sucuriscan-pull-right sucuriscan-navbar">
|
19 |
<ul>
|
20 |
-
<li><a href="https://goo.gl/aByqP5" target="_blank" rel="noopener" class="button button-secondary"
|
21 |
|
22 |
<li class="sucuriscan-%%SUCURI.GenerateAPIKey.Visibility%%">
|
23 |
<a href="#" class="button button-primary sucuriscan-modal-button sucuriscan-register-site-button"
|
24 |
-
data-modalid="sucuriscan-register-site"
|
25 |
</li>
|
26 |
|
27 |
-
<li><a href="%%SUCURI.URL.Dashboard%%" class="button button-primary"
|
28 |
|
29 |
-
<li><a href="%%SUCURI.URL.Firewall%%" class="button button-primary"
|
30 |
|
31 |
-
<li><a href="%%SUCURI.URL.Settings%%" class="button button-primary"
|
32 |
</ul>
|
33 |
</div>
|
34 |
</div>
|
@@ -38,6 +38,6 @@
|
|
38 |
</div>
|
39 |
|
40 |
<div class="sucuriscan-clearfix sucuriscan-footer">
|
41 |
-
<div
|
42 |
</div>
|
43 |
</div>
|
17 |
|
18 |
<div class="sucuriscan-pull-right sucuriscan-navbar">
|
19 |
<ul>
|
20 |
+
<li><a href="https://goo.gl/aByqP5" target="_blank" rel="noopener" class="button button-secondary">Review</a></li>
|
21 |
|
22 |
<li class="sucuriscan-%%SUCURI.GenerateAPIKey.Visibility%%">
|
23 |
<a href="#" class="button button-primary sucuriscan-modal-button sucuriscan-register-site-button"
|
24 |
+
data-modalid="sucuriscan-register-site">Generate API Key</a>
|
25 |
</li>
|
26 |
|
27 |
+
<li><a href="%%SUCURI.URL.Dashboard%%" class="button button-primary">Dashboard</a></li>
|
28 |
|
29 |
+
<li><a href="%%SUCURI.URL.Firewall%%" class="button button-primary">Firewall (WAF)</a></li>
|
30 |
|
31 |
+
<li><a href="%%SUCURI.URL.Settings%%" class="button button-primary">Settings</a></li>
|
32 |
</ul>
|
33 |
</div>
|
34 |
</div>
|
38 |
</div>
|
39 |
|
40 |
<div class="sucuriscan-clearfix sucuriscan-footer">
|
41 |
+
<div>Copyright © %%SUCURI.Year%% Sucuri Inc. All Rights Reserved.</div>
|
42 |
</div>
|
43 |
</div>
|
inc/tpl/dashboard.html.tpl
CHANGED
@@ -4,10 +4,10 @@
|
|
4 |
<script type="text/javascript">
|
5 |
/* global jQuery */
|
6 |
/* jshint camelcase: false */
|
7 |
-
jQuery(function ($) {
|
8 |
var sucuriscanSiteCheckLinks = function (target, links) {
|
9 |
if (links.length === 0) {
|
10 |
-
$(target).html('<div><em
|
11 |
return;
|
12 |
}
|
13 |
|
@@ -50,7 +50,7 @@ jQuery(function ($) {
|
|
50 |
<div class="sucuriscan-panel">
|
51 |
<div class="sucuriscan-tabs">
|
52 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
53 |
-
<li><a href="%%SUCURI.URL.Dashboard%%#auditlogs"
|
54 |
<li><a href="%%SUCURI.URL.Dashboard%%#iframes" id="sucuriscan-title-iframes">%%SUCURI.SiteCheck.iFramesTitle%%</a></li>
|
55 |
<li><a href="%%SUCURI.URL.Dashboard%%#links" id="sucuriscan-title-links">%%SUCURI.SiteCheck.LinksTitle%%</a></li>
|
56 |
<li><a href="%%SUCURI.URL.Dashboard%%#scripts" id="sucuriscan-title-scripts">%%SUCURI.SiteCheck.ScriptsTitle%%</a></li>
|
4 |
<script type="text/javascript">
|
5 |
/* global jQuery */
|
6 |
/* jshint camelcase: false */
|
7 |
+
jQuery(document).ready(function ($) {
|
8 |
var sucuriscanSiteCheckLinks = function (target, links) {
|
9 |
if (links.length === 0) {
|
10 |
+
$(target).html('<div><em>no data available</em></div>');
|
11 |
return;
|
12 |
}
|
13 |
|
50 |
<div class="sucuriscan-panel">
|
51 |
<div class="sucuriscan-tabs">
|
52 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
53 |
+
<li><a href="%%SUCURI.URL.Dashboard%%#auditlogs">Audit Logs</a></li>
|
54 |
<li><a href="%%SUCURI.URL.Dashboard%%#iframes" id="sucuriscan-title-iframes">%%SUCURI.SiteCheck.iFramesTitle%%</a></li>
|
55 |
<li><a href="%%SUCURI.URL.Dashboard%%#links" id="sucuriscan-title-links">%%SUCURI.SiteCheck.LinksTitle%%</a></li>
|
56 |
<li><a href="%%SUCURI.URL.Dashboard%%#scripts" id="sucuriscan-title-scripts">%%SUCURI.SiteCheck.ScriptsTitle%%</a></li>
|
inc/tpl/firewall-auditlogs.html.tpl
CHANGED
@@ -1,25 +1,25 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-info">
|
9 |
-
<p
|
10 |
</div>
|
11 |
|
12 |
<script type="text/javascript">
|
13 |
/* global jQuery */
|
14 |
/* jshint camelcase: false */
|
15 |
-
jQuery(function ($) {
|
16 |
$('#sucuriscan-firewall-auditlogs-button').on('click', function (event) {
|
17 |
event.preventDefault();
|
18 |
|
19 |
var params = {};
|
20 |
|
21 |
$('.sucuriscan-firewall-auditlogs tbody')
|
22 |
-
.html('<tr><td><em
|
23 |
|
24 |
params.action = 'sucuriscan_ajax';
|
25 |
params.form_action = 'get_firewall_logs';
|
@@ -44,24 +44,24 @@
|
|
44 |
|
45 |
<form action="%%SUCURI.URL.Firewall%%#auditlogs" method="post">
|
46 |
<fieldset class="sucuriscan-clearfix">
|
47 |
-
<label
|
48 |
<input type="text" id="sucuriscan_firewall_query" />
|
49 |
<select id="sucuriscan_firewall_day">%%%SUCURI.AuditLogs.DateDays%%%</select>
|
50 |
<select id="sucuriscan_firewall_month">%%%SUCURI.AuditLogs.DateMonths%%%</select>
|
51 |
<select id="sucuriscan_firewall_year">%%%SUCURI.AuditLogs.DateYears%%%</select>
|
52 |
-
<button id="sucuriscan-firewall-auditlogs-button" class="button button-primary"
|
53 |
</fieldset>
|
54 |
|
55 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-firewall-auditlogs">
|
56 |
<thead>
|
57 |
<tr>
|
58 |
-
<th
|
59 |
</tr>
|
60 |
</thead>
|
61 |
|
62 |
<tbody>
|
63 |
<tr>
|
64 |
-
<td><em
|
65 |
</tr>
|
66 |
</tbody>
|
67 |
</table>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Firewall Audit Logs</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>The firewall logs every request involved in an attack and separates them from the legitimate requests. You can analyze the data from the latest entries in the logs using this tool and take action either enabling the advanced features of the IDS <em>(Intrusion Detection System)</em> from the <a href="https://waf.sucuri.net/?settings" target="_blank" rel="noopener">Firewall Dashboard</a> and/or blocking IP addresses and URL paths directly from the <a href="https://waf.sucuri.net/?audit" target="_blank" rel="noopener">Firewall Audit Trails</a> page.</p>
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-info">
|
9 |
+
<p>Non-blocked requests are hidden from the logs, this is intentional.</p>
|
10 |
</div>
|
11 |
|
12 |
<script type="text/javascript">
|
13 |
/* global jQuery */
|
14 |
/* jshint camelcase: false */
|
15 |
+
jQuery(document).ready(function ($) {
|
16 |
$('#sucuriscan-firewall-auditlogs-button').on('click', function (event) {
|
17 |
event.preventDefault();
|
18 |
|
19 |
var params = {};
|
20 |
|
21 |
$('.sucuriscan-firewall-auditlogs tbody')
|
22 |
+
.html('<tr><td><em>Loading...</em></td></tr>');
|
23 |
|
24 |
params.action = 'sucuriscan_ajax';
|
25 |
params.form_action = 'get_firewall_logs';
|
44 |
|
45 |
<form action="%%SUCURI.URL.Firewall%%#auditlogs" method="post">
|
46 |
<fieldset class="sucuriscan-clearfix">
|
47 |
+
<label>Search:</label>
|
48 |
<input type="text" id="sucuriscan_firewall_query" />
|
49 |
<select id="sucuriscan_firewall_day">%%%SUCURI.AuditLogs.DateDays%%%</select>
|
50 |
<select id="sucuriscan_firewall_month">%%%SUCURI.AuditLogs.DateMonths%%%</select>
|
51 |
<select id="sucuriscan_firewall_year">%%%SUCURI.AuditLogs.DateYears%%%</select>
|
52 |
+
<button id="sucuriscan-firewall-auditlogs-button" class="button button-primary">Submit</button>
|
53 |
</fieldset>
|
54 |
|
55 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-firewall-auditlogs">
|
56 |
<thead>
|
57 |
<tr>
|
58 |
+
<th>Firewall Audit Logs</th>
|
59 |
</tr>
|
60 |
</thead>
|
61 |
|
62 |
<tbody>
|
63 |
<tr>
|
64 |
+
<td><em>Loading...</em></td>
|
65 |
</tr>
|
66 |
</tbody>
|
67 |
</table>
|
inc/tpl/firewall-clearcache.html.tpl
CHANGED
@@ -2,13 +2,13 @@
|
|
2 |
<script type="text/javascript">
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase: false */
|
5 |
-
jQuery(function ($) {
|
6 |
$('#firewall-clear-cache-button').on('click', function (event) {
|
7 |
event.preventDefault();
|
8 |
|
9 |
var button = $(this);
|
10 |
button.attr('disabled', true);
|
11 |
-
button.html('
|
12 |
$('#firewall-clear-cache-response').html('');
|
13 |
|
14 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
@@ -24,8 +24,7 @@ jQuery(function ($) {
|
|
24 |
$('#firewall-clear-cache-auto').on('change', 'input:checkbox', function () {
|
25 |
var checked = $(this).is(':checked');
|
26 |
|
27 |
-
$('#firewall-clear-cache-auto span').html(
|
28 |
-
'@@SUCURI.FirewallAutoClearCache@@ (@@SUCURI.Loading@@)');
|
29 |
|
30 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
31 |
action: 'sucuriscan_ajax',
|
@@ -33,33 +32,32 @@ jQuery(function ($) {
|
|
33 |
form_action: 'firewall_auto_clear_cache',
|
34 |
auto_clear_cache: (checked?'enable':'disable'),
|
35 |
}, function () {
|
36 |
-
$('#firewall-clear-cache-auto span')
|
37 |
-
.html('@@SUCURI.FirewallAutoClearCache@@');
|
38 |
});
|
39 |
});
|
40 |
});
|
41 |
</script>
|
42 |
|
43 |
<div class="sucuriscan-panel">
|
44 |
-
<h3 class="sucuriscan-title"
|
45 |
|
46 |
<div class="inside">
|
47 |
-
<p
|
48 |
|
49 |
<div class="sucuriscan-inline-alert-info">
|
50 |
-
<p
|
51 |
</div>
|
52 |
|
53 |
-
<p
|
54 |
|
55 |
<div id="firewall-clear-cache-auto">
|
56 |
<label>
|
57 |
<input type="checkbox" name="sucuriscan_auto_clear_cache" value="true" %%SUCURI.FirewallAutoClearCache%% />
|
58 |
-
<span
|
59 |
</label>
|
60 |
</div>
|
61 |
|
62 |
<div id="firewall-clear-cache-response"></div>
|
63 |
-
<button id="firewall-clear-cache-button" class="button button-primary"
|
64 |
</div>
|
65 |
</div>
|
2 |
<script type="text/javascript">
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase: false */
|
5 |
+
jQuery(document).ready(function ($) {
|
6 |
$('#firewall-clear-cache-button').on('click', function (event) {
|
7 |
event.preventDefault();
|
8 |
|
9 |
var button = $(this);
|
10 |
button.attr('disabled', true);
|
11 |
+
button.html('Loading...');
|
12 |
$('#firewall-clear-cache-response').html('');
|
13 |
|
14 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
24 |
$('#firewall-clear-cache-auto').on('change', 'input:checkbox', function () {
|
25 |
var checked = $(this).is(':checked');
|
26 |
|
27 |
+
$('#firewall-clear-cache-auto span').html('Clear cache when a post or page is updated (Loading...)');
|
|
|
28 |
|
29 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
30 |
action: 'sucuriscan_ajax',
|
32 |
form_action: 'firewall_auto_clear_cache',
|
33 |
auto_clear_cache: (checked?'enable':'disable'),
|
34 |
}, function () {
|
35 |
+
$('#firewall-clear-cache-auto span').html('Clear cache when a post or page is updated');
|
|
|
36 |
});
|
37 |
});
|
38 |
});
|
39 |
</script>
|
40 |
|
41 |
<div class="sucuriscan-panel">
|
42 |
+
<h3 class="sucuriscan-title">Clear Cache</h3>
|
43 |
|
44 |
<div class="inside">
|
45 |
+
<p>The firewall offers multiple options to configure the cache level applied to your website. You can either enable the full cache which is the recommended setting, or you can set the cache level to minimal which will keep the pages static for a couple of minutes, or force the usage of the website headers <em>(only for advanced users)</em>, or in extreme cases where you do not need the cache you can simply disable it. Find more information about it in the <a href="https://kb.sucuri.net/firewall/Performance/caching-options" target="_blank" rel="noopener">Sucuri Knowledge Base</a> website.</p>
|
46 |
|
47 |
<div class="sucuriscan-inline-alert-info">
|
48 |
+
<p>Note that the firewall has <a href="https://kb.sucuri.net/firewall/Performance/cache-exceptions" target="_blank" rel="noopener">special caching rules</a> for Images, CSS, PDF, TXT, JavaScript, media files and a few more extensions that are stored on our <a href="https://en.wikipedia.org/wiki/Edge_device" target="_blank" rel="noopener">edge</a>. The only way to flush the cache for these files is by clearing the firewall's cache completely <em>(for the whole website)</em>. Due to our caching of JavaScript and CSS files, often, as is best practice, the use of versioning during development will ensure updates going live as expected. This is done by adding a query string such as <code>?ver=1.2.3</code> and incrementing on each update.</p>
|
49 |
</div>
|
50 |
|
51 |
+
<p>A web cache (or HTTP cache) is an information technology for the temporary storage (caching) of web documents, such as HTML pages and images, to reduce bandwidth usage, server load, and perceived lag. A web cache system stores copies of documents passing through it; subsequent requests may be satisfied from the cache if certain conditions are met. A web cache system can refer either to an appliance, or to a computer program. — <a href="https://en.wikipedia.org/wiki/Web_cache" target="_blank" rel="noopener">WikiPedia - Web Cache</a></p>
|
52 |
|
53 |
<div id="firewall-clear-cache-auto">
|
54 |
<label>
|
55 |
<input type="checkbox" name="sucuriscan_auto_clear_cache" value="true" %%SUCURI.FirewallAutoClearCache%% />
|
56 |
+
<span>Clear cache when a post or page is updated</span>
|
57 |
</label>
|
58 |
</div>
|
59 |
|
60 |
<div id="firewall-clear-cache-response"></div>
|
61 |
+
<button id="firewall-clear-cache-button" class="button button-primary">Clear Cache</button>
|
62 |
</div>
|
63 |
</div>
|
inc/tpl/firewall-ipaccess.html.tpl
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
jQuery(document).ready(function ($) {
|
7 |
var sucuriscanLoadIPAccess = function () {
|
8 |
// $('.sucuriscan-ipaccess-table tbody').html('<tr>' +
|
9 |
-
// '<td colspan="2"
|
10 |
|
11 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
12 |
action: 'sucuriscan_ajax',
|
@@ -19,7 +19,7 @@ jQuery(document).ready(function ($) {
|
|
19 |
$('.sucuriscan-ipaccess-table tbody').append('<tr>' +
|
20 |
'<td><span class="sucuriscan-monospace">' + data.blacklist[i] + '</span></td>' +
|
21 |
'<td><button class="button button-primary sucuriscan-deblacklist" ' +
|
22 |
-
'ip="' + data.blacklist[i] + '"
|
23 |
'</tr>');
|
24 |
}
|
25 |
});
|
@@ -27,7 +27,7 @@ jQuery(document).ready(function ($) {
|
|
27 |
|
28 |
var sucuriscanPrintStatus = function (button, data) {
|
29 |
button.attr('disabled', false);
|
30 |
-
button.html('
|
31 |
|
32 |
if (data.ok) {
|
33 |
sucuriscanLoadIPAccess();
|
@@ -49,7 +49,7 @@ jQuery(document).ready(function ($) {
|
|
49 |
var ip = $('.sucuriscan-ipaccess-form input[name=sucuriscan_ip]').val();
|
50 |
|
51 |
button.attr('disabled', true);
|
52 |
-
button.html('
|
53 |
$('#sucuriscan-ipaccess-response').html('');
|
54 |
|
55 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
@@ -68,7 +68,7 @@ jQuery(document).ready(function ($) {
|
|
68 |
var button = $(this);
|
69 |
|
70 |
button.attr('disabled', true);
|
71 |
-
button.html('
|
72 |
$('#sucuriscan-ipaccess-response').html('');
|
73 |
|
74 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
@@ -86,32 +86,32 @@ jQuery(document).ready(function ($) {
|
|
86 |
</script>
|
87 |
|
88 |
<div class="sucuriscan-panel">
|
89 |
-
<h3 class="sucuriscan-title"
|
90 |
|
91 |
<div class="inside">
|
92 |
-
<p
|
93 |
|
94 |
<div id="sucuriscan-ipaccess-response"></div>
|
95 |
|
96 |
<form action="%%SUCURI.URL.Firewall%%#ipaccess" method="post" class="sucuriscan-ipaccess-form">
|
97 |
<input type="hidden" name="sucuriscan_blacklist_ip" value="true" />
|
98 |
<fieldset class="sucuriscan-clearfix">
|
99 |
-
<label
|
100 |
<input type="text" name="sucuriscan_ip" placeholder="e.g. 192.168.1.54" />
|
101 |
-
<button class="button button-primary sucuriscan-ipaccess-button"
|
102 |
</fieldset>
|
103 |
</form>
|
104 |
|
105 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-ipaccess-table">
|
106 |
<thead>
|
107 |
<tr>
|
108 |
-
<th
|
109 |
<th> </th>
|
110 |
</tr>
|
111 |
</thead>
|
112 |
|
113 |
<tbody>
|
114 |
-
<tr><td colspan="2"
|
115 |
</tbody>
|
116 |
</table>
|
117 |
</div>
|
6 |
jQuery(document).ready(function ($) {
|
7 |
var sucuriscanLoadIPAccess = function () {
|
8 |
// $('.sucuriscan-ipaccess-table tbody').html('<tr>' +
|
9 |
+
// '<td colspan="2">Loading...</td></tr>');
|
10 |
|
11 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
12 |
action: 'sucuriscan_ajax',
|
19 |
$('.sucuriscan-ipaccess-table tbody').append('<tr>' +
|
20 |
'<td><span class="sucuriscan-monospace">' + data.blacklist[i] + '</span></td>' +
|
21 |
'<td><button class="button button-primary sucuriscan-deblacklist" ' +
|
22 |
+
'ip="' + data.blacklist[i] + '">Delete</button></td>' +
|
23 |
'</tr>');
|
24 |
}
|
25 |
});
|
27 |
|
28 |
var sucuriscanPrintStatus = function (button, data) {
|
29 |
button.attr('disabled', false);
|
30 |
+
button.html('Submit');
|
31 |
|
32 |
if (data.ok) {
|
33 |
sucuriscanLoadIPAccess();
|
49 |
var ip = $('.sucuriscan-ipaccess-form input[name=sucuriscan_ip]').val();
|
50 |
|
51 |
button.attr('disabled', true);
|
52 |
+
button.html('Loading...');
|
53 |
$('#sucuriscan-ipaccess-response').html('');
|
54 |
|
55 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
68 |
var button = $(this);
|
69 |
|
70 |
button.attr('disabled', true);
|
71 |
+
button.html('Loading...');
|
72 |
$('#sucuriscan-ipaccess-response').html('');
|
73 |
|
74 |
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
86 |
</script>
|
87 |
|
88 |
<div class="sucuriscan-panel">
|
89 |
+
<h3 class="sucuriscan-title">IP Address Access</h3>
|
90 |
|
91 |
<div class="inside">
|
92 |
+
<p>This tool allows you to whitleist and blacklist one or more IP addresses from accessing your website. You can also configure the plugin to automatically blacklist any IP address involved in a password guessing brute-force attack. If a legitimate user fails to submit the correct credentials of their account they will have to log into the Firewall dashboard in order to delete their IP address from the blacklist, or try to login once again through a VPN.</p>
|
93 |
|
94 |
<div id="sucuriscan-ipaccess-response"></div>
|
95 |
|
96 |
<form action="%%SUCURI.URL.Firewall%%#ipaccess" method="post" class="sucuriscan-ipaccess-form">
|
97 |
<input type="hidden" name="sucuriscan_blacklist_ip" value="true" />
|
98 |
<fieldset class="sucuriscan-clearfix">
|
99 |
+
<label>Blacklist IP:</label>
|
100 |
<input type="text" name="sucuriscan_ip" placeholder="e.g. 192.168.1.54" />
|
101 |
+
<button class="button button-primary sucuriscan-ipaccess-button">Submit</button>
|
102 |
</fieldset>
|
103 |
</form>
|
104 |
|
105 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-ipaccess-table">
|
106 |
<thead>
|
107 |
<tr>
|
108 |
+
<th>IP Address</th>
|
109 |
<th> </th>
|
110 |
</tr>
|
111 |
</thead>
|
112 |
|
113 |
<tbody>
|
114 |
+
<tr><td colspan="2">Loading...</td></tr>
|
115 |
</tbody>
|
116 |
</table>
|
117 |
</div>
|
inc/tpl/firewall-settings.html.tpl
CHANGED
@@ -31,30 +31,30 @@ jQuery(document).ready(function ($) {
|
|
31 |
</script>
|
32 |
|
33 |
<div class="sucuriscan-panel">
|
34 |
-
<h3 class="sucuriscan-title"
|
35 |
|
36 |
<div class="inside">
|
37 |
-
<p
|
38 |
|
39 |
<div class="sucuriscan-inline-alert-info sucuriscan-%%SUCURI.Firewall.APIKeyFormVisibility%%">
|
40 |
-
<p
|
41 |
</div>
|
42 |
|
43 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-firewall-apikey sucuriscan-%%SUCURI.Firewall.APIKeyVisibility%%">
|
44 |
-
<strong
|
45 |
<span class="sucuriscan-monospace">%%SUCURI.Firewall.APIKey%%</span>
|
46 |
<form action="%%SUCURI.URL.Firewall%%" method="post">
|
47 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
48 |
-
<button type="submit" name="sucuriscan_delete_wafkey" class="button button-primary"
|
49 |
</form>
|
50 |
</div>
|
51 |
|
52 |
<form action="%%SUCURI.URL.Firewall%%" method="post" class="sucuriscan-%%SUCURI.Firewall.APIKeyFormVisibility%%">
|
53 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
54 |
<fieldset class="sucuriscan-clearfix">
|
55 |
-
<label
|
56 |
<input type="text" name="sucuriscan_cloudproxy_apikey" />
|
57 |
-
<button type="submit" class="button button-primary"
|
58 |
</fieldset>
|
59 |
<br>
|
60 |
</form>
|
@@ -62,16 +62,16 @@ jQuery(document).ready(function ($) {
|
|
62 |
<table class="wp-list-table widefat sucuriscan-table" id="firewall-settings-table">
|
63 |
<thead>
|
64 |
<tr>
|
65 |
-
<th
|
66 |
-
<th
|
67 |
</tr>
|
68 |
</thead>
|
69 |
|
70 |
<tbody>
|
71 |
-
<tr><td colspan="2"
|
72 |
</tbody>
|
73 |
</table>
|
74 |
|
75 |
-
<p
|
76 |
</div>
|
77 |
</div>
|
31 |
</script>
|
32 |
|
33 |
<div class="sucuriscan-panel">
|
34 |
+
<h3 class="sucuriscan-title">Firewall Settings</h3>
|
35 |
|
36 |
<div class="inside">
|
37 |
+
<p>A powerful Web Application Firewall and <b>Intrusion Detection System</b> for any WordPress user and many other platforms. This page will help you to configure and monitor your site through the <b>Sucuri Firewall</b>. Once enabled, our firewall will act as a shield, protecting your site from attacks and preventing malware infections and reinfections. It will block SQL injection attempts, brute force attacks, XSS, RFI, backdoors and many other threats against your site.</p>
|
38 |
|
39 |
<div class="sucuriscan-inline-alert-info sucuriscan-%%SUCURI.Firewall.APIKeyFormVisibility%%">
|
40 |
+
<p>Add your <a href="https://waf.sucuri.net/?settings&panel=api" target="_blank" rel="noopener">Firewall API key</a> in the form below to start communicating with the firewall API service.</p>
|
41 |
</div>
|
42 |
|
43 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-firewall-apikey sucuriscan-%%SUCURI.Firewall.APIKeyVisibility%%">
|
44 |
+
<strong>Firewall API Key:</strong>
|
45 |
<span class="sucuriscan-monospace">%%SUCURI.Firewall.APIKey%%</span>
|
46 |
<form action="%%SUCURI.URL.Firewall%%" method="post">
|
47 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
48 |
+
<button type="submit" name="sucuriscan_delete_wafkey" class="button button-primary">Delete</button>
|
49 |
</form>
|
50 |
</div>
|
51 |
|
52 |
<form action="%%SUCURI.URL.Firewall%%" method="post" class="sucuriscan-%%SUCURI.Firewall.APIKeyFormVisibility%%">
|
53 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
54 |
<fieldset class="sucuriscan-clearfix">
|
55 |
+
<label>Firewall API Key:</label>
|
56 |
<input type="text" name="sucuriscan_cloudproxy_apikey" />
|
57 |
+
<button type="submit" class="button button-primary">Save</button>
|
58 |
</fieldset>
|
59 |
<br>
|
60 |
</form>
|
62 |
<table class="wp-list-table widefat sucuriscan-table" id="firewall-settings-table">
|
63 |
<thead>
|
64 |
<tr>
|
65 |
+
<th>Name</th>
|
66 |
+
<th>Value</th>
|
67 |
</tr>
|
68 |
</thead>
|
69 |
|
70 |
<tbody>
|
71 |
+
<tr><td colspan="2">Loading...</td></tr>
|
72 |
</tbody>
|
73 |
</table>
|
74 |
|
75 |
+
<p><em>[1]</em> More information about the <a href="https://sucuri.net/website-firewall/" target="_blank" rel="noopener">Sucuri Firewall</a>, features and pricing.<br><em>[2]</em> Instructions and videos in the official <a href="https://kb.sucuri.net/firewall" target="_blank" rel="noopener">Knowledge Base</a> site.<br><em>[3]</em> <a href="https://login.sucuri.net/signup2/create?CloudProxy" target="_blank" rel="noopener">Sign up</a> for a new account and start protecting your site.</p>
|
76 |
</div>
|
77 |
</div>
|
inc/tpl/firewall.html.tpl
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
-
<li><a href="%%SUCURI.URL.Firewall%%#settings"
|
5 |
-
<li><a href="%%SUCURI.URL.Firewall%%#auditlogs"
|
6 |
-
<li><a href="%%SUCURI.URL.Firewall%%#ipaccess"
|
7 |
-
<li><a href="%%SUCURI.URL.Firewall%%#clearcache"
|
8 |
</ul>
|
9 |
|
10 |
<div class="sucuriscan-tabs-containers">
|
1 |
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
+
<li><a href="%%SUCURI.URL.Firewall%%#settings">Settings</a></li>
|
5 |
+
<li><a href="%%SUCURI.URL.Firewall%%#auditlogs">Audit Logs</a></li>
|
6 |
+
<li><a href="%%SUCURI.URL.Firewall%%#ipaccess">IP Access</a></li>
|
7 |
+
<li><a href="%%SUCURI.URL.Firewall%%#clearcache">Clear Cache</a></li>
|
8 |
</ul>
|
9 |
|
10 |
<div class="sucuriscan-tabs-containers">
|
inc/tpl/integrity-correct.html.tpl
CHANGED
@@ -2,17 +2,17 @@
|
|
2 |
<div class="sucuriscan-panel sucuriscan-integrity sucuriscan-integrity-correct">
|
3 |
<div class="sucuriscan-clearfix">
|
4 |
<div class="sucuriscan-pull-left sucuriscan-integrity-left">
|
5 |
-
<h2 class="sucuriscan-title"
|
6 |
|
7 |
-
<p
|
8 |
</div>
|
9 |
|
10 |
<div class="sucuriscan-pull-right sucuriscan-integrity-right">
|
11 |
-
<h2 class="sucuriscan-subtitle"
|
12 |
|
13 |
-
<p
|
14 |
|
15 |
-
<p><a href="%%SUCURI.URL.Settings%%#scanner"
|
16 |
</div>
|
17 |
</div>
|
18 |
|
2 |
<div class="sucuriscan-panel sucuriscan-integrity sucuriscan-integrity-correct">
|
3 |
<div class="sucuriscan-clearfix">
|
4 |
<div class="sucuriscan-pull-left sucuriscan-integrity-left">
|
5 |
+
<h2 class="sucuriscan-title">WordPress Integrity</h2>
|
6 |
|
7 |
+
<p>We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.</p>
|
8 |
</div>
|
9 |
|
10 |
<div class="sucuriscan-pull-right sucuriscan-integrity-right">
|
11 |
+
<h2 class="sucuriscan-subtitle">All Core WordPress Files Are Correct</h2>
|
12 |
|
13 |
+
<p>We have not identified additional files, deleted files, or relevant changes to the core files in your WordPress installation. If you are experiencing other malware issues, please use a <a href="https://sucuri.net/website-security/malware-removal" target="_blank" rel="noopener">Server Side Scanner</a>.</p>
|
14 |
|
15 |
+
<p><a href="%%SUCURI.URL.Settings%%#scanner">Review False Positives</a></p>
|
16 |
</div>
|
17 |
</div>
|
18 |
|
inc/tpl/integrity-diff-utility.html.tpl
CHANGED
@@ -2,10 +2,12 @@
|
|
2 |
<div class="sucuriscan-integrity-diff-utility">
|
3 |
%%%SUCURI.DiffUtility.Modal%%%
|
4 |
|
|
|
|
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase: false */
|
8 |
-
jQuery(function ($) {
|
9 |
$('.sucuriscan-integrity-table th .sucuriscan-tooltip').removeClass('sucuriscan-hidden');
|
10 |
|
11 |
$('.sucuriscan-integrity-table .sucuriscan-integrity-filepath').on('click', function (event) {
|
@@ -23,7 +25,13 @@
|
|
23 |
filepath: filepath,
|
24 |
}, function (data) {
|
25 |
$('.sucuriscan-diff-utility-modal .sucuriscan-modal-inside').html(data);
|
26 |
-
$('.sucuriscan-diff-content').before('<p
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
});
|
28 |
});
|
29 |
});
|
2 |
<div class="sucuriscan-integrity-diff-utility">
|
3 |
%%%SUCURI.DiffUtility.Modal%%%
|
4 |
|
5 |
+
<style type="text/css">.sucuriscan-integrity-filepath {cursor: pointer}</style>
|
6 |
+
|
7 |
<script type="text/javascript">
|
8 |
/* global jQuery */
|
9 |
/* jshint camelcase: false */
|
10 |
+
jQuery(document).ready(function ($) {
|
11 |
$('.sucuriscan-integrity-table th .sucuriscan-tooltip').removeClass('sucuriscan-hidden');
|
12 |
|
13 |
$('.sucuriscan-integrity-table .sucuriscan-integrity-filepath').on('click', function (event) {
|
25 |
filepath: filepath,
|
26 |
}, function (data) {
|
27 |
$('.sucuriscan-diff-utility-modal .sucuriscan-modal-inside').html(data);
|
28 |
+
$('.sucuriscan-diff-content').before('<p>Lines with a <b>minus' +
|
29 |
+
'</b> sign as the prefix <em>(here in red)</em> show the origi' +
|
30 |
+
'nal code. Lines with a <b>plus</b> sign as the prefix <em>(he' +
|
31 |
+
're in green)</em> show the modified code. You can read more a' +
|
32 |
+
'bout the DIFF format from the WikiPedia article about the <a ' +
|
33 |
+
'target="_blank" href="https://en.wikipedia.org/wiki/Diff_util' +
|
34 |
+
'ity" rel="noopener">Unix Diff Utility</a>.</p>');
|
35 |
});
|
36 |
});
|
37 |
});
|
inc/tpl/integrity-incorrect.html.tpl
CHANGED
@@ -2,17 +2,17 @@
|
|
2 |
<div class="sucuriscan-panel sucuriscan-integrity sucuriscan-integrity-incorrect">
|
3 |
<div class="sucuriscan-clearfix">
|
4 |
<div class="sucuriscan-pull-left sucuriscan-integrity-left">
|
5 |
-
<h2 class="sucuriscan-title"
|
6 |
|
7 |
-
<p
|
8 |
</div>
|
9 |
|
10 |
<div class="sucuriscan-pull-right sucuriscan-integrity-right">
|
11 |
-
<h2 class="sucuriscan-subtitle"
|
12 |
|
13 |
-
<p
|
14 |
|
15 |
-
<p><a href="%%SUCURI.URL.Settings%%#scanner"
|
16 |
</div>
|
17 |
</div>
|
18 |
|
@@ -27,9 +27,9 @@
|
|
27 |
<thead>
|
28 |
<tr>
|
29 |
<th colspan="5">
|
30 |
-
<span
|
31 |
|
32 |
-
<span class="sucuriscan-tooltip sucuriscan-hidden" content="
|
33 |
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14">
|
34 |
<path fill="#000000" d="m6.998315,0.033333c-3.846307,0 -6.964982,
|
35 |
3.118675 -6.964982,6.964982s3.118675,6.965574 6.964982,6.965574s6.965574,
|
@@ -71,9 +71,9 @@
|
|
71 |
<input id="cb-select-all-1" type="checkbox">
|
72 |
</td>
|
73 |
<th width="20" class="manage-column"> </th>
|
74 |
-
<th width="100" class="manage-column"
|
75 |
-
<th width="200" class="manage-column"
|
76 |
-
<th class="manage-column"
|
77 |
</tr>
|
78 |
</thead>
|
79 |
|
@@ -86,22 +86,22 @@
|
|
86 |
<label>
|
87 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
88 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
89 |
-
<span
|
90 |
</label>
|
91 |
</p>
|
92 |
|
93 |
<fieldset class="sucuriscan-clearfix">
|
94 |
-
<label
|
95 |
|
96 |
<select name="sucuriscan_integrity_action">
|
97 |
-
<option value="fixed"
|
98 |
-
<option value="restore"
|
99 |
-
<option value="delete"
|
100 |
</select>
|
101 |
|
102 |
-
<button type="submit" class="button button-primary"
|
103 |
|
104 |
-
<span class="sucuriscan-tooltip" content="
|
105 |
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14">
|
106 |
<path fill="#000000" d="m6.998315,0.033333c-3.846307,0 -6.964982,
|
107 |
3.118675 -6.964982,6.964982s3.118675,6.965574 6.964982,6.965574s6.965574,
|
2 |
<div class="sucuriscan-panel sucuriscan-integrity sucuriscan-integrity-incorrect">
|
3 |
<div class="sucuriscan-clearfix">
|
4 |
<div class="sucuriscan-pull-left sucuriscan-integrity-left">
|
5 |
+
<h2 class="sucuriscan-title">WordPress Integrity</h2>
|
6 |
|
7 |
+
<p>We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.</p>
|
8 |
</div>
|
9 |
|
10 |
<div class="sucuriscan-pull-right sucuriscan-integrity-right">
|
11 |
+
<h2 class="sucuriscan-subtitle">Core WordPress Files Were Modified</h2>
|
12 |
|
13 |
+
<p>We identified that some of your WordPress core files were modified. That might indicate a hack or a broken file on your installation. If you are experiencing other malware issues, please use a <a href="https://sucuri.net/website-security/malware-removal" target="_blank" rel="noopener">Server Side Scanner</a>.</p>
|
14 |
|
15 |
+
<p><a href="%%SUCURI.URL.Settings%%#scanner">Review False Positives</a></p>
|
16 |
</div>
|
17 |
</div>
|
18 |
|
27 |
<thead>
|
28 |
<tr>
|
29 |
<th colspan="5">
|
30 |
+
<span>WordPress Integrity (%%SUCURI.Integrity.ListCount%%)</span>
|
31 |
|
32 |
+
<span class="sucuriscan-tooltip sucuriscan-hidden" content="The Unix Diff Utility is enabled. You can click the files in the table to see the differences detected by the scanner. If you consider the differences to be harmless you can mark the file as fixed, otherwise it is adviced to restore the original content immediately.">
|
33 |
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14">
|
34 |
<path fill="#000000" d="m6.998315,0.033333c-3.846307,0 -6.964982,
|
35 |
3.118675 -6.964982,6.964982s3.118675,6.965574 6.964982,6.965574s6.965574,
|
71 |
<input id="cb-select-all-1" type="checkbox">
|
72 |
</td>
|
73 |
<th width="20" class="manage-column"> </th>
|
74 |
+
<th width="100" class="manage-column">File Size</th>
|
75 |
+
<th width="200" class="manage-column">Modified At</th>
|
76 |
+
<th class="manage-column">File Path</th>
|
77 |
</tr>
|
78 |
</thead>
|
79 |
|
86 |
<label>
|
87 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
88 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
89 |
+
<span>I understand that this operation can not be reverted.</span>
|
90 |
</label>
|
91 |
</p>
|
92 |
|
93 |
<fieldset class="sucuriscan-clearfix">
|
94 |
+
<label>Action:</label>
|
95 |
|
96 |
<select name="sucuriscan_integrity_action">
|
97 |
+
<option value="fixed">Mark as Fixed</option>
|
98 |
+
<option value="restore">Restore File</option>
|
99 |
+
<option value="delete">Delete File</option>
|
100 |
</select>
|
101 |
|
102 |
+
<button type="submit" class="button button-primary">Submit</button>
|
103 |
|
104 |
+
<span class="sucuriscan-tooltip" content="Marking one or more files as fixed will force the plugin to ignore them during the next scan, very useful when you find false positives. Additionally you can restore the original content of the core files that appear as modified or deleted, this will tell the plugin to download a copy of the original files from the official WordPress repository. Deleting a file is an irreversible action, be careful.">
|
105 |
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14">
|
106 |
<path fill="#000000" d="m6.998315,0.033333c-3.846307,0 -6.964982,
|
107 |
3.118675 -6.964982,6.964982s3.118675,6.965574 6.964982,6.965574s6.965574,
|
inc/tpl/integrity-notification.html.tpl
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
|
2 |
-
<p
|
3 |
|
4 |
<table border="1" cellspacing="1" cellpadding="5">
|
5 |
<thead>
|
6 |
<tr>
|
7 |
-
<th colspan="5"
|
8 |
</tr>
|
9 |
|
10 |
<tr>
|
11 |
<th> </th>
|
12 |
-
<th width="80"
|
13 |
-
<th width="100"
|
14 |
-
<th width="170"
|
15 |
-
<th
|
16 |
</tr>
|
17 |
</thead>
|
18 |
|
@@ -23,7 +23,7 @@
|
|
23 |
<tfoot>
|
24 |
<tr>
|
25 |
<td colspan="5">
|
26 |
-
<p
|
27 |
</td>
|
28 |
</tr>
|
29 |
</tfoot>
|
1 |
|
2 |
+
<p>We identified that some of your WordPress core files were modified. That might indicate a hack or a broken file on your installation. If you are experiencing other malware issues, please use a <a href="https://sucuri.net/website-security/malware-removal" target="_blank" rel="noopener">Server Side Scanner</a>.</p>
|
3 |
|
4 |
<table border="1" cellspacing="1" cellpadding="5">
|
5 |
<thead>
|
6 |
<tr>
|
7 |
+
<th colspan="5">WordPress Integrity (%%SUCURI.Integrity.ListCount%%)</th>
|
8 |
</tr>
|
9 |
|
10 |
<tr>
|
11 |
<th> </th>
|
12 |
+
<th width="80">Status</th>
|
13 |
+
<th width="100">File Size</th>
|
14 |
+
<th width="170">Modified At</th>
|
15 |
+
<th>File Path</th>
|
16 |
</tr>
|
17 |
</thead>
|
18 |
|
23 |
<tfoot>
|
24 |
<tr>
|
25 |
<td colspan="5">
|
26 |
+
<p>Marking one or more files as fixed will force the plugin to ignore them during the next scan, very useful when you find false positives. Additionally you can restore the original content of the core files that appear as modified or deleted, this will tell the plugin to download a copy of the original files from the official WordPress repository. Deleting a file is an irreversible action, be careful.</p>
|
27 |
</td>
|
28 |
</tr>
|
29 |
</tfoot>
|
inc/tpl/integrity.html.tpl
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<script type="text/javascript">
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase: false */
|
5 |
-
jQuery(function ($) {
|
6 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
7 |
action: 'sucuriscan_ajax',
|
8 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
@@ -19,9 +19,9 @@ jQuery(function ($) {
|
|
19 |
<div class="sucuriscan-panel sucuriscan-integrity sucuriscan-integrity-loading">
|
20 |
<div class="sucuriscan-clearfix">
|
21 |
<div class="sucuriscan-pull-left sucuriscan-integrity-left">
|
22 |
-
<h2 class="sucuriscan-title"
|
23 |
|
24 |
-
<p
|
25 |
</div>
|
26 |
|
27 |
<div class="sucuriscan-pull-right sucuriscan-integrity-right">
|
@@ -31,6 +31,6 @@ jQuery(function ($) {
|
|
31 |
</div>
|
32 |
</div>
|
33 |
|
34 |
-
<p
|
35 |
</div>
|
36 |
</div>
|
2 |
<script type="text/javascript">
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase: false */
|
5 |
+
jQuery(document).ready(function ($) {
|
6 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
7 |
action: 'sucuriscan_ajax',
|
8 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
19 |
<div class="sucuriscan-panel sucuriscan-integrity sucuriscan-integrity-loading">
|
20 |
<div class="sucuriscan-clearfix">
|
21 |
<div class="sucuriscan-pull-left sucuriscan-integrity-left">
|
22 |
+
<h2 class="sucuriscan-title">WordPress Integrity</h2>
|
23 |
|
24 |
+
<p>We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.</p>
|
25 |
</div>
|
26 |
|
27 |
<div class="sucuriscan-pull-right sucuriscan-integrity-right">
|
31 |
</div>
|
32 |
</div>
|
33 |
|
34 |
+
<p>Loading...</p>
|
35 |
</div>
|
36 |
</div>
|
inc/tpl/lastlogins-admins.html.tpl
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-adminusers">
|
9 |
<thead>
|
10 |
<tr>
|
11 |
-
<th class="manage-column"
|
12 |
-
<th class="manage-column"
|
13 |
-
<th class="manage-column"
|
14 |
<th class="manage-column"> </th>
|
15 |
</tr>
|
16 |
</thead>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Successful Logins (admins)</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Here you can see a list of all the successful logins of accounts with admin privileges.</p>
|
7 |
|
8 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-adminusers">
|
9 |
<thead>
|
10 |
<tr>
|
11 |
+
<th class="manage-column">Username</th>
|
12 |
+
<th class="manage-column">Registration</th>
|
13 |
+
<th class="manage-column">Newest To Oldest</th>
|
14 |
<th class="manage-column"> </th>
|
15 |
</tr>
|
16 |
</thead>
|
inc/tpl/lastlogins-admins.snippet.tpl
CHANGED
@@ -6,14 +6,14 @@
|
|
6 |
|
7 |
<td class="adminusers-lastlogin">
|
8 |
<div class="sucuriscan-%%SUCURI.AdminUsers.NoLastLogins%%">
|
9 |
-
<em
|
10 |
</div>
|
11 |
|
12 |
<table class="widefat sucuriscan-admins-lastlogins sucuriscan-%%SUCURI.AdminUsers.NoLastLoginsTable%%">
|
13 |
<thead>
|
14 |
<tr>
|
15 |
-
<th
|
16 |
-
<th
|
17 |
</tr>
|
18 |
</thead>
|
19 |
|
@@ -24,6 +24,6 @@
|
|
24 |
</td>
|
25 |
|
26 |
<td>
|
27 |
-
<a href="%%SUCURI.AdminUsers.UserURL%%" target="_blank" class="button button-primary"
|
28 |
</td>
|
29 |
</tr>
|
6 |
|
7 |
<td class="adminusers-lastlogin">
|
8 |
<div class="sucuriscan-%%SUCURI.AdminUsers.NoLastLogins%%">
|
9 |
+
<em>no data available</em>
|
10 |
</div>
|
11 |
|
12 |
<table class="widefat sucuriscan-admins-lastlogins sucuriscan-%%SUCURI.AdminUsers.NoLastLoginsTable%%">
|
13 |
<thead>
|
14 |
<tr>
|
15 |
+
<th>IP Address</th>
|
16 |
+
<th>Date/Time</th>
|
17 |
</tr>
|
18 |
</thead>
|
19 |
|
24 |
</td>
|
25 |
|
26 |
<td>
|
27 |
+
<a href="%%SUCURI.AdminUsers.UserURL%%" target="_blank" class="button button-primary" rel="noopener">Edit</a>
|
28 |
</td>
|
29 |
</tr>
|
inc/tpl/lastlogins-all.html.tpl
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-last-logins">
|
9 |
<thead>
|
10 |
<tr>
|
11 |
-
<th colspan="5"
|
12 |
</tr>
|
13 |
|
14 |
<tr>
|
15 |
-
<th class="manage-column"
|
16 |
-
<th class="manage-column"
|
17 |
-
<th class="manage-column"
|
18 |
-
<th class="manage-column"
|
19 |
<th class="manage-column"> </th>
|
20 |
</tr>
|
21 |
</thead>
|
@@ -25,7 +25,7 @@
|
|
25 |
|
26 |
<tr class="sucuriscan-%%SUCURI.UserList.NoItemsVisibility%%">
|
27 |
<td colspan="5">
|
28 |
-
<em
|
29 |
</td>
|
30 |
</tr>
|
31 |
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Successful Logins (all)</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Here you can see a list of all the successful user logins.</p>
|
7 |
|
8 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-last-logins">
|
9 |
<thead>
|
10 |
<tr>
|
11 |
+
<th colspan="5">Successful Logins (all)</th>
|
12 |
</tr>
|
13 |
|
14 |
<tr>
|
15 |
+
<th class="manage-column">Username</th>
|
16 |
+
<th class="manage-column">IP Address</th>
|
17 |
+
<th class="manage-column">Hostname</th>
|
18 |
+
<th class="manage-column">Date/Time</th>
|
19 |
<th class="manage-column"> </th>
|
20 |
</tr>
|
21 |
</thead>
|
25 |
|
26 |
<tr class="sucuriscan-%%SUCURI.UserList.NoItemsVisibility%%">
|
27 |
<td colspan="5">
|
28 |
+
<em>no data available</em>
|
29 |
</td>
|
30 |
</tr>
|
31 |
|
inc/tpl/lastlogins-all.snippet.tpl
CHANGED
@@ -8,5 +8,5 @@
|
|
8 |
|
9 |
<td><span title="%%SUCURI.UserList.Datetime%%">%%SUCURI.UserList.TimeAgo%%</span></td>
|
10 |
|
11 |
-
<td><a href="%%SUCURI.UserList.UserURL%%" target="_blank"
|
12 |
</tr>
|
8 |
|
9 |
<td><span title="%%SUCURI.UserList.Datetime%%">%%SUCURI.UserList.TimeAgo%%</span></td>
|
10 |
|
11 |
+
<td><a href="%%SUCURI.UserList.UserURL%%" target="_blank" rel="noopener">Edit</a></td>
|
12 |
</tr>
|
inc/tpl/lastlogins-blockedusers.html.tpl
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-info">
|
9 |
-
<p
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-inline-alert-error">
|
13 |
-
<p
|
14 |
</div>
|
15 |
|
16 |
<form action="%%SUCURI.URL.Lastlogins%%#blocked" method="post">
|
@@ -23,10 +23,10 @@
|
|
23 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
24 |
<input id="cb-select-all-1" type="checkbox">
|
25 |
</td>
|
26 |
-
<th class="manage-column"
|
27 |
-
<th class="manage-column"
|
28 |
-
<th class="manage-column"
|
29 |
-
<th class="manage-column"
|
30 |
</tr>
|
31 |
</thead>
|
32 |
|
@@ -35,13 +35,13 @@
|
|
35 |
|
36 |
<tr class="sucuriscan-%%SUCURI.BlockedUsers.NoItemsVisibility%%">
|
37 |
<td colspan="5">
|
38 |
-
<em
|
39 |
</td>
|
40 |
</tr>
|
41 |
</tbody>
|
42 |
</table>
|
43 |
|
44 |
-
<button type="submit" class="button button-primary"
|
45 |
</form>
|
46 |
</div>
|
47 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Blocked Users</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Any attempt to authenticate an user account using the functions provided by WordPress will be intercepted and analyzed by the plugin, if the username coincides with any of the users in this list, the authentication process will be immediately stopped. These attemps will not be logged and no email alerts will be sent.</p>
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-info">
|
9 |
+
<p>Take in consideration that this is not a 100% bulletproof mechanism to block unwanted user authentications from malicious users. Depending on the configuration of your website, installed plugins, installed themes, and even the version of WordPress there might still be weak points that automated tools can take advantage of to brute force the user accounts registered in your website. <a target="_blank" href="https://sucuri.net/website-firewall/?wp=bu" rel="noopener">Install a firewall</a> to have full protection and mitigate this and a myriad of other attacks.</p>
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-inline-alert-error">
|
13 |
+
<p>Blocking users per IP address is a feature provided by the <a href="https://sucuri.net/website-firewall/" target="_blank" rel="noopener">Sucuri Firewall</a>; to avoid the duplication of code and reduce the amount of false positives this feature will never be implemented in this plugin.</p>
|
14 |
</div>
|
15 |
|
16 |
<form action="%%SUCURI.URL.Lastlogins%%#blocked" method="post">
|
23 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
24 |
<input id="cb-select-all-1" type="checkbox">
|
25 |
</td>
|
26 |
+
<th class="manage-column">Username</th>
|
27 |
+
<th class="manage-column">Blocked At</th>
|
28 |
+
<th class="manage-column">First Attempt</th>
|
29 |
+
<th class="manage-column">Last Attempt</th>
|
30 |
</tr>
|
31 |
</thead>
|
32 |
|
35 |
|
36 |
<tr class="sucuriscan-%%SUCURI.BlockedUsers.NoItemsVisibility%%">
|
37 |
<td colspan="5">
|
38 |
+
<em>no data available</em>
|
39 |
</td>
|
40 |
</tr>
|
41 |
</tbody>
|
42 |
</table>
|
43 |
|
44 |
+
<button type="submit" class="button button-primary">Unblock</button>
|
45 |
</form>
|
46 |
</div>
|
47 |
</div>
|
inc/tpl/lastlogins-failedlogins.html.tpl
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Lastlogins%%#blocked" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -15,11 +15,11 @@
|
|
15 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
16 |
<input id="cb-select-all-1" type="checkbox">
|
17 |
</td>
|
18 |
-
<th class="manage-column"
|
19 |
-
<th class="manage-column"
|
20 |
-
<th class="manage-column"
|
21 |
-
<th class="manage-column"
|
22 |
-
<th class="manage-column" width="300"
|
23 |
</tr>
|
24 |
</thead>
|
25 |
|
@@ -28,7 +28,7 @@
|
|
28 |
|
29 |
<tr class="sucuriscan-%%SUCURI.FailedLogins.NoItemsVisibility%%">
|
30 |
<td colspan="6">
|
31 |
-
<em
|
32 |
</td>
|
33 |
</tr>
|
34 |
|
@@ -42,7 +42,7 @@
|
|
42 |
</tbody>
|
43 |
</table>
|
44 |
|
45 |
-
<button type="submit" class="button button-primary"
|
46 |
</form>
|
47 |
</div>
|
48 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Failed logins</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>This information will be used to determine if your site is being victim of <a href="https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing" target="_blank" rel="noopener">Password Guessing Brute Force Attacks</a>. These logs will be accumulated and the plugin will send a report via email if there are more than <code>%%SUCURI.FailedLogins.MaxFailedLogins%%</code> failed login attempts during the same hour, you can change this number from <a href="%%SUCURI.URL.Settings%%#alerts">here</a>. <b>NOTE:</b> Some <em>"Two-Factor Authentication"</em> plugins do not follow the same rules that WordPress have to report failed login attempts, so you may not see all the attempts in this panel if you have one of these plugins installed.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Lastlogins%%#blocked" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
15 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
16 |
<input id="cb-select-all-1" type="checkbox">
|
17 |
</td>
|
18 |
+
<th class="manage-column">Username</th>
|
19 |
+
<th class="manage-column">Password</th>
|
20 |
+
<th class="manage-column">IP Address</th>
|
21 |
+
<th class="manage-column">Date/Time</th>
|
22 |
+
<th class="manage-column" width="300">Web Browser</th>
|
23 |
</tr>
|
24 |
</thead>
|
25 |
|
28 |
|
29 |
<tr class="sucuriscan-%%SUCURI.FailedLogins.NoItemsVisibility%%">
|
30 |
<td colspan="6">
|
31 |
+
<em>no data available</em>
|
32 |
</td>
|
33 |
</tr>
|
34 |
|
42 |
</tbody>
|
43 |
</table>
|
44 |
|
45 |
+
<button type="submit" class="button button-primary">Block</button>
|
46 |
</form>
|
47 |
</div>
|
48 |
</div>
|
inc/tpl/lastlogins-loggedin.html.tpl
CHANGED
@@ -1,22 +1,22 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<table class="wp-list-table widefat sucuriscan-loggedin-users">
|
9 |
<thead>
|
10 |
<tr>
|
11 |
-
<th colspan="6"
|
12 |
</tr>
|
13 |
|
14 |
<tr>
|
15 |
<th>ID</th>
|
16 |
-
<th
|
17 |
-
<th
|
18 |
-
<th
|
19 |
-
<th
|
20 |
<th> </th>
|
21 |
</tr>
|
22 |
</thead>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Logged-in Users</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Here you can see a list of the users that are currently logged-in.</p>
|
7 |
|
8 |
<table class="wp-list-table widefat sucuriscan-loggedin-users">
|
9 |
<thead>
|
10 |
<tr>
|
11 |
+
<th colspan="6">Logged-in Users</th>
|
12 |
</tr>
|
13 |
|
14 |
<tr>
|
15 |
<th>ID</th>
|
16 |
+
<th>Username</th>
|
17 |
+
<th>Last Activity</th>
|
18 |
+
<th>Registered</th>
|
19 |
+
<th>IP Address</th>
|
20 |
<th> </th>
|
21 |
</tr>
|
22 |
</thead>
|
inc/tpl/lastlogins-loggedin.snippet.tpl
CHANGED
@@ -10,5 +10,5 @@
|
|
10 |
|
11 |
<td class="sucuriscan-monospace">%%SUCURI.LoggedInUsers.RemoteAddr%%</td>
|
12 |
|
13 |
-
<td><a href="%%SUCURI.LoggedInUsers.UserURL%%" target="_blank"
|
14 |
</tr>
|
10 |
|
11 |
<td class="sucuriscan-monospace">%%SUCURI.LoggedInUsers.RemoteAddr%%</td>
|
12 |
|
13 |
+
<td><a href="%%SUCURI.LoggedInUsers.UserURL%%" target="_blank">Edit</a></td>
|
14 |
</tr>
|
inc/tpl/lastlogins.html.tpl
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
-
<li><a href="%%SUCURI.URL.Lastlogins%%#allusers"
|
5 |
-
<li><a href="%%SUCURI.URL.Lastlogins%%#admins"
|
6 |
-
<li><a href="%%SUCURI.URL.Lastlogins%%#loggedin"
|
7 |
-
<li><a href="%%SUCURI.URL.Lastlogins%%#failed"
|
8 |
-
<li><a href="%%SUCURI.URL.Lastlogins%%#blocked"
|
9 |
</ul>
|
10 |
|
11 |
<div class="sucuriscan-tabs-containers">
|
1 |
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
+
<li><a href="%%SUCURI.URL.Lastlogins%%#allusers">All Users</a></li>
|
5 |
+
<li><a href="%%SUCURI.URL.Lastlogins%%#admins">Admins</a></li>
|
6 |
+
<li><a href="%%SUCURI.URL.Lastlogins%%#loggedin">Logged-in Users</a></li>
|
7 |
+
<li><a href="%%SUCURI.URL.Lastlogins%%#failed">Failed logins</a></li>
|
8 |
+
<li><a href="%%SUCURI.URL.Lastlogins%%#blocked">Blocked Users</a></li>
|
9 |
</ul>
|
10 |
|
11 |
<div class="sucuriscan-tabs-containers">
|
inc/tpl/notification-pretty.html.tpl
CHANGED
@@ -14,14 +14,14 @@
|
|
14 |
<tbody>
|
15 |
<tr>
|
16 |
<td style="padding:20px 20px 10px 20px;border:1px solid #ccc;border-top:none">
|
17 |
-
<h4 style="text-transform:uppercase;margin:0"
|
18 |
<p style="margin:0 0 10px 0">
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
%%SUCURI.User%%
|
23 |
</p>
|
24 |
-
<h4 style="text-transform:uppercase;margin:0"
|
25 |
<p style="margin:0 0 10px 0">%%%SUCURI.Message%%%</p>
|
26 |
</td>
|
27 |
</tr>
|
14 |
<tbody>
|
15 |
<tr>
|
16 |
<td style="padding:20px 20px 10px 20px;border:1px solid #ccc;border-top:none">
|
17 |
+
<h4 style="text-transform:uppercase;margin:0">Information:</h4>
|
18 |
<p style="margin:0 0 10px 0">
|
19 |
+
Website: <a href="http://%%SUCURI.Website%%">%%SUCURI.Website%%</a><br>
|
20 |
+
IP Address: %%SUCURI.RemoteAddress%%<br>
|
21 |
+
Date/Time: %%SUCURI.Time%%<br>
|
22 |
%%SUCURI.User%%
|
23 |
</p>
|
24 |
+
<h4 style="text-transform:uppercase;margin:0">Message:</h4>
|
25 |
<p style="margin:0 0 10px 0">%%%SUCURI.Message%%%</p>
|
26 |
</td>
|
27 |
</tr>
|
inc/tpl/notification-simple.html.tpl
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
%%SUCURI.User%%
|
7 |
|
8 |
-
|
1 |
|
2 |
+
Event: %%SUCURI.Subject%%
|
3 |
+
Website: http://%%SUCURI.Website%%
|
4 |
+
IP Address: %%SUCURI.RemoteAddress%%
|
5 |
+
Date/Time: %%SUCURI.Time%%
|
6 |
%%SUCURI.User%%
|
7 |
|
8 |
+
Message: %%SUCURI.Message%%
|
inc/tpl/register-site.html.tpl
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
|
2 |
-
<p
|
3 |
|
4 |
<div class="sucuriscan-inline-alert-info">
|
5 |
-
<p
|
6 |
</div>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
@@ -10,27 +10,27 @@
|
|
10 |
<input type="hidden" name="sucuriscan_plugin_api_key" value="1" />
|
11 |
|
12 |
<fieldset class="sucuriscan-clearfix">
|
13 |
-
<label
|
14 |
<input type="text" value="%%SUCURI.CleanDomain%%" readonly="readonly">
|
15 |
</fieldset>
|
16 |
|
17 |
<fieldset class="sucuriscan-clearfix">
|
18 |
-
<label
|
19 |
<select name="sucuriscan_setup_user">
|
20 |
%%%SUCURI.AdminEmails%%%
|
21 |
</select>
|
22 |
</fieldset>
|
23 |
|
24 |
<fieldset class="sucuriscan-clearfix">
|
25 |
-
<label
|
26 |
<input type="hidden" name="sucuriscan_dns_lookups" value="disable" />
|
27 |
<input type="checkbox" name="sucuriscan_dns_lookups" value="enable" checked="checked" />
|
28 |
-
<span class="sucuriscan-tooltip" content="
|
29 |
</fieldset>
|
30 |
|
31 |
<div class="sucuriscan-clearfix">
|
32 |
<div class="sucuriscan-pull-left">
|
33 |
-
<button type="submit" class="button button-primary"
|
34 |
</div>
|
35 |
</div>
|
36 |
</form>
|
1 |
|
2 |
+
<p>An API key is required to activate some additional tools available in this plugin. The keys are free and you can virtually generate an unlimited number of them as long as the domain name and email address are unique. The key is used to authenticate the HTTP requests sent by the plugin to a public API service managed by Sucuri Inc. Do not generate the key if you disagree with this.</p>
|
3 |
|
4 |
<div class="sucuriscan-inline-alert-info">
|
5 |
+
<p>If you experience issues generating the API key you can request one sending the domain name and email address that you want to use to <a href="mailto:info@sucuri.net">info@sucuri.net</a>. Note generating a key for a website that is not facing the Internet is not possible because the API service needs to validate that the domain name exists, however, if you want to test the plugin in a development environment please contact us so we can generate the key manually.</p>
|
6 |
</div>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
10 |
<input type="hidden" name="sucuriscan_plugin_api_key" value="1" />
|
11 |
|
12 |
<fieldset class="sucuriscan-clearfix">
|
13 |
+
<label>Website:</label>
|
14 |
<input type="text" value="%%SUCURI.CleanDomain%%" readonly="readonly">
|
15 |
</fieldset>
|
16 |
|
17 |
<fieldset class="sucuriscan-clearfix">
|
18 |
+
<label>E-mail:</label>
|
19 |
<select name="sucuriscan_setup_user">
|
20 |
%%%SUCURI.AdminEmails%%%
|
21 |
</select>
|
22 |
</fieldset>
|
23 |
|
24 |
<fieldset class="sucuriscan-clearfix">
|
25 |
+
<label>DNS Lookups</label>
|
26 |
<input type="hidden" name="sucuriscan_dns_lookups" value="disable" />
|
27 |
<input type="checkbox" name="sucuriscan_dns_lookups" value="enable" checked="checked" />
|
28 |
+
<span class="sucuriscan-tooltip" content="Check the box if your website is behind a known firewall service, this guarantees that the IP address of your visitors will be detected correctly for the security logs. You can change this later from the settings.">Enable DNS Lookups On Startup</span>
|
29 |
</fieldset>
|
30 |
|
31 |
<div class="sucuriscan-clearfix">
|
32 |
<div class="sucuriscan-pull-left">
|
33 |
+
<button type="submit" class="button button-primary">Submit</button>
|
34 |
</div>
|
35 |
</div>
|
36 |
</form>
|
inc/tpl/settings-alerts-bruteforce.html.tpl
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
-
<label
|
12 |
<select name="sucuriscan_maximum_failed_logins">
|
13 |
%%%SUCURI.Alerts.BruteForce%%%
|
14 |
</select>
|
15 |
-
<button type="submit" class="button button-primary"
|
16 |
</fieldset>
|
17 |
</form>
|
18 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Password Guessing Brute Force Attacks</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p><a href="https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing" target="_blank" rel="noopener">Password guessing brute force attacks</a> are very common against web sites and web servers. They are one of the most common vectors used to compromise web sites. The process is very simple and the attackers basically try multiple combinations of usernames and passwords until they find one that works. Once they get in, they can compromise the web site with malware, spam , phishing or anything else they want.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
+
<label>Consider Brute-Force Attack After:</label>
|
12 |
<select name="sucuriscan_maximum_failed_logins">
|
13 |
%%%SUCURI.Alerts.BruteForce%%%
|
14 |
</select>
|
15 |
+
<button type="submit" class="button button-primary">Submit</button>
|
16 |
</fieldset>
|
17 |
</form>
|
18 |
</div>
|
inc/tpl/settings-alerts-events.html.tpl
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.Alerts.NoAlertsVisibility%%">
|
7 |
-
<p
|
8 |
</div>
|
9 |
|
10 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
@@ -17,7 +17,7 @@
|
|
17 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
18 |
<input id="cb-select-all-1" type="checkbox">
|
19 |
</td>
|
20 |
-
<th class="manage-column"
|
21 |
</tr>
|
22 |
</thead>
|
23 |
|
@@ -27,7 +27,7 @@
|
|
27 |
</table>
|
28 |
|
29 |
<div class="sucuriscan-recipient-form">
|
30 |
-
<button type="submit" name="sucuriscan_save_alert_events" class="button button-primary"
|
31 |
</div>
|
32 |
</form>
|
33 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Security Alerts</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.Alerts.NoAlertsVisibility%%">
|
7 |
+
<p>You have installed a plugin or theme that is not fully compatible with our plugin, some of the security alerts (like the successful and failed logins) will not be sent to you. To prevent an infinite loop while detecting these changes in the website and sending the email alerts via a custom SMTP plugin, we have decided to stop any attempt to send the emails to prevent fatal errors.</p>
|
8 |
</div>
|
9 |
|
10 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
17 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
18 |
<input id="cb-select-all-1" type="checkbox">
|
19 |
</td>
|
20 |
+
<th class="manage-column">Event</th>
|
21 |
</tr>
|
22 |
</thead>
|
23 |
|
27 |
</table>
|
28 |
|
29 |
<div class="sucuriscan-recipient-form">
|
30 |
+
<button type="submit" name="sucuriscan_save_alert_events" class="button button-primary">Submit</button>
|
31 |
</div>
|
32 |
</form>
|
33 |
</div>
|
inc/tpl/settings-alerts-ignore-posts.html.tpl
CHANGED
@@ -1,42 +1,50 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.
|
7 |
-
<p
|
8 |
</div>
|
9 |
|
10 |
-
<p
|
11 |
-
|
12 |
-
<p>@@SUCURI.PostTypeAlertsInvisible@@</p>
|
13 |
|
14 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
15 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
16 |
<input type="hidden" name="sucuriscan_ignorerule_action" value="add">
|
17 |
|
18 |
<fieldset class="sucuriscan-clearfix">
|
19 |
-
<label
|
20 |
<input type="text" name="sucuriscan_ignorerule" placeholder="e.g. unique_post_type_id" />
|
21 |
-
<button type="submit" class="button button-primary"
|
22 |
</fieldset>
|
23 |
</form>
|
24 |
|
25 |
<hr>
|
26 |
|
27 |
-
<
|
28 |
-
<
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
<
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
</div>
|
42 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Post-Type Alerts</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.PostTypes.ErrorVisibility%%">
|
7 |
+
<p>It seems that you disabled the email alerts for <b>new site content</b>, this panel is intended to provide a way to ignore specific events in your site and with that the alerts reported to your email. Since you have deactivated the <b>new site content</b> alerts, this panel will be disabled too.</p>
|
8 |
</div>
|
9 |
|
10 |
+
<p>This is a list of registered <a href="https://codex.wordpress.org/Post_Types" target="_blank" rel="noopener">Post Types</a>. You will receive an email alert when a custom page or post associated to any of these types is created or updated. If you don't want to receive one or more of these alerts, feel free to uncheck the boxes in the table below. If you are receiving alerts for post types that are not listed in this table, it may be because there is an add-on that that is generating a custom post-type on runtime, you will have to find out by yourself what is the unique ID of that post-type and type it in the form below. The plugin will do its best to ignore these alerts as long as the unique ID is valid.</p>
|
|
|
|
|
11 |
|
12 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
13 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
14 |
<input type="hidden" name="sucuriscan_ignorerule_action" value="add">
|
15 |
|
16 |
<fieldset class="sucuriscan-clearfix">
|
17 |
+
<label>Stop Alerts For This Post-Type:</label>
|
18 |
<input type="text" name="sucuriscan_ignorerule" placeholder="e.g. unique_post_type_id" />
|
19 |
+
<button type="submit" class="button button-primary">Submit</button>
|
20 |
</fieldset>
|
21 |
</form>
|
22 |
|
23 |
<hr>
|
24 |
|
25 |
+
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
26 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
27 |
+
<input type="hidden" name="sucuriscan_ignorerule_action" value="batch" />
|
28 |
+
|
29 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-ignorerules">
|
30 |
+
<thead>
|
31 |
+
<tr>
|
32 |
+
<td id="cb" class="manage-column column-cb check-column">
|
33 |
+
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
34 |
+
<input id="cb-select-all-1" type="checkbox">
|
35 |
+
</td>
|
36 |
+
<th class="manage-column">Post Type</th>
|
37 |
+
<th class="manage-column">Post Type ID</th>
|
38 |
+
<th class="manage-column">Ignored At (optional)</th>
|
39 |
+
</tr>
|
40 |
+
</thead>
|
41 |
+
|
42 |
+
<tbody>
|
43 |
+
%%%SUCURI.PostTypes.List%%%
|
44 |
+
</tbody>
|
45 |
+
</table>
|
46 |
+
|
47 |
+
<button type="submit" class="button button-primary">Submit</button>
|
48 |
+
</form>
|
49 |
</div>
|
50 |
</div>
|
inc/tpl/settings-alerts-ignore-posts.snippet.tpl
CHANGED
@@ -1,17 +1,16 @@
|
|
1 |
|
2 |
<tr>
|
3 |
-
<
|
|
|
|
|
4 |
|
5 |
-
<td
|
6 |
|
7 |
-
<td
|
|
|
|
|
8 |
|
9 |
-
<td
|
10 |
-
<
|
11 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
12 |
-
<input type="hidden" name="sucuriscan_ignorerule" value="%%SUCURI.IgnoreRules.PostType%%" />
|
13 |
-
<input type="hidden" name="sucuriscan_ignorerule_action" value="%%SUCURI.IgnoreRules.Action%%" />
|
14 |
-
<button type="submit" class="button button-secondary">%%SUCURI.IgnoreRules.ButtonText%%</button>
|
15 |
-
</form>
|
16 |
</td>
|
17 |
</tr>
|
1 |
|
2 |
<tr>
|
3 |
+
<th class="check-column">
|
4 |
+
<input type="checkbox" name="sucuriscan_posttypes[]" %%SUCURI.PostTypes.Selected%% value="%%SUCURI.PostTypes.UniqueID%%" />
|
5 |
+
</th>
|
6 |
|
7 |
+
<td>%%SUCURI.PostTypes.Title%%</td>
|
8 |
|
9 |
+
<td>
|
10 |
+
<span class="sucuriscan-monospace">%%SUCURI.PostTypes.UniqueID%%</span>
|
11 |
+
</td>
|
12 |
|
13 |
+
<td>
|
14 |
+
<em class="sucuriscan-monospace">%%SUCURI.PostTypes.IgnoredAt%%</em>
|
|
|
|
|
|
|
|
|
|
|
15 |
</td>
|
16 |
</tr>
|
inc/tpl/settings-alerts-perhour.html.tpl
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
-
<label
|
12 |
<select name="sucuriscan_emails_per_hour">
|
13 |
%%%SUCURI.Alerts.PerHour%%%
|
14 |
</select>
|
15 |
-
<button type="submit" class="button button-primary"
|
16 |
</fieldset>
|
17 |
</form>
|
18 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Alerts Per Hour</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Configure the maximum number of email alerts per hour. If the number is exceeded and the plugin detects more events during the same hour, it will still log the events into the audit logs but will not send the email alerts. Be careful with this as you will miss important information.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
+
<label>Maximum Alerts Per Hour:</label>
|
12 |
<select name="sucuriscan_emails_per_hour">
|
13 |
%%%SUCURI.Alerts.PerHour%%%
|
14 |
</select>
|
15 |
+
<button type="submit" class="button button-primary">Submit</button>
|
16 |
</fieldset>
|
17 |
</form>
|
18 |
</div>
|
inc/tpl/settings-alerts-recipients.html.tpl
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
|
11 |
<fieldset class="sucuriscan-clearfix">
|
12 |
-
<label
|
13 |
<input type="text" name="sucuriscan_recipient" placeholder="e.g. user@example.com" />
|
14 |
-
<button type="submit" name="sucuriscan_save_recipient" class="button button-primary"
|
15 |
</fieldset>
|
16 |
|
17 |
<table class="wp-list-table widefat sucuriscan-table">
|
@@ -21,7 +21,7 @@
|
|
21 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
22 |
<input id="cb-select-all-1" type="checkbox">
|
23 |
</td>
|
24 |
-
<th class="manage-column"
|
25 |
</tr>
|
26 |
</thead>
|
27 |
|
@@ -30,8 +30,8 @@
|
|
30 |
</tbody>
|
31 |
</table>
|
32 |
|
33 |
-
<button type="submit" name="sucuriscan_delete_recipients" class="button button-primary"
|
34 |
-
<button type="submit" name="sucuriscan_debug_email" value="1" class="button button-primary"
|
35 |
</form>
|
36 |
</div>
|
37 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Alerts Recipient</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>By default, the plugin will send the email alerts to the primary admin account, the same account created during the installation of WordPress in your web server. You can add more people to the list, they will receive a copy of the same security alerts.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
|
11 |
<fieldset class="sucuriscan-clearfix">
|
12 |
+
<label>E-mail:</label>
|
13 |
<input type="text" name="sucuriscan_recipient" placeholder="e.g. user@example.com" />
|
14 |
+
<button type="submit" name="sucuriscan_save_recipient" class="button button-primary">Submit</button>
|
15 |
</fieldset>
|
16 |
|
17 |
<table class="wp-list-table widefat sucuriscan-table">
|
21 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
22 |
<input id="cb-select-all-1" type="checkbox">
|
23 |
</td>
|
24 |
+
<th class="manage-column">E-mail</th>
|
25 |
</tr>
|
26 |
</thead>
|
27 |
|
30 |
</tbody>
|
31 |
</table>
|
32 |
|
33 |
+
<button type="submit" name="sucuriscan_delete_recipients" class="button button-primary">Delete</button>
|
34 |
+
<button type="submit" name="sucuriscan_debug_email" value="1" class="button button-primary">Test Alerts</button>
|
35 |
</form>
|
36 |
</div>
|
37 |
</div>
|
inc/tpl/settings-alerts-subject.html.tpl
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -14,14 +14,14 @@
|
|
14 |
<li>
|
15 |
<label>
|
16 |
<input type="radio" name="sucuriscan_email_subject" value="custom" %%SUCURI.Alerts.CustomChecked%% />
|
17 |
-
<span
|
18 |
<input type="text" name="sucuriscan_custom_email_subject" value="%%SUCURI.Alerts.CustomValue%%" />
|
19 |
</label>
|
20 |
</li>
|
21 |
</ul>
|
22 |
|
23 |
<div class="sucuriscan-recipient-form">
|
24 |
-
<button type="submit" class="button button-primary"
|
25 |
</div>
|
26 |
</form>
|
27 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Alert Subject</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Format of the subject for the email alerts, by default the plugin will use the website name and the event identifier that is being reported, you can use this panel to include the IP address of the user that triggered the event and some additional data. You can create filters in your email client creating a custom email subject using the pseudo-tags shown below.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
14 |
<li>
|
15 |
<label>
|
16 |
<input type="radio" name="sucuriscan_email_subject" value="custom" %%SUCURI.Alerts.CustomChecked%% />
|
17 |
+
<span>Custom Format</span>
|
18 |
<input type="text" name="sucuriscan_custom_email_subject" value="%%SUCURI.Alerts.CustomValue%%" />
|
19 |
</label>
|
20 |
</li>
|
21 |
</ul>
|
22 |
|
23 |
<div class="sucuriscan-recipient-form">
|
24 |
+
<button type="submit" class="button button-primary">Submit</button>
|
25 |
</div>
|
26 |
</form>
|
27 |
</div>
|
inc/tpl/settings-alerts-trustedips.html.tpl
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="POST">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
|
11 |
<fieldset class="sucuriscan-clearfix">
|
12 |
-
<label
|
13 |
<input type="text" name="sucuriscan_trust_ip" placeholder="e.g. 182.120.56.0/24" />
|
14 |
-
<input type="submit" value="
|
15 |
</fieldset>
|
16 |
</form>
|
17 |
|
@@ -27,9 +27,9 @@
|
|
27 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
28 |
<input id="cb-select-all-1" type="checkbox">
|
29 |
</td>
|
30 |
-
<th class="manage-column"
|
31 |
-
<th class="manage-column"
|
32 |
-
<th class="manage-column"
|
33 |
</tr>
|
34 |
</thead>
|
35 |
|
@@ -38,13 +38,13 @@
|
|
38 |
|
39 |
<tr class="sucuriscan-%%SUCURI.TrustedIPs.NoItems.Visibility%%">
|
40 |
<td colspan="4">
|
41 |
-
<em
|
42 |
</td>
|
43 |
</tr>
|
44 |
</tbody>
|
45 |
</table>
|
46 |
|
47 |
-
<button type="submit" class="button button-primary"
|
48 |
</form>
|
49 |
</div>
|
50 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Trusted IP Addresses</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>If you are working in a LAN <em>(Local Area Network)</em> you may want to include the IP addresses of all the nodes in the subnet, this will force the plugin to stop sending email alerts about actions executed from trusted IP addresses. Use the CIDR <em>(Classless Inter Domain Routing)</em> format to specify ranges of IP addresses <em>(only 8, 16, and 24)</em>.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="POST">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
|
11 |
<fieldset class="sucuriscan-clearfix">
|
12 |
+
<label>IP Address:</label>
|
13 |
<input type="text" name="sucuriscan_trust_ip" placeholder="e.g. 182.120.56.0/24" />
|
14 |
+
<input type="submit" value="Submit" class="button button-primary" />
|
15 |
</fieldset>
|
16 |
</form>
|
17 |
|
27 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
28 |
<input id="cb-select-all-1" type="checkbox">
|
29 |
</td>
|
30 |
+
<th class="manage-column">IP Address</th>
|
31 |
+
<th class="manage-column">CIDR Format</th>
|
32 |
+
<th class="manage-column">IP Added At</th>
|
33 |
</tr>
|
34 |
</thead>
|
35 |
|
38 |
|
39 |
<tr class="sucuriscan-%%SUCURI.TrustedIPs.NoItems.Visibility%%">
|
40 |
<td colspan="4">
|
41 |
+
<em>no data available</em>
|
42 |
</td>
|
43 |
</tr>
|
44 |
</tbody>
|
45 |
</table>
|
46 |
|
47 |
+
<button type="submit" class="button button-primary">Delete</button>
|
48 |
</form>
|
49 |
</div>
|
50 |
</div>
|
inc/tpl/settings-apirecovery.html.tpl
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
|
2 |
<div class="sucuriscan-clearfix">
|
3 |
-
<p
|
4 |
|
5 |
-
<p
|
6 |
|
7 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
9 |
<fieldset class="sucuriscan-clearfix">
|
10 |
-
<label
|
11 |
<input type="text" name="sucuriscan_manual_api_key" />
|
12 |
-
<button type="submit" class="button button-primary"
|
13 |
</fieldset>
|
14 |
</form>
|
15 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-clearfix">
|
3 |
+
<p>If this operation was successful you will receive a message in the email used during the registration of the API key <em>(usually the email of the main admin user)</em>. This message contains the key in plain text, copy and paste the key in the form field below. The plugin will verify the authenticity of the key sending an initial HTTP request to the API service, if this fails the key will be removed automatically and you will have to start the process all over again.</p>
|
4 |
|
5 |
+
<p>There are cases where this operation may fail, an example would be when the email address is not associated with the domain anymore, this happens when the base URL changes <em>(from www to none or viceversa)</em>. If you are having issues recovering the key please send an email explaining the situation to <a href="mailto:info@sucuri.net">info@sucuri.net</a></p>
|
6 |
|
7 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
9 |
<fieldset class="sucuriscan-clearfix">
|
10 |
+
<label>API Key:</label>
|
11 |
<input type="text" name="sucuriscan_manual_api_key" />
|
12 |
+
<button type="submit" class="button button-primary">Submit</button>
|
13 |
</fieldset>
|
14 |
</form>
|
15 |
</div>
|
inc/tpl/settings-apiregistered.html.tpl
CHANGED
@@ -3,13 +3,13 @@
|
|
3 |
<div class="sucuriscan-pull-left sucuriscan-sitelogo"> </div>
|
4 |
|
5 |
<div class="sucuriscan-pull-right">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-success">
|
9 |
-
<p
|
10 |
</div>
|
11 |
|
12 |
-
<a href="%%SUCURI.URL.Dashboard%%" class="button button-primary"
|
13 |
-
<a href="%%SUCURI.URL.Settings%%" class="button button-primary"
|
14 |
</div>
|
15 |
</div>
|
3 |
<div class="sucuriscan-pull-left sucuriscan-sitelogo"> </div>
|
4 |
|
5 |
<div class="sucuriscan-pull-right">
|
6 |
+
<p>Congratulations! The rest of the features available in the plugin have been enabled. This product is designed to supplement existing security products. It's not a silver bullet for your security needs, but it'll give you greater security awareness and better posture, all with the intent of reducing risk.</p>
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-success">
|
9 |
+
<p>Your website has been granted a new API key and it was associated to the email address that you chose during the registration process. You can use the same email to recover the key if you happen to lose it sometime. We encourage you to check the rest of the settings page and configure the plugin to your own needs.</p>
|
10 |
</div>
|
11 |
|
12 |
+
<a href="%%SUCURI.URL.Dashboard%%" class="button button-primary">Dashboard</a>
|
13 |
+
<a href="%%SUCURI.URL.Settings%%" class="button button-primary">Settings</a>
|
14 |
</div>
|
15 |
</div>
|
inc/tpl/settings-apiservice-checksums.html.tpl
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
-
<span
|
10 |
href="%%SUCURI.ChecksumsAPI%%">%%SUCURI.ChecksumsAPI%%</a>
|
11 |
</span>
|
12 |
</div>
|
@@ -14,9 +14,9 @@
|
|
14 |
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
15 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
16 |
<fieldset class="sucuriscan-clearfix">
|
17 |
-
<label
|
18 |
<input type="text" name="sucuriscan_checksum_api" placeholder="e.g. URL — or — user/repo" size="30" />
|
19 |
-
<button type="submit" class="button button-primary"
|
20 |
</fieldset>
|
21 |
</form>
|
22 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">WordPress Checksums API</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>The WordPress integrity tool uses a remote API service maintained by the WordPress organization to determine which files in the installation were added, removed or modified. The API returns a list of files with their respective checksums, this information guarantees that the installation is not corrupt. You can, however, point the integrity tool to a GitHub repository in case that you are using a custom version of WordPress like the <a href="https://github.com/WordPress/WordPress" target="_blank" rel="noopener">development version of the code</a>.</p>
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
+
<span>WordPress Checksums API — <a target="_blank"
|
10 |
href="%%SUCURI.ChecksumsAPI%%">%%SUCURI.ChecksumsAPI%%</a>
|
11 |
</span>
|
12 |
</div>
|
14 |
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
15 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
16 |
<fieldset class="sucuriscan-clearfix">
|
17 |
+
<label>WordPress Checksums API:</label>
|
18 |
<input type="text" name="sucuriscan_checksum_api" placeholder="e.g. URL — or — user/repo" size="30" />
|
19 |
+
<button type="submit" class="button button-primary">Submit</button>
|
20 |
</fieldset>
|
21 |
</form>
|
22 |
</div>
|
inc/tpl/settings-apiservice-proxy.html.tpl
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-monospace">
|
9 |
-
<div
|
10 |
-
<div
|
11 |
-
<div
|
12 |
-
<div
|
13 |
</div>
|
14 |
</div>
|
15 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">API Communication via Proxy</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>All the HTTP requests used to communicate with the API service are being sent using the WordPress built-in functions, so (almost) all its official features are inherited, this is useful if you need to pass these HTTP requests through a proxy. According to the <a href="https://developer.wordpress.org/reference/classes/wp_http_proxy/" target="_blank" rel="noopener">official documentation</a> you have to add some constants to the main configuration file: <em>WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME, WP_PROXY_PASSWORD</em>.</p>
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-monospace">
|
9 |
+
<div>HTTP Proxy Hostname: %%SUCURI.APIProxy.Host%%</div>
|
10 |
+
<div>HTTP Proxy Port num: %%SUCURI.APIProxy.Port%%</div>
|
11 |
+
<div>HTTP Proxy Username: %%SUCURI.APIProxy.Username%%</div>
|
12 |
+
<div>HTTP Proxy Password: <span class="sucuriscan-label-%%SUCURI.APIProxy.PasswordType%%">%%SUCURI.APIProxy.PasswordText%%</span></div>
|
13 |
</div>
|
14 |
</div>
|
15 |
</div>
|
inc/tpl/settings-apiservice-status.html.tpl
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.ApiStatus.ErrorVisibility%%">
|
9 |
-
<p
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.ApiStatus.StatusNum%%">
|
13 |
-
<span
|
14 |
<span class="sucuriscan-monospace">%%SUCURI.ApiStatus.ServiceURL%%</span>
|
15 |
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
16 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">API Service Communication</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Once the API key is generate the plugin will communicate with a remote API service that will act as a safe data storage for the audit logs generated when the website triggers certain events that the plugin monitors. If the website is hacked the attacker will not have access to these logs and that way you can investigate what was modified <em>(for malware infaction)</em> and/or how the malicious person was able to gain access to the website.</p>
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.ApiStatus.ErrorVisibility%%">
|
9 |
+
<p>Disabling the API service communication will stop the event monitoring, consider to enable the <a href="%%SUCURI.URL.Settings%%#general">Log Exporter</a> to keep the monitoring working while the HTTP requests are ignored, otherwise an attacker may execute an action that will not be registered in the security logs and you will not have a way to investigate the attack in the future.</p>
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.ApiStatus.StatusNum%%">
|
13 |
+
<span>API Service Communication — %%SUCURI.ApiStatus.Status%% —</span>
|
14 |
<span class="sucuriscan-monospace">%%SUCURI.ApiStatus.ServiceURL%%</span>
|
15 |
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
16 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
inc/tpl/settings-general-apikey.html.tpl
CHANGED
@@ -4,36 +4,36 @@
|
|
4 |
%%%SUCURI.ModalForApiKeyRecovery%%%
|
5 |
|
6 |
<div class="sucuriscan-panel">
|
7 |
-
<h3 class="sucuriscan-title"
|
8 |
|
9 |
<div class="inside">
|
10 |
-
<p
|
11 |
|
12 |
<div class="sucuriscan-inline-alert-info">
|
13 |
-
<p
|
14 |
</div>
|
15 |
|
16 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.InvalidDomainVisibility%%">
|
17 |
-
<p
|
18 |
</div>
|
19 |
|
20 |
<div class="sucuriscan-%%SUCURI.APIKey.RecoverVisibility%%">
|
21 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-0">
|
22 |
-
<div class="sucuriscan-monospace"
|
23 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
24 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
25 |
-
<button type="submit" name="sucuriscan_recover_key" class="button button-primary"
|
26 |
</form>
|
27 |
</div>
|
28 |
|
29 |
-
<p
|
30 |
</div>
|
31 |
|
32 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-1 sucuriscan-%%SUCURI.APIKey.RemoveVisibility%%">
|
33 |
-
<div class="sucuriscan-monospace"
|
34 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
35 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
36 |
-
<button type="submit" name="sucuriscan_remove_api_key" class="button button-primary"
|
37 |
</form>
|
38 |
</div>
|
39 |
</div>
|
4 |
%%%SUCURI.ModalForApiKeyRecovery%%%
|
5 |
|
6 |
<div class="sucuriscan-panel">
|
7 |
+
<h3 class="sucuriscan-title">API Key</h3>
|
8 |
|
9 |
<div class="inside">
|
10 |
+
<p>Most of the tools in this plugin can be used without a specific configuration, but the core features <b>require an API key</b> to communicate with the Sucuri services. The key is generated using your administrator e-mail and the domain of this site, this will allow you to have access to our free monitoring tool and other extra features.</p>
|
11 |
|
12 |
<div class="sucuriscan-inline-alert-info">
|
13 |
+
<p>Generating an API key implies that you agree to send the information collected by the plugin to the Sucuri API service which is a remote server where the information for the audit logs is stored, this is to prevent malicious users to delete the logs during an attack which may affect an investigation if you suspect that your website was hacked. We also use this information to display <a href="https://sucuri.net/security-reports/brute-force/" target="_blank" rel="noopener">statistics</a> and try to use the data in an anonymous way as we are concerned about your privacy too. Please do not generate an API key if you do not agree with this, you can keep using the plugin without it anyway.</p>
|
14 |
</div>
|
15 |
|
16 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.InvalidDomainVisibility%%">
|
17 |
+
<p>Your domain <code>%%SUCURI.CleanDomain%%</code> does not seems to have a DNS <code>A</code> record so it will be considered as <em>invalid</em> by the API interface when you request the generation of a new key. Adding <code>www</code> at the beginning of the domain name may fix this issue. If you do not understand what is this then send an email to our support team requesting the key.</p>
|
18 |
</div>
|
19 |
|
20 |
<div class="sucuriscan-%%SUCURI.APIKey.RecoverVisibility%%">
|
21 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-0">
|
22 |
+
<div class="sucuriscan-monospace">API Key: %%SUCURI.APIKey%%</div>
|
23 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
24 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
25 |
+
<button type="submit" name="sucuriscan_recover_key" class="button button-primary">Recover Via E-mail</button>
|
26 |
</form>
|
27 |
</div>
|
28 |
|
29 |
+
<p>If you don't have access to the e-mail address used to generate the API key, but have a copy of the key at hand you can <a target="_self" href="%%SUCURI.URL.Settings%%&recover">click this link</a> to activate the plugin manually. Be aware that if the key is invalid the plugin will delete it afterwards.</p>
|
30 |
</div>
|
31 |
|
32 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-1 sucuriscan-%%SUCURI.APIKey.RemoveVisibility%%">
|
33 |
+
<div class="sucuriscan-monospace">API Key: %%SUCURI.APIKey%%</div>
|
34 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
35 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
36 |
+
<button type="submit" name="sucuriscan_remove_api_key" class="button button-primary">Delete</button>
|
37 |
</form>
|
38 |
</div>
|
39 |
</div>
|
inc/tpl/settings-general-datastorage.html.tpl
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
</div>
|
8 |
|
9 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
@@ -21,10 +21,10 @@
|
|
21 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
22 |
<input id="cb-select-all-1" type="checkbox">
|
23 |
</td>
|
24 |
-
<th class="manage-column"
|
25 |
-
<th class="manage-column"
|
26 |
-
<th class="manage-column"
|
27 |
-
<th class="manage-column"
|
28 |
</tr>
|
29 |
</thead>
|
30 |
|
@@ -34,7 +34,7 @@
|
|
34 |
</table>
|
35 |
|
36 |
<p>
|
37 |
-
<button type="submit" class="button button-primary"
|
38 |
</p>
|
39 |
</form>
|
40 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Data Storage</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>This is the directory where the plugin will store the security logs, the list of files marked as fixed in the core integrity tool, the cache for the malware scanner and 3rd-party plugin metadata. The plugin requires write permissions in this directory as well as the files contained in it. If you prefer to keep these files in a non-public directory <em>(one level up the document root)</em> please define a constant in the <em>"wp-config.php"</em> file named <em>"SUCURI_DATA_STORAGE"</em> with the absolute path to the new directory.</p>
|
7 |
</div>
|
8 |
|
9 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
21 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
22 |
<input id="cb-select-all-1" type="checkbox">
|
23 |
</td>
|
24 |
+
<th class="manage-column">File Path</th>
|
25 |
+
<th class="manage-column">File Size</th>
|
26 |
+
<th class="manage-column">Status</th>
|
27 |
+
<th class="manage-column">Writable</th>
|
28 |
</tr>
|
29 |
</thead>
|
30 |
|
34 |
</table>
|
35 |
|
36 |
<p>
|
37 |
+
<button type="submit" class="button button-primary">Delete</button>
|
38 |
</p>
|
39 |
</form>
|
40 |
</div>
|
inc/tpl/settings-general-importexport.html.tpl
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
7 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
8 |
|
9 |
-
<p
|
10 |
|
11 |
<textarea name="sucuriscan_settings" class="sucuriscan-full-textarea sucuriscan-monospace">%%SUCURI.Export%%</textarea>
|
12 |
|
@@ -14,11 +14,11 @@
|
|
14 |
<label>
|
15 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
16 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
17 |
-
<span
|
18 |
</label>
|
19 |
</p>
|
20 |
|
21 |
-
<button type="submit" name="sucuriscan_import" class="button button-primary"
|
22 |
</form>
|
23 |
</div>
|
24 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Import & Export Settings</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
7 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
8 |
|
9 |
+
<p>Copy the JSON-encoded data from the box below, go to your other websites and click the <em>"Import"</em> button in the settings page. The plugin will start using the same settings from this website. Notice that some options are omitted as they contain values specific to this website. To import the settings from another website into this one, replace the JSON-encoded data in the box below with the JSON-encoded data exported from the other website, then click the button <em>"Import"</em>. Notice that some options will not be imported to reduce the security risk of writing arbitrary data into the disk.</p>
|
10 |
|
11 |
<textarea name="sucuriscan_settings" class="sucuriscan-full-textarea sucuriscan-monospace">%%SUCURI.Export%%</textarea>
|
12 |
|
14 |
<label>
|
15 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
16 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
17 |
+
<span>I understand that this operation can not be reverted.</span>
|
18 |
</label>
|
19 |
</p>
|
20 |
|
21 |
+
<button type="submit" name="sucuriscan_import" class="button button-primary">Submit</button>
|
22 |
</form>
|
23 |
</div>
|
24 |
</div>
|
inc/tpl/settings-general-ipdiscoverer.html.tpl
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
-
<span
|
10 |
|
11 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
12 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -19,7 +19,7 @@
|
|
19 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
20 |
|
21 |
<fieldset class="sucuriscan-clearfix">
|
22 |
-
<label
|
23 |
<select name="sucuriscan_addr_header">
|
24 |
%%%SUCURI.AddrHeaderOptions%%%
|
25 |
</select>
|
@@ -28,11 +28,11 @@
|
|
28 |
|
29 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-monospace">
|
30 |
<div>Sucuri Firewall — %%SUCURI.IsUsingFirewall%%</div>
|
31 |
-
<div
|
32 |
<div>Top Level Domain: %%SUCURI.TopLevelDomain%%</div>
|
33 |
-
<div
|
34 |
-
<div
|
35 |
-
<div
|
36 |
</div>
|
37 |
</form>
|
38 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">IP Address Discoverer</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>IP address discoverer will use DNS lookups to automatically detect if the website is behind the <a href="https://sucuri.net/website-firewall/" target="_blank" rel="noopener">Sucuri Firewall</a> in which case will modify the global server variable <em>Remote-Addr</em> to set the real IP of the website's visitors. This check runs on every WordPress init action and that is why it may slow down your website as some hosting providers rely on slow DNS servers which makes the operation take more time than it should.</p>
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
+
<span>IP Address Discoverer — %%SUCURI.DnsLookupsStatus%%</span>
|
10 |
|
11 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
12 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
19 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
20 |
|
21 |
<fieldset class="sucuriscan-clearfix">
|
22 |
+
<label>HTTP Header:</label>
|
23 |
<select name="sucuriscan_addr_header">
|
24 |
%%%SUCURI.AddrHeaderOptions%%%
|
25 |
</select>
|
28 |
|
29 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-monospace">
|
30 |
<div>Sucuri Firewall — %%SUCURI.IsUsingFirewall%%</div>
|
31 |
+
<div>Website: %%SUCURI.WebsiteURL%%</div>
|
32 |
<div>Top Level Domain: %%SUCURI.TopLevelDomain%%</div>
|
33 |
+
<div>Hostname: %%SUCURI.WebsiteHostName%%</div>
|
34 |
+
<div>IP Address (Hostname): %%SUCURI.WebsiteHostAddress%%</div>
|
35 |
+
<div>IP Address (Username): %%SUCURI.RemoteAddress%% (%%SUCURI.RemoteAddressHeader%%)</div>
|
36 |
</div>
|
37 |
</form>
|
38 |
</div>
|
inc/tpl/settings-general-resetoptions.html.tpl
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -11,10 +11,10 @@
|
|
11 |
<label>
|
12 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
13 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
14 |
-
<span
|
15 |
</label>
|
16 |
</p>
|
17 |
-
<button type="submit" name="sucuriscan_reset_options" class="button button-primary"
|
18 |
</form>
|
19 |
</div>
|
20 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Reset Security Logs, Hardening and Settings</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>This action will trigger the deactivation / uninstallation process of the plugin. All local security logs, hardening and settings will be deleted. Notice that the security logs stored in the API service will not be deleted, this is to prevent tampering from a malicious user. You can request a new API key if you want to start from scratch.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
11 |
<label>
|
12 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
13 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
14 |
+
<span>I understand that this operation can not be reverted.</span>
|
15 |
</label>
|
16 |
</p>
|
17 |
+
<button type="submit" name="sucuriscan_reset_options" class="button button-primary">Submit</button>
|
18 |
</form>
|
19 |
</div>
|
20 |
</div>
|
inc/tpl/settings-general-reverseproxy.html.tpl
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
-
<span
|
10 |
|
11 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
12 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Reverse Proxy</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>The event monitor uses the API address of the origin of the request to track the actions, the plugin uses two methods to retrieve this: the main method uses the global server variable <em>Remote-Addr</em> available in most modern web servers, an alternative method uses custom HTTP headers <em>(which are unsafe by default)</em>. You should not worry about this option unless you know what a reverse proxy is. Services like the <a href="https://sucuri.net/website-firewall/" target="_blank" rel="noopener">Sucuri Firewall</a> — once active — forces the network traffic to pass through them to filter any security threat that may affect the original server. A side effect of this is that the real IP address is no longer available in the global server variable <em>REMOTE-ADDR</em> but in a custom HTTP header with a name provided by the service.</p>
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
+
<span>Reverse Proxy — %%SUCURI.ReverseProxyStatus%%</span>
|
10 |
|
11 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
12 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
inc/tpl/settings-general-selfhosting.html.tpl
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-%%SUCURI.SelfHosting.DisabledVisibility%%">
|
9 |
-
<span
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-monitor-fpath sucuriscan-%%SUCURI.SelfHosting.FpathVisibility%%">
|
@@ -21,9 +21,9 @@
|
|
21 |
<form action="%%SUCURI.URL.Settings%%#general" method="post">
|
22 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
23 |
<fieldset class="sucuriscan-clearfix">
|
24 |
-
<label
|
25 |
<input type="text" name="sucuriscan_selfhosting_fpath" />
|
26 |
-
<button type="submit" class="button button-primary"
|
27 |
</fieldset>
|
28 |
</form>
|
29 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Log Exporter</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>This option allows you to export the WordPress audit logs to a local log file that can be read by a SIEM or any log analysis software <em>(we recommend OSSEC)</em>. That will give visibility from within WordPress to complement your log monitoring infrastructure. <b>NOTE:</b> Do not use a publicly accessible file, you must use a file at least one level up the document root to prevent leaks of information.</p>
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-%%SUCURI.SelfHosting.DisabledVisibility%%">
|
9 |
+
<span>Log Exporter — %%SUCURI.SelfHosting.Status%%</span>
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-monitor-fpath sucuriscan-%%SUCURI.SelfHosting.FpathVisibility%%">
|
21 |
<form action="%%SUCURI.URL.Settings%%#general" method="post">
|
22 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
23 |
<fieldset class="sucuriscan-clearfix">
|
24 |
+
<label>File Path:</label>
|
25 |
<input type="text" name="sucuriscan_selfhosting_fpath" />
|
26 |
+
<button type="submit" class="button button-primary">Submit</button>
|
27 |
</fieldset>
|
28 |
</form>
|
29 |
</div>
|
inc/tpl/settings-general-timezone.html.tpl
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
-
<label
|
12 |
<select name="sucuriscan_timezone">
|
13 |
%%%SUCURI.Timezone.Dropdown%%%
|
14 |
</select>
|
15 |
-
<button type="submit" class="button button-primary"
|
16 |
<span><em>(%%SUCURI.Timezone.Example%%)</em></span>
|
17 |
</fieldset>
|
18 |
</form>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Timezone</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>This option defines the timezone that will be used through out the entire plugin to print the dates and times whenever is necessary. This option also affects the date and time of the logs visible in the audit logs panel which is data that comes from a remote server configured to use Eastern Daylight Time (EDT). WordPress offers an option in the general settings page to allow you to configure the timezone for the entire website, however, if you are experiencing problems with the time in the audit logs, this option will help you fix them.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
+
<label>Timezone:</label>
|
12 |
<select name="sucuriscan_timezone">
|
13 |
%%%SUCURI.Timezone.Dropdown%%%
|
14 |
</select>
|
15 |
+
<button type="submit" class="button button-primary">Submit</button>
|
16 |
<span><em>(%%SUCURI.Timezone.Example%%)</em></span>
|
17 |
</fieldset>
|
18 |
</form>
|
inc/tpl/settings-hardening-whitelist-phpfiles.html.tpl
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#hardening" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
-
<label
|
12 |
<input type="text" name="sucuriscan_hardening_whitelist" placeholder="e.g. wp-tinymce.php" />
|
13 |
<select name="sucuriscan_hardening_folder">
|
14 |
<option value="wp-includes">wp-includes</option>
|
15 |
<option value="wp-content">wp-content</option>
|
16 |
<option value="wp-content/uploads">wp-content/uploads</option>
|
17 |
</select>
|
18 |
-
<button type="submit" class="button button-primary"
|
19 |
</fieldset>
|
20 |
</form>
|
21 |
|
@@ -30,9 +30,9 @@
|
|
30 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
31 |
<input id="cb-select-all-1" type="checkbox">
|
32 |
</td>
|
33 |
-
<th class="manage-column"
|
34 |
-
<th class="manage-column"
|
35 |
-
<th class="manage-column"
|
36 |
</thead>
|
37 |
|
38 |
<tbody>
|
@@ -40,13 +40,13 @@
|
|
40 |
|
41 |
<tr class="sucuriscan-%%SUCURI.HardeningWhitelist.NoItemsVisibility%%">
|
42 |
<td colspan="4">
|
43 |
-
<em
|
44 |
</td>
|
45 |
</tr>
|
46 |
</tbody>
|
47 |
</table>
|
48 |
|
49 |
-
<button type="submit" class="button button-primary"
|
50 |
</form>
|
51 |
</div>
|
52 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Whitelist Blocked PHP Files</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>After you apply the hardening in either the includes, content, and/or upload directories the plugin will add a rule in the access control file to deny access to any PHP file located in these folders, this is a good precaution in case that an attacker is able to upload a shell script; with a few exceptions the <em>"index.php"</em> is the only one that should be publicly accessible, however many theme/plugin developers decide to use these folders to process some operations, in this case applying the hardening <strong>may break</strong> their functionality.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#hardening" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
+
<label>File Path:</label>
|
12 |
<input type="text" name="sucuriscan_hardening_whitelist" placeholder="e.g. wp-tinymce.php" />
|
13 |
<select name="sucuriscan_hardening_folder">
|
14 |
<option value="wp-includes">wp-includes</option>
|
15 |
<option value="wp-content">wp-content</option>
|
16 |
<option value="wp-content/uploads">wp-content/uploads</option>
|
17 |
</select>
|
18 |
+
<button type="submit" class="button button-primary">Submit</button>
|
19 |
</fieldset>
|
20 |
</form>
|
21 |
|
30 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
31 |
<input id="cb-select-all-1" type="checkbox">
|
32 |
</td>
|
33 |
+
<th class="manage-column">File Path</th>
|
34 |
+
<th class="manage-column">Directory</th>
|
35 |
+
<th class="manage-column">Pattern</th>
|
36 |
</thead>
|
37 |
|
38 |
<tbody>
|
40 |
|
41 |
<tr class="sucuriscan-%%SUCURI.HardeningWhitelist.NoItemsVisibility%%">
|
42 |
<td colspan="4">
|
43 |
+
<em>no data available</em>
|
44 |
</td>
|
45 |
</tr>
|
46 |
</tbody>
|
47 |
</table>
|
48 |
|
49 |
+
<button type="submit" class="button button-primary">Delete</button>
|
50 |
</form>
|
51 |
</div>
|
52 |
</div>
|
inc/tpl/settings-posthack-available-updates-alert.html.tpl
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
|
2 |
-
<p
|
3 |
|
4 |
<table border="1" cellspacing="1" cellpadding="5">
|
5 |
<thead>
|
6 |
<tr>
|
7 |
-
<th
|
8 |
-
<th
|
9 |
-
<th
|
10 |
-
<th
|
11 |
<th> </th>
|
12 |
</tr>
|
13 |
</thead>
|
1 |
|
2 |
+
<p>WordPress has a big user base in the public Internet, this brings interest to malicious people to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website update to prevent attacks as soon as disclosed vulnerabilities are patched.</p>
|
3 |
|
4 |
<table border="1" cellspacing="1" cellpadding="5">
|
5 |
<thead>
|
6 |
<tr>
|
7 |
+
<th>Name</th>
|
8 |
+
<th>Version</th>
|
9 |
+
<th>Update</th>
|
10 |
+
<th>Tested With</th>
|
11 |
<th> </th>
|
12 |
</tr>
|
13 |
</thead>
|
inc/tpl/settings-posthack-available-updates.html.tpl
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase: false */
|
8 |
-
jQuery(function ($) {
|
9 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
10 |
action: 'sucuriscan_ajax',
|
11 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
@@ -17,15 +17,15 @@
|
|
17 |
</script>
|
18 |
|
19 |
<div class="inside">
|
20 |
-
<p
|
21 |
|
22 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-available-updates-table">
|
23 |
<thead>
|
24 |
<tr>
|
25 |
-
<th class="manage-column"
|
26 |
-
<th class="manage-column"
|
27 |
-
<th class="manage-column"
|
28 |
-
<th class="manage-column"
|
29 |
<th class="manage-column"> </th>
|
30 |
</tr>
|
31 |
</thead>
|
@@ -33,7 +33,7 @@
|
|
33 |
<tbody>
|
34 |
<tr>
|
35 |
<td colspan="5">
|
36 |
-
<span
|
37 |
</td>
|
38 |
</tr>
|
39 |
</tbody>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Available Plugin and Theme Updates</h3>
|
4 |
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase: false */
|
8 |
+
jQuery(document).ready(function ($) {
|
9 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
10 |
action: 'sucuriscan_ajax',
|
11 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
17 |
</script>
|
18 |
|
19 |
<div class="inside">
|
20 |
+
<p>WordPress has a big user base in the public Internet, this brings interest to malicious people to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website update to prevent attacks as soon as disclosed vulnerabilities are patched.</p>
|
21 |
|
22 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-available-updates-table">
|
23 |
<thead>
|
24 |
<tr>
|
25 |
+
<th class="manage-column">Name</th>
|
26 |
+
<th class="manage-column">Version</th>
|
27 |
+
<th class="manage-column">Update</th>
|
28 |
+
<th class="manage-column">Tested With</th>
|
29 |
<th class="manage-column"> </th>
|
30 |
</tr>
|
31 |
</thead>
|
33 |
<tbody>
|
34 |
<tr>
|
35 |
<td colspan="5">
|
36 |
+
<span>Loading...</span>
|
37 |
</td>
|
38 |
</tr>
|
39 |
</tbody>
|
inc/tpl/settings-posthack-available-updates.snippet.tpl
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<tr>
|
3 |
<td>
|
4 |
<span class="dashicons-before dashicons-admin-%%SUCURI.Update.IconType%%">
|
5 |
-
<a href="%%SUCURI.Update.MarketUrl%%" target="_blank">%%SUCURI.Update.Extension%%</a>
|
6 |
</span>
|
7 |
</td>
|
8 |
|
@@ -12,5 +12,5 @@
|
|
12 |
|
13 |
<td>%%SUCURI.Update.TestedWith%%</td>
|
14 |
|
15 |
-
<td><a href="%%SUCURI.Update.ArchiveUrl%%" target="_blank"
|
16 |
</tr>
|
2 |
<tr>
|
3 |
<td>
|
4 |
<span class="dashicons-before dashicons-admin-%%SUCURI.Update.IconType%%">
|
5 |
+
<a href="%%SUCURI.Update.MarketUrl%%" target="_blank" rel="noopener">%%SUCURI.Update.Extension%%</a>
|
6 |
</span>
|
7 |
</td>
|
8 |
|
12 |
|
13 |
<td>%%SUCURI.Update.TestedWith%%</td>
|
14 |
|
15 |
+
<td><a href="%%SUCURI.Update.ArchiveUrl%%" target="_blank" rel="noopener">Download</a></td>
|
16 |
</tr>
|
inc/tpl/settings-posthack-reset-password-alert.html.tpl
CHANGED
@@ -1,2 +1,2 @@
|
|
1 |
|
2 |
-
|
1 |
|
2 |
+
WordPress has generated a new (random) password for your account <b>%%SUCURI.ResetPassword.UserName%%</b> at <a target="_blank" href="http://%%SUCURI.ResetPassword.Website%%" rel="noopener">%%SUCURI.ResetPassword.Website%%</a>. The change has been requested by one of the admins in this website for security reasons. Your new password is — <span style="font-family:Menlo, Monaco, monospace, serif;font-weight:700">%%%SUCURI.ResetPassword.Password%%%</span> — please change it as soon as possible.
|
inc/tpl/settings-posthack-reset-password.html.tpl
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase: false */
|
8 |
-
jQuery(function ($) {
|
9 |
$('#sucuriscan-reset-password-button').on('click', function (event) {
|
10 |
event.preventDefault();
|
11 |
$('.sucuriscan-reset-password-table :checkbox:checked').each(function (key, el) {
|
@@ -13,7 +13,7 @@
|
|
13 |
|
14 |
$('#sucuriscan-userid-' + user_id)
|
15 |
.find('.sucuriscan-response')
|
16 |
-
.html('(
|
17 |
|
18 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
19 |
action: 'sucuriscan_ajax',
|
@@ -31,7 +31,7 @@
|
|
31 |
</script>
|
32 |
|
33 |
<div class="inside">
|
34 |
-
<p
|
35 |
|
36 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-reset-password-table">
|
37 |
<thead>
|
@@ -40,10 +40,10 @@
|
|
40 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
41 |
<input id="cb-select-all-1" type="checkbox">
|
42 |
</td>
|
43 |
-
<th class="manage-column"
|
44 |
-
<th class="manage-column"
|
45 |
-
<th class="manage-column"
|
46 |
-
<th class="manage-column"
|
47 |
</tr>
|
48 |
</thead>
|
49 |
|
@@ -51,7 +51,7 @@
|
|
51 |
%%%SUCURI.ResetPassword.UserList%%%
|
52 |
|
53 |
<tr class="sucuriscan-%%SUCURI.ResetPassword.PaginationVisibility%%">
|
54 |
-
<td colspan="
|
55 |
<ul class="sucuriscan-pagination">
|
56 |
%%%SUCURI.ResetPassword.PaginationLinks%%%
|
57 |
</ul>
|
@@ -61,6 +61,6 @@
|
|
61 |
</table>
|
62 |
|
63 |
<button type="button" id="sucuriscan-reset-password-button"
|
64 |
-
class="button button-primary"
|
65 |
</div>
|
66 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Reset User Password</h3>
|
4 |
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase: false */
|
8 |
+
jQuery(document).ready(function ($) {
|
9 |
$('#sucuriscan-reset-password-button').on('click', function (event) {
|
10 |
event.preventDefault();
|
11 |
$('.sucuriscan-reset-password-table :checkbox:checked').each(function (key, el) {
|
13 |
|
14 |
$('#sucuriscan-userid-' + user_id)
|
15 |
.find('.sucuriscan-response')
|
16 |
+
.html('(Loading...)');
|
17 |
|
18 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
19 |
action: 'sucuriscan_ajax',
|
31 |
</script>
|
32 |
|
33 |
<div class="inside">
|
34 |
+
<p>You can generate a new random password for the user accounts that you select from the list. An email with the new password will be sent to the email address of each chosen users. If you choose to change the password of your own user, then your current session will expire immediately. You will need to log into the admin panel with the new password that will be sent to your email.</p>
|
35 |
|
36 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-reset-password-table">
|
37 |
<thead>
|
40 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
41 |
<input id="cb-select-all-1" type="checkbox">
|
42 |
</td>
|
43 |
+
<th class="manage-column">Username</th>
|
44 |
+
<th class="manage-column">E-mail</th>
|
45 |
+
<th class="manage-column">Registered</th>
|
46 |
+
<th class="manage-column">Roles</th>
|
47 |
</tr>
|
48 |
</thead>
|
49 |
|
51 |
%%%SUCURI.ResetPassword.UserList%%%
|
52 |
|
53 |
<tr class="sucuriscan-%%SUCURI.ResetPassword.PaginationVisibility%%">
|
54 |
+
<td colspan="5">
|
55 |
<ul class="sucuriscan-pagination">
|
56 |
%%%SUCURI.ResetPassword.PaginationLinks%%%
|
57 |
</ul>
|
61 |
</table>
|
62 |
|
63 |
<button type="button" id="sucuriscan-reset-password-button"
|
64 |
+
class="button button-primary">Submit</button>
|
65 |
</div>
|
66 |
</div>
|
inc/tpl/settings-posthack-reset-plugins.html.tpl
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase:false */
|
8 |
-
jQuery(function ($) {
|
9 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
10 |
action: 'sucuriscan_ajax',
|
11 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
@@ -22,7 +22,7 @@
|
|
22 |
|
23 |
$('#sucuriscan-plugin-' + unique)
|
24 |
.find('.sucuriscan-reset-plugin-response')
|
25 |
-
.html('
|
26 |
|
27 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
28 |
action: 'sucuriscan_ajax',
|
@@ -40,14 +40,14 @@
|
|
40 |
</script>
|
41 |
|
42 |
<div class="inside">
|
43 |
-
<p
|
44 |
|
45 |
<div class="sucuriscan-inline-alert-info">
|
46 |
-
<p
|
47 |
</div>
|
48 |
|
49 |
<div class="sucuriscan-inline-alert-error">
|
50 |
-
<p
|
51 |
</div>
|
52 |
|
53 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-reset-plugins-table">
|
@@ -57,22 +57,22 @@
|
|
57 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
58 |
<input id="cb-select-all-1" type="checkbox">
|
59 |
</td>
|
60 |
-
<th class="manage-column"
|
61 |
-
<th class="manage-column"
|
62 |
-
<th class="manage-column"
|
63 |
-
<th class="manage-column"
|
64 |
</tr>
|
65 |
</thead>
|
66 |
|
67 |
<tbody>
|
68 |
<tr>
|
69 |
<td colspan="5">
|
70 |
-
<span
|
71 |
</td>
|
72 |
</tr>
|
73 |
</tbody>
|
74 |
</table>
|
75 |
|
76 |
-
<button type="button" id="sucuriscan_reset_plugins" class="button button-primary"
|
77 |
</div>
|
78 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Reset Installed Plugins</h3>
|
4 |
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase:false */
|
8 |
+
jQuery(document).ready(function ($) {
|
9 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
10 |
action: 'sucuriscan_ajax',
|
11 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
22 |
|
23 |
$('#sucuriscan-plugin-' + unique)
|
24 |
.find('.sucuriscan-reset-plugin-response')
|
25 |
+
.html('Loading...');
|
26 |
|
27 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
28 |
action: 'sucuriscan_ajax',
|
40 |
</script>
|
41 |
|
42 |
<div class="inside">
|
43 |
+
<p>In case that you suspect of an infection in your site, or even after you got rid of a malicious code, it would be better if you reinstall all the plugins installed in your site, including the ones you are not using. Notice that premium plugins will not be reinstalled to prevent backward compatibility issues and problems with licenses.</p>
|
44 |
|
45 |
<div class="sucuriscan-inline-alert-info">
|
46 |
+
<p>The information shown here is cache for %%SUCURI.ResetPlugin.CacheLifeTime%% seconds, this is necessary to reduce the quantity of HTTP requests sent to the WordPress servers and the bandwidth of your site. Currently there is no option to recreate this cache so you have to wait until it resets itself.</p>
|
47 |
</div>
|
48 |
|
49 |
<div class="sucuriscan-inline-alert-error">
|
50 |
+
<p><b>WARNING!</b> This procedure can break your website. The reset will not affect the database nor the settings of each plugin but depending on how they were written the reset action might break them. Be sure to create a backup of the plugins directory before the execution of this tool.</p>
|
51 |
</div>
|
52 |
|
53 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-reset-plugins-table">
|
57 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
58 |
<input id="cb-select-all-1" type="checkbox">
|
59 |
</td>
|
60 |
+
<th class="manage-column">Name</th>
|
61 |
+
<th class="manage-column">Version</th>
|
62 |
+
<th class="manage-column">Type</th>
|
63 |
+
<th class="manage-column">Status</th>
|
64 |
</tr>
|
65 |
</thead>
|
66 |
|
67 |
<tbody>
|
68 |
<tr>
|
69 |
<td colspan="5">
|
70 |
+
<span>Loading...</span>
|
71 |
</td>
|
72 |
</tr>
|
73 |
</tbody>
|
74 |
</table>
|
75 |
|
76 |
+
<button type="button" id="sucuriscan_reset_plugins" class="button button-primary">Submit</button>
|
77 |
</div>
|
78 |
</div>
|
inc/tpl/settings-posthack-reset-plugins.snippet.tpl
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
</th>
|
6 |
|
7 |
<td>
|
8 |
-
<a href="%%SUCURI.ResetPlugin.Repository%%" target="_blank">%%SUCURI.ResetPlugin.Plugin%%</a>
|
9 |
</td>
|
10 |
|
11 |
<td class="sucuriscan-reset-plugin-response">
|
5 |
</th>
|
6 |
|
7 |
<td>
|
8 |
+
<a href="%%SUCURI.ResetPlugin.Repository%%" target="_blank" rel="noopener">%%SUCURI.ResetPlugin.Plugin%%</a>
|
9 |
</td>
|
10 |
|
11 |
<td class="sucuriscan-reset-plugin-response">
|
inc/tpl/settings-posthack-security-keys.html.tpl
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-error">
|
9 |
-
<p
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan_wpconfig_keys_updated sucuriscan-monospace sucuriscan-%%SUCURI.WPConfigUpdate.Visibility%%">
|
@@ -16,9 +16,9 @@
|
|
16 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-security-keys-table">
|
17 |
<thead>
|
18 |
<tr>
|
19 |
-
<th
|
20 |
-
<th
|
21 |
-
<th
|
22 |
</tr>
|
23 |
</thead>
|
24 |
|
@@ -35,11 +35,11 @@
|
|
35 |
<label>
|
36 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
37 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
38 |
-
<span
|
39 |
</label>
|
40 |
</p>
|
41 |
|
42 |
-
<input type="submit" value="
|
43 |
</form>
|
44 |
</div>
|
45 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Update Secret Keys</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>The secret or security keys are a list of constants added to your site to ensure better encryption of information stored in the user's cookies. A secret key makes your site harder to hack and access by adding random elements to the password. You do not have to remember the keys, just write a random, complicated, and long string in the <code>wp-config.php</code> file. You can change these keys at any point in time to invalidate all existing cookies, forcing all users to login again.</p>
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-error">
|
9 |
+
<p>Your current session will expire once the form is submitted.</p>
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan_wpconfig_keys_updated sucuriscan-monospace sucuriscan-%%SUCURI.WPConfigUpdate.Visibility%%">
|
16 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-security-keys-table">
|
17 |
<thead>
|
18 |
<tr>
|
19 |
+
<th>Status</th>
|
20 |
+
<th>Name</th>
|
21 |
+
<th>Value</th>
|
22 |
</tr>
|
23 |
</thead>
|
24 |
|
35 |
<label>
|
36 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
37 |
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
38 |
+
<span>I understand that this operation can not be reverted.</span>
|
39 |
</label>
|
40 |
</p>
|
41 |
|
42 |
+
<input type="submit" value="Generate New Security Keys" class="button button-primary" />
|
43 |
</form>
|
44 |
</div>
|
45 |
</div>
|
inc/tpl/settings-scanner-cronjobs.html.tpl
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.NoSPL.Visibility%%">
|
9 |
-
<p
|
10 |
</div>
|
11 |
|
12 |
-
<p
|
13 |
|
14 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
15 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -21,10 +21,10 @@
|
|
21 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
22 |
<input id="cb-select-all-1" type="checkbox">
|
23 |
</td>
|
24 |
-
<th
|
25 |
-
<th
|
26 |
-
<th
|
27 |
-
<th
|
28 |
</tr>
|
29 |
</thead>
|
30 |
|
@@ -34,11 +34,11 @@
|
|
34 |
</table>
|
35 |
|
36 |
<fieldset class="sucuriscan-clearfix">
|
37 |
-
<label
|
38 |
<select name="sucuriscan_cronjob_action">
|
39 |
%%%SUCURI.Cronjob.Schedules%%%
|
40 |
</select>
|
41 |
-
<button type="submit" class="button button-primary"
|
42 |
</fieldset>
|
43 |
</form>
|
44 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Scheduled Tasks</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>The plugin scans your entire website looking for changes which are later reported via the API in the audit logs page. This scanner runs daily but you can change the frequency to meet your own requirements. Notice that scanning your project files too frequently will affect the performance of your website. Be sure to have enough server resources before changing this option. The memory limit and maximum execution time are two of the PHP options that your server will set to stop your website from consuming too much resources.</p>
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.NoSPL.Visibility%%">
|
9 |
+
<p>The scanner uses the <a href="http://php.net/manual/en/class.splfileobject.php" target="_blank" rel="noopener">PHP SPL library</a> and the <a target="_blank" href="http://php.net/manual/en/class.filesystemiterator.php" rel="noopener">Filesystem Iterator</a> class to scan the directory tree where your website is located in the server. This library is only available on PHP 5 >= 5.3.0 — OR — PHP 7; if you have an older version of PHP the plugin will not work as expected. Please ask your hosting provider to advice you on this matter.</p>
|
10 |
</div>
|
11 |
|
12 |
+
<p>Scheduled tasks are rules registered in your database by a plugin, theme, or the base system itself; they are used to automatically execute actions defined in the code every certain amount of time. A good use of these rules is to generate backup files of your site, execute a security scanner, or remove unused elements like drafts. <b>Note:</b> Scheduled tasks can be re-installed by any plugin/theme automatically, consider to deactivate the plugin entirely if you want to get rid of the scheduled tasks.</p>
|
13 |
|
14 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
15 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
21 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
22 |
<input id="cb-select-all-1" type="checkbox">
|
23 |
</td>
|
24 |
+
<th>Name</th>
|
25 |
+
<th>Schedule</th>
|
26 |
+
<th>Next Due</th>
|
27 |
+
<th>Arguments</th>
|
28 |
</tr>
|
29 |
</thead>
|
30 |
|
34 |
</table>
|
35 |
|
36 |
<fieldset class="sucuriscan-clearfix">
|
37 |
+
<label>Action:</label>
|
38 |
<select name="sucuriscan_cronjob_action">
|
39 |
%%%SUCURI.Cronjob.Schedules%%%
|
40 |
</select>
|
41 |
+
<button type="submit" class="button button-primary">Submit</button>
|
42 |
</fieldset>
|
43 |
</form>
|
44 |
</div>
|
inc/tpl/settings-scanner-ignore-folders.html.tpl
CHANGED
@@ -1,35 +1,17 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
-
|
8 |
-
<script type="text/javascript">
|
9 |
-
/* global jQuery */
|
10 |
-
/* jshint camelcase: false */
|
11 |
-
jQuery(function ($) {
|
12 |
-
$('.sucuriscan-ignorescanning tbody').html(
|
13 |
-
'<tr><td colspan="3"><span>@@SUCURI.Loading@@</span></td></tr>'
|
14 |
-
);
|
15 |
-
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
16 |
-
action: 'sucuriscan_ajax',
|
17 |
-
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
18 |
-
form_action: 'get_ignored_files',
|
19 |
-
}, function (data) {
|
20 |
-
$('.sucuriscan-ignorescanning tbody').html(data);
|
21 |
-
});
|
22 |
-
});
|
23 |
-
</script>
|
24 |
|
25 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
26 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
27 |
-
<input type="hidden" name="sucuriscan_ignorescanning_action" value="ignore" />
|
28 |
|
29 |
<fieldset class="sucuriscan-clearfix">
|
30 |
-
<label
|
31 |
-
<input type="text" name="
|
32 |
-
<button type="submit" class="button button-primary"
|
33 |
</fieldset>
|
34 |
</form>
|
35 |
|
@@ -44,25 +26,16 @@
|
|
44 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
45 |
<input id="cb-select-all-1" type="checkbox">
|
46 |
</td>
|
47 |
-
<th class="manage-column"
|
48 |
-
<th class="manage-column"
|
49 |
</thead>
|
50 |
|
51 |
<tbody>
|
|
|
52 |
</tbody>
|
53 |
</table>
|
54 |
|
55 |
-
<
|
56 |
-
<label>
|
57 |
-
<select name="sucuriscan_ignorescanning_action">
|
58 |
-
<option value="">@@SUCURI.Action@@</option>
|
59 |
-
<option value="ignore">@@SUCURI.Ignore@@</option>
|
60 |
-
<option value="unignore">@@SUCURI.Unignore@@</option>
|
61 |
-
</select>
|
62 |
-
</label>
|
63 |
-
|
64 |
-
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
65 |
-
</div>
|
66 |
</form>
|
67 |
</div>
|
68 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Ignore Files And Folders During The Scans</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Use this tool to select the files and/or folders that are too heavy for the scanner to process. These are usually folders with images, media files like videos and audios, backups and — in general — anything that is not code-related. Ignoring these files or folders will reduce the memory consumption of the PHP script.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
|
|
10 |
|
11 |
<fieldset class="sucuriscan-clearfix">
|
12 |
+
<label>Ignore a file or directory:</label>
|
13 |
+
<input type="text" name="sucuriscan_ignorefolder" placeholder="e.g. /private/directory/" />
|
14 |
+
<button type="submit" class="button button-primary">Submit</button>
|
15 |
</fieldset>
|
16 |
</form>
|
17 |
|
26 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
27 |
<input id="cb-select-all-1" type="checkbox">
|
28 |
</td>
|
29 |
+
<th class="manage-column">File Path</th>
|
30 |
+
<th class="manage-column">Status</th>
|
31 |
</thead>
|
32 |
|
33 |
<tbody>
|
34 |
+
%%%SUCURI.IgnoreScan.List%%%
|
35 |
</tbody>
|
36 |
</table>
|
37 |
|
38 |
+
<button type="submit" class="button button-primary">Unignore Selected Directories</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
</form>
|
40 |
</div>
|
41 |
</div>
|
inc/tpl/settings-scanner-ignore-folders.snippet.tpl
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
|
2 |
<tr>
|
3 |
<th class="check-column">
|
4 |
-
<input type="checkbox" name="
|
5 |
</th>
|
6 |
|
7 |
-
<td><span class="sucuriscan-monospace sucuriscan-wraptext">%%SUCURI.IgnoreScan.
|
8 |
|
9 |
-
<td>%%SUCURI.IgnoreScan.
|
10 |
</tr>
|
1 |
|
2 |
<tr>
|
3 |
<th class="check-column">
|
4 |
+
<input type="checkbox" name="sucuriscan_unignorefolders[]" value="%%SUCURI.IgnoreScan.Directory%%" />
|
5 |
</th>
|
6 |
|
7 |
+
<td><span class="sucuriscan-monospace sucuriscan-wraptext">%%SUCURI.IgnoreScan.Directory%%</span></td>
|
8 |
|
9 |
+
<td>%%SUCURI.IgnoreScan.IgnoredAt%%</td>
|
10 |
</tr>
|
inc/tpl/settings-scanner-integrity-cache.html.tpl
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -16,9 +16,9 @@
|
|
16 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
17 |
<input id="cb-select-all-1" type="checkbox">
|
18 |
</td>
|
19 |
-
<th
|
20 |
-
<th
|
21 |
-
<th
|
22 |
</tr>
|
23 |
</thead>
|
24 |
|
@@ -27,14 +27,14 @@
|
|
27 |
|
28 |
<tr class="sucuriscan-%%SUCURI.NoFilesVisibility%%">
|
29 |
<td colspan="4">
|
30 |
-
<em
|
31 |
</td>
|
32 |
</tr>
|
33 |
</tbody>
|
34 |
</table>
|
35 |
|
36 |
<p>
|
37 |
-
<button type="submit" class="button button-primary"
|
38 |
</p>
|
39 |
</form>
|
40 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">WordPress Integrity (False Positives)</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>Since the scanner doesn't reads the files during the execution of the integrity check, it is possible to find false positives. Files listed here have been marked as false positives and will be ignored by the scanner in subsequent scans.</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
16 |
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
17 |
<input id="cb-select-all-1" type="checkbox">
|
18 |
</td>
|
19 |
+
<th>Reason</th>
|
20 |
+
<th>Ignored At</th>
|
21 |
+
<th>File Path</th>
|
22 |
</tr>
|
23 |
</thead>
|
24 |
|
27 |
|
28 |
<tr class="sucuriscan-%%SUCURI.NoFilesVisibility%%">
|
29 |
<td colspan="4">
|
30 |
+
<em>no data available</em>
|
31 |
</td>
|
32 |
</tr>
|
33 |
</tbody>
|
34 |
</table>
|
35 |
|
36 |
<p>
|
37 |
+
<button type="submit" class="button button-primary">Stop Ignoring the Selected Files</button>
|
38 |
</p>
|
39 |
</form>
|
40 |
</div>
|
inc/tpl/settings-scanner-integrity-diff-utility.html.tpl
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.DiffUtility.StatusNum%%">
|
9 |
-
<span
|
10 |
|
11 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
12 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">WordPress Integrity Diff Utility</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>If your server allows the execution of system commands, you can configure the plugin to use the <a href="https://en.wikipedia.org/wiki/Diff_utility" target="_blank" rel="noopener">Unix Diff Utility</a> to compare the actual content of the file installed in the website and the original file provided by WordPress. This will show the differences between both files and then you can act upon the information provided.</p>
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.DiffUtility.StatusNum%%">
|
9 |
+
<span>WordPress Integrity Diff Utility — %%SUCURI.DiffUtility.Status%%</span>
|
10 |
|
11 |
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
12 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
inc/tpl/settings-scanner-integrity-language.html.tpl
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
|
2 |
-
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title">@@SUCURI.IntegrityLanguageTitle@@</h3>
|
4 |
-
|
5 |
-
<div class="inside">
|
6 |
-
<p>@@SUCURI.IntegrityInfo@@</p>
|
7 |
-
|
8 |
-
<div class="sucuriscan-inline-alert-info">
|
9 |
-
<p>@@SUCURI.IntegrityNote@@</p>
|
10 |
-
</div>
|
11 |
-
|
12 |
-
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
13 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
14 |
-
<fieldset class="sucuriscan-clearfix">
|
15 |
-
<label>WordPress Locale:</label>
|
16 |
-
<select name="sucuriscan_set_language">
|
17 |
-
%%%SUCURI.Integrity.LanguageDropdown%%%
|
18 |
-
</select>
|
19 |
-
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
20 |
-
<span><em>(WordPress Locale %%SUCURI.Integrity.WordPressLocale%%)</em></span>
|
21 |
-
</fieldset>
|
22 |
-
</form>
|
23 |
-
</div>
|
24 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/settings-webinfo-details.html.tpl
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-server-info">
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Environment Variables</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-server-info">
|
inc/tpl/settings-webinfo-htaccess.html.tpl
CHANGED
@@ -1,20 +1,20 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-success sucuriscan-%%SUCURI.HTAccess.FoundVisible%%">
|
9 |
-
<p
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.HTAccess.NotFoundVisible%%">
|
13 |
-
<p
|
14 |
</div>
|
15 |
|
16 |
<div class="sucuriscan-inline-alert-info sucuriscan-%%SUCURI.HTAccess.StandardVisible%%">
|
17 |
-
<p
|
18 |
</div>
|
19 |
|
20 |
<textarea readonly class="sucuriscan-full-textarea sucuriscan-monospace %%SUCURI.HTAccess.TextareaVisible%%">%%SUCURI.HTAccess.Content%%</textarea>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Access File Integrity</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>The <code>.htaccess</code> is a distributed configuration file, and is how the Apache web server handles configuration changes on a per-directory basis. WordPress uses this file to manipulate how Apache serves files from its root directory and subdirectories thereof; most notably, it modifies this file to be able to handle pretty permalinks.</p>
|
7 |
|
8 |
<div class="sucuriscan-inline-alert-success sucuriscan-%%SUCURI.HTAccess.FoundVisible%%">
|
9 |
+
<p>Htaccess file found in <code>%%SUCURI.HTAccess.Fpath%%</code></p>
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.HTAccess.NotFoundVisible%%">
|
13 |
+
<p>Your website has no <code>.htaccess</code> file or it was not found in the default location.</p>
|
14 |
</div>
|
15 |
|
16 |
<div class="sucuriscan-inline-alert-info sucuriscan-%%SUCURI.HTAccess.StandardVisible%%">
|
17 |
+
<p>The main <code>.htaccess</code> file in your site has the standard rules for a WordPress installation. You can customize it to improve the performance and change the behaviour of the redirections for pages and posts in your site. To get more information visit the official documentation at <a target="_blank" rel="noopener" href="https://codex.wordpress.org/Using_Permalinks#Creating_and_editing_.28.htaccess.29"> Codex WordPress - Creating and editing (.htaccess)</a></p>
|
18 |
</div>
|
19 |
|
20 |
<textarea readonly class="sucuriscan-full-textarea sucuriscan-monospace %%SUCURI.HTAccess.TextareaVisible%%">%%SUCURI.HTAccess.Content%%</textarea>
|
inc/tpl/settings.html.tpl
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
-
<li><a href="%%SUCURI.URL.Settings%%#general"
|
5 |
-
<li><a href="%%SUCURI.URL.Settings%%#scanner"
|
6 |
-
<li><a href="%%SUCURI.URL.Settings%%#hardening"
|
7 |
-
<li><a href="%%SUCURI.URL.Settings%%#posthack"
|
8 |
-
<li><a href="%%SUCURI.URL.Settings%%#alerts"
|
9 |
-
<li><a href="%%SUCURI.URL.Settings%%#apiservice"
|
10 |
-
<li><a href="%%SUCURI.URL.Settings%%#webinfo"
|
11 |
</ul>
|
12 |
|
13 |
<div class="sucuriscan-tabs-containers">
|
@@ -34,8 +34,6 @@
|
|
34 |
|
35 |
%%%SUCURI.Settings.Scanner.IntegrityDiffUtility%%%
|
36 |
|
37 |
-
%%%SUCURI.Settings.Scanner.IntegrityLanguage%%%
|
38 |
-
|
39 |
%%%SUCURI.Settings.Scanner.IntegrityCache%%%
|
40 |
|
41 |
%%%SUCURI.Settings.Scanner.IgnoreFolders%%%
|
1 |
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
+
<li><a href="%%SUCURI.URL.Settings%%#general">General</a></li>
|
5 |
+
<li><a href="%%SUCURI.URL.Settings%%#scanner">Scanner</a></li>
|
6 |
+
<li><a href="%%SUCURI.URL.Settings%%#hardening">Hardening</a></li>
|
7 |
+
<li><a href="%%SUCURI.URL.Settings%%#posthack">Post-Hack</a></li>
|
8 |
+
<li><a href="%%SUCURI.URL.Settings%%#alerts">Alerts</a></li>
|
9 |
+
<li><a href="%%SUCURI.URL.Settings%%#apiservice">API Service Communication</a></li>
|
10 |
+
<li><a href="%%SUCURI.URL.Settings%%#webinfo">Website Info</a></li>
|
11 |
</ul>
|
12 |
|
13 |
<div class="sucuriscan-tabs-containers">
|
34 |
|
35 |
%%%SUCURI.Settings.Scanner.IntegrityDiffUtility%%%
|
36 |
|
|
|
|
|
37 |
%%%SUCURI.Settings.Scanner.IntegrityCache%%%
|
38 |
|
39 |
%%%SUCURI.Settings.Scanner.IgnoreFolders%%%
|
inc/tpl/sitecheck-blacklist.html.tpl
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel sucuriscan-sitecheck-list sucuriscan-sitecheck-blacklist">
|
3 |
-
<h3 class="sucuriscan-tag-title sucuriscan-tag-%%SUCURI.Blacklist.Color%%">
|
4 |
-
%%SUCURI.Blacklist.Title%%
|
5 |
-
</h3>
|
6 |
|
7 |
<ul>
|
8 |
%%%SUCURI.Blacklist.Content%%%
|
1 |
|
2 |
<div class="sucuriscan-panel sucuriscan-sitecheck-list sucuriscan-sitecheck-blacklist">
|
3 |
+
<h3 class="sucuriscan-tag-title sucuriscan-tag-%%SUCURI.Blacklist.Color%%">%%SUCURI.Blacklist.Title%%</h3>
|
|
|
|
|
4 |
|
5 |
<ul>
|
6 |
%%%SUCURI.Blacklist.Content%%%
|
inc/tpl/sitecheck-blacklist.snippet.tpl
CHANGED
@@ -1,6 +1,4 @@
|
|
1 |
|
2 |
<li class="sucuriscan-sitecheck-list-%%SUCURI.Blacklist.Status%%">
|
3 |
-
<a href="%%SUCURI.Blacklist.URL%%" target="_blank">
|
4 |
-
%%SUCURI.Blacklist.Service%%
|
5 |
-
</a>
|
6 |
</li>
|
1 |
|
2 |
<li class="sucuriscan-sitecheck-list-%%SUCURI.Blacklist.Status%%">
|
3 |
+
<a href="%%SUCURI.Blacklist.URL%%" target="_blank" rel="noopener">%%SUCURI.Blacklist.Service%%</a>
|
|
|
|
|
4 |
</li>
|
inc/tpl/sitecheck-malware.html.tpl
CHANGED
@@ -17,6 +17,6 @@
|
|
17 |
</ul>
|
18 |
|
19 |
<div class="sucuriscan-sitecheck-footnote">
|
20 |
-
<p
|
21 |
</div>
|
22 |
</div>
|
17 |
</ul>
|
18 |
|
19 |
<div class="sucuriscan-sitecheck-footnote">
|
20 |
+
<p>If our free scanner did not detect any issue, you may have a more complicated and hidden problem. You can <a href="https://sucuri.net/website-security-platform/signup" target="_blank" rel="noopener">sign up with Sucuri</a> for a complete and in-depth scan + cleanup (not included in the free checks).</p>
|
21 |
</div>
|
22 |
</div>
|
inc/tpl/sitecheck-malware.snippet.tpl
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
|
2 |
<li class="sucuriscan-sitecheck-list-WARN">
|
3 |
-
<a href="%%SUCURI.Malware.MalwareDocs%%" target="_blank">%%SUCURI.Malware.MalwareType%%</a>
|
4 |
|
5 |
-
<p>%%SUCURI.Malware.AlertMessage%% <a href="%%SUCURI.Malware.InfectedURL%%" target="_blank">%%SUCURI.Malware.InfectedURL%%</a></p>
|
6 |
|
7 |
-
<p><em class="sucuriscan-tooltip" content="%%SUCURI.Malware.MalwarePayload%%">(
|
8 |
</li>
|
1 |
|
2 |
<li class="sucuriscan-sitecheck-list-WARN">
|
3 |
+
<a href="%%SUCURI.Malware.MalwareDocs%%" target="_blank" rel="noopener">%%SUCURI.Malware.MalwareType%%</a>
|
4 |
|
5 |
+
<p>%%SUCURI.Malware.AlertMessage%% <a href="%%SUCURI.Malware.InfectedURL%%" target="_blank" rel="noopener">%%SUCURI.Malware.InfectedURL%%</a></p>
|
6 |
|
7 |
+
<p><em class="sucuriscan-tooltip" content="%%SUCURI.Malware.MalwarePayload%%">(Hover to see the Payload)</em></p>
|
8 |
</li>
|
inc/tpl/sitecheck-recommendations.html.tpl
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel sucuriscan-sitecheck-list sucuriscan-sitecheck-recommendations sucuriscan-%%SUCURI.Recommendations.Visibility%%">
|
3 |
-
<h3 class="sucuriscan-tag-title sucuriscan-tag-blue"
|
4 |
|
5 |
<ul>
|
6 |
%%%SUCURI.Recommendations.Content%%%
|
1 |
|
2 |
<div class="sucuriscan-panel sucuriscan-sitecheck-list sucuriscan-sitecheck-recommendations sucuriscan-%%SUCURI.Recommendations.Visibility%%">
|
3 |
+
<h3 class="sucuriscan-tag-title sucuriscan-tag-blue">Recomendations</h3>
|
4 |
|
5 |
<ul>
|
6 |
%%%SUCURI.Recommendations.Content%%%
|
inc/tpl/sitecheck-recommendations.snippet.tpl
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
<li class="sucuriscan-sitecheck-list-NOTICE">
|
3 |
-
<a href="%%SUCURI.Recommendations.URL%%" target="_blank">
|
4 |
<b>%%SUCURI.Recommendations.Title%%</b><br>
|
5 |
<span>%%SUCURI.Recommendations.Value%%</span>
|
6 |
</a>
|
1 |
|
2 |
<li class="sucuriscan-sitecheck-list-NOTICE">
|
3 |
+
<a href="%%SUCURI.Recommendations.URL%%" target="_blank" rel="noopener">
|
4 |
<b>%%SUCURI.Recommendations.Title%%</b><br>
|
5 |
<span>%%SUCURI.Recommendations.Value%%</span>
|
6 |
</a>
|
inc/tpl/sitecheck-target.html.tpl
CHANGED
@@ -1,23 +1,20 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title"
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
-
<span
|
10 |
-
href="https://sitecheck.sucuri.net/results/%%SUCURI.SiteCheck.Target%%">
|
11 |
-
https://sitecheck.sucuri.net/results/%%SUCURI.SiteCheck.Target%%</a>
|
12 |
-
</span>
|
13 |
</div>
|
14 |
|
15 |
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
16 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
17 |
<fieldset class="sucuriscan-clearfix">
|
18 |
-
<label
|
19 |
<input type="text" name="sucuriscan_sitecheck_target" />
|
20 |
-
<button type="submit" class="button button-primary"
|
21 |
</fieldset>
|
22 |
</form>
|
23 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">Malware Scan Target</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>The remote malware scanner provided by the plugin is powered by <a href="https://sitecheck.sucuri.net/" target="_blank" rel="noopener">Sucuri SiteCheck</a>, a service that takes a publicly accessible URL and scans it for malicious code. If your website is not visible to the Internet, for example, if it is hosted in a local development environment or a restricted network, the scanner will not be able to work on it. Additionally, if the website was installed in a non-standard directory the scanner will report a "404 Not Found" error. You can use this option to change the URL that will be scanned.</p>
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
+
<span>Malware Scan Target — <a href="https://sitecheck.sucuri.net/results/%%SUCURI.SiteCheck.Target%%" target="_blank" rel="noopener">https://sitecheck.sucuri.net/results/%%SUCURI.SiteCheck.Target%%</a></span>
|
|
|
|
|
|
|
10 |
</div>
|
11 |
|
12 |
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
13 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
14 |
<fieldset class="sucuriscan-clearfix">
|
15 |
+
<label>Malware Scan Target:</label>
|
16 |
<input type="text" name="sucuriscan_sitecheck_target" />
|
17 |
+
<button type="submit" class="button button-primary">Submit</button>
|
18 |
</fieldset>
|
19 |
</form>
|
20 |
</div>
|
languages/index.html
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
<!-- Avoid the directory listing. -->
|
|
languages/sucuri-scanner-en_US.mo
DELETED
Binary file
|
languages/sucuri-scanner-en_US.po
DELETED
@@ -1,1512 +0,0 @@
|
|
1 |
-
msgid ""
|
2 |
-
msgstr ""
|
3 |
-
"Content-Transfer-Encoding: 8bit\n"
|
4 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
5 |
-
"Language-Team: https://sucuri.net/\n"
|
6 |
-
"Language: en_US\n"
|
7 |
-
"Last-Translator: Sucuri Inc. <info@sucuri.net>\n"
|
8 |
-
"MIME-Version: 1.0\n"
|
9 |
-
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
10 |
-
"PO-Revision-Date: \n"
|
11 |
-
"POT-Creation-Date: 2017-06-01 09:00-0700\n"
|
12 |
-
"Project-Id-Version: Sucuri Scanner\n"
|
13 |
-
|
14 |
-
msgid "Review"
|
15 |
-
msgstr "Review"
|
16 |
-
|
17 |
-
msgid "Dashboard"
|
18 |
-
msgstr "Dashboard"
|
19 |
-
|
20 |
-
msgid "Firewall"
|
21 |
-
msgstr "Firewall (WAF)"
|
22 |
-
|
23 |
-
msgid "LastLogins"
|
24 |
-
msgstr "Last Logins"
|
25 |
-
|
26 |
-
msgid "Settings"
|
27 |
-
msgstr "Settings"
|
28 |
-
|
29 |
-
msgid "AuditLogs"
|
30 |
-
msgstr "Audit Logs"
|
31 |
-
|
32 |
-
msgid "ClearCache"
|
33 |
-
msgstr "Clear Cache"
|
34 |
-
|
35 |
-
msgid "IPAccess"
|
36 |
-
msgstr "IP Access"
|
37 |
-
|
38 |
-
msgid "GenerateAPIKey"
|
39 |
-
msgstr "Generate API Key"
|
40 |
-
|
41 |
-
msgid "APIKeyRecovery"
|
42 |
-
msgstr "Plugin API Key Recovery"
|
43 |
-
|
44 |
-
msgid "Copyright"
|
45 |
-
msgstr "Copyright © %%SUCURI.Year%% Sucuri Inc. All Rights Reserved."
|
46 |
-
|
47 |
-
msgid "AccessDenied"
|
48 |
-
msgstr "Access denied by Sucuri Inc."
|
49 |
-
|
50 |
-
msgid "NonceFailure"
|
51 |
-
msgstr "WordPress Nonce verification failed, try again going back and checking the form."
|
52 |
-
|
53 |
-
msgid "NewsletterInvitation"
|
54 |
-
msgstr "Do you want to get vulnerability disclosures? Subscribe to our newsletter <a href=\"http://sucuri.hs-sites.com/subscribe-to-security\" target=\"_blank\" rel=\"noopener\">here</a>"
|
55 |
-
|
56 |
-
msgid "EnableAPIServiceAgain"
|
57 |
-
msgstr "API service communication is disabled, if you just updated the plugin this might be a good opportunity to test this feature once again with the new code. Enable it again from the \"API Service\" panel located in the settings page."
|
58 |
-
|
59 |
-
msgid "Save"
|
60 |
-
msgstr "Save"
|
61 |
-
|
62 |
-
msgid "Delete"
|
63 |
-
msgstr "Delete"
|
64 |
-
|
65 |
-
msgid "InvalidAPIKey"
|
66 |
-
msgstr "Invalid API key format"
|
67 |
-
|
68 |
-
msgid "ErrorNoInfo"
|
69 |
-
msgstr "Unknown error, there is no information."
|
70 |
-
|
71 |
-
msgid "ErrorLogFileNotFound"
|
72 |
-
msgstr "; this generally happens when you add an invalid API key, the key will be deleted automatically to hide these warnings, if you want to recover it go to the settings page and use the recover button to send the key to your email address: %1$s"
|
73 |
-
|
74 |
-
msgid "ErrorWrongAPIKey"
|
75 |
-
msgstr "; invalid firewall API key: %1$s"
|
76 |
-
|
77 |
-
msgid "ErrorSSLCertificate"
|
78 |
-
msgstr ". Your website seems to use an old version of the OpenSSL library or the CURL extension was compiled without support for the algorithm used on the API service. Contact your hosting provider to fix this issue."
|
79 |
-
|
80 |
-
msgid "ErrorInvalidEmail"
|
81 |
-
msgstr "Email has an invalid format, or the host associated to the email has no MX records."
|
82 |
-
|
83 |
-
msgid "AlertAPIKeySet"
|
84 |
-
msgstr "The API key for your site was successfully generated and saved."
|
85 |
-
|
86 |
-
msgid "Yes"
|
87 |
-
msgstr "Yes"
|
88 |
-
|
89 |
-
msgid "No"
|
90 |
-
msgstr "No"
|
91 |
-
|
92 |
-
msgid "Okay"
|
93 |
-
msgstr "OK"
|
94 |
-
|
95 |
-
msgid "Enable"
|
96 |
-
msgstr "Enable"
|
97 |
-
|
98 |
-
msgid "Enabled"
|
99 |
-
msgstr "Enabled"
|
100 |
-
|
101 |
-
msgid "Disable"
|
102 |
-
msgstr "Disable"
|
103 |
-
|
104 |
-
msgid "Disabled"
|
105 |
-
msgstr "Disabled"
|
106 |
-
|
107 |
-
msgid "Ignore"
|
108 |
-
msgstr "Ignore"
|
109 |
-
|
110 |
-
msgid "Unignore"
|
111 |
-
msgstr "Unignore"
|
112 |
-
|
113 |
-
msgid "Ignored"
|
114 |
-
msgstr "Ignored"
|
115 |
-
|
116 |
-
msgid "Submit"
|
117 |
-
msgstr "Submit"
|
118 |
-
|
119 |
-
msgid "Done"
|
120 |
-
msgstr "Done"
|
121 |
-
|
122 |
-
msgid "Error"
|
123 |
-
msgstr "Error"
|
124 |
-
|
125 |
-
msgid "Good"
|
126 |
-
msgstr "good"
|
127 |
-
|
128 |
-
msgid "Edit"
|
129 |
-
msgstr "Edit"
|
130 |
-
|
131 |
-
msgid "NotSet"
|
132 |
-
msgstr "(not set)"
|
133 |
-
|
134 |
-
msgid "Download"
|
135 |
-
msgstr "Download"
|
136 |
-
|
137 |
-
msgid "NotRandomized"
|
138 |
-
msgstr "not randomized"
|
139 |
-
|
140 |
-
msgid "NotWritable"
|
141 |
-
msgstr "Not Writable"
|
142 |
-
|
143 |
-
msgid "ParentNotWritable"
|
144 |
-
msgstr "File parent directory is not writable."
|
145 |
-
|
146 |
-
msgid "DoesNotExist"
|
147 |
-
msgstr "Does Not Exist"
|
148 |
-
|
149 |
-
msgid "Email"
|
150 |
-
msgstr "E-mail"
|
151 |
-
|
152 |
-
msgid "Website"
|
153 |
-
msgstr "Website"
|
154 |
-
|
155 |
-
msgid "Message"
|
156 |
-
msgstr "Message"
|
157 |
-
|
158 |
-
msgid "Information"
|
159 |
-
msgstr "Information"
|
160 |
-
|
161 |
-
msgid "Event"
|
162 |
-
msgstr "Event"
|
163 |
-
|
164 |
-
msgid "Exists"
|
165 |
-
msgstr "Exists"
|
166 |
-
|
167 |
-
msgid "Writable"
|
168 |
-
msgstr "Writable"
|
169 |
-
|
170 |
-
msgid "Today"
|
171 |
-
msgstr "Today"
|
172 |
-
|
173 |
-
msgid "NoLogs"
|
174 |
-
msgstr "There are no logs."
|
175 |
-
|
176 |
-
msgid "SelfHosting"
|
177 |
-
msgstr "Log Exporter"
|
178 |
-
|
179 |
-
msgid "SelfHostingEnabled"
|
180 |
-
msgstr "The log exporter feature has been enabled and the data file was successfully set."
|
181 |
-
|
182 |
-
msgid "SelfHostingDisabled"
|
183 |
-
msgstr "The log exporter feature has been disabled"
|
184 |
-
|
185 |
-
msgid "SelfHostingInfo"
|
186 |
-
msgstr "This option allows you to export the WordPress audit logs to a local log file that can be read by a SIEM or any log analysis software <em>(we recommend OSSEC)</em>. That will give visibility from within WordPress to complement your log monitoring infrastructure. <b>NOTE:</b> Do not use a publicly accessible file, you must use a file at least one level up the document root to prevent leaks of information."
|
187 |
-
|
188 |
-
msgid "SelfHostingFallback"
|
189 |
-
msgstr "You don't have a valid API key to communicate with the remote API service. However, the self-hosting monitor is enabled, the plugin will read the logs from that file and display the data here. Notice that only the latest logs will be processed to keep a low memory footprint. Consider to generate a free API key to get a better coverage of the activity in your website."
|
190 |
-
|
191 |
-
msgid "AuditLogsCache"
|
192 |
-
msgstr "This data is cached for %%SUCURI.AuditLogs.Lifetime%% seconds"
|
193 |
-
|
194 |
-
msgid "Refresh"
|
195 |
-
msgstr "Refresh"
|
196 |
-
|
197 |
-
msgid "AuditLogsNoAPI"
|
198 |
-
msgstr "The API service is not available; logs are coming from the local server"
|
199 |
-
|
200 |
-
msgid "AuditLogsQueue"
|
201 |
-
msgstr "logs in the queue"
|
202 |
-
|
203 |
-
msgid "SendLogs"
|
204 |
-
msgstr "Send Logs"
|
205 |
-
|
206 |
-
msgid "UnsupportedWordPress"
|
207 |
-
msgstr "WordPress version is not supported."
|
208 |
-
|
209 |
-
msgid "NoWordPressFile"
|
210 |
-
msgstr "File is not part of the official WordPress installation."
|
211 |
-
|
212 |
-
msgid "ThereAreNoDifferences"
|
213 |
-
msgstr "There are no differences between the installed and original files"
|
214 |
-
|
215 |
-
msgid "ScheduledTask"
|
216 |
-
msgstr "%1$s (every %2$d seconds)"
|
217 |
-
|
218 |
-
msgid "ScheduledTaskNever"
|
219 |
-
msgstr "Never (no execution)"
|
220 |
-
|
221 |
-
msgid "SucuriAlert"
|
222 |
-
msgstr "Sucuri Alert"
|
223 |
-
|
224 |
-
msgid "UpdatedEmailSubject"
|
225 |
-
msgstr "The email subject has been successfully updated"
|
226 |
-
|
227 |
-
msgid "InvalidEmailSubject"
|
228 |
-
msgstr "Invalid characters in the email subject."
|
229 |
-
|
230 |
-
msgid "EmailSubject.available_updates"
|
231 |
-
msgstr "Available Updates"
|
232 |
-
|
233 |
-
msgid "EmailSubject.bruteforce_attack"
|
234 |
-
msgstr "Bruteforce Attack"
|
235 |
-
|
236 |
-
msgid "EmailSubject.failed_login"
|
237 |
-
msgstr "Failed Login"
|
238 |
-
|
239 |
-
msgid "EmailSubject.plugin_activated"
|
240 |
-
msgstr "Plugin Activated"
|
241 |
-
|
242 |
-
msgid "EmailSubject.plugin_change"
|
243 |
-
msgstr "Plugin Change"
|
244 |
-
|
245 |
-
msgid "EmailSubject.plugin_deactivated"
|
246 |
-
msgstr "Plugin Deactivated"
|
247 |
-
|
248 |
-
msgid "EmailSubject.plugin_deleted"
|
249 |
-
msgstr "Plugin Deleted"
|
250 |
-
|
251 |
-
msgid "EmailSubject.plugin_installed"
|
252 |
-
msgstr "Plugin Installed"
|
253 |
-
|
254 |
-
msgid "EmailSubject.plugin_updated"
|
255 |
-
msgstr "Plugin Updated"
|
256 |
-
|
257 |
-
msgid "EmailSubject.post_publication"
|
258 |
-
msgstr "Post Publication"
|
259 |
-
|
260 |
-
msgid "EmailSubject.scan_checksums"
|
261 |
-
msgstr "Scan Checksums"
|
262 |
-
|
263 |
-
msgid "EmailSubject.settings_updated"
|
264 |
-
msgstr "Settings Updated"
|
265 |
-
|
266 |
-
msgid "EmailSubject.success_login"
|
267 |
-
msgstr "Success Login"
|
268 |
-
|
269 |
-
msgid "EmailSubject.theme_activated"
|
270 |
-
msgstr "Theme Activated"
|
271 |
-
|
272 |
-
msgid "EmailSubject.theme_deleted"
|
273 |
-
msgstr "Theme Deleted"
|
274 |
-
|
275 |
-
msgid "EmailSubject.theme_editor"
|
276 |
-
msgstr "Theme Editor"
|
277 |
-
|
278 |
-
msgid "EmailSubject.theme_installed"
|
279 |
-
msgstr "Theme Installed"
|
280 |
-
|
281 |
-
msgid "EmailSubject.theme_updated"
|
282 |
-
msgstr "Theme Updated"
|
283 |
-
|
284 |
-
msgid "EmailSubject.user_registration"
|
285 |
-
msgstr "User Registration"
|
286 |
-
|
287 |
-
msgid "EmailSubject.website_updated"
|
288 |
-
msgstr "Website Updated"
|
289 |
-
|
290 |
-
msgid "EmailSubject.widget_added"
|
291 |
-
msgstr "Widget Added"
|
292 |
-
|
293 |
-
msgid "EmailSubject.widget_deleted"
|
294 |
-
msgstr "Widget Deleted"
|
295 |
-
|
296 |
-
msgid "EmailSubject.post_update"
|
297 |
-
msgstr "Post Update"
|
298 |
-
|
299 |
-
msgid "EmailSubject.core_integrity_checks"
|
300 |
-
msgstr "Core Integrity Checks"
|
301 |
-
|
302 |
-
msgid "EmailSubject.password_change"
|
303 |
-
msgstr "Password Change"
|
304 |
-
|
305 |
-
msgid "FailedLoginFooter"
|
306 |
-
msgstr "<br><br><em>Explanation: Someone failed to login to your site. If you are getting too many of these messages, it is likely your site is under a password guessing brute-force attack [1]. You can disable the failed login alerts from here [2]. Alternatively, you can consider to install a firewall between your website and your visitors to filter out these and other attacks, take a look at Sucuri Firewall [3].</em><br><br>[1] <a href='https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing'>https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing</a><br>[2] <a href='%1$s'>%2$s</a> <br>[3] <a href='https://sucuri.net/website-firewall/?wpalert'>https://sucuri.net/website-firewall/</a><br>"
|
307 |
-
|
308 |
-
msgid "FirewallAPIKeySet"
|
309 |
-
msgstr "Firewall API key was successfully saved"
|
310 |
-
|
311 |
-
msgid "FirewallAPIKeyUnset"
|
312 |
-
msgstr "Firewall API key was successfully removed"
|
313 |
-
|
314 |
-
msgid "FirewallAPIKeyInvalid"
|
315 |
-
msgstr "Invalid firewall API key"
|
316 |
-
|
317 |
-
msgid "FirewallAPIKeyMissing"
|
318 |
-
msgstr "Firewall API key was not found."
|
319 |
-
|
320 |
-
msgid "NoData"
|
321 |
-
msgstr "no data available"
|
322 |
-
|
323 |
-
msgid "FirewallDoCache"
|
324 |
-
msgstr "enabled (recommended)"
|
325 |
-
|
326 |
-
msgid "FirewallSiteCache"
|
327 |
-
msgstr "site caching (using your site headers)"
|
328 |
-
|
329 |
-
msgid "FirewallNoCache"
|
330 |
-
msgstr "minimal (only for a few minutes)"
|
331 |
-
|
332 |
-
msgid "FirewallNoCacheAtAll"
|
333 |
-
msgstr "caching disabled (use with caution)"
|
334 |
-
|
335 |
-
msgid "FirewallNotEnabled"
|
336 |
-
msgstr "Firewall is not enabled on your site, or your API key is invalid."
|
337 |
-
|
338 |
-
msgid "FirewallClearCacheFailure"
|
339 |
-
msgstr "Could not clear the cache of your site, try later again."
|
340 |
-
|
341 |
-
msgid "Active"
|
342 |
-
msgstr "active"
|
343 |
-
|
344 |
-
msgid "NotActive"
|
345 |
-
msgstr "not active"
|
346 |
-
|
347 |
-
msgid "Unknown"
|
348 |
-
msgstr "unknown"
|
349 |
-
|
350 |
-
msgid "Undefined"
|
351 |
-
msgstr "Undefined"
|
352 |
-
|
353 |
-
msgid "January"
|
354 |
-
msgstr "January"
|
355 |
-
|
356 |
-
msgid "February"
|
357 |
-
msgstr "February"
|
358 |
-
|
359 |
-
msgid "March"
|
360 |
-
msgstr "March"
|
361 |
-
|
362 |
-
msgid "April"
|
363 |
-
msgstr "April"
|
364 |
-
|
365 |
-
msgid "May"
|
366 |
-
msgstr "May"
|
367 |
-
|
368 |
-
msgid "June"
|
369 |
-
msgstr "June"
|
370 |
-
|
371 |
-
msgid "July"
|
372 |
-
msgstr "July"
|
373 |
-
|
374 |
-
msgid "August"
|
375 |
-
msgstr "August"
|
376 |
-
|
377 |
-
msgid "September"
|
378 |
-
msgstr "September"
|
379 |
-
|
380 |
-
msgid "October"
|
381 |
-
msgstr "October"
|
382 |
-
|
383 |
-
msgid "November"
|
384 |
-
msgstr "November"
|
385 |
-
|
386 |
-
msgid "December"
|
387 |
-
msgstr "December"
|
388 |
-
|
389 |
-
msgid "Username"
|
390 |
-
msgstr "Username"
|
391 |
-
|
392 |
-
msgid "Password"
|
393 |
-
msgstr "Password"
|
394 |
-
|
395 |
-
msgid "RemoteAddr"
|
396 |
-
msgstr "IP Address"
|
397 |
-
|
398 |
-
msgid "Hostname"
|
399 |
-
msgstr "Hostname"
|
400 |
-
|
401 |
-
msgid "Browser"
|
402 |
-
msgstr "Web Browser"
|
403 |
-
|
404 |
-
msgid "Datetime"
|
405 |
-
msgstr "Date/Time"
|
406 |
-
|
407 |
-
msgid "Block"
|
408 |
-
msgstr "Block"
|
409 |
-
|
410 |
-
msgid "Unblock"
|
411 |
-
msgstr "Unblock"
|
412 |
-
|
413 |
-
msgid "BlockedAt"
|
414 |
-
msgstr "Blocked At"
|
415 |
-
|
416 |
-
msgid "FirstAttempt"
|
417 |
-
msgstr "First Attempt"
|
418 |
-
|
419 |
-
msgid "LastAttempt"
|
420 |
-
msgstr "Last Attempt"
|
421 |
-
|
422 |
-
msgid "LastActivity"
|
423 |
-
msgstr "Last Activity"
|
424 |
-
|
425 |
-
msgid "AttemptTimestamp"
|
426 |
-
msgstr "Attempt Timestamp"
|
427 |
-
|
428 |
-
msgid "AttemptDatetime"
|
429 |
-
msgstr "Attempt Date/Time"
|
430 |
-
|
431 |
-
msgid "ConfirmOperation"
|
432 |
-
msgstr "You need to confirm that you understand the risk of this operation."
|
433 |
-
|
434 |
-
msgid "UnderstandTheRisk"
|
435 |
-
msgstr "I understand that this operation can not be reverted."
|
436 |
-
|
437 |
-
msgid "NonSupportedAction"
|
438 |
-
msgstr "Requested action is not supported."
|
439 |
-
|
440 |
-
msgid "NonSupportedLanguage"
|
441 |
-
msgstr "Selected language is not supported."
|
442 |
-
|
443 |
-
msgid "NothingSelected"
|
444 |
-
msgstr "Nothing was selected from the list."
|
445 |
-
|
446 |
-
msgid "ItemsProcessed"
|
447 |
-
msgstr "The selected files have been successfully processed."
|
448 |
-
|
449 |
-
msgid "AllItemsProcessed"
|
450 |
-
msgstr "<b>%1$d</b> out of <b>%2$d</b> files were successfully processed."
|
451 |
-
|
452 |
-
msgid "SomeItemsProcessed"
|
453 |
-
msgstr "Only <b>%1$d</b> out of <b>%2$d</b> files were processed."
|
454 |
-
|
455 |
-
msgid "ErrorIntegrityAdded"
|
456 |
-
msgstr "The plugin has no permission to delete this file because it was created by a different system user who has more privileges than your account. Please use FTP to delete it."
|
457 |
-
|
458 |
-
msgid "ErrorIntegrityModified"
|
459 |
-
msgstr "The plugin has no permission to restore this file because it was modified by a different system user who has more privileges than your account. Please use FTP to restore it."
|
460 |
-
|
461 |
-
msgid "ErrorIntegrityRemoved"
|
462 |
-
msgstr "The plugin has no permission to restore this file because its directory is owned by a different system user who has more privileges than your account. Please use FTP to restore it."
|
463 |
-
|
464 |
-
msgid "SecurityAlerts"
|
465 |
-
msgstr "Security Alerts"
|
466 |
-
|
467 |
-
msgid "NoAlertsError"
|
468 |
-
msgstr "You have installed a plugin or theme that is not fully compatible with our plugin, some of the security alerts (like the successful and failed logins) will not be sent to you. To prevent an infinite loop while detecting these changes in the website and sending the email alerts via a custom SMTP plugin, we have decided to stop any attempt to send the emails to prevent fatal errors."
|
469 |
-
|
470 |
-
msgid "AlertSettingsUpdated"
|
471 |
-
msgstr "The alert settings have been updated"
|
472 |
-
|
473 |
-
msgid "OptionNotifyPluginChange"
|
474 |
-
msgstr "Receive email alerts for changes in the settings of the Sucuri plugin"
|
475 |
-
|
476 |
-
msgid "OptionPrettifyMails"
|
477 |
-
msgstr "Receive email alerts in HTML <em>(there may be issues with some mail services)</em>"
|
478 |
-
|
479 |
-
msgid "OptionUseWordPressMail"
|
480 |
-
msgstr "Use WordPress functions to send mails <em>(uncheck to use native PHP functions)</em>"
|
481 |
-
|
482 |
-
msgid "OptionLastLoginRedirection"
|
483 |
-
msgstr "Allow redirection after login to report the last-login information"
|
484 |
-
|
485 |
-
msgid "OptionNotifyScanChecksums"
|
486 |
-
msgstr "Receive email alerts for core integrity checks"
|
487 |
-
|
488 |
-
msgid "OptionNotifyAvailableUpdates"
|
489 |
-
msgstr "Receive email alerts for available updates"
|
490 |
-
|
491 |
-
msgid "OptionNotifyUserRegistration"
|
492 |
-
msgstr "Receive email alerts for new user registration"
|
493 |
-
|
494 |
-
msgid "OptionNotifySuccessLogin"
|
495 |
-
msgstr "Receive email alerts for successful login attempts"
|
496 |
-
|
497 |
-
msgid "OptionNotifyFailedLogin"
|
498 |
-
msgstr "Receive email alerts for failed login attempts <em>(you may receive tons of emails)</em>"
|
499 |
-
|
500 |
-
msgid "OptionNotifyFailedPassword"
|
501 |
-
msgstr "Receive email alerts for failed login attempts including the submitted password"
|
502 |
-
|
503 |
-
msgid "OptionNotifyBruteforceAttack"
|
504 |
-
msgstr "Receive email alerts for password guessing attacks <em>(summary of failed logins per hour)</em>"
|
505 |
-
|
506 |
-
msgid "OptionNotifyPostPublication"
|
507 |
-
msgstr "Receive email alerts for changes in the post status <em>(configure from Ignore Posts Changes)</em>"
|
508 |
-
|
509 |
-
msgid "OptionNotifyWebsiteUpdated"
|
510 |
-
msgstr "Receive email alerts when the WordPress version is updated"
|
511 |
-
|
512 |
-
msgid "OptionNotifySettingsUpdated"
|
513 |
-
msgstr "Receive email alerts when your website settings are updated"
|
514 |
-
|
515 |
-
msgid "OptionNotifyThemeEditor"
|
516 |
-
msgstr "Receive email alerts when a file is modified with theme/plugin editor"
|
517 |
-
|
518 |
-
msgid "OptionNotifyPluginInstalled"
|
519 |
-
msgstr "Receive email alerts when a <b>plugin is installed</b>"
|
520 |
-
|
521 |
-
msgid "OptionNotifyPluginActivated"
|
522 |
-
msgstr "Receive email alerts when a <b>plugin is activated</b>"
|
523 |
-
|
524 |
-
msgid "OptionNotifyPluginDeactivated"
|
525 |
-
msgstr "Receive email alerts when a <b>plugin is deactivated</b>"
|
526 |
-
|
527 |
-
msgid "OptionNotifyPluginUpdated"
|
528 |
-
msgstr "Receive email alerts when a <b>plugin is updated</b>"
|
529 |
-
|
530 |
-
msgid "OptionNotifyPluginDeleted"
|
531 |
-
msgstr "Receive email alerts when a <b>plugin is deleted</b>"
|
532 |
-
|
533 |
-
msgid "OptionNotifyWidgetAdded"
|
534 |
-
msgstr "Receive email alerts when a <b>widget is added</b> to a sidebar"
|
535 |
-
|
536 |
-
msgid "OptionNotifyWidgetDeleted"
|
537 |
-
msgstr "Receive email alerts when a <b>widget is deleted</b> from a sidebar"
|
538 |
-
|
539 |
-
msgid "OptionNotifyThemeInstalled"
|
540 |
-
msgstr "Receive email alerts when a <b>theme is installed</b>"
|
541 |
-
|
542 |
-
msgid "OptionNotifyThemeActivated"
|
543 |
-
msgstr "Receive email alerts when a <b>theme is activated</b>"
|
544 |
-
|
545 |
-
msgid "OptionNotifyThemeUpdated"
|
546 |
-
msgstr "Receive email alerts when a <b>theme is updated</b>"
|
547 |
-
|
548 |
-
msgid "OptionNotifyThemeDeleted"
|
549 |
-
msgstr "Receive email alerts when a <b>theme is deleted</b>"
|
550 |
-
|
551 |
-
msgid "MaximumAlertsSuccess"
|
552 |
-
msgstr "The maximum number of alerts per hour has been updated"
|
553 |
-
|
554 |
-
msgid "MaximumAlertsFailure"
|
555 |
-
msgstr "Error updating the maximum number of alerts per hour"
|
556 |
-
|
557 |
-
msgid "OptionPerHour5"
|
558 |
-
msgstr "Maximum 5 per hour"
|
559 |
-
|
560 |
-
msgid "OptionPerHour10"
|
561 |
-
msgstr "Maximum 10 per hour"
|
562 |
-
|
563 |
-
msgid "OptionPerHour20"
|
564 |
-
msgstr "Maximum 20 per hour"
|
565 |
-
|
566 |
-
msgid "OptionPerHour40"
|
567 |
-
msgstr "Maximum 40 per hour"
|
568 |
-
|
569 |
-
msgid "OptionPerHour80"
|
570 |
-
msgstr "Maximum 80 per hour"
|
571 |
-
|
572 |
-
msgid "OptionPerHour160"
|
573 |
-
msgstr "Maximum 160 per hour"
|
574 |
-
|
575 |
-
msgid "BruteForceAlertSuccess"
|
576 |
-
msgstr "The plugin will assume that your website is under a brute-force attack after %1$s failed logins are detected during the same hour"
|
577 |
-
|
578 |
-
msgid "BruteForceAlertFailure"
|
579 |
-
msgstr "Invalid number of failed logins per hour to consider your website under a brute-force attack, try another number"
|
580 |
-
|
581 |
-
msgid "OptionPerHourUnlimited"
|
582 |
-
msgstr "Unlimited alerts per hour"
|
583 |
-
|
584 |
-
msgid "OptionFailedLogins30"
|
585 |
-
msgstr "30 failed logins per hour"
|
586 |
-
|
587 |
-
msgid "OptionFailedLogins60"
|
588 |
-
msgstr "60 failed logins per hour"
|
589 |
-
|
590 |
-
msgid "OptionFailedLogins120"
|
591 |
-
msgstr "120 failed logins per hour"
|
592 |
-
|
593 |
-
msgid "OptionFailedLogins240"
|
594 |
-
msgstr "240 failed logins per hour"
|
595 |
-
|
596 |
-
msgid "OptionFailedLogins480"
|
597 |
-
msgstr "480 failed logins per hour"
|
598 |
-
|
599 |
-
msgid "HTAccessIsMissing"
|
600 |
-
msgstr "Access control file does not exists"
|
601 |
-
|
602 |
-
msgid "HTAccessNotWritable"
|
603 |
-
msgstr "Access control file is not writable"
|
604 |
-
|
605 |
-
msgid "DiffUtility"
|
606 |
-
msgstr "WordPress Integrity Diff Utility"
|
607 |
-
|
608 |
-
msgid "DiffUtilityDescription"
|
609 |
-
msgstr "If your server allows the execution of system commands, you can configure the plugin to use the <a href=\"https://en.wikipedia.org/wiki/Diff_utility\" target=\"_blank\" rel=\"noopener\">Unix Diff Utility</a> to compare the actual content of the file installed in the website and the original file provided by WordPress. This will show the differences between both files and then you can act upon the information provided."
|
610 |
-
|
611 |
-
msgid "DiffUtilityInfo"
|
612 |
-
msgstr "The Unix Diff Utility is enabled. You can click the files in the table to see the differences detected by the scanner. If you consider the differences to be harmless you can mark the file as fixed, otherwise it is adviced to restore the original content immediately."
|
613 |
-
|
614 |
-
msgid "DiffUtilityInstructions"
|
615 |
-
msgstr "Lines with a <b>minus</b> sign as the prefix <em>(here in red)</em> show the original code. Lines with a <b>plus</b> sign as the prefix <em>(here in green)</em> show the modified code. You can read more about the DIFF format from the WikiPedia article about the <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Diff_utility\" rel=\"noopener\">Unix Diff Utility</a>."
|
616 |
-
|
617 |
-
msgid "AccountsWereBlocked"
|
618 |
-
msgstr "Selected user accounts were blocked"
|
619 |
-
|
620 |
-
msgid "AccountsWereUnblocked"
|
621 |
-
msgstr "Selected user accounts were unblocked"
|
622 |
-
|
623 |
-
msgid "LastLoginMessage"
|
624 |
-
msgstr "Last login was at <b>%1$s</b> from <b>%2$s</b> <em>(%3$s)</em> <a href='%4$s'>view all logs</a>"
|
625 |
-
|
626 |
-
msgid "LastLoginsNotWritable"
|
627 |
-
msgstr "Last-logins data file is not writable: <code>%1$s</code>"
|
628 |
-
|
629 |
-
msgid "UserInfo"
|
630 |
-
msgstr "User: %1$s (%2$s)"
|
631 |
-
|
632 |
-
msgid "ReverseProxy"
|
633 |
-
msgstr "Reverse Proxy"
|
634 |
-
|
635 |
-
msgid "ReverseProxyStatus"
|
636 |
-
msgstr "Reverse proxy support was set to <b>%1$s</b>"
|
637 |
-
|
638 |
-
msgid "ReverseProxyInfo"
|
639 |
-
msgstr "The event monitor uses the API address of the origin of the request to track the actions, the plugin uses two methods to retrieve this: the main method uses the global server variable <em>Remote-Addr</em> available in most modern web servers, an alternative method uses custom HTTP headers <em>(which are unsafe by default)</em>. You should not worry about this option unless you know what a reverse proxy is. Services like the <a href=\"https://sucuri.net/website-firewall/\" target=\"_blank\">Sucuri Firewall</a> — once active — forces the network traffic to pass through them to filter any security threat that may affect the original server. A side effect of this is that the real IP address is no longer available in the global server variable <em>REMOTE-ADDR</em> but in a custom HTTP header with a name provided by the service."
|
640 |
-
|
641 |
-
msgid "IPDiscoverer"
|
642 |
-
msgstr "IP Address Discoverer"
|
643 |
-
|
644 |
-
msgid "IPDiscovererInfo"
|
645 |
-
msgstr "IP address discoverer will use DNS lookups to automatically detect if the website is behind the <a href=\"https://sucuri.net/website-firewall/\" target=\"_blank\">Sucuri Firewall</a> in which case will modify the global server variable <em>Remote-Addr</em> to set the real IP of the website's visitors. This check runs on every WordPress init action and that is why it may slow down your website as some hosting providers rely on slow DNS servers which makes the operation take more time than it should."
|
646 |
-
|
647 |
-
msgid "HTTPHeader"
|
648 |
-
msgstr "HTTP Header"
|
649 |
-
|
650 |
-
msgid "HTTPHeaderStatus"
|
651 |
-
msgstr "HTTP header was set to <code>%1$s</code>"
|
652 |
-
|
653 |
-
msgid "DisallowedHTTPHeader"
|
654 |
-
msgstr "HTTP header is not allowed"
|
655 |
-
|
656 |
-
msgid "RequiresModernPHP"
|
657 |
-
msgstr "The plugin requires PHP 5 >= 5.3.0 - OR - PHP 7"
|
658 |
-
|
659 |
-
msgid "General"
|
660 |
-
msgstr "General"
|
661 |
-
|
662 |
-
msgid "Scanner"
|
663 |
-
msgstr "Scanner"
|
664 |
-
|
665 |
-
msgid "Hardening"
|
666 |
-
msgstr "Hardening"
|
667 |
-
|
668 |
-
msgid "PostHack"
|
669 |
-
msgstr "Post-Hack"
|
670 |
-
|
671 |
-
msgid "Alerts"
|
672 |
-
msgstr "Alerts"
|
673 |
-
|
674 |
-
msgid "WebsiteInfo"
|
675 |
-
msgstr "Website Info"
|
676 |
-
|
677 |
-
msgid "Loading"
|
678 |
-
msgstr "Loading..."
|
679 |
-
|
680 |
-
msgid "iFrames"
|
681 |
-
msgstr "iFrames"
|
682 |
-
|
683 |
-
msgid "Links"
|
684 |
-
msgstr "Links"
|
685 |
-
|
686 |
-
msgid "Scripts"
|
687 |
-
msgstr "Scripts"
|
688 |
-
|
689 |
-
msgid "iFramesNum"
|
690 |
-
msgstr "iFrames: %1$d"
|
691 |
-
|
692 |
-
msgid "LinksNum"
|
693 |
-
msgstr "Links: %1$d"
|
694 |
-
|
695 |
-
msgid "ScriptsNum"
|
696 |
-
msgstr "Scripts: %1$d"
|
697 |
-
|
698 |
-
msgid "Type"
|
699 |
-
msgstr "Type"
|
700 |
-
|
701 |
-
msgid "Name"
|
702 |
-
msgstr "Name"
|
703 |
-
|
704 |
-
msgid "Value"
|
705 |
-
msgstr "Value"
|
706 |
-
|
707 |
-
msgid "Version"
|
708 |
-
msgstr "Version"
|
709 |
-
|
710 |
-
msgid "NextDue"
|
711 |
-
msgstr "Next Due"
|
712 |
-
|
713 |
-
msgid "Schedule"
|
714 |
-
msgstr "Schedule"
|
715 |
-
|
716 |
-
msgid "Arguments"
|
717 |
-
msgstr "Arguments"
|
718 |
-
|
719 |
-
msgid "EnvVariables"
|
720 |
-
msgstr "Environment Variables"
|
721 |
-
|
722 |
-
msgid "ConfigVariables"
|
723 |
-
msgstr "Configuration Variables"
|
724 |
-
|
725 |
-
msgid "ConfigNotFound"
|
726 |
-
msgstr "WordPress configuration file was not found."
|
727 |
-
|
728 |
-
msgid "ConfigNotWritable"
|
729 |
-
msgstr "WordPress configuration file is not writable."
|
730 |
-
|
731 |
-
msgid "LastLoginsResetSuccess"
|
732 |
-
msgstr "Last-Logins logs were successfully reset."
|
733 |
-
|
734 |
-
msgid "LastLoginsResetFailure"
|
735 |
-
msgstr "Could not reset the last-logins data file."
|
736 |
-
|
737 |
-
msgid "WillReceiveAlerts"
|
738 |
-
msgstr "The email alerts will be sent to: <code>%1$s</code>"
|
739 |
-
|
740 |
-
msgid "WillNotReceiveAlerts"
|
741 |
-
msgstr "These emails will stop receiving alerts: <code>%1$s</code>"
|
742 |
-
|
743 |
-
msgid "TestAlertSent"
|
744 |
-
msgstr "A test alert was sent to your email, check your inbox"
|
745 |
-
|
746 |
-
msgid "InvalidEmail"
|
747 |
-
msgstr "Email format not supported."
|
748 |
-
|
749 |
-
msgid "TrustedIPDuplicate"
|
750 |
-
msgstr "The IP specified address was already added."
|
751 |
-
|
752 |
-
msgid "TrustedIPAdded"
|
753 |
-
msgstr "Events generated from this IP will be ignored: <code>%1$s</code>"
|
754 |
-
|
755 |
-
msgid "TrustedIPFailure"
|
756 |
-
msgstr "The IP address could not be added to the trusted list"
|
757 |
-
|
758 |
-
msgid "TrustedIPDeleted"
|
759 |
-
msgstr "The selected IP addresses were successfully deleted."
|
760 |
-
|
761 |
-
msgid "OnlyLowerUppercase"
|
762 |
-
msgstr "Only lowercase letters and underscores are allowed."
|
763 |
-
|
764 |
-
msgid "PostTypeIgnore"
|
765 |
-
msgstr "Receive These Alerts"
|
766 |
-
|
767 |
-
msgid "PostTypeUnignore"
|
768 |
-
msgstr "Stop These Alerts"
|
769 |
-
|
770 |
-
msgid "PostTypeIgnored"
|
771 |
-
msgstr "Post-type has been successfully ignored."
|
772 |
-
|
773 |
-
msgid "PostTypeUnignored"
|
774 |
-
msgstr "The selected post-type will not be ignored anymore."
|
775 |
-
|
776 |
-
msgid "PostTypeFailure"
|
777 |
-
msgstr "The post-type is invalid or it may be already ignored."
|
778 |
-
|
779 |
-
msgid "APIServiceChanged"
|
780 |
-
msgstr "The status of the API service has been changed"
|
781 |
-
|
782 |
-
msgid "PluginResetSuccess"
|
783 |
-
msgstr "Local security logs, hardening and settings were deleted"
|
784 |
-
|
785 |
-
msgid "StorageNotWritable"
|
786 |
-
msgstr "Storage is not writable: <code>%1$s</code>"
|
787 |
-
|
788 |
-
msgid "SiteWasRegistered"
|
789 |
-
msgstr "Site registered successfully"
|
790 |
-
|
791 |
-
msgid "NFilesWereDeleted"
|
792 |
-
msgstr "%1$d out of %2$d files has been deleted"
|
793 |
-
|
794 |
-
msgid "AvoidDocumentRoot"
|
795 |
-
msgstr "File should not be publicly accessible."
|
796 |
-
|
797 |
-
msgid "AvoidFileOverride"
|
798 |
-
msgstr "File already exists and will not be overwritten."
|
799 |
-
|
800 |
-
msgid "Cronjobs"
|
801 |
-
msgstr "Scheduled Tasks"
|
802 |
-
|
803 |
-
msgid "CronjobsInfo"
|
804 |
-
msgstr "Scheduled tasks are rules registered in your database by a plugin, theme, or the base system itself; they are used to automatically execute actions defined in the code every certain amount of time. A good use of these rules is to generate backup files of your site, execute a security scanner, or remove unused elements like drafts. <b>Note:</b> Scheduled tasks can be re-installed by any plugin/theme automatically, consider to deactivate the plugin entirely if you want to get rid of the scheduled tasks."
|
805 |
-
|
806 |
-
msgid "CronjobRunNow"
|
807 |
-
msgstr "Execute Now (in +10 seconds)"
|
808 |
-
|
809 |
-
msgid "CronjobsWillRunSoon"
|
810 |
-
msgstr "%1$d tasks has been scheduled to run in the next ten seconds."
|
811 |
-
|
812 |
-
msgid "CronjobsWereDeleted"
|
813 |
-
msgstr "%1$d scheduled tasks have been removed."
|
814 |
-
|
815 |
-
msgid "CronjobsWereReinstalled"
|
816 |
-
msgstr "%1$d tasks has been re-scheduled to run <code>%2$s</code>.'"
|
817 |
-
|
818 |
-
msgid "CronjobsWereNotSelected"
|
819 |
-
msgstr "No scheduled tasks were selected from the list."
|
820 |
-
|
821 |
-
msgid "DNSLookupStatus"
|
822 |
-
msgstr "The status of the DNS lookups for the reverse proxy detection has been changed"
|
823 |
-
|
824 |
-
msgid "IncorrectEncoding"
|
825 |
-
msgstr "Data is incorrectly encoded"
|
826 |
-
|
827 |
-
msgid "ImportCount"
|
828 |
-
msgstr "%1$d out of %2$d option have been successfully imported"
|
829 |
-
|
830 |
-
msgid "APIKey"
|
831 |
-
msgstr "API Key"
|
832 |
-
|
833 |
-
msgid "APIKeyInfo"
|
834 |
-
msgstr "Most of the tools in this plugin can be used without a specific configuration, but the core features <b>require an API key</b> to communicate with the Sucuri services. The key is generated using your administrator e-mail and the domain of this site, this will allow you to have access to our free monitoring tool and other extra features."
|
835 |
-
|
836 |
-
msgid "APIKeyTerms"
|
837 |
-
msgstr "Generating an API key implies that you agree to send the information collected by the plugin to the Sucuri API service which is a remote server where the information for the audit logs is stored, this is to prevent malicious users to delete the logs during an attack which may affect an investigation if you suspect that your website was hacked. We also use this information to display <a href=\"https://sucuri.net/security-reports/brute-force/\" target=\"_blank\">statistics</a> and try to use the data in an anonymous way as we are concerned about your privacy too. Please do not generate an API key if you do not agree with this, you can keep using the plugin without it anyway."
|
838 |
-
|
839 |
-
msgid "APIKeyMissing"
|
840 |
-
msgstr "API key is missing"
|
841 |
-
|
842 |
-
msgid "APIKeyInvalidDomain"
|
843 |
-
msgstr "Your domain <code>%%SUCURI.CleanDomain%%</code> does not seems to have a DNS <code>A</code> record so it will be considered as <em>invalid</em> by the API interface when you request the generation of a new key. Adding <code>www</code> at the beginning of the domain name may fix this issue. If you do not understand what is this then send an email to our support team requesting the key."
|
844 |
-
|
845 |
-
msgid "APIKeyRecoverButton"
|
846 |
-
msgstr "Recover Via E-mail"
|
847 |
-
|
848 |
-
msgid "APIKeyRecoveryCondition"
|
849 |
-
msgstr "If you don't have access to the e-mail address used to generate the API key, but have a copy of the key at hand you can <a target=\"_self\" href=\"%%SUCURI.URL.Settings%%&recover\">click this link</a> to activate the plugin manually. Be aware that if the key is invalid the plugin will delete it afterwards."
|
850 |
-
|
851 |
-
msgid "ApplyHardening"
|
852 |
-
msgstr "Apply Hardening"
|
853 |
-
|
854 |
-
msgid "RevertHardening"
|
855 |
-
msgstr "Revert Hardening"
|
856 |
-
|
857 |
-
msgid "HardeningFirewallTitle"
|
858 |
-
msgstr "Website Firewall Protection"
|
859 |
-
|
860 |
-
msgid "HardeningFirewallDescription"
|
861 |
-
msgstr "A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, DDoS, SQL injections, etc) and helping it remain malware and blacklist free. This test checks if your site is using Sucuri Firewall to protect your site."
|
862 |
-
|
863 |
-
msgid "HardeningFirewallPurchase"
|
864 |
-
msgstr "The firewall is a premium service that you need purchase at - <a href='https://goo.gl/qfNkMq' target='_blank'>Sucuri Firewall</a>"
|
865 |
-
|
866 |
-
msgid "HardeningVersionTitle"
|
867 |
-
msgstr "Verify WordPress Version"
|
868 |
-
|
869 |
-
msgid "HardeningVersionDescription"
|
870 |
-
msgstr "Why keep your site updated? WordPress is an open-source project which means that with every update the details of the changes made to the source code are made public, if there were security fixes then someone with malicious intent can use this information to attack any site that has not been upgraded."
|
871 |
-
|
872 |
-
msgid "HardeningPHPVersionTitle"
|
873 |
-
msgstr "Verify PHP Version"
|
874 |
-
|
875 |
-
msgid "HardeningPHPVersionDescription"
|
876 |
-
msgstr "PHP %1$s is installed."
|
877 |
-
|
878 |
-
msgid "HardeningPHPVersionLifetime"
|
879 |
-
msgstr "Ask your hosting provider to install an updated version of PHP - <a href='http://php.net/supported-versions.php' target='_blank' rel='noopener'>List of PHP Supported Versions</a>"
|
880 |
-
|
881 |
-
msgid "HardeningGeneratorTitle"
|
882 |
-
msgstr "Remove WordPress Version"
|
883 |
-
|
884 |
-
msgid "HardeningGeneratorDescription"
|
885 |
-
msgstr "It checks if your WordPress version is being leaked to the public via a HTML meta-tag. Many web vulnerability scanners use this to determine which version of the code is running in your website. They use this to find disclosed vulnerabilities associated to this version number. A vulnerability scanner can still guess which version of WordPress is installed by comparing the checksum of some static files."
|
886 |
-
|
887 |
-
msgid "HardeningNginxTitle"
|
888 |
-
msgstr "Block of Certain PHP Files"
|
889 |
-
|
890 |
-
msgid "HardeningNginxDescription"
|
891 |
-
msgstr "Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the 'Whitelist PHP Files' tool to add exceptions to individual files."
|
892 |
-
|
893 |
-
msgid "HardeningNginxField"
|
894 |
-
msgstr "Check Hardening"
|
895 |
-
|
896 |
-
msgid "HardeningNginxSuggestion"
|
897 |
-
msgstr "Read the official WordPress guidelines to learn how to restrict access to PHP files in sensitive directories - <a href='https://codex.wordpress.org/Nginx#Global_restrictions_file' target='_blank' rel='noopener'>Nginx Global Restrictions For WordPress</a>"
|
898 |
-
|
899 |
-
msgid "HardeningUploadsTitle"
|
900 |
-
msgstr "Block PHP Files in Uploads Directory"
|
901 |
-
|
902 |
-
msgid "HardeningUploadsDescription"
|
903 |
-
msgstr "Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the 'Whitelist PHP Files' tool to add exceptions to individual files."
|
904 |
-
|
905 |
-
msgid "HardeningUploadsApplySuccess"
|
906 |
-
msgstr "Hardening applied to the uploads directory"
|
907 |
-
|
908 |
-
msgid "HardeningUploadsApplyFailure"
|
909 |
-
msgstr "Error hardening directory, check the permissions."
|
910 |
-
|
911 |
-
msgid "HardeningUploadsRevertSuccess"
|
912 |
-
msgstr "Hardening reverted in the uploads directory"
|
913 |
-
|
914 |
-
msgid "HardeningUploadsRevertFailure"
|
915 |
-
msgstr "Access file is not writable, check the permissions."
|
916 |
-
|
917 |
-
msgid "HardeningContentTitle"
|
918 |
-
msgstr "Block PHP Files in WP-CONTENT Directory"
|
919 |
-
|
920 |
-
msgid "HardeningContentDescription"
|
921 |
-
msgstr "Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the 'Whitelist PHP Files' tool to add exceptions to individual files."
|
922 |
-
|
923 |
-
msgid "HardeningContentApplySuccess"
|
924 |
-
msgstr "Hardening applied to the content directory"
|
925 |
-
|
926 |
-
msgid "HardeningContentApplyFailure"
|
927 |
-
msgstr "Error hardening directory, check the permissions."
|
928 |
-
|
929 |
-
msgid "HardeningContentRevertSuccess"
|
930 |
-
msgstr "Hardening reverted in the content directory"
|
931 |
-
|
932 |
-
msgid "HardeningContentRevertFailure"
|
933 |
-
msgstr "Access file is not writable, check the permissions."
|
934 |
-
|
935 |
-
msgid "HardeningIncludesTitle"
|
936 |
-
msgstr "Block PHP Files in WP-INCLUDES Directory"
|
937 |
-
|
938 |
-
msgid "HardeningIncludesDescription"
|
939 |
-
msgstr "Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the 'Whitelist PHP Files' tool to add exceptions to individual files."
|
940 |
-
|
941 |
-
msgid "HardeningIncludesApplySuccess"
|
942 |
-
msgstr "Hardening applied to the library directory"
|
943 |
-
|
944 |
-
msgid "HardeningIncludesApplyFailure"
|
945 |
-
msgstr "Error hardening directory, check the permissions."
|
946 |
-
|
947 |
-
msgid "HardeningIncludesRevertSuccess"
|
948 |
-
msgstr "Hardening reverted in the library directory"
|
949 |
-
|
950 |
-
msgid "HardeningIncludesRevertFailure"
|
951 |
-
msgstr "Access file is not writable, check the permissions."
|
952 |
-
|
953 |
-
msgid "HardeningReadmeTitle"
|
954 |
-
msgstr "Information Leakage"
|
955 |
-
|
956 |
-
msgid "HardeningReadmeDescription"
|
957 |
-
msgstr "Checks if the WordPress README file still exists in the website. The information in this file can be used by malicious users to pin-point which disclosed vulnerabilities are associated to the website. Be aware that WordPress recreates this file automatically with every update."
|
958 |
-
|
959 |
-
msgid "HardeningReadmeApplySuccess"
|
960 |
-
msgstr "Hardening applied to the <code>readme.html</code> file"
|
961 |
-
|
962 |
-
msgid "HardeningReadmeApplyFailure"
|
963 |
-
msgstr "Cannot delete <code>%1$s/readme.html</code>"
|
964 |
-
|
965 |
-
msgid "HardeningAdminUserTitle"
|
966 |
-
msgstr "Default Admin Account"
|
967 |
-
|
968 |
-
msgid "HardeningAdminUserDescription"
|
969 |
-
msgstr "Check if the primary user account still uses the name 'admin'. This allows malicious users to easily identify which account has the highest privileges to target an attack."
|
970 |
-
|
971 |
-
msgid "HardeningFileEditorTitle"
|
972 |
-
msgstr "Plugin and Theme Editor"
|
973 |
-
|
974 |
-
msgid "HardeningFileEditorDescription"
|
975 |
-
msgstr "Disables the theme and plugin editors to prevent unwanted modifications to the code. If you are having problems reverting this hardening option please open the wp-config.php file and delete the line with the constant DISALLOW_FILE_EDIT."
|
976 |
-
|
977 |
-
msgid "HardeningFileEditorApplySuccess"
|
978 |
-
msgstr "Hardening applied to the plugin and theme editor"
|
979 |
-
|
980 |
-
msgid "HardeningFileEditorRevertSuccess"
|
981 |
-
msgstr "Hardening reverted in the plugin and theme editor"
|
982 |
-
|
983 |
-
msgid "HardeningFileEditorRevertFailure"
|
984 |
-
msgstr "File Editor was not disabled using this tool. You must scan your project for a constant defined as DISALLOW_FILE_EDIT, then either delete it or set its value to False. Any plugin/theme can disable the file editor, so it is impossible to determine the origin of the constant."
|
985 |
-
|
986 |
-
msgid "PHPWhitelistSuccess"
|
987 |
-
msgstr "The file has been whitelisted from the hardening"
|
988 |
-
|
989 |
-
msgid "PHPWhitelistFailure"
|
990 |
-
msgstr "Specified folder is not hardened by this plugin"
|
991 |
-
|
992 |
-
msgid "PHPDewhitelistSuccess"
|
993 |
-
msgstr "The selected files have been removed from the hardening exception list"
|
994 |
-
|
995 |
-
msgid "DiffUtilityStatus"
|
996 |
-
msgstr "The status of the integrity diff utility has been changed"
|
997 |
-
|
998 |
-
msgid "DiffUtilityMissing"
|
999 |
-
msgstr "Your hosting provider has blocked the execution of external commands."
|
1000 |
-
|
1001 |
-
msgid "IntegrityLanguage"
|
1002 |
-
msgstr "The language for the core integrity checks has been changed"
|
1003 |
-
|
1004 |
-
msgid "NotInstalled"
|
1005 |
-
msgstr "not installed"
|
1006 |
-
|
1007 |
-
msgid "PremiumPlugin"
|
1008 |
-
msgstr "Plugin is Premium"
|
1009 |
-
|
1010 |
-
msgid "MissingLibrary"
|
1011 |
-
msgstr "Missing Library"
|
1012 |
-
|
1013 |
-
msgid "CannotDownload"
|
1014 |
-
msgstr "Cannot Download"
|
1015 |
-
|
1016 |
-
msgid "CannotBackup"
|
1017 |
-
msgstr "Cannot Backup"
|
1018 |
-
|
1019 |
-
msgid "CannotInstall"
|
1020 |
-
msgstr "Cannot Install"
|
1021 |
-
|
1022 |
-
msgid "VersionInstalled"
|
1023 |
-
msgstr "Installed v%1$s"
|
1024 |
-
|
1025 |
-
msgid "NewestWordPress"
|
1026 |
-
msgstr "Newest WordPress"
|
1027 |
-
|
1028 |
-
msgid "NoUpdates"
|
1029 |
-
msgstr "There are no updates available."
|
1030 |
-
|
1031 |
-
msgid "SiteClean"
|
1032 |
-
msgstr "Site is Clean"
|
1033 |
-
|
1034 |
-
msgid "SiteNotClean"
|
1035 |
-
msgstr "Site is not Clean"
|
1036 |
-
|
1037 |
-
msgid "Blacklisted"
|
1038 |
-
msgstr "Blacklisted"
|
1039 |
-
|
1040 |
-
msgid "NotBlacklisted"
|
1041 |
-
msgstr "Not Blacklisted"
|
1042 |
-
|
1043 |
-
msgid "APIKeyExplanation"
|
1044 |
-
msgstr "An API key is required to activate some additional tools available in this plugin. The keys are free and you can virtually generate an unlimited number of them as long as the domain name and email address are unique. The key is used to authenticate the HTTP requests sent by the plugin to a public API service managed by Sucuri Inc. Do not generate the key if you disagree with this."
|
1045 |
-
|
1046 |
-
msgid "APIKeyHelp"
|
1047 |
-
msgstr "If you experience issues generating the API key you can request one sending the domain name and email address that you want to use to <a href=\"mailto:info@sucuri.net\">info@sucuri.net</a>. Note generating a key for a website that is not facing the Internet is not possible because the API service needs to validate that the domain name exists, however, if you want to test the plugin in a development environment please contact us so we can generate the key manually."
|
1048 |
-
|
1049 |
-
msgid "APIKeyGenerated"
|
1050 |
-
msgstr "Congratulations! The rest of the features available in the plugin have been enabled. This product is designed to supplement existing security products. It's not a silver bullet for your security needs, but it'll give you greater security awareness and better posture, all with the intent of reducing risk."
|
1051 |
-
|
1052 |
-
msgid "APIKeyContinueSetup"
|
1053 |
-
msgstr "Your website has been granted a new API key and it was associated to the email address that you chose during the registration process. You can use the same email to recover the key if you happen to lose it sometime. We encourage you to check the rest of the settings page and configure the plugin to your own needs."
|
1054 |
-
|
1055 |
-
msgid "APIKeyRecoveryExplanation"
|
1056 |
-
msgstr "If this operation was successful you will receive a message in the email used during the registration of the API key <em>(usually the email of the main admin user)</em>. This message contains the key in plain text, copy and paste the key in the form field below. The plugin will verify the authenticity of the key sending an initial HTTP request to the API service, if this fails the key will be removed automatically and you will have to start the process all over again."
|
1057 |
-
|
1058 |
-
msgid "APIKeyRecoveryPossibleFailures"
|
1059 |
-
msgstr "There are cases where this operation may fail, an example would be when the email address is not associated with the domain anymore, this happens when the base URL changes <em>(from www to none or viceversa)</em>. If you are having issues recovering the key please send an email explaining the situation to <a href=\"mailto:info@sucuri.net\">info@sucuri.net</a>"
|
1060 |
-
|
1061 |
-
msgid "DNSLookups"
|
1062 |
-
msgstr "DNS Lookups"
|
1063 |
-
|
1064 |
-
msgid "DNSLookupsLabel"
|
1065 |
-
msgstr "Enable DNS Lookups On Startup"
|
1066 |
-
|
1067 |
-
msgid "DNSLookupsText"
|
1068 |
-
msgstr "Check the box if your website is behind a known firewall service, this guarantees that the IP address of your visitors will be detected correctly for the security logs. You can change this later from the settings."
|
1069 |
-
|
1070 |
-
msgid "IntegrityTitle"
|
1071 |
-
msgstr "WordPress Integrity"
|
1072 |
-
|
1073 |
-
msgid "IntegrityDescription"
|
1074 |
-
msgstr "We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack."
|
1075 |
-
|
1076 |
-
msgid "ReviewFalsePositives"
|
1077 |
-
msgstr "Review False/Positives"
|
1078 |
-
|
1079 |
-
msgid "IntegrityGoodTitle"
|
1080 |
-
msgstr "All Core WordPress Files Are Correct"
|
1081 |
-
|
1082 |
-
msgid "IntegrityGoodDescription"
|
1083 |
-
msgstr "We have not identified additional files, deleted files, or relevant changes to the core files in your WordPress installation. If you are experiencing other malware issues, please use a <a target=\"_blank\" href=\"https://sucuri.net/website-security/malware-removal\">Server Side Scanner</a>."
|
1084 |
-
|
1085 |
-
msgid "IntegrityBadTitle"
|
1086 |
-
msgstr "Core WordPress Files Were Modified"
|
1087 |
-
|
1088 |
-
msgid "IntegrityBadDescription"
|
1089 |
-
msgstr "We identified that some of your WordPress core files were modified. That might indicate a hack or a broken file on your installation. If you are experiencing other malware issues, please use a <a href=\"https://sucuri.net/website-security/malware-removal\" target=\"_blank\">Server Side Scanner</a>."
|
1090 |
-
|
1091 |
-
msgid "MarkFixedDescription"
|
1092 |
-
msgstr "Marking one or more files as fixed will force the plugin to ignore them during the next scan, very useful when you find false positives. Additionally you can restore the original content of the core files that appear as modified or deleted, this will tell the plugin to download a copy of the original files from the official WordPress repository. Deleting a file is an irreversible action, be careful."
|
1093 |
-
|
1094 |
-
msgid "Action"
|
1095 |
-
msgstr "Action"
|
1096 |
-
|
1097 |
-
msgid "Status"
|
1098 |
-
msgstr "Status"
|
1099 |
-
|
1100 |
-
msgid "FileSize"
|
1101 |
-
msgstr "File Size"
|
1102 |
-
|
1103 |
-
msgid "ModifiedAt"
|
1104 |
-
msgstr "Modified At"
|
1105 |
-
|
1106 |
-
msgid "Pattern"
|
1107 |
-
msgstr "Pattern"
|
1108 |
-
|
1109 |
-
msgid "FilePath"
|
1110 |
-
msgstr "File Path"
|
1111 |
-
|
1112 |
-
msgid "Directory"
|
1113 |
-
msgstr "Directory"
|
1114 |
-
|
1115 |
-
msgid "MarkFixed"
|
1116 |
-
msgstr "Mark as Fixed"
|
1117 |
-
|
1118 |
-
msgid "RestoreFile"
|
1119 |
-
msgstr "Restore File"
|
1120 |
-
|
1121 |
-
msgid "DeleteFile"
|
1122 |
-
msgstr "Delete File"
|
1123 |
-
|
1124 |
-
msgid "HoverForPayload"
|
1125 |
-
msgstr "Hover to see the Payload"
|
1126 |
-
|
1127 |
-
msgid "LogsPerEvent"
|
1128 |
-
msgstr "Audit Logs per Event"
|
1129 |
-
|
1130 |
-
msgid "LogsForLogins"
|
1131 |
-
msgstr "Successful/Failed Logins"
|
1132 |
-
|
1133 |
-
msgid "LogsPerUser"
|
1134 |
-
msgstr "Audit Logs per User"
|
1135 |
-
|
1136 |
-
msgid "LogsPerIP"
|
1137 |
-
msgstr "Audit Logs per IP Address"
|
1138 |
-
|
1139 |
-
msgid "Search"
|
1140 |
-
msgstr "Search"
|
1141 |
-
|
1142 |
-
msgid "FirewallSettingsTitle"
|
1143 |
-
msgstr "Firewall Settings"
|
1144 |
-
|
1145 |
-
msgid "FirewallSettingsInfo"
|
1146 |
-
msgstr "A powerful Web Application Firewall and <b>Intrusion Detection System</b> for any WordPress user and many other platforms. This page will help you to configure and monitor your site through the <b>Sucuri Firewall</b>. Once enabled, our firewall will act as a shield, protecting your site from attacks and preventing malware infections and reinfections. It will block SQL injection attempts, brute force attacks, XSS, RFI, backdoors and many other threats against your site."
|
1147 |
-
|
1148 |
-
msgid "FirewallKey"
|
1149 |
-
msgstr "Firewall API Key"
|
1150 |
-
|
1151 |
-
msgid "FirewallAddKey"
|
1152 |
-
msgstr "Add your <a href=\"https://waf.sucuri.net/?settings&panel=api\" target=\"_blank\">Firewall API key</a> in the form below to start communicating with the firewall API service."
|
1153 |
-
|
1154 |
-
msgid "FirewallFootNote"
|
1155 |
-
msgstr "<em>[1]</em> More information about the <a href=\"https://sucuri.net/website-firewall/\" target=\"_blank\">Sucuri Firewall</a>, features and pricing.<br><em>[2]</em> Instructions and videos in the official <a href=\"https://kb.sucuri.net/firewall\" target=\"_blank\">Knowledge Base</a> site.<br><em>[3]</em> <a href=\"https://login.sucuri.net/signup2/create?CloudProxy\" target=\"_blank\">Sign up</a> for a new account and start protecting your site."
|
1156 |
-
|
1157 |
-
msgid "FirewallLogsTitle"
|
1158 |
-
msgstr "Firewall Audit Logs"
|
1159 |
-
|
1160 |
-
msgid "FirewallLogsInfo"
|
1161 |
-
msgstr "The firewall logs every request involved in an attack and separates them from the legitimate requests. You can analyze the data from the latest entries in the logs using this tool and take action either enabling the advanced features of the IDS <em>(Intrusion Detection System)</em> from the <a target=\"_blank\" href=\"https://waf.sucuri.net/?settings\">Firewall Dashboard</a> and/or blocking IP addresses and URL paths directly from the <a href=\"https://waf.sucuri.net/?audit\" target=\"_blank\">Firewall Audit Trails</a> page."
|
1162 |
-
|
1163 |
-
msgid "FirewallLogsNote"
|
1164 |
-
msgstr "Note that non-blocked requests are hidden from the logs, this is intentional."
|
1165 |
-
|
1166 |
-
msgid "FirewallIPAccessTitle"
|
1167 |
-
msgstr "IP Address Access"
|
1168 |
-
|
1169 |
-
msgid "FirewallIPAccessInfo"
|
1170 |
-
msgstr "This tool allows you to whitleist and blacklist one or more IP addresses from accessing your website. You can also configure the plugin to automatically blacklist any IP address involved in a password guessing brute-force attack. If a legitimate user fails to submit the correct credentials of their account they will have to log into the Firewall dashboard in order to delete their IP address from the blacklist, or try to login once again through a VPN."
|
1171 |
-
|
1172 |
-
msgid "WhitelistIP"
|
1173 |
-
msgstr "Whitelist IP"
|
1174 |
-
|
1175 |
-
msgid "BlacklistIP"
|
1176 |
-
msgstr "Blacklist IP"
|
1177 |
-
|
1178 |
-
msgid "FirewallCacheTitle"
|
1179 |
-
msgstr "Clear Cache"
|
1180 |
-
|
1181 |
-
msgid "FirewallCacheButton"
|
1182 |
-
msgstr "Clear Cache"
|
1183 |
-
|
1184 |
-
msgid "FirewallCacheInfo"
|
1185 |
-
msgstr "The firewall offers multiple options to configure the cache level applied to your website. You can either enable the full cache which is the recommended setting, or you can set the cache level to minimal which will keep the pages static for a couple of minutes, or force the usage of the website headers <em>(only for advanced users)</em>, or in extreme cases where you do not need the cache you can simply disable it. Find more information about it in the <a target=\"_blank\" href=\"https://kb.sucuri.net/firewall/Performance/caching-options\">Sucuri Knowledge Base</a> website."
|
1186 |
-
|
1187 |
-
msgid "FirewallCacheNote"
|
1188 |
-
msgstr "Note that the firewall has <a href=\"https://kb.sucuri.net/firewall/Performance/cache-exceptions\" target=\"_blank\">special caching rules</a> for Images, CSS, PDF, TXT, JavaScript, media files and a few more extensions that are stored on our <a href=\"https://en.wikipedia.org/wiki/Edge_device\" target=\"_blank\" rel=\"noopener\">edge</a>. The only way to flush the cache for these files is by clearing the firewall's cache completely <em>(for the whole website)</em>. Due to our caching of JavaScript and CSS files, often, as is best practice, the use of versioning during development will ensure updates going live as expected. This is done by adding a query string such as <code>?ver=1.2.3</code> and incrementing on each update."
|
1189 |
-
|
1190 |
-
msgid "FirewallCacheWiki"
|
1191 |
-
msgstr "A web cache (or HTTP cache) is an information technology for the temporary storage (caching) of web documents, such as HTML pages and images, to reduce bandwidth usage, server load, and perceived lag. A web cache system stores copies of documents passing through it; subsequent requests may be satisfied from the cache if certain conditions are met. A web cache system can refer either to an appliance, or to a computer program. — <a href=\"https://en.wikipedia.org/wiki/Web_cache\" target=\"_blank\" rel=\"noopener\">WikiPedia - Web Cache</a>"
|
1192 |
-
|
1193 |
-
msgid "FirewallAutoClearCache"
|
1194 |
-
msgstr "Clear cache automatically when a post or page is updated"
|
1195 |
-
|
1196 |
-
msgid "LoginsAdmins"
|
1197 |
-
msgstr "Successful Logins (admins)"
|
1198 |
-
|
1199 |
-
msgid "LoginsAdminsInfo"
|
1200 |
-
msgstr "Here you can see a list of all the successful logins of accounts with admin privileges."
|
1201 |
-
|
1202 |
-
msgid "Registration"
|
1203 |
-
msgstr "Registration"
|
1204 |
-
|
1205 |
-
msgid "NewestLogins"
|
1206 |
-
msgstr "Newest To Oldest"
|
1207 |
-
|
1208 |
-
msgid "Admins"
|
1209 |
-
msgstr "Admins"
|
1210 |
-
|
1211 |
-
msgid "AllUsers"
|
1212 |
-
msgstr "All Users"
|
1213 |
-
|
1214 |
-
msgid "LoginsAll"
|
1215 |
-
msgstr "Successful Logins (all)"
|
1216 |
-
|
1217 |
-
msgid "LoginsAllInfo"
|
1218 |
-
msgstr "Here you can see a list of all the successful user logins."
|
1219 |
-
|
1220 |
-
msgid "BlockedUsers"
|
1221 |
-
msgstr "Blocked Users"
|
1222 |
-
|
1223 |
-
msgid "BlockedUsersInfo"
|
1224 |
-
msgstr "Any attempt to authenticate an user account using the functions provided by WordPress will be intercepted and analyzed by the plugin, if the username coincides with any of the users in this list, the authentication process will be immediately stopped. These attemps will not be logged and no email alerts will be sent."
|
1225 |
-
|
1226 |
-
msgid "BlockedUsersNote"
|
1227 |
-
msgstr "Take in consideration that this is not a 100% bulletproof mechanism to block unwanted user authentications from malicious users. Depending on the configuration of your website, installed plugins, installed themes, and even the version of WordPress there might still be weak points that automated tools can take advantage of to brute force the user accounts registered in your website. <a target=\"_blank\" href=\"https://sucuri.net/website-firewall/?wp=bu\">Install a firewall</a> to have full protection and mitigate this and a myriad of other attacks."
|
1228 |
-
|
1229 |
-
msgid "BlockedUsersByIP"
|
1230 |
-
msgstr "Blocking users per IP address is a feature provided by the <a href=\"https://sucuri.net/website-firewall/\" target=\"_blank\">Sucuri Firewall</a>; to avoid the duplication of code and reduce the amount of false/positives this feature will never be implemented in this plugin."
|
1231 |
-
|
1232 |
-
msgid "FailedLogins"
|
1233 |
-
msgstr "Failed logins"
|
1234 |
-
|
1235 |
-
msgid "FailedLoginsInfo"
|
1236 |
-
msgstr "This information will be used to determine if your site is being victim of <a href=\"https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing\" target=\"_blank\">Password Guessing Brute Force Attacks</a>. These logs will be accumulated and the plugin will send a report via email if there are more than <code>%%SUCURI.FailedLogins.MaxFailedLogins%%</code> failed login attempts during the same hour, you can change this number from <a href=\"%%SUCURI.URL.Settings%%#alerts\">here</a>. <b>NOTE:</b> Some <em>\"Two-Factor Authentication\"</em> plugins do not follow the same rules that WordPress have to report failed login attempts, so you may not see all the attempts in this panel if you have one of these plugins installed."
|
1237 |
-
|
1238 |
-
msgid "LoggedInUsers"
|
1239 |
-
msgstr "Logged-in Users"
|
1240 |
-
|
1241 |
-
msgid "LoggedInUsersInfo"
|
1242 |
-
msgstr "Here you can see a list of the users that are currently logged-in."
|
1243 |
-
|
1244 |
-
msgid "Recomendations"
|
1245 |
-
msgstr "Recomendations"
|
1246 |
-
|
1247 |
-
msgid "SiteCheckNoResults"
|
1248 |
-
msgstr "If our free scanner did not detect any issue, you may have a more complicated and hidden problem. You can <a target=\"_blank\" href=\"https://sucuri.net/website-security-platform/signup\">sign up with Sucuri</a> for a complete and in-depth scan + cleanup (not included in the free checks)."
|
1249 |
-
|
1250 |
-
msgid "SiteCheckTarget"
|
1251 |
-
msgstr "Malware Scan Target"
|
1252 |
-
|
1253 |
-
msgid "SiteCheckTargetInfo"
|
1254 |
-
msgstr "The remote malware scanner provided by the plugin is powered by <a href=\"https://sitecheck.sucuri.net/\" target=\"_blank\">Sucuri SiteCheck</a>, a service that takes a publicly accessible URL and scans it for malicious code. If your website is not visible to the Internet, for example, if it is hosted in a local development environment or a restricted network, the scanner will not be able to work on it. Additionally, if the website was installed in a non-standard directory the scanner will report a \"404 Not Found\" error. You can use this option to change the URL that will be scanned."
|
1255 |
-
|
1256 |
-
msgid "PasswordAttack"
|
1257 |
-
msgstr "Password Guessing Brute Force Attacks"
|
1258 |
-
|
1259 |
-
msgid "PasswordAttackAfter"
|
1260 |
-
msgstr "Consider Brute-Force Attack After"
|
1261 |
-
|
1262 |
-
msgid "PasswordAttackInfo"
|
1263 |
-
msgstr "<a href=\"https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing\" target=\"_blank\">Password guessing brute force attacks</a> are very common against web sites and web servers. They are one of the most common vectors used to compromise web sites. The process is very simple and the attackers basically try multiple combinations of usernames and passwords until they find one that works. Once they get in, they can compromise the web site with malware, spam , phishing or anything else they want."
|
1264 |
-
|
1265 |
-
msgid "PostTypeAlerts"
|
1266 |
-
msgstr "Post-Type Alerts"
|
1267 |
-
|
1268 |
-
msgid "IgnoredAt"
|
1269 |
-
msgstr "Ignored At"
|
1270 |
-
|
1271 |
-
msgid "PostType"
|
1272 |
-
msgstr "Post-Type"
|
1273 |
-
|
1274 |
-
msgid "PostTypeAlertsDisabled"
|
1275 |
-
msgstr "It seems that you disabled the email alerts for <b>new site content</b>, this panel is intended to provide a way to ignore specific events in your site and with that the alerts reported to your email. Since you have deactivated the <b>new site content</b> alerts, this panel will be disabled too."
|
1276 |
-
|
1277 |
-
msgid "PostTypeAlertsInfo"
|
1278 |
-
msgstr "This is a list of registered <a href=\"https://codex.wordpress.org/Post_Types\" target=\"_blank\" rel=\"noopener\">Post Types</a>. You will receive an email alert when a custom page or post associated to any of these types is created or updated. Some of these are created by WordPress but the majority are created by 3rd-party plugins and themes to extend functionality from WordPress. If you don't want to receive alerts for certain posts you can stop them from here."
|
1279 |
-
|
1280 |
-
msgid "PostTypeAlertsInvisible"
|
1281 |
-
msgstr "If you are receiving alerts for post types that are not listed here it may be because the theme or plugin that is making these changes is registering the custom post-type on runtime, in this case our plugin will not be able to detect these changes and consequently you will not be able to ignore those alerts. However, if you know the unique identifier of the post-type you can type it in the form bellow and our plugin will do its best to skip the alerts associated to that."
|
1282 |
-
|
1283 |
-
msgid "PostTypeAlertsStop"
|
1284 |
-
msgstr "Stop Alerts For This Post-Type"
|
1285 |
-
|
1286 |
-
msgid "AlertsPerHour"
|
1287 |
-
msgstr "Alerts Per Hour"
|
1288 |
-
|
1289 |
-
msgid "AlertsPerHourMaximum"
|
1290 |
-
msgstr "Maximum Alerts Per Hour"
|
1291 |
-
|
1292 |
-
msgid "AlertsPerHourInfo"
|
1293 |
-
msgstr "Configure the maximum number of email alerts per hour. If the number is exceeded and the plugin detects more events during the same hour, it will still log the events into the audit logs but will not send the email alerts. Be careful with this as you will miss important information."
|
1294 |
-
|
1295 |
-
msgid "TestAlerts"
|
1296 |
-
msgstr "Test Alerts"
|
1297 |
-
|
1298 |
-
msgid "AlertsRecipient"
|
1299 |
-
msgstr "Alerts Recipient"
|
1300 |
-
|
1301 |
-
msgid "AlertsRecipientInfo"
|
1302 |
-
msgstr "By default, the plugin will send the email alerts to the primary admin account, the same account created during the installation of WordPress in your web server. You can add more people to the list, they will receive a copy of the same security alerts."
|
1303 |
-
|
1304 |
-
msgid "CustomFormat"
|
1305 |
-
msgstr "Custom Format"
|
1306 |
-
|
1307 |
-
msgid "AlertsSubject"
|
1308 |
-
msgstr "Alert Subject"
|
1309 |
-
|
1310 |
-
msgid "AlertsSubjectInfo"
|
1311 |
-
msgstr "Format of the subject for the email alerts, by default the plugin will use the website name and the event identifier that is being reported, you can use this panel to include the IP address of the user that triggered the event and some additional data. You can create filters in your email client creating a custom email subject using the pseudo-tags shown below."
|
1312 |
-
|
1313 |
-
msgid "TrustedIPs"
|
1314 |
-
msgstr "Trusted IP Addresses"
|
1315 |
-
|
1316 |
-
msgid "CIDRFormat"
|
1317 |
-
msgstr "CIDR Format"
|
1318 |
-
|
1319 |
-
msgid "IPAddedAt"
|
1320 |
-
msgstr "IP Added At"
|
1321 |
-
|
1322 |
-
msgid "TrustedIPsInfo"
|
1323 |
-
msgstr "If you are working in a LAN <em>(Local Area Network)</em> you may want to include the IP addresses of all the nodes in the subnet, this will force the plugin to stop sending email alerts about actions executed from trusted IP addresses. Use the CIDR <em>(Classless Inter Domain Routing)</em> format to specify ranges of IP addresses <em>(only 8, 16, and 24)</em>."
|
1324 |
-
|
1325 |
-
msgid "APIViaProxy"
|
1326 |
-
msgstr "API Communication via Proxy"
|
1327 |
-
|
1328 |
-
msgid "APIViaProxyInfo"
|
1329 |
-
msgstr "All the HTTP requests used to communicate with the API service are being sent using the WordPress built-in functions, so (almost) all its official features are inherited, this is useful if you need to pass these HTTP requests through a proxy. According to the <a href=\"https://developer.wordpress.org/reference/classes/wp_http_proxy/\" target=\"_blank\" rel=\"noopener\">official documentation</a> you have to add some constants to the main configuration file: <em>WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME, WP_PROXY_PASSWORD</em>."
|
1330 |
-
|
1331 |
-
msgid "ProxyHostname"
|
1332 |
-
msgstr "HTTP Proxy Hostname"
|
1333 |
-
|
1334 |
-
msgid "ProxyPort"
|
1335 |
-
msgstr "HTTP Proxy Port num"
|
1336 |
-
|
1337 |
-
msgid "ProxyUsername"
|
1338 |
-
msgstr "HTTP Proxy Username"
|
1339 |
-
|
1340 |
-
msgid "ProxyPassword"
|
1341 |
-
msgstr "HTTP Proxy Password"
|
1342 |
-
|
1343 |
-
msgid "APICommunication"
|
1344 |
-
msgstr "API Service Communication"
|
1345 |
-
|
1346 |
-
msgid "APICommunicationInfo"
|
1347 |
-
msgstr "Once the API key is generate the plugin will communicate with a remote API service that will act as a safe data storage for the audit logs generated when the website triggers certain events that the plugin monitors. If the website is hacked the attacker will not have access to these logs and that way you can investigate what was modified <em>(for malware infaction)</em> and/or how the malicious person was able to gain access to the website."
|
1348 |
-
|
1349 |
-
msgid "APICommunicationDisabled"
|
1350 |
-
msgstr "Disabling the API service communication will stop the event monitoring, consider to enable the <a href=\"%%SUCURI.URL.Settings%%#general\">Log Exporter</a> to keep the monitoring working while the HTTP requests are ignored, otherwise an attacker may execute an action that will not be registered in the security logs and you will not have a way to investigate the attack in the future."
|
1351 |
-
|
1352 |
-
msgid "APITimeout"
|
1353 |
-
msgstr "API Request Timeout"
|
1354 |
-
|
1355 |
-
msgid "APITimeoutLabel"
|
1356 |
-
msgstr "API Request Timeout (in seconds)"
|
1357 |
-
|
1358 |
-
msgid "APITimeoutValue"
|
1359 |
-
msgstr "Wait <b>%%SUCURI.RequestTimeout%%</b> before timeout"
|
1360 |
-
|
1361 |
-
msgid "APITimeoutInfo"
|
1362 |
-
msgstr "The plugin sends the data associated to the events triggered by WordPress when it considers the action is suspicious, it sends this information via HTTP requests using the HTTP transport protocol available in the system and the <a target=\"_blank\" href=\"https://developer.wordpress.org/reference/functions/wp_remote_post/\" rel=\"noopener\">built-in functions</a> provided by WordPress, then it waits for the response. If you start experiencing issues related with the timeout of the requests you may consider to increase the number of seconds to wait for the response. You may also want to check with your hosting provider to see if there is something in the server blocking the connection."
|
1363 |
-
|
1364 |
-
msgid "HTAccessTitle"
|
1365 |
-
msgstr "Access File Integrity"
|
1366 |
-
|
1367 |
-
msgid "HTAccessInfo"
|
1368 |
-
msgstr "The <code>.htaccess</code> is a distributed configuration file, and is how the Apache web server handles configuration changes on a per-directory basis. WordPress uses this file to manipulate how Apache serves files from its root directory and subdirectories thereof; most notably, it modifies this file to be able to handle pretty permalinks."
|
1369 |
-
|
1370 |
-
msgid "HTAccessFound"
|
1371 |
-
msgstr "HTAccess file found in this path <code>%%SUCURI.HTAccess.Fpath%%</code>"
|
1372 |
-
|
1373 |
-
msgid "HTAccessNotFound"
|
1374 |
-
msgstr "Your website has no <code>.htaccess</code> file or it was not found in the default location."
|
1375 |
-
|
1376 |
-
msgid "HTAccessStandard"
|
1377 |
-
msgstr "The main <code>.htaccess</code> file in your site has the standard rules for a WordPress installation. You can customize it to improve the performance and change the behaviour of the redirections for pages and posts in your site. To get more information visit the official documentation at <a target=\"_blank\" rel=\"noopener\" href=\"https://codex.wordpress.org/Using_Permalinks#Creating_and_editing_.28.htaccess.29\"> Codex WordPress - Creating and editing (.htaccess)</a>"
|
1378 |
-
|
1379 |
-
msgid "ScannerDescription"
|
1380 |
-
msgstr "The plugin scans your entire website looking for changes which are later reported via the API in the audit logs page. This scanner runs daily but you can change the frequency to meet your own requirements. Notice that scanning your project files too frequently will affect the performance of your website. Be sure to have enough server resources before changing this option. The memory limit and maximum execution time are two of the PHP options that your server will set to stop your website from consuming too much resources."
|
1381 |
-
|
1382 |
-
msgid "ScannerWithoutSPL"
|
1383 |
-
msgstr "The scanner uses the <a href=\"http://php.net/manual/en/class.splfileobject.php\" target=\"_blank\" rel=\"noopener\">PHP SPL library</a> and the <a target=\"_blank\" href=\"http://php.net/manual/en/class.filesystemiterator.php\" rel=\"noopener\">Filesystem Iterator</a> class to scan the directory tree where your website is located in the server. This library is only available on PHP 5 >= 5.3.0 — OR — PHP 7; if you have an older version of PHP the plugin will not work as expected. Please ask your hosting provider to advice you on this matter."
|
1384 |
-
|
1385 |
-
msgid "IntegrityLanguageTitle"
|
1386 |
-
msgstr "WordPress Integrity (Language)"
|
1387 |
-
|
1388 |
-
msgid "IntegrityInfo"
|
1389 |
-
msgstr "The information necessary to check the WordPress integrity uses data obtained from the <a href=\"http://codex.wordpress.org/WordPress.org_API\" target=\"_blank\" rel=\"noopener\">WordPress API</a>. It compares this data with the content of the files installed in your website. By default the API returns this data for the English version of WordPress. If your website is using a non-English version of the code you will have to specify the language to reduce the amount of false/positives."
|
1390 |
-
|
1391 |
-
msgid "IntegrityNote"
|
1392 |
-
msgstr "<b>NOTE:</b> Not all the languages are supported. If you notice a high amount of false/positives please consider to switch the option back to English and then mark the files that you consider are clean as such, they will be ignored by the scanner the next time it runs."
|
1393 |
-
|
1394 |
-
msgid "Reason"
|
1395 |
-
msgstr "Reason"
|
1396 |
-
|
1397 |
-
msgid "FalsePositives"
|
1398 |
-
msgstr "WordPress Integrity (False/Positives)"
|
1399 |
-
|
1400 |
-
msgid "FalsePositivesUnignore"
|
1401 |
-
msgstr "Stop Ignoring the Selected Files"
|
1402 |
-
|
1403 |
-
msgid "FalsePositivesInfo"
|
1404 |
-
msgstr "Since the scanner doesn't reads the files during the execution of the integrity check, it is possible to find false/positives. Files listed here have been marked as false/positives and will be ignored by the scanner in subsequent scans."
|
1405 |
-
|
1406 |
-
msgid "IgnoreFiles"
|
1407 |
-
msgstr "Ignore Files And Folders During The Scans"
|
1408 |
-
|
1409 |
-
msgid "IgnoreFilesSingle"
|
1410 |
-
msgstr "Ignore One Single File"
|
1411 |
-
|
1412 |
-
msgid "IgnoreFilesInfo"
|
1413 |
-
msgstr "Use this tool to select the files and/or folders that are too heavy for the scanner to process. These are usually folders with images, media files like videos and audios, backups and — in general — anything that is not code-related. Ignoring these files or folders will reduce the memory consumption of the PHP script."
|
1414 |
-
|
1415 |
-
msgid "SecretKeys"
|
1416 |
-
msgstr "Update Secret Keys"
|
1417 |
-
|
1418 |
-
msgid "SecretKeysUpdated"
|
1419 |
-
msgstr "Secret keys updated successfully (summary of the operation bellow)."
|
1420 |
-
|
1421 |
-
msgid "SecretKeysGenerate"
|
1422 |
-
msgstr "Generate New Security Keys"
|
1423 |
-
|
1424 |
-
msgid "SecretKeysExpiration"
|
1425 |
-
msgstr "Your session will expire immediately after the security keys are changed."
|
1426 |
-
|
1427 |
-
msgid "SecretKeysInfo"
|
1428 |
-
msgstr "The secret or security keys are a list of constants added to your site to ensure better encryption of information stored in the user's cookies. A secret key makes your site harder to hack and access by adding random elements to the password. You do not have to remember the keys, just write a random, complicated, and long string in the <code>wp-config.php</code> file. You can change these keys at any point in time to invalidate all existing cookies, forcing all users to login again."
|
1429 |
-
|
1430 |
-
msgid "PluginReinstall"
|
1431 |
-
msgstr "Reset Installed Plugins"
|
1432 |
-
|
1433 |
-
msgid "PluginReinstallInfo"
|
1434 |
-
msgstr "In case that you suspect of an infection in your site, or even after you got rid of a malicious code, it would be better if you reinstall all the plugins installed in your site, including the ones you are not using. Notice that premium plugins will not be reinstalled to prevent backward compatibility issues and problems with licenses."
|
1435 |
-
|
1436 |
-
msgid "PluginReinstallCache"
|
1437 |
-
msgstr "The information shown here is cache for %%SUCURI.ResetPlugin.CacheLifeTime%% seconds, this is necessary to reduce the quantity of HTTP requests sent to the WordPress servers and the bandwidth of your site. Currently there is no option to recreate this cache so you have to wait until it resets itself."
|
1438 |
-
|
1439 |
-
msgid "PluginReinstallWarning"
|
1440 |
-
msgstr "<b>WARNING!</b> This procedure can break your website. The reset will not affect the database nor the settings of each plugin but depending on how they were written the reset action might break them. Be sure to create a backup of the plugins directory before the execution of this tool."
|
1441 |
-
|
1442 |
-
msgid "Roles"
|
1443 |
-
msgstr "Roles"
|
1444 |
-
|
1445 |
-
msgid "Registered"
|
1446 |
-
msgstr "Registered"
|
1447 |
-
|
1448 |
-
msgid "PasswordChange"
|
1449 |
-
msgstr "Reset User Password"
|
1450 |
-
|
1451 |
-
msgid "PasswordChangeInfo"
|
1452 |
-
msgstr "You can generate a new random password for the user accounts that you select from the list. An email with the new password will be sent to the email address of each chosen users. If you choose to change the password of your own user, then your current session will expire immediately. You will need to log into the admin panel with the new password that will be sent to your email."
|
1453 |
-
|
1454 |
-
msgid "PasswordChangeAlert"
|
1455 |
-
msgstr "WordPress has generated a new (random) password for your account <b>%%SUCURI.ResetPassword.UserName%%</b> at <a target=\"_blank\" href=\"http://%%SUCURI.ResetPassword.Website%%\">%%SUCURI.ResetPassword.Website%%</a>. The change has been requested by one of the admins in this website for security reasons. Your new password is — <span style=\"font-family:Menlo, Monaco, monospace, serif;font-weight:700\">%%%SUCURI.ResetPassword.Password%%%</span> — please change it as soon as possible."
|
1456 |
-
|
1457 |
-
msgid "Update"
|
1458 |
-
msgstr "Update"
|
1459 |
-
|
1460 |
-
msgid "TestedWith"
|
1461 |
-
msgstr "Tested With"
|
1462 |
-
|
1463 |
-
msgid "AvailableUpdates"
|
1464 |
-
msgstr "Available Plugin and Theme Updates"
|
1465 |
-
|
1466 |
-
msgid "AvailableUpdatesInfo"
|
1467 |
-
msgstr "WordPress has a big user base in the public Internet, this brings interest to malicious people to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website update to prevent attacks as soon as disclosed vulnerabilities are patched."
|
1468 |
-
|
1469 |
-
msgid "WhitelistScript"
|
1470 |
-
msgstr "Whitelist Blocked PHP Files"
|
1471 |
-
|
1472 |
-
msgid "WhitelistScriptInfo"
|
1473 |
-
msgstr "After you apply the hardening in either the includes, content, and/or upload directories the plugin will add a rule in the access control file to deny access to any PHP file located in these folders, this is a good precaution in case that an attacker is able to upload a shell script; with a few exceptions the <em>\"index.php\"</em> is the only one that should be publicly accessible, however many theme/plugin developers decide to use these folders to process some operations, in this case applying the hardening <strong>may break</strong> their functionality."
|
1474 |
-
|
1475 |
-
msgid "Uninstall"
|
1476 |
-
msgstr "Reset Security Logs, Hardening and Settings"
|
1477 |
-
|
1478 |
-
msgid "UninstallInfo"
|
1479 |
-
msgstr "This action will trigger the deactivation / uninstallation process of the plugin. All local security logs, hardening and settings will be deleted. Notice that the security logs stored in the API service will not be deleted, this is to prevent tampering from a malicious user. You can request a new API key if you want to start from scratch."
|
1480 |
-
|
1481 |
-
msgid "ImportExport"
|
1482 |
-
msgstr "Import & Export Settings"
|
1483 |
-
|
1484 |
-
msgid "ImportExportInfo"
|
1485 |
-
msgstr "Copy the JSON-encoded data from the box below, go to your other websites and click the <em>\"Import\"</em> button in the settings page. The plugin will start using the same settings from this website. Notice that some options are omitted as they contain values specific to this website. To import the settings from another website into this one, replace the JSON-encoded data in the box below with the JSON-encoded data exported from the other website, then click the button <em>\"Import\"</em>. Notice that some options will not be imported to reduce the security risk of writing arbitrary data into the disk."
|
1486 |
-
|
1487 |
-
msgid "DataStorage"
|
1488 |
-
msgstr "Data Storage"
|
1489 |
-
|
1490 |
-
msgid "DataStorageInfo"
|
1491 |
-
msgstr "This is the directory where the plugin will store the security logs, the list of files marked as fixed in the core integrity tool, the cache for the malware scanner and 3rd-party plugin metadata. The plugin requires write permissions in this directory as well as the files contained in it. If you prefer to keep these files in a non-public directory <em>(one level up the document root) </em> please define a constant in the <em>\"wp-config.php\"</em> file named <em>\"SUCURI_DATA_STORAGE\"</em> with the absolute path to the new directory."
|
1492 |
-
|
1493 |
-
msgid "TimezoneTitle"
|
1494 |
-
msgstr "Timezone"
|
1495 |
-
|
1496 |
-
msgid "TimezoneInfo"
|
1497 |
-
msgstr "This option defines the timezone that will be used through out the entire plugin to print the dates and times whenever is necessary. This option also affects the date and time of the logs visible in the audit logs panel which is data that comes from a remote server configured to use Eastern Daylight Time (EDT). WordPress offers an option in the general settings page to allow you to configure the timezone for the entire website, however, if you are experiencing problems with the time in the audit logs, this option will help you fix them."
|
1498 |
-
|
1499 |
-
msgid "TimezoneStatus"
|
1500 |
-
msgstr "The timezone for the date and time in the audit logs has been changed"
|
1501 |
-
|
1502 |
-
msgid "ChecksumsAPI"
|
1503 |
-
msgstr "WordPress Checksums API"
|
1504 |
-
|
1505 |
-
msgid "ChecksumsAPIInfo"
|
1506 |
-
msgstr "The WordPress integrity tool uses a remote API service maintained by the WordPress organization to determine which files in the installation were added, removed or modified. The API returns a list of files with their respective checksums, this information guarantees that the installation is not corrupt. You can, however, point the integrity tool to a GitHub repository in case that you are using a custom version of WordPress like the <a href=\"https://github.com/WordPress/WordPress\" target=\"_blank\">development version of the code</a>."
|
1507 |
-
|
1508 |
-
msgid "ChecksumsAPIChanged"
|
1509 |
-
msgstr "The URL to retrieve the WordPress checksums has been changed"
|
1510 |
-
|
1511 |
-
msgid "MaxExecutionTimeAlert"
|
1512 |
-
msgstr "Server is not fast enough to process this action; maximum execution time reached"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
languages/sucuri-scanner-es_ES.mo
DELETED
Binary file
|
languages/sucuri-scanner-es_ES.po
DELETED
@@ -1,1513 +0,0 @@
|
|
1 |
-
msgid ""
|
2 |
-
msgstr ""
|
3 |
-
"Content-Transfer-Encoding: 8bit\n"
|
4 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
5 |
-
"Language-Team: https://sucuri.net/\n"
|
6 |
-
"Language: es_ES\n"
|
7 |
-
"Last-Translator: Sucuri Inc. <info@sucuri.net>\n"
|
8 |
-
"MIME-Version: 1.0\n"
|
9 |
-
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
10 |
-
"PO-Revision-Date: \n"
|
11 |
-
"POT-Creation-Date: 2017-06-01 09:00-0700\n"
|
12 |
-
"Project-Id-Version: Sucuri Scanner\n"
|
13 |
-
"X-Generator: Poedit 1.8.12\n"
|
14 |
-
|
15 |
-
msgid "Review"
|
16 |
-
msgstr "Revisión"
|
17 |
-
|
18 |
-
msgid "Dashboard"
|
19 |
-
msgstr "Inicio"
|
20 |
-
|
21 |
-
msgid "Firewall"
|
22 |
-
msgstr "Firewall (WAF)"
|
23 |
-
|
24 |
-
msgid "LastLogins"
|
25 |
-
msgstr "Autenticaciones"
|
26 |
-
|
27 |
-
msgid "Settings"
|
28 |
-
msgstr "Ajustes"
|
29 |
-
|
30 |
-
msgid "AuditLogs"
|
31 |
-
msgstr "Registros"
|
32 |
-
|
33 |
-
msgid "ClearCache"
|
34 |
-
msgstr "Limpiar Cache"
|
35 |
-
|
36 |
-
msgid "IPAccess"
|
37 |
-
msgstr "Acceso Por IP"
|
38 |
-
|
39 |
-
msgid "GenerateAPIKey"
|
40 |
-
msgstr "Generar Llave"
|
41 |
-
|
42 |
-
msgid "APIKeyRecovery"
|
43 |
-
msgstr "Recuperacion de Llave"
|
44 |
-
|
45 |
-
msgid "Copyright"
|
46 |
-
msgstr "© %%SUCURI.Year%% Sucuri Inc. Todos los derechos reservados."
|
47 |
-
|
48 |
-
msgid "AccessDenied"
|
49 |
-
msgstr "Accesso denegado por Sucuri Inc."
|
50 |
-
|
51 |
-
msgid "NonceFailure"
|
52 |
-
msgstr "Error al verificar el código Nonce del formulario, verifica los datos e inténtalo de nuevo."
|
53 |
-
|
54 |
-
msgid "NewsletterInvitation"
|
55 |
-
msgstr "¿Te gustaría recibir información sobre vulnerabilidades descubiertas? Subscríbete a nuestro newsletter <a href=\"http://sucuri.hs-sites.com/subscribe-to-security\" target=\"_blank\" rel=\"noopener\">aquí</a>"
|
56 |
-
|
57 |
-
msgid "EnableAPIServiceAgain"
|
58 |
-
msgstr "La comunicación con la API de Sucuri está deshabilitada, si acabas de actualizar el plugin esta podría ser una buena oportunidad para probar esta herramienta una vez más con el nuevo código. Habilite la comunicación con la API desde la página de ajustes."
|
59 |
-
|
60 |
-
msgid "Save"
|
61 |
-
msgstr "Guardar"
|
62 |
-
|
63 |
-
msgid "Delete"
|
64 |
-
msgstr "Eliminar"
|
65 |
-
|
66 |
-
msgid "InvalidAPIKey"
|
67 |
-
msgstr "El formato de la llave es inválido"
|
68 |
-
|
69 |
-
msgid "ErrorNoInfo"
|
70 |
-
msgstr "Error desconocido, no hay más información."
|
71 |
-
|
72 |
-
msgid "ErrorLogFileNotFound"
|
73 |
-
msgstr "; esto generalmente sucede cuando una llave inválida es agregada al plugin, la llave será eliminada automáticamente para reducir la cantidad de errores, si quieres recuperarla, utiliza el botón de recuperación en la página de ajustes, y recibirás un correo con las instrucciones de activación: %1$s"
|
74 |
-
|
75 |
-
msgid "ErrorWrongAPIKey"
|
76 |
-
msgstr "; la llave del Firewall es inválida: %1$s"
|
77 |
-
|
78 |
-
msgid "ErrorSSLCertificate"
|
79 |
-
msgstr ". Tu sitio web parece estar usando una versión desactualizada de la librería OpenSSL o el módulo de CURL ha sido compilado sin soporte para el algoritmo usado para establecer un enlace de comunicación segura con la API. Contácta a tu proveedor de hosting para solucionar el problema."
|
80 |
-
|
81 |
-
msgid "ErrorInvalidEmail"
|
82 |
-
msgstr "El correo electrónico tiene un formato inválido o el dominio asociado no tiene asociado un servidor MX."
|
83 |
-
|
84 |
-
msgid "AlertAPIKeySet"
|
85 |
-
msgstr "La llave para la comunicación con la API ha sido generada y registrada."
|
86 |
-
|
87 |
-
msgid "Yes"
|
88 |
-
msgstr "Sí"
|
89 |
-
|
90 |
-
msgid "No"
|
91 |
-
msgstr "No"
|
92 |
-
|
93 |
-
msgid "Okay"
|
94 |
-
msgstr "OK"
|
95 |
-
|
96 |
-
msgid "Enable"
|
97 |
-
msgstr "Activar"
|
98 |
-
|
99 |
-
msgid "Enabled"
|
100 |
-
msgstr "Activado"
|
101 |
-
|
102 |
-
msgid "Disable"
|
103 |
-
msgstr "Desactivar"
|
104 |
-
|
105 |
-
msgid "Disabled"
|
106 |
-
msgstr "Desactivado"
|
107 |
-
|
108 |
-
msgid "Ignore"
|
109 |
-
msgstr "Ignorar"
|
110 |
-
|
111 |
-
msgid "Unignore"
|
112 |
-
msgstr "No Ignorar"
|
113 |
-
|
114 |
-
msgid "Ignored"
|
115 |
-
msgstr "Ignorado"
|
116 |
-
|
117 |
-
msgid "Done"
|
118 |
-
msgstr "Hecho"
|
119 |
-
|
120 |
-
msgid "Submit"
|
121 |
-
msgstr "Proceder"
|
122 |
-
|
123 |
-
msgid "Error"
|
124 |
-
msgstr "Error"
|
125 |
-
|
126 |
-
msgid "Good"
|
127 |
-
msgstr "bien"
|
128 |
-
|
129 |
-
msgid "Edit"
|
130 |
-
msgstr "Editar"
|
131 |
-
|
132 |
-
msgid "NotSet"
|
133 |
-
msgstr "(no existe)"
|
134 |
-
|
135 |
-
msgid "Download"
|
136 |
-
msgstr "Descargar"
|
137 |
-
|
138 |
-
msgid "NotRandomized"
|
139 |
-
msgstr "no es aleatorio"
|
140 |
-
|
141 |
-
msgid "NotWritable"
|
142 |
-
msgstr "No es Modificable"
|
143 |
-
|
144 |
-
msgid "ParentNotWritable"
|
145 |
-
msgstr "El directorio donde el archivo está ubicado no tiene permisos de escritura."
|
146 |
-
|
147 |
-
msgid "DoesNotExist"
|
148 |
-
msgstr "No Existe"
|
149 |
-
|
150 |
-
msgid "Email"
|
151 |
-
msgstr "Correo Electrónico"
|
152 |
-
|
153 |
-
msgid "Website"
|
154 |
-
msgstr "Sitio Web"
|
155 |
-
|
156 |
-
msgid "Message"
|
157 |
-
msgstr "Mensaje"
|
158 |
-
|
159 |
-
msgid "Information"
|
160 |
-
msgstr "Información"
|
161 |
-
|
162 |
-
msgid "Event"
|
163 |
-
msgstr "Evento"
|
164 |
-
|
165 |
-
msgid "Exists"
|
166 |
-
msgstr "Existe"
|
167 |
-
|
168 |
-
msgid "Writable"
|
169 |
-
msgstr "Modificable"
|
170 |
-
|
171 |
-
msgid "Today"
|
172 |
-
msgstr "Hoy"
|
173 |
-
|
174 |
-
msgid "NoLogs"
|
175 |
-
msgstr "No existen registros."
|
176 |
-
|
177 |
-
msgid "SelfHosting"
|
178 |
-
msgstr "Exportador de Registros"
|
179 |
-
|
180 |
-
msgid "SelfHostingEnabled"
|
181 |
-
msgstr "La herramienta para exportar los registros de seguridad ha sido activada"
|
182 |
-
|
183 |
-
msgid "SelfHostingDisabled"
|
184 |
-
msgstr "La herramienta para exportar los registros de seguridad ha sido desactivada"
|
185 |
-
|
186 |
-
msgid "SelfHostingInfo"
|
187 |
-
msgstr "Esta opción te permite guardar una copia de los registros de seguridad en un archivo ubicado en tu servidor que puede ser leído por un SIEM o cualquier otro sistema de análisis (le recomendamos OSSEC). Esto te dará visibilidad de lo que sucede en tu sitio web para complementar tu infraestructura de monitoreo. <b>NOTA:</b> No use archivos que sean accesibles de forma pública, use un archivo que esté por lo menos un nivel arriva de la raíz del sitio web para evitar fugas de información."
|
188 |
-
|
189 |
-
msgid "SelfHostingFallback"
|
190 |
-
msgstr "No tienes una llave para comunicarte con la API. Sin embargo, la herramienta para exportar los registros de seguridad está activada, el plugin leerá el contenido de este archivo y mostrará esa información aquí. Ten en cuenta que solo los últimos registros serán procesados para mantener un consumo de memoria bajo. Considera generar una llave para obtener una mayor cobertura en la actividad de tu sitio web."
|
191 |
-
|
192 |
-
msgid "AuditLogsCache"
|
193 |
-
msgstr "Los registros son guardados por %%SUCURI.AuditLogs.Lifetime%% segundos"
|
194 |
-
|
195 |
-
msgid "Refresh"
|
196 |
-
msgstr "Actualizar"
|
197 |
-
|
198 |
-
msgid "AuditLogsNoAPI"
|
199 |
-
msgstr "La API no está disponible; la información viene del servidor local"
|
200 |
-
|
201 |
-
msgid "AuditLogsQueue"
|
202 |
-
msgstr "registros en cola"
|
203 |
-
|
204 |
-
msgid "SendLogs"
|
205 |
-
msgstr "Enviar"
|
206 |
-
|
207 |
-
msgid "UnsupportedWordPress"
|
208 |
-
msgstr "esta versión de WordPress no tiene soporte."
|
209 |
-
|
210 |
-
msgid "NoWordPressFile"
|
211 |
-
msgstr "El archivo no hace parte de la instalación oficial de WordPress."
|
212 |
-
|
213 |
-
msgid "ThereAreNoDifferences"
|
214 |
-
msgstr "No existen diferencias entre el archivo instalado y el original"
|
215 |
-
|
216 |
-
msgid "ScheduledTask"
|
217 |
-
msgstr "%1$s (cada %2$d segundos)"
|
218 |
-
|
219 |
-
msgid "ScheduledTaskNever"
|
220 |
-
msgstr "Nunca (no ejecutar)"
|
221 |
-
|
222 |
-
msgid "SucuriAlert"
|
223 |
-
msgstr "Alerta de Sucuri"
|
224 |
-
|
225 |
-
msgid "UpdatedEmailSubject"
|
226 |
-
msgstr "El asunto para las alertas de seguridad ha sido actualizado"
|
227 |
-
|
228 |
-
msgid "InvalidEmailSubject"
|
229 |
-
msgstr "El asunto para las alertas de seguridad contiene letras inválidas."
|
230 |
-
|
231 |
-
msgid "EmailSubject.available_updates"
|
232 |
-
msgstr "Actualizaciones Disponibles"
|
233 |
-
|
234 |
-
msgid "EmailSubject.bruteforce_attack"
|
235 |
-
msgstr "Ataque de Fuerza Bruta"
|
236 |
-
|
237 |
-
msgid "EmailSubject.failed_login"
|
238 |
-
msgstr "Autenticación Fallida"
|
239 |
-
|
240 |
-
msgid "EmailSubject.plugin_activated"
|
241 |
-
msgstr "Plugin Activado"
|
242 |
-
|
243 |
-
msgid "EmailSubject.plugin_change"
|
244 |
-
msgstr "Plugin Modificado"
|
245 |
-
|
246 |
-
msgid "EmailSubject.plugin_deactivated"
|
247 |
-
msgstr "Plugin Desactivado"
|
248 |
-
|
249 |
-
msgid "EmailSubject.plugin_deleted"
|
250 |
-
msgstr "Plugin Eliminado"
|
251 |
-
|
252 |
-
msgid "EmailSubject.plugin_installed"
|
253 |
-
msgstr "Plugin Instalado"
|
254 |
-
|
255 |
-
msgid "EmailSubject.plugin_updated"
|
256 |
-
msgstr "Plugin Actualizado"
|
257 |
-
|
258 |
-
msgid "EmailSubject.post_publication"
|
259 |
-
msgstr "Publicación"
|
260 |
-
|
261 |
-
msgid "EmailSubject.scan_checksums"
|
262 |
-
msgstr "Escaneo de Checksums"
|
263 |
-
|
264 |
-
msgid "EmailSubject.settings_updated"
|
265 |
-
msgstr "Ajustes Actualizados"
|
266 |
-
|
267 |
-
msgid "EmailSubject.success_login"
|
268 |
-
msgstr "Autenticación Exitosa"
|
269 |
-
|
270 |
-
msgid "EmailSubject.theme_activated"
|
271 |
-
msgstr "Plantilla Activada"
|
272 |
-
|
273 |
-
msgid "EmailSubject.theme_deleted"
|
274 |
-
msgstr "Plantilla Eliminada"
|
275 |
-
|
276 |
-
msgid "EmailSubject.theme_editor"
|
277 |
-
msgstr "Editor de Plantilla"
|
278 |
-
|
279 |
-
msgid "EmailSubject.theme_installed"
|
280 |
-
msgstr "Plantilla Instalada"
|
281 |
-
|
282 |
-
msgid "EmailSubject.theme_updated"
|
283 |
-
msgstr "Plantilla Actualizada"
|
284 |
-
|
285 |
-
msgid "EmailSubject.user_registration"
|
286 |
-
msgstr "Registro de Usuario"
|
287 |
-
|
288 |
-
msgid "EmailSubject.website_updated"
|
289 |
-
msgstr "Sitio Web Actualizado"
|
290 |
-
|
291 |
-
msgid "EmailSubject.widget_added"
|
292 |
-
msgstr "Widget Agregado"
|
293 |
-
|
294 |
-
msgid "EmailSubject.widget_deleted"
|
295 |
-
msgstr "Widget Eliminado"
|
296 |
-
|
297 |
-
msgid "EmailSubject.post_update"
|
298 |
-
msgstr "Publicación Actualizada"
|
299 |
-
|
300 |
-
msgid "EmailSubject.core_integrity_checks"
|
301 |
-
msgstr "Integridad de Archivos de WordPress"
|
302 |
-
|
303 |
-
msgid "EmailSubject.password_change"
|
304 |
-
msgstr "Cambio de Contraseña"
|
305 |
-
|
306 |
-
msgid "FailedLoginFooter"
|
307 |
-
msgstr "<br><br><em>Explicación: Alguien intentó ingresar al sistema de administración de tu sitio web. Si estás recibiendo muchas de estas alertas, es posible que alguien esté utilizando un ataque de fuerza bruta para vulnerar tu sitio [1]. Puedes desactivar estas alertas desde aquí [2]. También puedes considerar la instalación de un Firewall para filtrar el tráfico malicioso y ataques como este [3].</em><br><br>[1] <a href='https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing'>https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing</a><br>[2] <a href='%1$s'>%2$s</a> <br>[3] <a href='https://sucuri.net/es/firewall-de-sitios-web/?wpalert'>https://sucuri.net/es/firewall-de-sitios-web/</a><br>"
|
308 |
-
|
309 |
-
msgid "FirewallAPIKeySet"
|
310 |
-
msgstr "La llave del Firewall ha sido guardada"
|
311 |
-
|
312 |
-
msgid "FirewallAPIKeyUnset"
|
313 |
-
msgstr "La llave del Firewall ha sido eliminada"
|
314 |
-
|
315 |
-
msgid "FirewallAPIKeyInvalid"
|
316 |
-
msgstr "La llave del Firewall es inválida"
|
317 |
-
|
318 |
-
msgid "FirewallAPIKeyMissing"
|
319 |
-
msgstr "La llave del Firewall no fué encontrada."
|
320 |
-
|
321 |
-
msgid "NoData"
|
322 |
-
msgstr "No existen datos"
|
323 |
-
|
324 |
-
msgid "FirewallDoCache"
|
325 |
-
msgstr "Activada (recomendada)"
|
326 |
-
|
327 |
-
msgid "FirewallSiteCache"
|
328 |
-
msgstr "Cache usando cabeceras de HTTP"
|
329 |
-
|
330 |
-
msgid "FirewallNoCache"
|
331 |
-
msgstr "Mínima (solo por algunos minutos)"
|
332 |
-
|
333 |
-
msgid "FirewallNoCacheAtAll"
|
334 |
-
msgstr "Desactivada (use con precaución)"
|
335 |
-
|
336 |
-
msgid "FirewallNotEnabled"
|
337 |
-
msgstr "El Firewall no ha sido activado en tu sitio o la llave de autenticación es inválida."
|
338 |
-
|
339 |
-
msgid "FirewallClearCacheFailure"
|
340 |
-
msgstr "No se pudo actualizar la cache de tu sitio, inténtalo más tarde."
|
341 |
-
|
342 |
-
msgid "Active"
|
343 |
-
msgstr "activo"
|
344 |
-
|
345 |
-
msgid "NotActive"
|
346 |
-
msgstr "inactivo"
|
347 |
-
|
348 |
-
msgid "Unknown"
|
349 |
-
msgstr "desconocido"
|
350 |
-
|
351 |
-
msgid "Undefined"
|
352 |
-
msgstr "Indefinido"
|
353 |
-
|
354 |
-
msgid "January"
|
355 |
-
msgstr "Enero"
|
356 |
-
|
357 |
-
msgid "February"
|
358 |
-
msgstr "Febrero"
|
359 |
-
|
360 |
-
msgid "March"
|
361 |
-
msgstr "Marzo"
|
362 |
-
|
363 |
-
msgid "April"
|
364 |
-
msgstr "Abril"
|
365 |
-
|
366 |
-
msgid "May"
|
367 |
-
msgstr "Mayo"
|
368 |
-
|
369 |
-
msgid "June"
|
370 |
-
msgstr "Junio"
|
371 |
-
|
372 |
-
msgid "July"
|
373 |
-
msgstr "Julio"
|
374 |
-
|
375 |
-
msgid "August"
|
376 |
-
msgstr "Agosto"
|
377 |
-
|
378 |
-
msgid "September"
|
379 |
-
msgstr "Septiembre"
|
380 |
-
|
381 |
-
msgid "October"
|
382 |
-
msgstr "Octubre"
|
383 |
-
|
384 |
-
msgid "November"
|
385 |
-
msgstr "Noviembre"
|
386 |
-
|
387 |
-
msgid "December"
|
388 |
-
msgstr "Deciembre"
|
389 |
-
|
390 |
-
msgid "Username"
|
391 |
-
msgstr "Usuario"
|
392 |
-
|
393 |
-
msgid "Password"
|
394 |
-
msgstr "Contraseña"
|
395 |
-
|
396 |
-
msgid "RemoteAddr"
|
397 |
-
msgstr "Dirección IP"
|
398 |
-
|
399 |
-
msgid "Hostname"
|
400 |
-
msgstr "Servidor"
|
401 |
-
|
402 |
-
msgid "Browser"
|
403 |
-
msgstr "Navegador Web"
|
404 |
-
|
405 |
-
msgid "Datetime"
|
406 |
-
msgstr "Fecha/Hora"
|
407 |
-
|
408 |
-
msgid "Block"
|
409 |
-
msgstr "Bloquear"
|
410 |
-
|
411 |
-
msgid "Unblock"
|
412 |
-
msgstr "Desbloquear"
|
413 |
-
|
414 |
-
msgid "BlockedAt"
|
415 |
-
msgstr "Bloqueado en"
|
416 |
-
|
417 |
-
msgid "FirstAttempt"
|
418 |
-
msgstr "Primer Intento"
|
419 |
-
|
420 |
-
msgid "LastAttempt"
|
421 |
-
msgstr "Último Intento"
|
422 |
-
|
423 |
-
msgid "LastActivity"
|
424 |
-
msgstr "Último Ingreso"
|
425 |
-
|
426 |
-
msgid "AttemptTimestamp"
|
427 |
-
msgstr "Timestamp"
|
428 |
-
|
429 |
-
msgid "AttemptDatetime"
|
430 |
-
msgstr "Fecha/Hora"
|
431 |
-
|
432 |
-
msgid "ConfirmOperation"
|
433 |
-
msgstr "Debes confirmar que entiendes el riesgo de esta operación."
|
434 |
-
|
435 |
-
msgid "UnderstandTheRisk"
|
436 |
-
msgstr "Entiendo que esta operación no puede ser revertida."
|
437 |
-
|
438 |
-
msgid "NonSupportedAction"
|
439 |
-
msgstr "La acción ejecutada no está soportada."
|
440 |
-
|
441 |
-
msgid "NonSupportedLanguage"
|
442 |
-
msgstr "El idioma seleccionado no está soportado."
|
443 |
-
|
444 |
-
msgid "NothingSelected"
|
445 |
-
msgstr "Nada ha sido seleccionado de la lista."
|
446 |
-
|
447 |
-
msgid "ItemsProcessed"
|
448 |
-
msgstr "Los items seleccionados han sido procesados."
|
449 |
-
|
450 |
-
msgid "AllItemsProcessed"
|
451 |
-
msgstr "<b>%1$d</b> de <b>%2$d</b> archivos fueron procesados."
|
452 |
-
|
453 |
-
msgid "SomeItemsProcessed"
|
454 |
-
msgstr "Solo <b>%1$d</b> de <b>%2$d</b> archivos fueron procesados."
|
455 |
-
|
456 |
-
msgid "ErrorIntegrityAdded"
|
457 |
-
msgstr "El plugin no tiene permiso para eliminar este archivo porque fué creado por otro usuario del sistema con más privilegios que tu cuenta. Conéctate a tu sitio a través de FTP para eliminarlo."
|
458 |
-
|
459 |
-
msgid "ErrorIntegrityModified"
|
460 |
-
msgstr "El plugin no tiene permiso para restablecer el contenido de este archivo porque fué modificado por otro usuario del sistema con más privilegios que tu cuenta. Conéctate a tu sitio a través de FTP para restablecerlo."
|
461 |
-
|
462 |
-
msgid "ErrorIntegrityRemoved"
|
463 |
-
msgstr "El plugin no tiene permiso para restablecer el contenido de este archivo porque el directorio donde está ubicado pertenece a otro usuario del sistema con más privilegios que tu cuenta. Conéctate a tu sitio a través de FTP para restablecerlo."
|
464 |
-
|
465 |
-
msgid "SecurityAlerts"
|
466 |
-
msgstr "Alertas de Seguridad"
|
467 |
-
|
468 |
-
msgid "NoAlertsError"
|
469 |
-
msgstr "Usted ha instalado un plugin o plantilla que no es completamente compatible con nuestro plugin, algunas de las alertas de seguridad (como las autenticaciones exitosas y fallidas de usuario) no serán enviadas. Para prevenir un ciclo infinito mientras el plugin detecta cambios en el sitio y envía las alertas de seguridad a través de un plugin de SMTP personalizado, hemos decidido detener cualquier intento de enviar los correos para prevenir errores fatales."
|
470 |
-
|
471 |
-
msgid "AlertSettingsUpdated"
|
472 |
-
msgstr "La configuración para las alertas de seguridad ha sido actualizada"
|
473 |
-
|
474 |
-
msgid "OptionNotifyPluginChange"
|
475 |
-
msgstr "Recibir alertas por cambios en la configuración del plugin de Sucuri"
|
476 |
-
|
477 |
-
msgid "OptionPrettifyMails"
|
478 |
-
msgstr "Recibir alertas en HTML <em>(podrías experimentar problemas con tu servicio de correo electrónico)</em>"
|
479 |
-
|
480 |
-
msgid "OptionUseWordPressMail"
|
481 |
-
msgstr "Usar funciones nativas de WordPress para enviar las alertas <em>(deselecciona para usar funciones nativas de PHP)</em>"
|
482 |
-
|
483 |
-
msgid "OptionLastLoginRedirection"
|
484 |
-
msgstr "Permitir redirección durante el login para reportar información acerca de la última autenticación exitosa de tu cuenta de usuario"
|
485 |
-
|
486 |
-
msgid "OptionNotifyScanChecksums"
|
487 |
-
msgstr "Recibir alertas por diferencias en los archivos originales de WordPress"
|
488 |
-
|
489 |
-
msgid "OptionNotifyAvailableUpdates"
|
490 |
-
msgstr "Recibir alertas con actualizaciones disponibles"
|
491 |
-
|
492 |
-
msgid "OptionNotifyUserRegistration"
|
493 |
-
msgstr "Recibir alertas por registros de nuevas cuentas de usuario"
|
494 |
-
|
495 |
-
msgid "OptionNotifySuccessLogin"
|
496 |
-
msgstr "Recibir alertas por autenticaciones exitosas de usuario"
|
497 |
-
|
498 |
-
msgid "OptionNotifyFailedLogin"
|
499 |
-
msgstr "Recibir alertas por autenticaciones de usuario fallidas <em>(si tu sitio está siendo atacado recibirás multiples alertas por segundo, deselecciona para reducir el Spam)</em>"
|
500 |
-
|
501 |
-
msgid "OptionNotifyFailedPassword"
|
502 |
-
msgstr "Recibir alertas por autenticaciones de usuario fallidas incluyendo la contraseña enviada"
|
503 |
-
|
504 |
-
msgid "OptionNotifyBruteforceAttack"
|
505 |
-
msgstr "Recibir un resumen con todos los intentos de autenticación de usuario fallidos durante la misma hora. El reporte será eliminado del servidor una vez la información sea enviada a su correo"
|
506 |
-
|
507 |
-
msgid "OptionNotifyPostPublication"
|
508 |
-
msgstr "Recibir alertas por cambios en el estado de las publicaciones y páginas <em>(puedes configurar qué alertas serán monitoreadas desde el panel \"Ignorar Cambios en Publicaciones\")</em>"
|
509 |
-
|
510 |
-
msgid "OptionNotifyWebsiteUpdated"
|
511 |
-
msgstr "Recibir alertas cuando tu sitio web sea actualizado"
|
512 |
-
|
513 |
-
msgid "OptionNotifySettingsUpdated"
|
514 |
-
msgstr "Recibir alertas por cambios en la configuración general de tu sitio web"
|
515 |
-
|
516 |
-
msgid "OptionNotifyThemeEditor"
|
517 |
-
msgstr "Recibir alertas cuando un archivo sea modificado a través del editor de Plugins/Plantillas"
|
518 |
-
|
519 |
-
msgid "OptionNotifyPluginInstalled"
|
520 |
-
msgstr "Recibir alertas cuando un <b>plugin sea instalado</b>"
|
521 |
-
|
522 |
-
msgid "OptionNotifyPluginActivated"
|
523 |
-
msgstr "Recibir alertas cuando un <b>plugin sea activado</b>"
|
524 |
-
|
525 |
-
msgid "OptionNotifyPluginDeactivated"
|
526 |
-
msgstr "Recibir alertas cuando un <b>plugin sea desactivado</b>"
|
527 |
-
|
528 |
-
msgid "OptionNotifyPluginUpdated"
|
529 |
-
msgstr "Recibir alertas cuando un <b>plugin sea actualizado</b>"
|
530 |
-
|
531 |
-
msgid "OptionNotifyPluginDeleted"
|
532 |
-
msgstr "Recibir alertas cuando un <b>plugin sea eliminado</b>"
|
533 |
-
|
534 |
-
msgid "OptionNotifyWidgetAdded"
|
535 |
-
msgstr "Recibir alertas cuando un <b>widget sea agregado</b> a tu sitio web"
|
536 |
-
|
537 |
-
msgid "OptionNotifyWidgetDeleted"
|
538 |
-
msgstr "Recibir alertas cuando un <b>widget sea eliminado</b> de tu sitio web"
|
539 |
-
|
540 |
-
msgid "OptionNotifyThemeInstalled"
|
541 |
-
msgstr "Recibir alertas cuando una <b>plantilla sea instalada</b>"
|
542 |
-
|
543 |
-
msgid "OptionNotifyThemeActivated"
|
544 |
-
msgstr "Recibir alertas cuando una <b>plantilla sea activada</b>"
|
545 |
-
|
546 |
-
msgid "OptionNotifyThemeUpdated"
|
547 |
-
msgstr "Recibir alertas cuando una <b>plantilla sea actualizada</b>"
|
548 |
-
|
549 |
-
msgid "OptionNotifyThemeDeleted"
|
550 |
-
msgstr "Recibir alertas cuando una <b>plantilla sea eliminada</b>"
|
551 |
-
|
552 |
-
msgid "MaximumAlertsSuccess"
|
553 |
-
msgstr "El número máximo de alertas por hora ha sido actualizado"
|
554 |
-
|
555 |
-
msgid "MaximumAlertsFailure"
|
556 |
-
msgstr "Error al actualizar el número máximo de alertas por hora"
|
557 |
-
|
558 |
-
msgid "OptionPerHour5"
|
559 |
-
msgstr "Máximo 5 por hora"
|
560 |
-
|
561 |
-
msgid "OptionPerHour10"
|
562 |
-
msgstr "Máximo 10 por hora"
|
563 |
-
|
564 |
-
msgid "OptionPerHour20"
|
565 |
-
msgstr "Máximo 20 por hora"
|
566 |
-
|
567 |
-
msgid "OptionPerHour40"
|
568 |
-
msgstr "Máximo 40 por hora"
|
569 |
-
|
570 |
-
msgid "OptionPerHour80"
|
571 |
-
msgstr "Máximo 80 por hora"
|
572 |
-
|
573 |
-
msgid "OptionPerHour160"
|
574 |
-
msgstr "Máximo 160 por hora"
|
575 |
-
|
576 |
-
msgid "BruteForceAlertSuccess"
|
577 |
-
msgstr "El plugin asumirá que tu sitio web está siendo atacado después de %1$s autenticaciones de usuario fallidas durante la misma hora"
|
578 |
-
|
579 |
-
msgid "BruteForceAlertFailure"
|
580 |
-
msgstr "Ese número no está soportado por el plugin, use uno de la lista"
|
581 |
-
|
582 |
-
msgid "OptionPerHourUnlimited"
|
583 |
-
msgstr "Alertas ilimitadas por hora"
|
584 |
-
|
585 |
-
msgid "OptionFailedLogins30"
|
586 |
-
msgstr "30 autenticaciones fallidas por hora"
|
587 |
-
|
588 |
-
msgid "OptionFailedLogins60"
|
589 |
-
msgstr "60 autenticaciones fallidas por hora"
|
590 |
-
|
591 |
-
msgid "OptionFailedLogins120"
|
592 |
-
msgstr "120 autenticaciones fallidas por hora"
|
593 |
-
|
594 |
-
msgid "OptionFailedLogins240"
|
595 |
-
msgstr "240 autenticaciones fallidas por hora"
|
596 |
-
|
597 |
-
msgid "OptionFailedLogins480"
|
598 |
-
msgstr "480 autenticaciones fallidas por hora"
|
599 |
-
|
600 |
-
msgid "HTAccessIsMissing"
|
601 |
-
msgstr "Archivo .htaccess no existe"
|
602 |
-
|
603 |
-
msgid "HTAccessNotWritable"
|
604 |
-
msgstr "Archivo .htaccess no es modificable"
|
605 |
-
|
606 |
-
msgid "DiffUtility"
|
607 |
-
msgstr "Herramienta de Integridad de Archivos"
|
608 |
-
|
609 |
-
msgid "DiffUtilityDescription"
|
610 |
-
msgstr "Si tu proveedor de hosting permite la ejecución de comandos del sistema a través de PHP, puedes configurar el plugin para usar el comando <a href=\"https://en.wikipedia.org/wiki/Diff_utility\" target=\"_blank\" rel=\"noopener\">Diff de UNIX</a> para comparar el contenido actual de tus archivos con los archivos originales de WordPress. Esta herramienta te permitirá ver las diferencias entre ambos repositorios y actuar dependiendo de la información encontrada."
|
611 |
-
|
612 |
-
msgid "DiffUtilityInfo"
|
613 |
-
msgstr "El comando diff de Unix está activado. Puedes hacer clic en los archivos en la tabla para ver las diferencias detectadas por el escáner. Si consideras que las diferencias no causan daño a tu sitio, puedes marcar el archivo como revisado, de otra forma se te sugiere restaurar el contenido original inmediatamente."
|
614 |
-
|
615 |
-
msgid "DiffUtilityInstructions"
|
616 |
-
msgstr "Las lineas con un signo <b>negativo</b> como prefijo <em>(marcadas en rojo)</em> muestran el código original. Las lineas con un signo <b>positivo</b> como prefijo <em>(marcadas en verde)</em> muestran el código actual. Puedes leer más acerca del formato DIFF en el artículo de WikiPedia <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Diff_utility\" rel=\"noopener\">Unix Diff Utility</a>."
|
617 |
-
|
618 |
-
msgid "AccountsWereBlocked"
|
619 |
-
msgstr "Las cuentas de usuario seleccionadas han sido bloqueadas"
|
620 |
-
|
621 |
-
msgid "AccountsWereUnblocked"
|
622 |
-
msgstr "Las cuentas de usuario seleccionadas han sido desbloqueadas"
|
623 |
-
|
624 |
-
msgid "LastLoginMessage"
|
625 |
-
msgstr "El último acceso de tu cuenta fué en <b>%1$s</b> desde <b>%2$s</b> <em>(%3$s)</em> <a href='%4$s'>ver todos los registros</a>"
|
626 |
-
|
627 |
-
msgid "LastLoginsNotWritable"
|
628 |
-
msgstr "El archivo para los registros de autenticaciones de usuario no es modificable: <code>%1$s</code>"
|
629 |
-
|
630 |
-
msgid "UserInfo"
|
631 |
-
msgstr "Usuario: %1$s (%2$s)"
|
632 |
-
|
633 |
-
msgid "ReverseProxy"
|
634 |
-
msgstr "Túneles Proxy"
|
635 |
-
|
636 |
-
msgid "ReverseProxyStatus"
|
637 |
-
msgstr "El soporte para túneles proxy ha sido cambiado a <b>%1$s</b>"
|
638 |
-
|
639 |
-
msgid "ReverseProxyInfo"
|
640 |
-
msgstr "El plugin utiliza la dirección IP de cada usuario para registrar los eventos ejecutados, el plugin utiliza dos métodos para obtener esta dirección: el método principal usa una variable global del servidor llamada <em>Remote-Addr</em> disponible en la mayoría de servidores web, un método alternativo usa cabeceras de HTTP personalizadas <em>(que son consideradas inseguras por defecto)</em>. No es necesario que te preocupes por esta opción a menos que tu sitio web esté detrás de un túnel proxy. Servicios como el <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a> — una vez activo — fuerzan el paso del tráfico de red a través de ellos para filtrar amenazas de seguridad que podrían afectar el servidor original. Un efecto secundario del uso de estos servicios es que la dirección IP de los usuarios ya no está disponible entre las variables globales del servidor sino que es enviada a través de una cabecera HTTP personalizada."
|
641 |
-
|
642 |
-
msgid "IPDiscoverer"
|
643 |
-
msgstr "Detección de Direcciones IP"
|
644 |
-
|
645 |
-
msgid "IPDiscovererInfo"
|
646 |
-
msgstr "La detección de direcciones IP hace uso de DNS para detectar si el sitio web está detrás del <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a> en cuyo caso modificará las variables globales del servidor para configurar la dirección IP real de cada visitante del sitio. Este proceso es ejecutado con cada proceso de WordPress, y es posible que la velocidad de tu sitio sea afectada ya que algunos proveedores de hosting utilizan servidores DNS lentos, lo que hace que esta operación tome más tiempo de lo que se espera."
|
647 |
-
|
648 |
-
msgid "HTTPHeader"
|
649 |
-
msgstr "Cabecera de HTTP"
|
650 |
-
|
651 |
-
msgid "HTTPHeaderStatus"
|
652 |
-
msgstr "La cabecera de HTTP ha sido cambiada a <code>%1$s</code>"
|
653 |
-
|
654 |
-
msgid "DisallowedHTTPHeader"
|
655 |
-
msgstr "La cabecera de HTTP no es permitida"
|
656 |
-
|
657 |
-
msgid "RequiresModernPHP"
|
658 |
-
msgstr "El plugin requiere de PHP 5 >= 5.3.0 - o - PHP 7"
|
659 |
-
|
660 |
-
msgid "General"
|
661 |
-
msgstr "Generales"
|
662 |
-
|
663 |
-
msgid "Scanner"
|
664 |
-
msgstr "Escáner"
|
665 |
-
|
666 |
-
msgid "Hardening"
|
667 |
-
msgstr "Hardening"
|
668 |
-
|
669 |
-
msgid "PostHack"
|
670 |
-
msgstr "Pos-Ataque"
|
671 |
-
|
672 |
-
msgid "Alerts"
|
673 |
-
msgstr "Alertas"
|
674 |
-
|
675 |
-
msgid "WebsiteInfo"
|
676 |
-
msgstr "Información"
|
677 |
-
|
678 |
-
msgid "Loading"
|
679 |
-
msgstr "Cargando..."
|
680 |
-
|
681 |
-
msgid "iFrames"
|
682 |
-
msgstr "iFrames"
|
683 |
-
|
684 |
-
msgid "Links"
|
685 |
-
msgstr "Vínculos"
|
686 |
-
|
687 |
-
msgid "Scripts"
|
688 |
-
msgstr "Scripts"
|
689 |
-
|
690 |
-
msgid "iFramesNum"
|
691 |
-
msgstr "iFrames: %1$d"
|
692 |
-
|
693 |
-
msgid "LinksNum"
|
694 |
-
msgstr "Vínculos: %1$d"
|
695 |
-
|
696 |
-
msgid "ScriptsNum"
|
697 |
-
msgstr "Scripts: %1$d"
|
698 |
-
|
699 |
-
msgid "Type"
|
700 |
-
msgstr "Tipo"
|
701 |
-
|
702 |
-
msgid "Name"
|
703 |
-
msgstr "Nombre"
|
704 |
-
|
705 |
-
msgid "Value"
|
706 |
-
msgstr "Valor"
|
707 |
-
|
708 |
-
msgid "Version"
|
709 |
-
msgstr "Versión"
|
710 |
-
|
711 |
-
msgid "NextDue"
|
712 |
-
msgstr "Próxima Ejecución"
|
713 |
-
|
714 |
-
msgid "Schedule"
|
715 |
-
msgstr "Frecuencia"
|
716 |
-
|
717 |
-
msgid "Arguments"
|
718 |
-
msgstr "Argumentos"
|
719 |
-
|
720 |
-
msgid "EnvVariables"
|
721 |
-
msgstr "Variables del Servidor"
|
722 |
-
|
723 |
-
msgid "ConfigVariables"
|
724 |
-
msgstr "Variables de Configuración"
|
725 |
-
|
726 |
-
msgid "ConfigNotFound"
|
727 |
-
msgstr "El archivo de configuración de WordPress no fué encontrado."
|
728 |
-
|
729 |
-
msgid "ConfigNotWritable"
|
730 |
-
msgstr "El archivo de configuraciòn de WordPress no es modificable."
|
731 |
-
|
732 |
-
msgid "LastLoginsResetSuccess"
|
733 |
-
msgstr "El archivo para los registros de autenticaciones de usuario ha sido reseteado."
|
734 |
-
|
735 |
-
msgid "LastLoginsResetFailure"
|
736 |
-
msgstr "No se pudo resetear el archivo para los registros de autenticaciones de usuario."
|
737 |
-
|
738 |
-
msgid "WillReceiveAlerts"
|
739 |
-
msgstr "Las alertas de seguridad serán enviadas a: <code>%1$s</code>"
|
740 |
-
|
741 |
-
msgid "WillNotReceiveAlerts"
|
742 |
-
msgstr "Estos correos no recibirán más alertas de seguridad: <code>%1$s</code>"
|
743 |
-
|
744 |
-
msgid "TestAlertSent"
|
745 |
-
msgstr "Un correo de prueba ha sido enviado a tu dirección, revisa tu bandeja de entrada"
|
746 |
-
|
747 |
-
msgid "InvalidEmail"
|
748 |
-
msgstr "Formato de correo electrónico inválido."
|
749 |
-
|
750 |
-
msgid "TrustedIPDuplicate"
|
751 |
-
msgstr "La dirección IP especificada ya ha sido agregada."
|
752 |
-
|
753 |
-
msgid "TrustedIPAdded"
|
754 |
-
msgstr "Eventos sospechosos generados desde esta dirección IP serán ignorados: <code>%1$s</code>"
|
755 |
-
|
756 |
-
msgid "TrustedIPFailure"
|
757 |
-
msgstr "La dirección IP no pudo ser agregada a la lista"
|
758 |
-
|
759 |
-
msgid "TrustedIPDeleted"
|
760 |
-
msgstr "La dirección IP ha sido eliminada de la lista"
|
761 |
-
|
762 |
-
msgid "OnlyLowerUppercase"
|
763 |
-
msgstr "Solo se permiten letras en minúscula y guiones-bajo"
|
764 |
-
|
765 |
-
msgid "PostTypeIgnore"
|
766 |
-
msgstr "Recibir Estas Alertas"
|
767 |
-
|
768 |
-
msgid "PostTypeUnignore"
|
769 |
-
msgstr "No Recibir Estas Alertas"
|
770 |
-
|
771 |
-
msgid "PostTypeIgnored"
|
772 |
-
msgstr "Este tipo de publicaciones serán ignoradas"
|
773 |
-
|
774 |
-
msgid "PostTypeUnignored"
|
775 |
-
msgstr "Este tipo de publicaciones no serán ignoradas"
|
776 |
-
|
777 |
-
msgid "PostTypeFailure"
|
778 |
-
msgstr "Este tipo de publicaciones no es válido o ya han sido ignoradas"
|
779 |
-
|
780 |
-
msgid "APIServiceChanged"
|
781 |
-
msgstr "El estado de comunicación con la API ha sido cambiado"
|
782 |
-
|
783 |
-
msgid "PluginResetSuccess"
|
784 |
-
msgstr "Los registros de seguridad, configuraciones y cambios adicionales hechos por el plugin han sido eliminados"
|
785 |
-
|
786 |
-
msgid "StorageNotWritable"
|
787 |
-
msgstr "El plugin no tiene acceso a este directorio: <code>%1$s</code>"
|
788 |
-
|
789 |
-
msgid "SiteWasRegistered"
|
790 |
-
msgstr "Sitio web registrado exitosamente"
|
791 |
-
|
792 |
-
msgid "NFilesWereDeleted"
|
793 |
-
msgstr "%1$d de %2$d archivos han sido eliminados"
|
794 |
-
|
795 |
-
msgid "AvoidDocumentRoot"
|
796 |
-
msgstr "El archivo no puede ser accesible públicamente"
|
797 |
-
|
798 |
-
msgid "AvoidFileOverride"
|
799 |
-
msgstr "El archivo ya existe; no será sobre-escrito"
|
800 |
-
|
801 |
-
msgid "Cronjobs"
|
802 |
-
msgstr "Acciones Automatizadas"
|
803 |
-
|
804 |
-
msgid "CronjobsInfo"
|
805 |
-
msgstr "Acciones automatizadas son reglas registradas en tu base de datos por un plugin, plantilla o WordPress; estas reglas son usadas para ejecutar automáticamente acciones definidas en el código con un intervalo de tiempo definido. Un buen uso de estas reglas es la generación de copias de seguridad, la ejecución de escáneres de seguridad o la remoción de elementos innecesarios de la base de datos como borradores de publicaciones. <b>Nota:</b> Las acciones automatizadas pueden ser re-instaladas por cualquier plugin/plantilla automáticamente, considera desactivar el plugin completamente si quieres eliminar una de estas acciones."
|
806 |
-
|
807 |
-
msgid "CronjobRunNow"
|
808 |
-
msgstr "Ejecutar Ahora (en +10 segundos)"
|
809 |
-
|
810 |
-
msgid "CronjobsWillRunSoon"
|
811 |
-
msgstr "%1$d acciones automatizadas serán ejecutadas en los próximos segundos"
|
812 |
-
|
813 |
-
msgid "CronjobsWereDeleted"
|
814 |
-
msgstr "%1$d acciones automatizadas han sido eliminadas"
|
815 |
-
|
816 |
-
msgid "CronjobsWereReinstalled"
|
817 |
-
msgstr "%1$d acciones automatizadas han sido reinstaladas para ser ejecutadas con este intervalo de tiempo: <code>%2$s</code>.'"
|
818 |
-
|
819 |
-
msgid "CronjobsWereNotSelected"
|
820 |
-
msgstr "Ninguna acción automatizada ha sido seleccionada de la lista"
|
821 |
-
|
822 |
-
msgid "DNSLookupStatus"
|
823 |
-
msgstr "El estado de las conexiones vía DNS para detectar el uso de túneles proxy ha sido cambiado"
|
824 |
-
|
825 |
-
msgid "IncorrectEncoding"
|
826 |
-
msgstr "Los datos han sido codificados incorrectamente"
|
827 |
-
|
828 |
-
msgid "ImportCount"
|
829 |
-
msgstr "%1$d de %2$d opciones han sido importadas exitosamente"
|
830 |
-
|
831 |
-
msgid "APIKey"
|
832 |
-
msgstr "Llave de Autenticación"
|
833 |
-
|
834 |
-
msgid "APIKeyInfo"
|
835 |
-
msgstr "La mayoría de herramientas en este plugin pueden ser usadas sin una configuración específica, pero las herramientas más importantes requieren de una <b>llave de autenticación</b> para establecer un túnel de comunicación segura con los servidores de Sucuri. La llave es generada usando tu correo electrónico y el nombre de dominio de tu sitio web, esto te permitirá tener acceso a la herramienta de monitoreo y opciones extra."
|
836 |
-
|
837 |
-
msgid "APIKeyTerms"
|
838 |
-
msgstr "Ten en cuenta que generar una llave implica que estás de acuerdo con enviar la información recolectada por el plugin a los servidores de Sucuri, esto te permite mantener los Tem de seguridad fuera del alcance de usuarios maliciosos que podrían intentar eliminarlos para limpiar sus huellas durante un ataque. Nosotros además usamos esta información de forma anónima para generar <a href=\"https://sucuri.net/security-reports/brute-force/\" target=\"_blank\">estadísticas</a>. Por favor, no generes la llave de autenticación si estás en desacuerdo con esto, puedes seguir usando el plugin sin la llave."
|
839 |
-
|
840 |
-
msgid "APIKeyMissing"
|
841 |
-
msgstr "La llave no existe"
|
842 |
-
|
843 |
-
msgid "APIKeyInvalidDomain"
|
844 |
-
msgstr "Tu sitio web <code>%%SUCURI.CleanDomain%%</code> parece no tener un registro de DNS tipo <code>A</code> así que la API lo considerará inválido durante el proceso de generación de la llave. Agrega <code>www</code> al inicio del dominio para intentar solucionar el problema. Envía un mensaje a nuestro servicio de soporte si no entiendes qué significa esto."
|
845 |
-
|
846 |
-
msgid "APIKeyRecoverButton"
|
847 |
-
msgstr "Recuperar Por Correo Electrónico"
|
848 |
-
|
849 |
-
msgid "APIKeyRecoveryCondition"
|
850 |
-
msgstr "Si no tienes acceso al correo electrónico usado para generar la llave pero tienes una copia de la misma a la mano, haz <a target=\"_self\" href=\"%%SUCURI.URL.Settings%%&recover\">clic aquí</a> para activar el plugin manualmente. Ten en cuenta que si la llave es inválida el plugin la eliminará inmediatamente."
|
851 |
-
|
852 |
-
msgid "ApplyHardening"
|
853 |
-
msgstr "Aplicar Hardening"
|
854 |
-
|
855 |
-
msgid "RevertHardening"
|
856 |
-
msgstr "Revertir Hardening"
|
857 |
-
|
858 |
-
msgid "HardeningFirewallTitle"
|
859 |
-
msgstr "Firewall Para Aplicaciones Web"
|
860 |
-
|
861 |
-
msgid "HardeningFirewallDescription"
|
862 |
-
msgstr "Un WAF (Web Application Firewall) es una capa de protección para tu sitio web que bloquea todo tipo de ataques (fuerza bruta, denegación de servicios, inyecciones a base de datos, etc) y te ayuda a permanecer limpio de código malicioso y fuera de listas negras. Esta opción verifica si tu sitio web está usando el Firewall de Sucuri como tu capa de protección primaria."
|
863 |
-
|
864 |
-
msgid "HardeningFirewallPurchase"
|
865 |
-
msgstr "El Firewall de Sucuri es un servicio premium que puedes comprar aquí - <a href='https://goo.gl/qfNkMq' target='_blank'>Sucuri Firewall</a>"
|
866 |
-
|
867 |
-
msgid "HardeningVersionTitle"
|
868 |
-
msgstr "Verificar la Versión de WordPress"
|
869 |
-
|
870 |
-
msgid "HardeningVersionDescription"
|
871 |
-
msgstr "¿Por qué mantener tu sitio web actualizado? WordPress es un proyecto de código libre lo que significa que todos los cambios hechos al código son hechos de forma pública, si alguno de esos cambios hace parte de una solución para un problema de seguridad, cualquier persona puede utilizar esta información para atacar tu sitio web si este aún no ha aplicado el parche de seguridad."
|
872 |
-
|
873 |
-
msgid "HardeningPHPVersionTitle"
|
874 |
-
msgstr "Verificar la Versión de PHP"
|
875 |
-
|
876 |
-
msgid "HardeningPHPVersionDescription"
|
877 |
-
msgstr "PHP %1$s está instalado."
|
878 |
-
|
879 |
-
msgid "HardeningPHPVersionLifetime"
|
880 |
-
msgstr "Comunícate con tu proveedor de hosting para instalar una versión actualizada de PHP - <a href='http://php.net/supported-versions.php' target='_blank' rel='noopener'>Lista de Versiones de PHP Soportadas</a>"
|
881 |
-
|
882 |
-
msgid "HardeningGeneratorTitle"
|
883 |
-
msgstr "Eliminar Versión de WordPress"
|
884 |
-
|
885 |
-
msgid "HardeningGeneratorDescription"
|
886 |
-
msgstr "Esta opción verifica si la versión de WordPress usada en tu sitio web está siendo expuesta de forma pública a través del código HTML. Muchos escáneres de vulnerabilidades web utilizan esta información para determinar si tu página web tiene vulnerabilidades para luego ser explotadas. Ten en cuenta que aún sin esta información un escáner inteligente puede detectar la versión de WordPress en uso comparando los Checksums de algunos archivos estáticos distribuidos con cada instalación."
|
887 |
-
|
888 |
-
msgid "HardeningNginxTitle"
|
889 |
-
msgstr "Bloquear Algunos Archivos PHP"
|
890 |
-
|
891 |
-
msgid "HardeningNginxDescription"
|
892 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando apliques esta opción, ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
893 |
-
|
894 |
-
msgid "HardeningNginxField"
|
895 |
-
msgstr "Verificar Hardening"
|
896 |
-
|
897 |
-
msgid "HardeningNginxSuggestion"
|
898 |
-
msgstr "Lee las instrucciones oficiales de WordPress para aprender como restringir el acceso a archivos PHP en directorios sensitivos - <a href='https://codex.wordpress.org/Nginx#Global_restrictions_file' target='_blank' rel='noopener'>Restricciones Globales para Nginx y WordPress</a>"
|
899 |
-
|
900 |
-
msgid "HardeningUploadsTitle"
|
901 |
-
msgstr "Bloquear Archivos PHP en el Directorio de Subidas"
|
902 |
-
|
903 |
-
msgid "HardeningUploadsDescription"
|
904 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando aplique esta opción ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
905 |
-
|
906 |
-
msgid "HardeningUploadsApplySuccess"
|
907 |
-
msgstr "Hardening aplicado al directorio de subidas"
|
908 |
-
|
909 |
-
msgid "HardeningUploadsApplyFailure"
|
910 |
-
msgstr "Error aplicando hardening en el directorio seleccionado"
|
911 |
-
|
912 |
-
msgid "HardeningUploadsRevertSuccess"
|
913 |
-
msgstr "Hardening revertido en el directorio de subidas"
|
914 |
-
|
915 |
-
msgid "HardeningUploadsRevertFailure"
|
916 |
-
msgstr "El archivo .htaccess no es modificable"
|
917 |
-
|
918 |
-
msgid "HardeningContentTitle"
|
919 |
-
msgstr "Bloquear Archivos PHP en el Directorio de Contenido"
|
920 |
-
|
921 |
-
msgid "HardeningContentDescription"
|
922 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando aplique esta opción ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
923 |
-
|
924 |
-
msgid "HardeningContentApplySuccess"
|
925 |
-
msgstr "Hardening aplicado al directorio de contenido"
|
926 |
-
|
927 |
-
msgid "HardeningContentApplyFailure"
|
928 |
-
msgstr "Error aplicando hardening en el directorio seleccionado"
|
929 |
-
|
930 |
-
msgid "HardeningContentRevertSuccess"
|
931 |
-
msgstr "Hardening revertido en el directorio de contenido"
|
932 |
-
|
933 |
-
msgid "HardeningContentRevertFailure"
|
934 |
-
msgstr "El archivo .htaccess no es modificable"
|
935 |
-
|
936 |
-
msgid "HardeningIncludesTitle"
|
937 |
-
msgstr "Bloquear Archivos PHP en el Directorio de Inclusiones"
|
938 |
-
|
939 |
-
msgid "HardeningIncludesDescription"
|
940 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando aplique esta opción ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
941 |
-
|
942 |
-
msgid "HardeningIncludesApplySuccess"
|
943 |
-
msgstr "Hardening aplicado al directory de inclusiones"
|
944 |
-
|
945 |
-
msgid "HardeningIncludesApplyFailure"
|
946 |
-
msgstr "Error aplicando hardening en el directorio de inclusiones"
|
947 |
-
|
948 |
-
msgid "HardeningIncludesRevertSuccess"
|
949 |
-
msgstr "Hardening revertido en el directorio de inclusiones"
|
950 |
-
|
951 |
-
msgid "HardeningIncludesRevertFailure"
|
952 |
-
msgstr "El archivo .htaccess no es modificable"
|
953 |
-
|
954 |
-
msgid "HardeningReadmeTitle"
|
955 |
-
msgstr "Exposición de Información"
|
956 |
-
|
957 |
-
msgid "HardeningReadmeDescription"
|
958 |
-
msgstr "Esta opción verifica si el archivo README todavía existe. La información en este archivo puede ser usada por personas maliciosas para encontrar vulnerabilidades asociadas con la versión de WordPress que has instalado. Ten en cuenta que este archivo is re-creado cada vez que una actualización es ejecutada."
|
959 |
-
|
960 |
-
msgid "HardeningReadmeApplySuccess"
|
961 |
-
msgstr "Hardening aplicado sobre el archivo README"
|
962 |
-
|
963 |
-
msgid "HardeningReadmeApplyFailure"
|
964 |
-
msgstr "No se puede eliminar el archivo README"
|
965 |
-
|
966 |
-
msgid "HardeningAdminUserTitle"
|
967 |
-
msgstr "Cuenta de Administración Primaria"
|
968 |
-
|
969 |
-
msgid "HardeningAdminUserDescription"
|
970 |
-
msgstr "Esta opción verifica si la cuenta de administración primaria está usando un nombre fácil de adivinar como \"admin\". Esto permite a personas maliciosas identificar fácilmente qué cuenta tiene los privilegios más altos entre todos los usuarios registrados."
|
971 |
-
|
972 |
-
msgid "HardeningFileEditorTitle"
|
973 |
-
msgstr "Editor de Plugins y Plantillas"
|
974 |
-
|
975 |
-
msgid "HardeningFileEditorDescription"
|
976 |
-
msgstr "Esta opción desactiva el editor de plugins y plantillas para prevenir modificaciones innecesarias en el código."
|
977 |
-
|
978 |
-
msgid "HardeningFileEditorApplySuccess"
|
979 |
-
msgstr "Hardening aplicado al editor de plugins y plantillas"
|
980 |
-
|
981 |
-
msgid "HardeningFileEditorRevertSuccess"
|
982 |
-
msgstr "Hardening revertido en el editor de plugins y plantillas"
|
983 |
-
|
984 |
-
msgid "HardeningFileEditorRevertFailure"
|
985 |
-
msgstr "El editor de plugins y plantillas no fue desactivado usando el plugin de Sucuri. Debes escanear tu sitio web por una constante definida como \"DISALLOW_FILE_EDIT\" cuando la encuentres, debes eliminarla o cambiar su valor a \"False\". Ten en cuenta que cualquier otro plugin o plantilla puede desactivar el editor, así que es imposible determinar el origen de la constante."
|
986 |
-
|
987 |
-
msgid "PHPWhitelistSuccess"
|
988 |
-
msgstr "El archivo ha sido agregado a la lista blanca de archivos PHP"
|
989 |
-
|
990 |
-
msgid "PHPWhitelistFailure"
|
991 |
-
msgstr "El directorio especificado no fue fortalecido por el plugin de Sucuri"
|
992 |
-
|
993 |
-
msgid "PHPDewhitelistSuccess"
|
994 |
-
msgstr "Los archivos seleccionados han sido eliminados de la lista blanca de archivos PHP"
|
995 |
-
|
996 |
-
msgid "DiffUtilityStatus"
|
997 |
-
msgstr "El estado de la herramienta de integridad ha sido cambiado"
|
998 |
-
|
999 |
-
msgid "DiffUtilityMissing"
|
1000 |
-
msgstr "Tu proveedor de hosting no permite la ejecución de comandos del sistema a través de archivos PHP."
|
1001 |
-
|
1002 |
-
msgid "IntegrityLanguage"
|
1003 |
-
msgstr "El idioma para la herramienta de integridad de archivos de WordPress ha sido cambiado"
|
1004 |
-
|
1005 |
-
msgid "NotInstalled"
|
1006 |
-
msgstr "no instalado"
|
1007 |
-
|
1008 |
-
msgid "PremiumPlugin"
|
1009 |
-
msgstr "Plugin Premium"
|
1010 |
-
|
1011 |
-
msgid "MissingLibrary"
|
1012 |
-
msgstr "NO_INSTALLER"
|
1013 |
-
|
1014 |
-
msgid "CannotDownload"
|
1015 |
-
msgstr "Imposible Descargar"
|
1016 |
-
|
1017 |
-
msgid "CannotBackup"
|
1018 |
-
msgstr "Imposible Hacer Copia de Seguridad"
|
1019 |
-
|
1020 |
-
msgid "CannotInstall"
|
1021 |
-
msgstr "Imposible Instalar"
|
1022 |
-
|
1023 |
-
msgid "VersionInstalled"
|
1024 |
-
msgstr "Instalado v%1$s"
|
1025 |
-
|
1026 |
-
msgid "NewestWordPress"
|
1027 |
-
msgstr "Última Versión"
|
1028 |
-
|
1029 |
-
msgid "NoUpdates"
|
1030 |
-
msgstr "No existen actualizaciones."
|
1031 |
-
|
1032 |
-
msgid "SiteClean"
|
1033 |
-
msgstr "Sitio Limpio"
|
1034 |
-
|
1035 |
-
msgid "SiteNotClean"
|
1036 |
-
msgstr "Sitio Infectado"
|
1037 |
-
|
1038 |
-
msgid "Blacklisted"
|
1039 |
-
msgstr "Lista Negra"
|
1040 |
-
|
1041 |
-
msgid "NotBlacklisted"
|
1042 |
-
msgstr "Sin Lista Negra"
|
1043 |
-
|
1044 |
-
msgid "APIKeyExplanation"
|
1045 |
-
msgstr "Una llave de autenticación es necesaria para activar herramientas adicionales disponibles en el plugin. Las llaves son gratuitas y puedes generar un número ilimitado de ellas siempre y cuando el nombre del sitio web y el correo electrónico sean únicos. La llave es usada para autenticar las conexiones a través de HTTP hechas a la API administrada por Sucuri Inc. No generes la llave si estás en desacuerdo con el envío de información a nuestros servidores."
|
1046 |
-
|
1047 |
-
msgid "APIKeyHelp"
|
1048 |
-
msgstr "Si experimentas problemas con la generación de la llave, puedes solicitar una enviando la dirección de tu sitio web y el correo electrónico que deseas usar para la asociación a <a href=\"mailto:info@sucuri.net\">info@sucuri.net</a>. Ten en cuenta que generar una llave para un sitio web que no es público en Internet no es posible, ya que la API necesita validar que el nombre del host existe, sin embargo, si deseas probar el plugin en un ambiente de desarrollo, por favor contáctanos para poder generar una llave manualmente."
|
1049 |
-
|
1050 |
-
msgid "APIKeyGenerated"
|
1051 |
-
msgstr "¡Felicitaciones! Todas las herramientas disponibles en el plugin han sido habilitadas. Este producto está diseñado para suplementar productos de seguridad existentes en tu sitio web. El plugin no provee una solución completa a tus necesidades de seguridad, pero te ofrece más herramientas para controlar el funcionamiento de tu sitio y tener una mejor postura con respecto a ataques que puedas sufrir en el futuro, todo esto con la intensión de reducir riesgos."
|
1052 |
-
|
1053 |
-
msgid "APIKeyContinueSetup"
|
1054 |
-
msgstr "Sucuri Inc. ha generado una llave única para tu sitio web, esta llave fue asociada al correo electrónico que seleccionaste anteriormente, correo que puedes utilizar para recuperar dicha llave si llegaras a perderla en el futuro. Te invitamos a revisar el resto de opciones disponibles en la página de ajustes para que configures el plugin a la medida de tu sitio."
|
1055 |
-
|
1056 |
-
msgid "APIKeyRecoveryExplanation"
|
1057 |
-
msgstr "Si esta operación fue exitosa, recibirás un mensaje en el correo electrónico que usaste durante la generación de la llave <em>(usualmente este correo es el mismo asociado a la cuenta de administración primaria)</em>. Este mensaje contiene una copia de la llave, por favor copia y pega la llave en el formulario de abajo. El plugin verificará la autenticidad de la misma, si esta verificación falla, la llave será eliminada automáticamente y deberás iniciar el proceso de recuperación nuevamente."
|
1058 |
-
|
1059 |
-
msgid "APIKeyRecoveryPossibleFailures"
|
1060 |
-
msgstr "Existen casos en los que esta operación puede fallar, un ejemplo sería cuando el correo electrónico ya no está asociado al sitio web, esto sucede cuando la base de la URL cambia <em>(de www a nada y viceversa)</em>. Si estás teniendo problemas con el proceso de recuperación de la llave, por favor envía un mensaje explicando la situación a <a href=\"mailto:info@sucuri.net\">info@sucuri.net</a>"
|
1061 |
-
|
1062 |
-
msgid "DNSLookups"
|
1063 |
-
msgstr "Conexiones DNS"
|
1064 |
-
|
1065 |
-
msgid "DNSLookupsLabel"
|
1066 |
-
msgstr "Activar conexiones DNS al inicio de cada proceso"
|
1067 |
-
|
1068 |
-
msgid "DNSLookupsText"
|
1069 |
-
msgstr "Activa esta opción si tu sitio web está detrás de un Firewall, esto garantizará que la dirección IP de tus visitantes será detectada correctamente para los registros de seguridad. Puedes cambiar esto después desde la página de configuraciones del plugin."
|
1070 |
-
|
1071 |
-
msgid "IntegrityTitle"
|
1072 |
-
msgstr "Integridad de la Instalación"
|
1073 |
-
|
1074 |
-
msgid "IntegrityDescription"
|
1075 |
-
msgstr "El plugin inspecciona la instalación de WordPress en busca de modificaciones en los archivos originales disponibles en WordPress.org. Archivos ubicados en la raíz del proyecto, el directorio wp-admin y el directorio wp-includes serán comparados con los archivos distribuidos en la versión v%%SUCURI.WordPressVersion%%; todos los archivos con inconsistencias aparecerán en esta lista. Cualquiera de estos cambios podría indicar un problema de seguridad."
|
1076 |
-
|
1077 |
-
msgid "ReviewFalsePositives"
|
1078 |
-
msgstr "Revisar Falsos/Positivos"
|
1079 |
-
|
1080 |
-
msgid "IntegrityGoodTitle"
|
1081 |
-
msgstr "Todos los Archivos Están Intáctos"
|
1082 |
-
|
1083 |
-
msgid "IntegrityGoodDescription"
|
1084 |
-
msgstr "No hemos detectado archivos adicionales, eliminados o cambios relevantes en los archivos originales de WordPress. Si estás experimentando otros problemas, por favor usa un <a target=\"_blank\" href=\"https://sucuri.net/es/seguridad-de-sitios-web/remocion-de-malware\">servicio de limpieza de malware</a>."
|
1085 |
-
|
1086 |
-
msgid "IntegrityBadTitle"
|
1087 |
-
msgstr "Archivos de WordPress Modificados"
|
1088 |
-
|
1089 |
-
msgid "IntegrityBadDescription"
|
1090 |
-
msgstr "Hemos identificado que algunos de los archivos de WordPress han sido modificados. Esto podría indicar un ataque o la existencia de un archivo corrupto en tu instalación. Si estás experimentando otros problemas, por favor usa un <a target=\"_blank\" href=\"https://sucuri.net/es/seguridad-de-sitios-web/remocion-de-malware\">servicio de limpieza de malware</a>."
|
1091 |
-
|
1092 |
-
msgid "MarkFixedDescription"
|
1093 |
-
msgstr "Marcar uno o más archivos como revisado forzará al plugin a ignorar dichos archivos durante futuros escaneos, esto es útil cuando un archivo contiene falsos/positivos. Adicionalmente, puedes restaurar el contenido original si estos han sido modificados o eliminados, el plugin descargará una copia del código desde el repositorio oficial de WordPress. La eliminación de archivos es una operación irreversible, ten cuidado."
|
1094 |
-
|
1095 |
-
msgid "Action"
|
1096 |
-
msgstr "Acción"
|
1097 |
-
|
1098 |
-
msgid "Status"
|
1099 |
-
msgstr "Estado"
|
1100 |
-
|
1101 |
-
msgid "FileSize"
|
1102 |
-
msgstr "Tamaño"
|
1103 |
-
|
1104 |
-
msgid "ModifiedAt"
|
1105 |
-
msgstr "Modificado en"
|
1106 |
-
|
1107 |
-
msgid "Pattern"
|
1108 |
-
msgstr "Patrón"
|
1109 |
-
|
1110 |
-
msgid "FilePath"
|
1111 |
-
msgstr "Ubicación del Archivo"
|
1112 |
-
|
1113 |
-
msgid "Directory"
|
1114 |
-
msgstr "Directorio"
|
1115 |
-
|
1116 |
-
msgid "MarkFixed"
|
1117 |
-
msgstr "Marcar como Revisado"
|
1118 |
-
|
1119 |
-
msgid "RestoreFile"
|
1120 |
-
msgstr "Restaurar Archivo"
|
1121 |
-
|
1122 |
-
msgid "DeleteFile"
|
1123 |
-
msgstr "Eliminar Archivo"
|
1124 |
-
|
1125 |
-
msgid "HoverForPayload"
|
1126 |
-
msgstr "Ver Código Malicioso"
|
1127 |
-
|
1128 |
-
msgid "LogsPerEvent"
|
1129 |
-
msgstr "Tipos de Eventos"
|
1130 |
-
|
1131 |
-
msgid "LogsForLogins"
|
1132 |
-
msgstr "Autenticaciones Exitosas/Fallidas"
|
1133 |
-
|
1134 |
-
msgid "LogsPerUser"
|
1135 |
-
msgstr "Registros Por Usuario"
|
1136 |
-
|
1137 |
-
msgid "LogsPerIP"
|
1138 |
-
msgstr "Registros Por Dirección IP"
|
1139 |
-
|
1140 |
-
msgid "Search"
|
1141 |
-
msgstr "Buscar"
|
1142 |
-
|
1143 |
-
msgid "FirewallSettingsTitle"
|
1144 |
-
msgstr "Ajustes del Firewall"
|
1145 |
-
|
1146 |
-
msgid "FirewallSettingsInfo"
|
1147 |
-
msgstr "Un poderoso Firewall para aplicaciones web y <b>Sistema para la Detección de Intrusiones</b> para cualquier usuario de WordPress y cualquier otra plataforma. Esta página te ayudará a configurar y monitorear tu sitio web a través del <b>Firewall de Sucuri</b>. Una vez activado, nuestro Firewall actuará como un escudo, protegiendo tu sitio de ataques y previniendo infecciones de malware y reinfecciones. El Firewall también bloqueará inyecciones a bases de datos, ataques de fuerza bruta, XSS, RFI, puertas traseras y muchas otras amenazas en contra de tu sitio web."
|
1148 |
-
|
1149 |
-
msgid "FirewallKey"
|
1150 |
-
msgstr "Llave del Firewall"
|
1151 |
-
|
1152 |
-
msgid "FirewallAddKey"
|
1153 |
-
msgstr "Agrega la <a href=\"https://waf.sucuri.net/?settings&panel=api\" target=\"_blank\">llave del Firewall</a> en el formulario para iniciar una conexión con la API."
|
1154 |
-
|
1155 |
-
msgid "FirewallFootNote"
|
1156 |
-
msgstr "<em>[1]</em> Más información acerca del <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a>, herramientas disponibles y precios.<br><em>[2]</em> Instrucciones y videos en la <a href=\"https://kb.sucuri.net/firewall\" target=\"_blank\">Wiki de Sucuri</a>.<br><em>[3]</em> <a href=\"https://login.sucuri.net/signup2/create?CloudProxy\" target=\"_blank\">Registra</a> una cuenta nueva y empieza a proteger tu sitio web."
|
1157 |
-
|
1158 |
-
msgid "FirewallLogsTitle"
|
1159 |
-
msgstr "Registros de Seguridad del Firewall"
|
1160 |
-
|
1161 |
-
msgid "FirewallLogsInfo"
|
1162 |
-
msgstr "El Firewall de Sucuri registra todas las conexiones HTTP involucradas en un ataque y las separa de las conexiones legítimas. Puedes usar esta herramienta para analizar la información de las últimas conexiones y tomar acción. O sea, activando las herramientas avanzadas del IDS <em>(Intrusion Detection System)</em> desde el <a target=\"_blank\" href=\"https://waf.sucuri.net/?settings\">panel de administración del Firewall</a> y/o bloquear las direcciones IP y URL directamente desde la <a href=\"https://waf.sucuri.net/?audit\" target=\"_blank\">página de registros de seguridad del Firewall</a>."
|
1163 |
-
|
1164 |
-
msgid "FirewallLogsNote"
|
1165 |
-
msgstr "Las conexiones que no fueron bloqueadas son omitidas de la lista, esto es intencional."
|
1166 |
-
|
1167 |
-
msgid "FirewallIPAccessTitle"
|
1168 |
-
msgstr "Dirección IP (Acceso)"
|
1169 |
-
|
1170 |
-
msgid "FirewallIPAccessInfo"
|
1171 |
-
msgstr "Esta herramienta le permite bloquear y desbloquear el acceso a su sitio web de una o mas direcciones IP. Además, puede bloquear direcciones IP automáticamente cuando estas están involucradas en un ataque de fuerza bruta para adivinar la contraseña de uno o más usuarios registrados. Si un usuario legítimo es bloqueado después de enviar las credenciales incorrectas de su cuenta más de tres veces, ellos deberán ingresar al panel de control del Firewall para eliminar su dirección IP de la lista negra, o intentar acceder al sitio a través de una VPN."
|
1172 |
-
|
1173 |
-
msgid "WhitelistIP"
|
1174 |
-
msgstr "Desbloquear Dirección IP"
|
1175 |
-
|
1176 |
-
msgid "BlacklistIP"
|
1177 |
-
msgstr "Bloquear Dirección IP"
|
1178 |
-
|
1179 |
-
msgid "FirewallCacheTitle"
|
1180 |
-
msgstr "Caché del Firewall"
|
1181 |
-
|
1182 |
-
msgid "FirewallCacheButton"
|
1183 |
-
msgstr "Limpiar Caché"
|
1184 |
-
|
1185 |
-
msgid "FirewallCacheInfo"
|
1186 |
-
msgstr "El Firewall ofrece multiples opciones para configurar el nivel de caché aplicado a tu sitio web. Puedes considerar activar la cobertura total de la caché <em>(que es lo recomendado)</em>, o puedes configurar la caché a un nivel mínimo, o forzar el uso de las cabeceras HTTP <em>(solo para usuarios avanzados)</em>, o en casos extremos donde no necesitas la caché, puedes desactivarla completamente. Puedes encontrar más información acerca de estas opciones <a target=\"_blank\" href=\"https://kb.sucuri.net/firewall/Performance/caching-options\">aquí</a>."
|
1187 |
-
|
1188 |
-
msgid "FirewallCacheNote"
|
1189 |
-
msgstr "Tenga en cuenta que el Firewall tiene unas <a href=\"https://kb.sucuri.net/firewall/Performance/cache-exceptions\" target=\"_blank\">reglas especiales para la caché</a> de imágenes, archivos CSS, archivos PDF, archivos de texto, código JavaScript, archivos audio visuales y algunas otros formatos de archivo que son guardados en nuestros <a href=\"https://en.wikipedia.org/wiki/Edge_device\" target=\"_blank\" rel=\"noopener\">Edge Devices</a>. La única forma de limpiar la caché de estos archivos es haciendo uso de parámetros aleatorios en la URL, puede agregar un parametro como este <code>?ver=1.2.3</code> e incrementar el número con cada actualización."
|
1190 |
-
|
1191 |
-
msgid "FirewallCacheWiki"
|
1192 |
-
msgstr "La caché web es una tecnología para el almacenamiento temporal (caching) de documentos web, como páginas en HTML e imágenes, para reducir el uso de ancho de banda, la carga del servidor, y retrasos en las descargas. Un sistema de caché web guarda copias de los documentos que pasan a través de él; conexiones subsecuentes pueden devolver el contenido desde la caché si las condiciones lo permiten. — <a href=\"https://en.wikipedia.org/wiki/Web_cache\" target=\"_blank\" rel=\"noopener\">WikiPedia - Web Cache</a>"
|
1193 |
-
|
1194 |
-
msgid "FirewallAutoClearCache"
|
1195 |
-
msgstr "Limpiar cache automáticamente cuando una publicación o página sea modificada"
|
1196 |
-
|
1197 |
-
msgid "LoginsAdmins"
|
1198 |
-
msgstr "Autenticaciones Exitosas (admins)"
|
1199 |
-
|
1200 |
-
msgid "LoginsAdminsInfo"
|
1201 |
-
msgstr "Aquí puede encontrar una lista con todas las autenticaciones exitosas de cuentas de usuario con privilegios de administración."
|
1202 |
-
|
1203 |
-
msgid "Registration"
|
1204 |
-
msgstr "Registro"
|
1205 |
-
|
1206 |
-
msgid "NewestLogins"
|
1207 |
-
msgstr "Ordenados de Nuevos a Viejos"
|
1208 |
-
|
1209 |
-
msgid "Admins"
|
1210 |
-
msgstr "Administradores"
|
1211 |
-
|
1212 |
-
msgid "AllUsers"
|
1213 |
-
msgstr "Todos Los Usuarios"
|
1214 |
-
|
1215 |
-
msgid "LoginsAll"
|
1216 |
-
msgstr "Autenticaciones Exitosas (todos)"
|
1217 |
-
|
1218 |
-
msgid "LoginsAllInfo"
|
1219 |
-
msgstr "Aquí puede encontrar una lista con todas las autenticaciones exitosas de todas las cuentas de usuario."
|
1220 |
-
|
1221 |
-
msgid "BlockedUsers"
|
1222 |
-
msgstr "Usuarios Bloqueados"
|
1223 |
-
|
1224 |
-
msgid "BlockedUsersInfo"
|
1225 |
-
msgstr "Todo intento de autenticación que haga uso de las funciones nativas de WordPress será interceptado y analizado por el plugin, si el nombre de usuario coincide con alguno en esta lista la conexión al servidor será inmediatamente detenida. Estos intentos no serán registrados y ninguna alerta de seguridad será enviada."
|
1226 |
-
|
1227 |
-
msgid "BlockedUsersNote"
|
1228 |
-
msgstr "Ten en cuenta que esta herramienta no intenta proveer una protección completa para bloquear autenticaciones indeseadas de usuarios maliciosos. Dependiendo de la configuración de tu sitio web, los plugins o plantillas que sean instalados, o inclusive la versión de WordPress que estés usando, habrán huecos en el sistema que usuarios maliciosos pueden utilizar para evadir estos bloqueos e iniciar un ataque por fuerza bruta. <a target=\"_blank\" href=\"https://sucuri.net/es/firewall-de-sitios-web/?wp=bu\">Instala un Firewall</a> para obtener protección completa y mitigar este y otros ataques en contra tu sitio web."
|
1229 |
-
|
1230 |
-
msgid "BlockedUsersByIP"
|
1231 |
-
msgstr "El bloqueo de usuarios por dirección IP es una opción disponible en el <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a>; para evitar la duplicación de código y reducir la cantidad de falsos/positivos esta opción nunca será implementada en este plugin."
|
1232 |
-
|
1233 |
-
msgid "FailedLogins"
|
1234 |
-
msgstr "Autenticaciones Fallidas"
|
1235 |
-
|
1236 |
-
msgid "FailedLoginsInfo"
|
1237 |
-
msgstr "Esta información será usada para determinar si tu sitio es víctima de un <a href=\"https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing\" target=\"_blank\">Password Guessing Brute Force Attacks</a>. Estos registros serán acumulados, si más de <code>%%SUCURI.FailedLogins.MaxFailedLogins%%</code> autenticaciones fallidas son registradas durante la misma hora, el plugin enviará un correo electrónico con un resumen del ataque <em>(debe activar esta opción desde la página de ajustes, sección alertas)</em>. <b>NOTA:</b> Algunos plugins que ofrecen la opción de <em>\"Autenticación por Dos-Pasos\"</em> no usan las funciones nativas de WordPress, motivo por el cual algunos intentos de autenticación no podrán ser interceptados ni analizados."
|
1238 |
-
|
1239 |
-
msgid "LoggedInUsers"
|
1240 |
-
msgstr "Usuarios Activos"
|
1241 |
-
|
1242 |
-
msgid "LoggedInUsersInfo"
|
1243 |
-
msgstr "Aquí puedes encontrar una lista de usuarios que han iniciado una sesión en los últimos minutos."
|
1244 |
-
|
1245 |
-
msgid "Recomendations"
|
1246 |
-
msgstr "Recomendaciones"
|
1247 |
-
|
1248 |
-
msgid "SiteCheckNoResults"
|
1249 |
-
msgstr "Si nuestro escáner gratuito no ha detectado ningún problema, es posible que tu sitio tenga un problema más complicado y la infección esté escondida. Puede <a target=\"_blank\" href=\"https://sucuri.net/es/plataforma-de-seguridad-de-sitios-web/signup\">registrar una cuenta con Sucuri</a> para obtener un escaneo más detallado y eventualmente una limpieza absoluta de tu sitio web (no incluido con el plan gratuito)."
|
1250 |
-
|
1251 |
-
msgid "SiteCheckTarget"
|
1252 |
-
msgstr "URL Para el Escáner de Malware"
|
1253 |
-
|
1254 |
-
msgid "SiteCheckTargetInfo"
|
1255 |
-
msgstr "El escáner remoto de malware funciona gracias a <a href=\"https://sitecheck.sucuri.net/\" target=\"_blank\">Sucuri SiteCheck</a>, un servicio que toma la dirección de un sitio web con acceso público y la escanea en busca de código malicioso. Si su sitio web no es visible a través de Internet, por ejemplo, si el sitio está en un ambiente de desarrollo local or una red restringida, el escáner no podrá trabajar en él. Adicionalmente, si el sitio web fué instalado en un directorio diferente al sugerido el escáner reportará un error \"404 Not Found\". Puedes usar esta opción para cambiar la dirección del sitio web que será escaneado."
|
1256 |
-
|
1257 |
-
msgid "PasswordAttack"
|
1258 |
-
msgstr "Ataque De Fuerza Bruta En Contra De Contraseñas"
|
1259 |
-
|
1260 |
-
msgid "PasswordAttackAfter"
|
1261 |
-
msgstr "Considerar Ataque Después De"
|
1262 |
-
|
1263 |
-
msgid "PasswordAttackInfo"
|
1264 |
-
msgstr "Los <a href=\"https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing\" target=\"_blank\">ataques de fuerza bruta en contra de contraseñas</a> son muy comunes en sitios web y páneles de administración. Estos son uno de los vectores más comunes usado para comprometer sitios web. El proceso es muy simple, los atacantes básicamente intentan múltiple combinaciones de usuario y contraseña hasta que encuentran una que funciona. Una vez el acceso al sitio es obtenido, ellos inyectan código malicioso para generar spam, crear páginas fraudulentas, etc."
|
1265 |
-
|
1266 |
-
msgid "PostTypeAlerts"
|
1267 |
-
msgstr "Alerts Para Diferentes Tipos de Publicaciones"
|
1268 |
-
|
1269 |
-
msgid "IgnoredAt"
|
1270 |
-
msgstr "Ignorado en"
|
1271 |
-
|
1272 |
-
msgid "PostType"
|
1273 |
-
msgstr "Tipo de Publicación"
|
1274 |
-
|
1275 |
-
msgid "PostTypeAlertsDisabled"
|
1276 |
-
msgstr "Desactivaste las alertas de seguridad, cuando una publicación es creada o modificada, esta herramienta espera que esa opción esté activa para poder filtrar los tipos de publicaciones que no son relevantes para el administrador del sitio."
|
1277 |
-
|
1278 |
-
msgid "PostTypeAlertsInfo"
|
1279 |
-
msgstr "Esta es una lista de <a href=\"https://codex.wordpress.org/Post_Types\" target=\"_blank\" rel=\"noopener\">tipos de publicaciones</a> registradas. Recibirás alertas de seguridad cuando una página o publicación sea creada o modificada. Algunos de estos tipos son nativos de WordPress pero la mayoría son creados por plugins y plantillas que tengas instalados. Si no quieres recibir alertas por cambios en uno o más de estos tipos, puedes usar este panel para desactivarlas."
|
1280 |
-
|
1281 |
-
msgid "PostTypeAlertsInvisible"
|
1282 |
-
msgstr "Si estás recibiendo alertas por cambios en tipos de publicaciones que no aparecen en la lista, es posible que estas hayan sido creadas dinámicamente por un plugin o plantilla sin usar las funciones nativas de WordPress. Si conoce el identificador único del tipo de publicación, puedes ingresarlo en el formulario y el plugin de Sucuri hará lo mejor posible para ignorar estas alertas."
|
1283 |
-
|
1284 |
-
msgid "PostTypeAlertsStop"
|
1285 |
-
msgstr "Ignorar Cambios En Este Tipo De Publicaciones"
|
1286 |
-
|
1287 |
-
msgid "AlertsPerHour"
|
1288 |
-
msgstr "Alertas Por Hora"
|
1289 |
-
|
1290 |
-
msgid "AlertsPerHourMaximum"
|
1291 |
-
msgstr "Número Máximo De Alertas Por Hora"
|
1292 |
-
|
1293 |
-
msgid "AlertsPerHourInfo"
|
1294 |
-
msgstr "Utiliza esta opción para configurar el número máximo de alertas de seguridad por hora. Si el número es excedido y el plugin detecta más eventos durante la misma hora, estos serán agregados al registro de seguridad pero no serán enviados por correo electrónico. Ten cuidado con esta opción, ya que puedes perder información importante."
|
1295 |
-
|
1296 |
-
msgid "TestAlerts"
|
1297 |
-
msgstr "Probar Alertas"
|
1298 |
-
|
1299 |
-
msgid "AlertsRecipient"
|
1300 |
-
msgstr "Quién Recibirá Alertas"
|
1301 |
-
|
1302 |
-
msgid "AlertsRecipientInfo"
|
1303 |
-
msgstr "Por defecto, el plugin enviará las alertas de seguridad a la cuenta de administración primaria, la misma cuenta que fue creada durante el proceso de instalación de WordPress en tu servidor web. Puedes agregar más direcciones de correo a la lista, ellos recibirán una copia de las mismas alertas de seguridad."
|
1304 |
-
|
1305 |
-
msgid "CustomFormat"
|
1306 |
-
msgstr "Formato Personalizado"
|
1307 |
-
|
1308 |
-
msgid "AlertsSubject"
|
1309 |
-
msgstr "Asunto de la Alerta"
|
1310 |
-
|
1311 |
-
msgid "AlertsSubjectInfo"
|
1312 |
-
msgstr "El formato para el asunto de las alertas de seguridad, por defecto las alertas incluirán el nombre del sitio web y el identificador del evento, puedes usar este panel para agregar la dirección IP del usuario o cualquier otra información adicional. También puedes crear filtros en tu cliente de correo electrónico, agregando etiquetas personalizadas en el formulario."
|
1313 |
-
|
1314 |
-
msgid "TrustedIPs"
|
1315 |
-
msgstr "Direcciones IP Seguras"
|
1316 |
-
|
1317 |
-
msgid "CIDRFormat"
|
1318 |
-
msgstr "Formato CIDR"
|
1319 |
-
|
1320 |
-
msgid "IPAddedAt"
|
1321 |
-
msgstr "Dirección Agregada en"
|
1322 |
-
|
1323 |
-
msgid "TrustedIPsInfo"
|
1324 |
-
msgstr "Si estás trabajando en una red de área local, puedes querer incluir las direcciones IP de todos los nodos de la red en esta lista, esto hará que el plugin ignore todos los eventos originados desde estas direcciones para reducir la cantidad de falsos/positivos. Puede usar el formato CIDR <em>(Classless Inter Domain Routing)</em> para especificar un rango de direcciones IP <em>(solo 8, 16, y 24)</em>."
|
1325 |
-
|
1326 |
-
msgid "APIViaProxy"
|
1327 |
-
msgstr "API a Través de un Proxy"
|
1328 |
-
|
1329 |
-
msgid "APIViaProxyInfo"
|
1330 |
-
msgstr "Todas las conexiones a través de HTTP usadas para comunicarse con la API utilizan las funciones nativas de WordPress, esto significa que puedes usar el mismo mecanismo sugerido por WordPress para establecer estas conexiones a través de un proxy. De acuerdo a la <a href=\"https://developer.wordpress.org/reference/classes/wp_http_proxy/\" target=\"_blank\" rel=\"noopener\">documentación oficial</a>, debes agregar estas constantes en el archivo de configuración: <em>WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME, WP_PROXY_PASSWORD</em>."
|
1331 |
-
|
1332 |
-
msgid "ProxyHostname"
|
1333 |
-
msgstr "Dirección del Servidor Proxy"
|
1334 |
-
|
1335 |
-
msgid "ProxyPort"
|
1336 |
-
msgstr "Número del Puerto del Proxy"
|
1337 |
-
|
1338 |
-
msgid "ProxyUsername"
|
1339 |
-
msgstr "Nombre de Usuario del Proxy"
|
1340 |
-
|
1341 |
-
msgid "ProxyPassword"
|
1342 |
-
msgstr "Contraseña del Proxy"
|
1343 |
-
|
1344 |
-
msgid "APICommunication"
|
1345 |
-
msgstr "Conexión con la API"
|
1346 |
-
|
1347 |
-
msgid "APICommunicationInfo"
|
1348 |
-
msgstr "Una vez la llave para la API haya sido generada, el plugin establecerá una comunicación con un servicio remoto que actuará como una caja fuerte para almacenar los registros de seguridad generados cuando algo sospechoso suceda en tu sitio web. Si el sitio es comprometido, el hacker no podrá eliminar los registros de seguridad para encubrir sus huellas, de esta forma podrás investigar el ataque y prevenir futuros problemas."
|
1349 |
-
|
1350 |
-
msgid "APICommunicationDisabled"
|
1351 |
-
msgstr "Desactivar la comunicación entre el plugin y la API detendrá el monitor de eventos de seguridad. Considera activar el exportador de registros desde la página general de ajustes para mantener el monitor de eventos funcionando sin enviar datos a la API, de lo contrario, un usuario malicioso podrá ejecutar acciones sin que un administrador se de cuenta de lo que está sucediendo."
|
1352 |
-
|
1353 |
-
msgid "APITimeout"
|
1354 |
-
msgstr "Tiempo de Espera para la API"
|
1355 |
-
|
1356 |
-
msgid "APITimeoutLabel"
|
1357 |
-
msgstr "Tiempo de Espera (en segundos)"
|
1358 |
-
|
1359 |
-
msgid "APITimeoutValue"
|
1360 |
-
msgstr "Esperar <b>%%SUCURI.RequestTimeout%%</b> antes de terminar la conexión"
|
1361 |
-
|
1362 |
-
msgid "APITimeoutInfo"
|
1363 |
-
msgstr "El plugin envía a la API información asociada a los eventos generados por WordPress que sean considerados sospechosos. El envío de estos datos se hace a través de HTTP usando uno de los protocolos de comunicación disponibles en el sistema y <a target=\"_blank\" href=\"https://developer.wordpress.org/reference/functions/wp_remote_post/\" rel=\"noopener\">funciones nativas de WordPress</a>. Si la conexión o el servicio remoto excede la cantidad de segundos configurados en esta opción, la operación es cancelada. Si experimentas problemas de conexión, por favor comunícate con tu proveedor de hosting para investigar los bloqueos."
|
1364 |
-
|
1365 |
-
msgid "HTAccessTitle"
|
1366 |
-
msgstr "Integridad del Archivo .htaccess"
|
1367 |
-
|
1368 |
-
msgid "HTAccessInfo"
|
1369 |
-
msgstr "El archivo <code>.htaccess</code> es un archivo de configuración usado por el servidor web Apache para aplicar cambios generales por directorio. WordPress utiliza este archivo para manipular las direcciones de las páginas creadas por los usuarios; más notable, WordPress utiliza este archivo para generar URL amigables."
|
1370 |
-
|
1371 |
-
msgid "HTAccessFound"
|
1372 |
-
msgstr "Archivo encontrado en esta ubicación <code>%%SUCURI.HTAccess.Fpath%%</code>"
|
1373 |
-
|
1374 |
-
msgid "HTAccessNotFound"
|
1375 |
-
msgstr "El sitio web no tiene un archivo <code>.htaccess</code> o no se encuentra en la ubicación esperada."
|
1376 |
-
|
1377 |
-
msgid "HTAccessStandard"
|
1378 |
-
msgstr "El archivo <code>.htaccess</code> principal contiene las reglas estándares de WordPress generadas durante la instalación del sitio web. Puedes modificar estas reglas para aumentar el rendimiento del servidor o para generar redirecciones a otras páginas. Para obtener más información al respecto visita la página oficial con la documentación en <a target=\"_blank\" rel=\"noopener\" href=\"https://codex.wordpress.org/Using_Permalinks#Creating_and_editing_.28.htaccess.29\"> Codex WordPress - Creating and editing (.htaccess)</a>"
|
1379 |
-
|
1380 |
-
msgid "ScannerDescription"
|
1381 |
-
msgstr "El plugin escanea tu sitio web en busca de cambios que son eventualmente reportados a la API y visualizados a través de los registros de seguridad. Este escáner es ejecutado automáticamente cada día, pero puedes cambiar la frecuencia dependiendo de tus necesidades. Ten en cuenta que si tu sitio contiene una gran cantidad de archivos, es posible que el escáner sea bloqueado por tu proveedor de hosting si este excede el límite de ejecución que ellos hayan impuesto sobre su cuenta."
|
1382 |
-
|
1383 |
-
msgid "ScannerWithoutSPL"
|
1384 |
-
msgstr "El escáner hace uso de las librerías <a href=\"http://php.net/manual/en/class.splfileobject.php\" target=\"_blank\" rel=\"noopener\">SPL</a> y <a target=\"_blank\" href=\"http://php.net/manual/en/class.filesystemiterator.php\" rel=\"noopener\">Filesystem Iterator</a> de PHP para escanear el árbol de directorios de tu sitio web. Esta librería solo está disponible en PHP 5 >= 5.3.0 — y — PHP 7; si tu servidor hace uso de una versión antigua, el plugin no funcionará como se espera. Por favor, contacta a tu proveedor de hosting para obtener ayuda al respecto."
|
1385 |
-
|
1386 |
-
msgid "IntegrityLanguageTitle"
|
1387 |
-
msgstr "Integridad de WordPress (Idioma)"
|
1388 |
-
|
1389 |
-
msgid "IntegrityInfo"
|
1390 |
-
msgstr "La información necesaria para verificar la integridad de tu instalación de WordPress proviene de la <a href=\"http://codex.wordpress.org/WordPress.org_API\" target=\"_blank\" rel=\"noopener\">API Oficial de WordPress</a>. El plugin compara esta información con los archivos instalados en tu sitio web. Por defecto, la API provee una copia de los archivos en Inglés, si instalaste un idioma diferente, por favor selecciónalo en esta opción para reducir la cantidad de falsos/positivos que el escáner pueda encontrar."
|
1391 |
-
|
1392 |
-
msgid "IntegrityNote"
|
1393 |
-
msgstr "<b>Nota:</b> No todos los idiomas están soportados por la API de WordPress. Es posible que tengas que usar la versión en Inglés para reducir la cantidad de falsos/positivos arrojados por el escáner durante su ejecución. Como alternativa, puede seleccionar dichos archivos y marcarlos como revisados para que el escáner los ignore."
|
1394 |
-
|
1395 |
-
msgid "Reason"
|
1396 |
-
msgstr "Motivo"
|
1397 |
-
|
1398 |
-
msgid "FalsePositives"
|
1399 |
-
msgstr "Integridad de WordPress (Falsos/Positivos)"
|
1400 |
-
|
1401 |
-
msgid "FalsePositivesUnignore"
|
1402 |
-
msgstr "No Ignorar Estos Archivos"
|
1403 |
-
|
1404 |
-
msgid "FalsePositivesInfo"
|
1405 |
-
msgstr "El escáner de archivos no lee el contenido de estos, sino que compara el Checksum para saber si han sido modificados. Un falso/positivo ocurre cuando la modificación no hace parte de una inyección de código malicioso, estas modificaciones pueden ser consideradas inofencivas. Los archivos en esta lista han sido marcados como falsos/positivos y serán ignorados durante los próximos escaneos del sistema."
|
1406 |
-
|
1407 |
-
msgid "IgnoreFiles"
|
1408 |
-
msgstr "Ignorar Archivos Durante Los Escaneos"
|
1409 |
-
|
1410 |
-
msgid "IgnoreFilesSingle"
|
1411 |
-
msgstr "Ignorar Un Solo Archivo"
|
1412 |
-
|
1413 |
-
msgid "IgnoreFilesInfo"
|
1414 |
-
msgstr "Utiliza esta herramienta para seleccionar directorios que contienen muchos archivos o archivos que son muy pesados para ser procesados por el escáner de seguridad. Esto usualmente incluye directorios con imágenes, archivos multimedia, y en general cualquier archivo que no tenga código. Ignorar estos archivos mejorará el rendimiento del plugin y mantendrá el consumo de memoria a niveles mínimos."
|
1415 |
-
|
1416 |
-
msgid "SecretKeys"
|
1417 |
-
msgstr "Llaves de Seguridad"
|
1418 |
-
|
1419 |
-
msgid "SecretKeysUpdated"
|
1420 |
-
msgstr "Las llaves de seguridad han sido cambiadas (abajo puedes encontrar un resumen de la operación)."
|
1421 |
-
|
1422 |
-
msgid "SecretKeysGenerate"
|
1423 |
-
msgstr "Generar Nuevas Llaves de Seguridad"
|
1424 |
-
|
1425 |
-
msgid "SecretKeysExpiration"
|
1426 |
-
msgstr "Tu sesión de usuario expirará inmediatamente cuando las nuevas llaves de seguridad sean generadas."
|
1427 |
-
|
1428 |
-
msgid "SecretKeysInfo"
|
1429 |
-
msgstr "Las llaves secretas o de seguridad son una lista de constantes aleatorias agregadas a tu sitio web, para mejorar el proceso de encriptación de las cookies para cada usuario. Las llaves hacen que tu sitio sea más difícil de vulnerar, al agregar elementos aleatorios en las contraseñas. No necesitas memorizar estas llaves, ellas serán guardadas en el archivo de configuración de WordPress. Puede cambiarlas en cualquier momento para invalidar sesiones de usuario existentes, forzando a todos los usuarios a autenticar sus cuentas nuevamente."
|
1430 |
-
|
1431 |
-
msgid "PluginReinstall"
|
1432 |
-
msgstr "Re-Instalar Plugins"
|
1433 |
-
|
1434 |
-
msgid "PluginReinstallInfo"
|
1435 |
-
msgstr "En el caso de que sospeches que tu sitio web está infectado con código maliciosos, o incluso después de limpiar tu sitio, es una buena idea reinstalar todos los plugins y plantillas, incluso aquellos que no están activados, para asegurar que el código es el original. Ten en cuenta que plugins y plantillas premium no pueden ser reinstaladas por motivos de compatibilidad con sus licencias."
|
1436 |
-
|
1437 |
-
msgid "PluginReinstallCache"
|
1438 |
-
msgstr "La información mostrada aquí es guardada en cache por %%SUCURI.ResetPlugin.CacheLifeTime%% segundos, esto es necesario para reducir el número de conexiones HTTP y subsecuentemente el consumo de ancho de banda de tu servidor. Actualmente no existe una opción para limpiar esta caché, debes esperar a que el plugin la regenere automáticamente."
|
1439 |
-
|
1440 |
-
msgid "PluginReinstallWarning"
|
1441 |
-
msgstr "<b>¡ADVERTENCIA!</b> La reinstalación de uno o más plugin puede ocasionar daños irreversibles a tu sitio web, procede con cuidado y asegúrate de mantener una copia de seguridad actualizada del sitio a la mano. Esta herramienta no tendrá ningún efecto sobre la base de datos."
|
1442 |
-
|
1443 |
-
msgid "Roles"
|
1444 |
-
msgstr "Privilegios"
|
1445 |
-
|
1446 |
-
msgid "Registered"
|
1447 |
-
msgstr "Registrado"
|
1448 |
-
|
1449 |
-
msgid "PasswordChange"
|
1450 |
-
msgstr "Cambiar la Contraseña de Usuario"
|
1451 |
-
|
1452 |
-
msgid "PasswordChangeInfo"
|
1453 |
-
msgstr "Puedes generar una nueva contraseña aleatoria para las cuentas de usuario que selecciones de la lista. Un correo será enviado a cada usuario. Si decides cambiar tu propia contraseña, tu sesión de usuario expirará inmediatamente. Necesitarás autenticar tu cuenta nuevamente con la nueva contraseña que recibirás en tu correo electrónico."
|
1454 |
-
|
1455 |
-
msgid "PasswordChangeAlert"
|
1456 |
-
msgstr "WordPress ha generado una nueva contraseña de forma aleatoria para tu cuenta de usuario <b>%%SUCURI.ResetPassword.UserName%%</b> en este sitio web <a target=\"_blank\" href=\"http://%%SUCURI.ResetPassword.Website%%\">%%SUCURI.ResetPassword.Website%%</a>. El cambio ha sido solicitado por uno de los administradores del sitio por motivos de seguridad. Tu nueva contraseña es — <span style=\"font-family:Menlo, Monaco, monospace, serif;font-weight:700\">%%%SUCURI.ResetPassword.Password%%%</span> — por favor cámbiala lo antes posible."
|
1457 |
-
|
1458 |
-
msgid "Update"
|
1459 |
-
msgstr "Actualización"
|
1460 |
-
|
1461 |
-
msgid "TestedWith"
|
1462 |
-
msgstr "Probado Con"
|
1463 |
-
|
1464 |
-
msgid "AvailableUpdates"
|
1465 |
-
msgstr "Actualizaciones Disponibles"
|
1466 |
-
|
1467 |
-
msgid "AvailableUpdatesInfo"
|
1468 |
-
msgstr "WordPress tiene una acogida muy grande en Internet, esto atrae la atención de personas maliciosas para encontrar vulnerabilidades en el código, al igual que en el código de plugins y plantillas que otras empresas desarrollan. Es recomendable mantener plugins y plantillas actualizadas para prevenir ataques tan pronto como vulnerabilidades sean descubiertas."
|
1469 |
-
|
1470 |
-
msgid "WhitelistScript"
|
1471 |
-
msgstr "Desbloquear Archivos PHP"
|
1472 |
-
|
1473 |
-
msgid "WhitelistScriptInfo"
|
1474 |
-
msgstr "Después de aplicar el hardening en los directorios soportados por el plugin, un archivo .htaccess será creado con reglas para bloquear el acceso directo a todos los archivos PHP contenidos en dichos directorios, esta es una buena precaución para evitar la ejecución de código malicioso; con algunas excepciones, el archivo <em>\"index.php\"</em> es el único que debería tener acceso público, sin embargo muchos plugins y plantillas requieren de este acceso también, utilice esta herramienta para desbloquearlos."
|
1475 |
-
|
1476 |
-
msgid "Uninstall"
|
1477 |
-
msgstr "Eliminar Registros de Seguridad, Hardening y Configuraciones"
|
1478 |
-
|
1479 |
-
msgid "UninstallInfo"
|
1480 |
-
msgstr "Esta acción iniciará el proceso de desactivación / desinstalación del plugin. Todos los registro de seguridad guardados en el disco local, las reglas de hardening y las configuraciones serán eliminadas. Ten en cuenta que los registros de seguridad guardados en el servidor de Sucuri no serán eliminados, esto es para prevenir que usuarios maliciosos intenten borrar sus huellas después de ejecutar un ataque en contra del sitio web."
|
1481 |
-
|
1482 |
-
msgid "ImportExport"
|
1483 |
-
msgstr "Importar Y Exportar Ajustes"
|
1484 |
-
|
1485 |
-
msgid "ImportExportInfo"
|
1486 |
-
msgstr "Copie la información codificada en JSON que aparece en la caja de abajo, pegue esta información en la misma caja en el sitio web donde desea importar esta configuración. Ten en cuenta que algunas opciones serán omitidas, ya que estas contienen información irrelevante para otros sitios. Para importar la configuración de otro sitio web a este, reemplace el contenido de la caja con los datos codificados en JSON de otro sitio, luego presione el botón para continuar. Ten en cuenta que algunas opciones no serán importadas para reducir el riesgo de insertar datos arbitrarios en el disco."
|
1487 |
-
|
1488 |
-
msgid "DataStorage"
|
1489 |
-
msgstr "Almacenamiento de Datos"
|
1490 |
-
|
1491 |
-
msgid "DataStorageInfo"
|
1492 |
-
msgstr "Este es el directorio donde el plugin guardará los registros de seguridad, el archivo con las configuraciones, la caché y datos adicionales de otras herramientas. El plugin requiere de permisos de escritura en este directorio, así como en los archivos contenidos allí. Si prefieres mantener estos archivos en un directorio diferente al especificado, por favor define una constante llamada <em>\"SUCURI_DATA_STORAGE\"</em> en el archivo de configuración de WordPress, con la ruta absoluta del nuevo directorio."
|
1493 |
-
|
1494 |
-
msgid "TimezoneTitle"
|
1495 |
-
msgstr "Zona Horaria"
|
1496 |
-
|
1497 |
-
msgid "TimezoneInfo"
|
1498 |
-
msgstr "Esta opción define la zona horaria que será usada a través de todo el plugin para mostrar las fechas y horas cuando sea necesario. Esta opción también afecta la fecha y hora de la información visible en el panel de registros de seguridad que viene de un servidor remoto configurado para usar Horario del este de Norteamérica (EDT por sus siglas en Inglés). WordPress ofrece una opción en la página de ajustes generales que te permite configurar la zona horaria para todo el sitio web, sin embargo, si estás experimentando problemas con la hora en los registros de seguridad, esta opción te ayudará a solucionarlos."
|
1499 |
-
|
1500 |
-
msgid "TimezoneStatus"
|
1501 |
-
msgstr "La zona horaria para la fecha y hora en los registros de seguridad ha sido cambiada"
|
1502 |
-
|
1503 |
-
msgid "ChecksumsAPI"
|
1504 |
-
msgstr "WordPress Checksums API"
|
1505 |
-
|
1506 |
-
msgid "ChecksumsAPIInfo"
|
1507 |
-
msgstr "La herramienta que verifica la integridad de la instalación usa un servicio remoto mantenido por WordPress.org para determinar qué archivos fueron agregados, eliminados o modificados. La API devuelve una lista de archivos con sus respectivos checksums, esta información garantiza que la instalación no está corrupta. Tu puedes, sin embargo, apuntar el plugin a un repositorio en GitHub en caso de que estés usando una versión personalizada de WordPress como la <a href=\"https://github.com/WordPress/WordPress\" target=\"_blank\">versión alpha del código</a>."
|
1508 |
-
|
1509 |
-
msgid "ChecksumsAPIChanged"
|
1510 |
-
msgstr "La dirección web para obtener los checksums de WordPress ha sido cambiada"
|
1511 |
-
|
1512 |
-
msgid "MaxExecutionTimeAlert"
|
1513 |
-
msgstr "El servidor no pudo procesar esta acción rápido; tiempo máximo de ejecución alcanzado"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -265,7 +265,7 @@ This version adds support for the latest version of WordPress. Introduces new fe
|
|
265 |
* Fix lazy load of the CSS and Scripts on the correct pages
|
266 |
* Add audit log message fixer for the wpephpcompat_jobs event
|
267 |
* Fix website URL in the template for the email alerts
|
268 |
-
* Add message in the core integrity tool for false
|
269 |
* Add option to reset the content of some storage files
|
270 |
* Add mechanism to display self-hosting logs as fallback
|
271 |
* Fix incoherent failed login processor on pagination
|
265 |
* Fix lazy load of the CSS and Scripts on the correct pages
|
266 |
* Add audit log message fixer for the wpephpcompat_jobs event
|
267 |
* Fix website URL in the template for the email alerts
|
268 |
+
* Add message in the core integrity tool for false positives
|
269 |
* Add option to reset the content of some storage files
|
270 |
* Add mechanism to display self-hosting logs as fallback
|
271 |
* Fix incoherent failed login processor on pagination
|
src/api.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the api.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -33,7 +39,13 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
33 |
* APIs allow the combination of multiple APIs into new applications known as
|
34 |
* mashups.
|
35 |
*
|
36 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
*/
|
38 |
class SucuriScanAPI extends SucuriScanOption
|
39 |
{
|
@@ -45,8 +57,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
45 |
* URL, because of this we decided to write our own URL query builder to
|
46 |
* keep control of the output.
|
47 |
*
|
48 |
-
* @param
|
49 |
-
* @return string
|
50 |
*/
|
51 |
private static function buildQuery($params = array())
|
52 |
{
|
@@ -63,14 +75,15 @@ class SucuriScanAPI extends SucuriScanOption
|
|
63 |
/**
|
64 |
* Sends a HTTP request via WordPress WP_HTTP class.
|
65 |
*
|
|
|
66 |
* @see https://secure.php.net/manual/en/book.curl.php
|
67 |
* @see https://developer.wordpress.org/reference/classes/wp_http/request/
|
68 |
*
|
69 |
-
* @param
|
70 |
-
* @param
|
71 |
-
* @param
|
72 |
-
* @param
|
73 |
-
* @return
|
74 |
*/
|
75 |
public static function apiCall($url = '', $method = 'GET', $params = array(), $args = array())
|
76 |
{
|
@@ -141,18 +154,15 @@ class SucuriScanAPI extends SucuriScanOption
|
|
141 |
}
|
142 |
|
143 |
/* try to return a JSON-encode object */
|
144 |
-
|
145 |
-
|
146 |
-
}
|
147 |
-
|
148 |
-
return $res['body'];
|
149 |
}
|
150 |
|
151 |
/**
|
152 |
* Check whether the plugin API key is valid or not.
|
153 |
*
|
154 |
-
* @param
|
155 |
-
* @return bool
|
156 |
*/
|
157 |
private static function isValidKey($api_key = '')
|
158 |
{
|
@@ -162,14 +172,14 @@ class SucuriScanAPI extends SucuriScanOption
|
|
162 |
/**
|
163 |
* Store the API key locally.
|
164 |
*
|
165 |
-
* @param
|
166 |
-
* @param
|
167 |
-
* @return bool
|
168 |
*/
|
169 |
public static function setPluginKey($api_key = '', $validate = false)
|
170 |
{
|
171 |
if ($validate && !self::isValidKey($api_key)) {
|
172 |
-
return SucuriScanInterface::error(
|
173 |
}
|
174 |
|
175 |
if (!empty($api_key)) {
|
@@ -198,11 +208,11 @@ class SucuriScanAPI extends SucuriScanOption
|
|
198 |
/**
|
199 |
* Call an action from the remote API interface of our WordPress service.
|
200 |
*
|
201 |
-
* @param
|
202 |
-
* @param
|
203 |
-
* @param
|
204 |
-
* @param
|
205 |
-
* @return array|bool
|
206 |
*/
|
207 |
public static function apiCallWordpress($method = 'GET', $params = array(), $send_api_key = true, $args = array())
|
208 |
{
|
@@ -223,9 +233,10 @@ class SucuriScanAPI extends SucuriScanOption
|
|
223 |
}
|
224 |
|
225 |
/**
|
226 |
-
* Determine whether an API response was successful or not checking the
|
227 |
-
* generic variables and types, in case of an error a notification
|
228 |
-
* in the administrator panel explaining the result of the
|
|
|
229 |
*
|
230 |
* For failures in the HTTP response:
|
231 |
*
|
@@ -239,22 +250,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
239 |
* address of the site administrator was changed so the data is not valid
|
240 |
* anymore.
|
241 |
*
|
242 |
-
*
|
243 |
-
*
|
244 |
-
* deployed. There is an option in the settings page that allows to temporarily
|
245 |
-
* disable the communication with the API service while the server is down, this
|
246 |
-
* allows the admins to keep the latency at zero and continue working in their
|
247 |
-
* websites without interruptions.
|
248 |
-
*
|
249 |
-
* SSL issues: depending on the options used to compile the OpenSSL library
|
250 |
-
* built by each hosting provider, the connection with the HTTPs version of the
|
251 |
-
* API service may be rejected because of a failure in the SSL algorithm check.
|
252 |
-
* There is an option in the settings page that allows to disable the SSL pair
|
253 |
-
* verification, this option it disable automatically when the error is detected
|
254 |
-
* for the first time.
|
255 |
-
*
|
256 |
-
* @param array $res HTTP response after API endpoint execution.
|
257 |
-
* @return bool False if the API call failed, true otherwise.
|
258 |
*/
|
259 |
public static function handleResponse($res = array())
|
260 |
{
|
@@ -277,7 +274,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
277 |
|| !isset($res['messages'])
|
278 |
|| empty($res['messages'])
|
279 |
) {
|
280 |
-
return SucuriScanInterface::error(
|
281 |
}
|
282 |
|
283 |
$msg = implode(".\x20", $res['messages']);
|
@@ -286,8 +283,11 @@ class SucuriScanAPI extends SucuriScanOption
|
|
286 |
// Special response for invalid API keys.
|
287 |
if (stripos($raw, 'log file not found') !== false) {
|
288 |
$key = SucuriScanOption::getOption(':api_key');
|
289 |
-
$
|
290 |
-
|
|
|
|
|
|
|
291 |
|
292 |
SucuriScanOption::deleteOption(':api_key');
|
293 |
}
|
@@ -296,7 +296,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
296 |
if (stripos($raw, 'wrong api key') !== false) {
|
297 |
$key = SucuriScanOption::getOption(':cloudproxy_apikey');
|
298 |
$key = SucuriScan::escape($key);
|
299 |
-
$msg .= sprintf(
|
300 |
|
301 |
SucuriScanOption::setRevProxy('disable', true);
|
302 |
SucuriScanOption::setAddrHeader('REMOTE_ADDR', true);
|
@@ -310,12 +310,15 @@ class SucuriScanAPI extends SucuriScanOption
|
|
310 |
|| stripos($raw, 'error setting certificate')
|
311 |
|| stripos($raw, 'SSL connect error')
|
312 |
) {
|
313 |
-
$msg .=
|
|
|
|
|
|
|
314 |
}
|
315 |
|
316 |
// Check if the MX records as missing for API registration.
|
317 |
if (strpos($raw, 'Invalid email') !== false) {
|
318 |
-
$msg =
|
319 |
}
|
320 |
|
321 |
return SucuriScanInterface::error($msg);
|
@@ -324,8 +327,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
324 |
/**
|
325 |
* Send a request to the API to register this site.
|
326 |
*
|
327 |
-
* @param
|
328 |
-
* @return bool
|
329 |
*/
|
330 |
public static function registerSite($email = '')
|
331 |
{
|
@@ -333,21 +336,26 @@ class SucuriScanAPI extends SucuriScanOption
|
|
333 |
$email = self::getSiteEmail();
|
334 |
}
|
335 |
|
336 |
-
$res = self::apiCallWordpress(
|
337 |
-
'
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
|
|
344 |
|
345 |
-
|
346 |
-
|
347 |
-
return SucuriScanInterface::info(__('AlertAPIKeySet', SUCURISCAN_TEXTDOMAIN));
|
348 |
}
|
349 |
|
350 |
-
|
|
|
|
|
|
|
|
|
|
|
351 |
}
|
352 |
|
353 |
/**
|
@@ -359,32 +367,40 @@ class SucuriScanAPI extends SucuriScanOption
|
|
359 |
{
|
360 |
$domain = self::getDomain();
|
361 |
|
362 |
-
$res = self::apiCallWordpress(
|
363 |
-
'
|
364 |
-
|
365 |
-
|
366 |
-
|
|
|
|
|
|
|
|
|
367 |
|
368 |
-
if (self::handleResponse($res)) {
|
369 |
-
|
370 |
-
return SucuriScanInterface::info($res['output']['message']);
|
371 |
}
|
372 |
|
373 |
-
|
|
|
|
|
374 |
}
|
375 |
|
376 |
/**
|
377 |
* Retrieve the event logs registered by the API service.
|
378 |
*
|
379 |
-
* @param
|
380 |
* @return array|bool The data structure with the logs.
|
381 |
*/
|
382 |
public static function getAuditLogs($lines = 50)
|
383 |
{
|
384 |
-
$res = self::apiCallWordpress(
|
385 |
-
'
|
386 |
-
|
387 |
-
|
|
|
|
|
|
|
388 |
|
389 |
if (!self::handleResponse($res)) {
|
390 |
return false;
|
@@ -402,11 +418,17 @@ class SucuriScanAPI extends SucuriScanOption
|
|
402 |
{
|
403 |
$auditlogs = array();
|
404 |
$cache = new SucuriScanCache('auditqueue');
|
|
|
405 |
|
406 |
-
if ($events
|
407 |
$events = array_reverse($events);
|
408 |
|
409 |
foreach ($events as $micro => $message) {
|
|
|
|
|
|
|
|
|
|
|
410 |
$offset = strpos($micro, '_');
|
411 |
$time = substr($micro, 0, $offset);
|
412 |
$auditlogs[] = sprintf(
|
@@ -418,21 +440,23 @@ class SucuriScanAPI extends SucuriScanOption
|
|
418 |
}
|
419 |
}
|
420 |
|
421 |
-
|
422 |
'status' => 1,
|
423 |
'action' => 'get_logs',
|
424 |
'request_time' => time(),
|
425 |
'verbose' => 0,
|
426 |
'output' => array_reverse($auditlogs),
|
427 |
'total_entries' => count($auditlogs),
|
428 |
-
)
|
|
|
|
|
429 |
}
|
430 |
|
431 |
/**
|
432 |
* Reads, parses and extracts relevant data from the security logs.
|
433 |
*
|
434 |
-
* @param
|
435 |
-
* @return array
|
436 |
*/
|
437 |
private static function parseAuditLogs($res)
|
438 |
{
|
@@ -494,7 +518,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
494 |
}
|
495 |
|
496 |
/* extract the IP address */
|
497 |
-
$log_data['message'] = substr($log_data['message'], $offset+2);
|
498 |
$offset = strpos($log_data['message'], ";\x20");
|
499 |
$log_data['remote_addr'] = substr($log_data['message'], 0, $offset);
|
500 |
|
@@ -502,11 +526,11 @@ class SucuriScanAPI extends SucuriScanOption
|
|
502 |
if (strpos($log_data['remote_addr'], ",\x20")) {
|
503 |
$index = strpos($log_data['remote_addr'], ",\x20");
|
504 |
$log_data['username'] = substr($log_data['remote_addr'], 0, $index);
|
505 |
-
$log_data['remote_addr'] = substr($log_data['remote_addr'], $index+2);
|
506 |
}
|
507 |
|
508 |
/* fix old user authentication logs for backward compatibility */
|
509 |
-
$log_data['message'] = substr($log_data['message'], $offset+2);
|
510 |
$log_data['message'] = str_replace(
|
511 |
'logged in',
|
512 |
'authentication succeeded',
|
@@ -516,7 +540,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
516 |
/* extract the username of a successful/failed login */
|
517 |
if (strpos($log_data['message'], "User authentication\x20") === 0) {
|
518 |
$offset = strpos($log_data['message'], ":\x20");
|
519 |
-
$username = substr($log_data['message'], $offset+2);
|
520 |
if (strpos($username, ';') !== false) {
|
521 |
$username = substr($username, 0, strpos($username, ';'));
|
522 |
}
|
@@ -527,8 +551,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
527 |
/* extract more information from the special formatted logs */
|
528 |
if (strpos($log_data['message'], "(multiple entries):\x20")) {
|
529 |
$offset = strpos($log_data['message'], "(multiple entries):\x20");
|
530 |
-
$message = substr($log_data['message'], 0, $offset+19);
|
531 |
-
$entries = substr($log_data['message'], $offset+20);
|
532 |
|
533 |
$log_data['message'] = $message;
|
534 |
$entries = str_replace(', new size', '; new size', $entries);
|
@@ -548,7 +572,9 @@ class SucuriScanAPI extends SucuriScanOption
|
|
548 |
$log_data['file_list_count'] = count($log_data['file_list']);
|
549 |
}
|
550 |
|
551 |
-
|
|
|
|
|
552 |
$res['output_data'][] = $log_data;
|
553 |
}
|
554 |
}
|
@@ -559,8 +585,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
559 |
/**
|
560 |
* Modifies some of the security logs to detail the information.
|
561 |
*
|
562 |
-
* @param
|
563 |
-
* @return array|bool
|
564 |
*/
|
565 |
private static function getLogsHotfix($data)
|
566 |
{
|
@@ -577,11 +603,11 @@ class SucuriScanAPI extends SucuriScanOption
|
|
577 |
*/
|
578 |
if (isset($data['message']) && strpos($data['message'], 'Wpephpcompat_jobs') === 0) {
|
579 |
$offset = strpos($data['message'], "ID:\x20");
|
580 |
-
$id = substr($data['message'], $offset+4);
|
581 |
$id = substr($id, 0, strpos($id, ';'));
|
582 |
|
583 |
$offset = strpos($data['message'], "name:\x20");
|
584 |
-
$name = substr($data['message'], $offset+6);
|
585 |
|
586 |
$data['message'] = sprintf(
|
587 |
'WP Engine PHP Compatibility Checker: %s (created post #%d as cache)',
|
@@ -613,8 +639,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
613 |
/**
|
614 |
* Parse the event logs with multiple entries.
|
615 |
*
|
616 |
-
* @param
|
617 |
-
* @return string|array
|
618 |
*/
|
619 |
public static function parseMultipleEntries($event_log = '')
|
620 |
{
|
@@ -627,98 +653,14 @@ class SucuriScanAPI extends SucuriScanOption
|
|
627 |
return $event_log;
|
628 |
}
|
629 |
|
630 |
-
/**
|
631 |
-
* Collect the information for the audit log report.
|
632 |
-
*
|
633 |
-
* @param int $lines How many lines from the log file will be retrieved.
|
634 |
-
* @return array|bool All the information necessary to display the audit logs report.
|
635 |
-
*/
|
636 |
-
public static function getAuditReport($lines = 50)
|
637 |
-
{
|
638 |
-
$audit_logs = self::getAuditLogs($lines);
|
639 |
-
|
640 |
-
if (is_array($audit_logs)
|
641 |
-
&& array_key_exists('total_entries', $audit_logs)
|
642 |
-
&& array_key_exists('output_data', $audit_logs)
|
643 |
-
&& !empty($audit_logs['output_data'])
|
644 |
-
) {
|
645 |
-
// Data structure that will be returned.
|
646 |
-
$report = array(
|
647 |
-
'total_events' => 0,
|
648 |
-
'start_timestamp' => 0,
|
649 |
-
'end_timestamp' => 0,
|
650 |
-
'event_colors' => array(),
|
651 |
-
'events_per_type' => array(),
|
652 |
-
'events_per_user' => array(),
|
653 |
-
'events_per_ipaddress' => array(),
|
654 |
-
'events_per_login' => array(
|
655 |
-
'successful' => 0,
|
656 |
-
'failed' => 0,
|
657 |
-
),
|
658 |
-
);
|
659 |
-
|
660 |
-
// Get a list of valid audit event types.
|
661 |
-
$event_types = self::getAuditEventTypes();
|
662 |
-
foreach ($event_types as $event => $event_color) {
|
663 |
-
$report['events_per_type'][$event] = 0;
|
664 |
-
$report['event_colors'][] = $event_color;
|
665 |
-
}
|
666 |
-
|
667 |
-
// Collect information for each report chart.
|
668 |
-
foreach ($audit_logs['output_data'] as $event) {
|
669 |
-
$_username = SucuriScan::escape($event['username']);
|
670 |
-
$_remote_addr = SucuriScan::escape($event['remote_addr']);
|
671 |
-
|
672 |
-
@$report['total_events']++;
|
673 |
-
@$report['events_per_user'][$_username]++;
|
674 |
-
@$report['events_per_type'][$event['event']]++;
|
675 |
-
@$report['events_per_ipaddress'][$_remote_addr]++;
|
676 |
-
|
677 |
-
// Find the lowest datetime among the filtered events.
|
678 |
-
if ($event['timestamp'] <= $report['start_timestamp']
|
679 |
-
|| $report['start_timestamp'] === 0
|
680 |
-
) {
|
681 |
-
$report['start_timestamp'] = $event['timestamp'];
|
682 |
-
}
|
683 |
-
|
684 |
-
// Find the highest datetime among the filtered events.
|
685 |
-
if ($event['timestamp'] >= $report['end_timestamp']) {
|
686 |
-
$report['end_timestamp'] = $event['timestamp'];
|
687 |
-
}
|
688 |
-
|
689 |
-
/* backward compatibility for previous user login messages */
|
690 |
-
if (strpos($event['message'], 'User logged in:') === 0) {
|
691 |
-
$report['events_per_login']['successful']++;
|
692 |
-
continue;
|
693 |
-
}
|
694 |
-
|
695 |
-
/* detect successful user authentications */
|
696 |
-
if (strpos($event['message'], 'User authentication succeeded:') === 0) {
|
697 |
-
$report['events_per_login']['successful']++;
|
698 |
-
continue;
|
699 |
-
}
|
700 |
-
|
701 |
-
/* detect failed user authentications */
|
702 |
-
if (strpos($event['message'], 'User authentication failed:') === 0) {
|
703 |
-
$report['events_per_login']['failed']++;
|
704 |
-
continue;
|
705 |
-
}
|
706 |
-
}
|
707 |
-
|
708 |
-
return $report['total_events'] ? $report : false;
|
709 |
-
}
|
710 |
-
|
711 |
-
return false;
|
712 |
-
}
|
713 |
-
|
714 |
/**
|
715 |
* Send a request to the API to store and analyze the file's hashes of the site.
|
716 |
* This will be the core of the monitoring tools and will enhance the
|
717 |
* information of the audit logs alerting the administrator of suspicious
|
718 |
* changes in the system.
|
719 |
*
|
720 |
-
* @param
|
721 |
-
* @return bool
|
722 |
*/
|
723 |
public static function sendHashes($hashes = '')
|
724 |
{
|
@@ -726,10 +668,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
726 |
return false;
|
727 |
}
|
728 |
|
729 |
-
$
|
730 |
-
|
731 |
-
'h' => $hashes,
|
732 |
-
));
|
733 |
|
734 |
return self::handleResponse($res);
|
735 |
}
|
@@ -762,8 +702,9 @@ class SucuriScanAPI extends SucuriScanOption
|
|
762 |
public static function checksumAPI()
|
763 |
{
|
764 |
$url = 'https://api.wordpress.org/core/checksums/1.0/?version={version}&locale={locale}';
|
|
|
765 |
|
766 |
-
if ($custom
|
767 |
$url = sprintf(
|
768 |
'https://api.github.com/repos/%s/git/trees/master?recursive=1',
|
769 |
$custom /* expect: username/repository */
|
@@ -771,7 +712,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
771 |
}
|
772 |
|
773 |
$url = str_replace('{version}', SucuriScan::siteVersion(), $url);
|
774 |
-
$url = str_replace('{locale}',
|
775 |
|
776 |
return $url;
|
777 |
}
|
@@ -809,9 +750,9 @@ class SucuriScanAPI extends SucuriScanOption
|
|
809 |
*
|
810 |
* @see https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#_object_storage
|
811 |
*
|
812 |
-
* @param
|
813 |
-
* @param
|
814 |
-
* @return string
|
815 |
*/
|
816 |
public static function checksum($algorithm, $filename)
|
817 |
{
|
@@ -850,7 +791,6 @@ class SucuriScanAPI extends SucuriScanOption
|
|
850 |
*/
|
851 |
public static function getOfficialChecksums()
|
852 |
{
|
853 |
-
$result = false;
|
854 |
$url = self::checksumAPI();
|
855 |
$version = SucuriScan::siteVersion();
|
856 |
$res = self::apiCall($url, 'GET', array());
|
@@ -868,13 +808,16 @@ class SucuriScanAPI extends SucuriScanOption
|
|
868 |
$res = array('checksums' => array($version => $checksums));
|
869 |
}
|
870 |
|
871 |
-
if (
|
872 |
-
|
873 |
-
|
874 |
-
|
|
|
|
|
|
|
875 |
}
|
876 |
|
877 |
-
return $
|
878 |
}
|
879 |
|
880 |
/**
|
@@ -920,7 +863,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
920 |
$is_free_plugin = true;
|
921 |
$repository = $plugin_data['PluginURI'];
|
922 |
$offset = strpos($plugin_data['PluginURI'], '/plugins/');
|
923 |
-
$repository_name = substr($plugin_data['PluginURI'], $offset+9);
|
924 |
|
925 |
if (strpos($repository_name, '/') !== false) {
|
926 |
$offset = strpos($repository_name, '/');
|
@@ -969,8 +912,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
969 |
*
|
970 |
* The second filter, 'plugins_api', is the result that would be returned.
|
971 |
*
|
972 |
-
* @param
|
973 |
-
* @return array|bool
|
974 |
*/
|
975 |
public static function getRemotePluginData($plugin = '')
|
976 |
{
|
@@ -987,15 +930,16 @@ class SucuriScanAPI extends SucuriScanOption
|
|
987 |
* @see https://i18n.svn.wordpress.org/
|
988 |
* @see https://core.svn.wordpress.org/tags/VERSION_NUMBER/
|
989 |
*
|
990 |
-
* @param
|
991 |
-
* @return string|bool
|
992 |
*/
|
993 |
public static function getOriginalCoreFile($filename)
|
994 |
{
|
995 |
$version = self::siteVersion();
|
996 |
$url = 'https://core.svn.wordpress.org/tags/{version}/{filename}';
|
|
|
997 |
|
998 |
-
if ($custom
|
999 |
$url = sprintf(
|
1000 |
'https://raw.githubusercontent.com/%s/master/{filename}',
|
1001 |
$custom /* expect: username/repository */
|
3 |
/**
|
4 |
* Code related to the api.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
39 |
* APIs allow the combination of multiple APIs into new applications known as
|
40 |
* mashups.
|
41 |
*
|
42 |
+
* @category Library
|
43 |
+
* @package Sucuri
|
44 |
+
* @subpackage SucuriScanner
|
45 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
46 |
+
* @copyright 2010-2017 Sucuri Inc.
|
47 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
48 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
49 |
*/
|
50 |
class SucuriScanAPI extends SucuriScanOption
|
51 |
{
|
57 |
* URL, because of this we decided to write our own URL query builder to
|
58 |
* keep control of the output.
|
59 |
*
|
60 |
+
* @param array $params May be an array or object containing properties.
|
61 |
+
* @return string Returns a URL-encoded string.
|
62 |
*/
|
63 |
private static function buildQuery($params = array())
|
64 |
{
|
75 |
/**
|
76 |
* Sends a HTTP request via WordPress WP_HTTP class.
|
77 |
*
|
78 |
+
* @suppress PhanNonClassMethodCall
|
79 |
* @see https://secure.php.net/manual/en/book.curl.php
|
80 |
* @see https://developer.wordpress.org/reference/classes/wp_http/request/
|
81 |
*
|
82 |
+
* @param string $url The target URL where the request will be sent.
|
83 |
+
* @param string $method HTTP method that will be used to send the request.
|
84 |
+
* @param array $params Parameters for the request defined in an associative array.
|
85 |
+
* @param array $args Request arguments like the timeout, headers, cookies, etc.
|
86 |
+
* @return mixed HTTP response, JSON-decoded array, or false on failure.
|
87 |
*/
|
88 |
public static function apiCall($url = '', $method = 'GET', $params = array(), $args = array())
|
89 |
{
|
154 |
}
|
155 |
|
156 |
/* try to return a JSON-encode object */
|
157 |
+
$data = @json_decode($res['body'], true);
|
158 |
+
return $data ? $data : $res['body'];
|
|
|
|
|
|
|
159 |
}
|
160 |
|
161 |
/**
|
162 |
* Check whether the plugin API key is valid or not.
|
163 |
*
|
164 |
+
* @param string $api_key An unique string to identify this installation.
|
165 |
+
* @return bool True if the API key is valid, false otherwise.
|
166 |
*/
|
167 |
private static function isValidKey($api_key = '')
|
168 |
{
|
172 |
/**
|
173 |
* Store the API key locally.
|
174 |
*
|
175 |
+
* @param string $api_key An unique string of characters to identify this installation.
|
176 |
+
* @param bool $validate Whether the format of the key should be validated before store it.
|
177 |
+
* @return bool Either true or false if the key was saved successfully or not respectively.
|
178 |
*/
|
179 |
public static function setPluginKey($api_key = '', $validate = false)
|
180 |
{
|
181 |
if ($validate && !self::isValidKey($api_key)) {
|
182 |
+
return SucuriScanInterface::error('Invalid API key format');
|
183 |
}
|
184 |
|
185 |
if (!empty($api_key)) {
|
208 |
/**
|
209 |
* Call an action from the remote API interface of our WordPress service.
|
210 |
*
|
211 |
+
* @param string $method HTTP method that will be used to send the request.
|
212 |
+
* @param array $params Parameters for the request defined in an associative array of key-value.
|
213 |
+
* @param bool $send_api_key Whether the API key should be added to the request parameters or not.
|
214 |
+
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
215 |
+
* @return array|bool Response object after the HTTP request is executed.
|
216 |
*/
|
217 |
public static function apiCallWordpress($method = 'GET', $params = array(), $send_api_key = true, $args = array())
|
218 |
{
|
233 |
}
|
234 |
|
235 |
/**
|
236 |
+
* Determine whether an API response was successful or not by checking the
|
237 |
+
* expected generic variables and types, in case of an error a notification
|
238 |
+
* will appears in the administrator panel explaining the result of the
|
239 |
+
* operation.
|
240 |
*
|
241 |
* For failures in the HTTP response:
|
242 |
*
|
250 |
* address of the site administrator was changed so the data is not valid
|
251 |
* anymore.
|
252 |
*
|
253 |
+
* @param array $res HTTP response after API endpoint execution.
|
254 |
+
* @return bool False if the API call failed, true otherwise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
*/
|
256 |
public static function handleResponse($res = array())
|
257 |
{
|
274 |
|| !isset($res['messages'])
|
275 |
|| empty($res['messages'])
|
276 |
) {
|
277 |
+
return SucuriScanInterface::error('Unknown error, there is no information');
|
278 |
}
|
279 |
|
280 |
$msg = implode(".\x20", $res['messages']);
|
283 |
// Special response for invalid API keys.
|
284 |
if (stripos($raw, 'log file not found') !== false) {
|
285 |
$key = SucuriScanOption::getOption(':api_key');
|
286 |
+
$msg .= '; this generally happens when you use an invalid API key,'
|
287 |
+
. ' the key will be deleted to hide these warnings, if you want to'
|
288 |
+
. ' recover it go to the settings page and follow the instructions'
|
289 |
+
. ' in the "API Key" section: <code>' . SucuriScan::escape($key)
|
290 |
+
. '</code>';
|
291 |
|
292 |
SucuriScanOption::deleteOption(':api_key');
|
293 |
}
|
296 |
if (stripos($raw, 'wrong api key') !== false) {
|
297 |
$key = SucuriScanOption::getOption(':cloudproxy_apikey');
|
298 |
$key = SucuriScan::escape($key);
|
299 |
+
$msg .= sprintf('; invalid firewall API key: %s', $key);
|
300 |
|
301 |
SucuriScanOption::setRevProxy('disable', true);
|
302 |
SucuriScanOption::setAddrHeader('REMOTE_ADDR', true);
|
310 |
|| stripos($raw, 'error setting certificate')
|
311 |
|| stripos($raw, 'SSL connect error')
|
312 |
) {
|
313 |
+
$msg .= '. The website seems to be using an old version of the Ope'
|
314 |
+
. 'nSSL library or the CURL extension was compiled without support'
|
315 |
+
. ' for the algorithm used in the certificate installed in the API'
|
316 |
+
. ' service. Contact your hosting provider to fix this issue.';
|
317 |
}
|
318 |
|
319 |
// Check if the MX records as missing for API registration.
|
320 |
if (strpos($raw, 'Invalid email') !== false) {
|
321 |
+
$msg = 'Invalid email format or the host is missing MX records.';
|
322 |
}
|
323 |
|
324 |
return SucuriScanInterface::error($msg);
|
327 |
/**
|
328 |
* Send a request to the API to register this site.
|
329 |
*
|
330 |
+
* @param string $email Optional email address for the registration.
|
331 |
+
* @return bool True if the API key was generated, false otherwise.
|
332 |
*/
|
333 |
public static function registerSite($email = '')
|
334 |
{
|
336 |
$email = self::getSiteEmail();
|
337 |
}
|
338 |
|
339 |
+
$res = self::apiCallWordpress(
|
340 |
+
'POST',
|
341 |
+
array(
|
342 |
+
'e' => $email,
|
343 |
+
's' => self::getDomain(),
|
344 |
+
'a' => 'register_site',
|
345 |
+
),
|
346 |
+
false
|
347 |
+
);
|
348 |
|
349 |
+
if (!self::handleResponse($res)) {
|
350 |
+
return false;
|
|
|
351 |
}
|
352 |
|
353 |
+
self::setPluginKey($res['output']['api_key']);
|
354 |
+
|
355 |
+
SucuriScanEvent::installScheduledTask();
|
356 |
+
SucuriScanEvent::notifyEvent('plugin_change', 'API key was generated and set');
|
357 |
+
|
358 |
+
return SucuriScanInterface::info('API key successfully generated and saved.');
|
359 |
}
|
360 |
|
361 |
/**
|
367 |
{
|
368 |
$domain = self::getDomain();
|
369 |
|
370 |
+
$res = self::apiCallWordpress(
|
371 |
+
'GET',
|
372 |
+
array(
|
373 |
+
'e' => self::getSiteEmail(),
|
374 |
+
's' => $domain,
|
375 |
+
'a' => 'recover_key',
|
376 |
+
),
|
377 |
+
false
|
378 |
+
);
|
379 |
|
380 |
+
if (!self::handleResponse($res)) {
|
381 |
+
return false;
|
|
|
382 |
}
|
383 |
|
384 |
+
SucuriScanEvent::notifyEvent('plugin_change', 'API key recovery for domain: ' . $domain);
|
385 |
+
|
386 |
+
return SucuriScanInterface::info($res['output']['message']);
|
387 |
}
|
388 |
|
389 |
/**
|
390 |
* Retrieve the event logs registered by the API service.
|
391 |
*
|
392 |
+
* @param int $lines Maximum number of logs to return.
|
393 |
* @return array|bool The data structure with the logs.
|
394 |
*/
|
395 |
public static function getAuditLogs($lines = 50)
|
396 |
{
|
397 |
+
$res = self::apiCallWordpress(
|
398 |
+
'GET',
|
399 |
+
array(
|
400 |
+
'a' => 'get_logs',
|
401 |
+
'l' => $lines,
|
402 |
+
)
|
403 |
+
);
|
404 |
|
405 |
if (!self::handleResponse($res)) {
|
406 |
return false;
|
418 |
{
|
419 |
$auditlogs = array();
|
420 |
$cache = new SucuriScanCache('auditqueue');
|
421 |
+
$events = $cache->getAll();
|
422 |
|
423 |
+
if (is_array($events) && !empty($events)) {
|
424 |
$events = array_reverse($events);
|
425 |
|
426 |
foreach ($events as $micro => $message) {
|
427 |
+
if (!is_string($message)) {
|
428 |
+
/* incompatible JSON data */
|
429 |
+
continue;
|
430 |
+
}
|
431 |
+
|
432 |
$offset = strpos($micro, '_');
|
433 |
$time = substr($micro, 0, $offset);
|
434 |
$auditlogs[] = sprintf(
|
440 |
}
|
441 |
}
|
442 |
|
443 |
+
$res = array(
|
444 |
'status' => 1,
|
445 |
'action' => 'get_logs',
|
446 |
'request_time' => time(),
|
447 |
'verbose' => 0,
|
448 |
'output' => array_reverse($auditlogs),
|
449 |
'total_entries' => count($auditlogs),
|
450 |
+
);
|
451 |
+
|
452 |
+
return self::parseAuditLogs($res);
|
453 |
}
|
454 |
|
455 |
/**
|
456 |
* Reads, parses and extracts relevant data from the security logs.
|
457 |
*
|
458 |
+
* @param array $res JSON-decoded logs.
|
459 |
+
* @return array Full data extracted from the logs.
|
460 |
*/
|
461 |
private static function parseAuditLogs($res)
|
462 |
{
|
518 |
}
|
519 |
|
520 |
/* extract the IP address */
|
521 |
+
$log_data['message'] = substr($log_data['message'], $offset + 2);
|
522 |
$offset = strpos($log_data['message'], ";\x20");
|
523 |
$log_data['remote_addr'] = substr($log_data['message'], 0, $offset);
|
524 |
|
526 |
if (strpos($log_data['remote_addr'], ",\x20")) {
|
527 |
$index = strpos($log_data['remote_addr'], ",\x20");
|
528 |
$log_data['username'] = substr($log_data['remote_addr'], 0, $index);
|
529 |
+
$log_data['remote_addr'] = substr($log_data['remote_addr'], $index + 2);
|
530 |
}
|
531 |
|
532 |
/* fix old user authentication logs for backward compatibility */
|
533 |
+
$log_data['message'] = substr($log_data['message'], $offset + 2);
|
534 |
$log_data['message'] = str_replace(
|
535 |
'logged in',
|
536 |
'authentication succeeded',
|
540 |
/* extract the username of a successful/failed login */
|
541 |
if (strpos($log_data['message'], "User authentication\x20") === 0) {
|
542 |
$offset = strpos($log_data['message'], ":\x20");
|
543 |
+
$username = substr($log_data['message'], $offset + 2);
|
544 |
if (strpos($username, ';') !== false) {
|
545 |
$username = substr($username, 0, strpos($username, ';'));
|
546 |
}
|
551 |
/* extract more information from the special formatted logs */
|
552 |
if (strpos($log_data['message'], "(multiple entries):\x20")) {
|
553 |
$offset = strpos($log_data['message'], "(multiple entries):\x20");
|
554 |
+
$message = substr($log_data['message'], 0, $offset + 19);
|
555 |
+
$entries = substr($log_data['message'], $offset + 20);
|
556 |
|
557 |
$log_data['message'] = $message;
|
558 |
$entries = str_replace(', new size', '; new size', $entries);
|
572 |
$log_data['file_list_count'] = count($log_data['file_list']);
|
573 |
}
|
574 |
|
575 |
+
$log_data = self::getLogsHotfix($log_data);
|
576 |
+
|
577 |
+
if ($log_data) {
|
578 |
$res['output_data'][] = $log_data;
|
579 |
}
|
580 |
}
|
585 |
/**
|
586 |
* Modifies some of the security logs to detail the information.
|
587 |
*
|
588 |
+
* @param array $data Valid security log data structure.
|
589 |
+
* @return array|bool Modified security log.
|
590 |
*/
|
591 |
private static function getLogsHotfix($data)
|
592 |
{
|
603 |
*/
|
604 |
if (isset($data['message']) && strpos($data['message'], 'Wpephpcompat_jobs') === 0) {
|
605 |
$offset = strpos($data['message'], "ID:\x20");
|
606 |
+
$id = substr($data['message'], $offset + 4);
|
607 |
$id = substr($id, 0, strpos($id, ';'));
|
608 |
|
609 |
$offset = strpos($data['message'], "name:\x20");
|
610 |
+
$name = substr($data['message'], $offset + 6);
|
611 |
|
612 |
$data['message'] = sprintf(
|
613 |
'WP Engine PHP Compatibility Checker: %s (created post #%d as cache)',
|
639 |
/**
|
640 |
* Parse the event logs with multiple entries.
|
641 |
*
|
642 |
+
* @param string $event_log Event log that will be processed.
|
643 |
+
* @return string|array List of parts of the event log.
|
644 |
*/
|
645 |
public static function parseMultipleEntries($event_log = '')
|
646 |
{
|
653 |
return $event_log;
|
654 |
}
|
655 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
656 |
/**
|
657 |
* Send a request to the API to store and analyze the file's hashes of the site.
|
658 |
* This will be the core of the monitoring tools and will enhance the
|
659 |
* information of the audit logs alerting the administrator of suspicious
|
660 |
* changes in the system.
|
661 |
*
|
662 |
+
* @param string $hashes The information gathered after the scanning of the site's files.
|
663 |
+
* @return bool True if the hashes were stored, false otherwise.
|
664 |
*/
|
665 |
public static function sendHashes($hashes = '')
|
666 |
{
|
668 |
return false;
|
669 |
}
|
670 |
|
671 |
+
$params = array('a' => 'send_hashes', 'h' => $hashes);
|
672 |
+
$res = self::apiCallWordpress('POST', $params);
|
|
|
|
|
673 |
|
674 |
return self::handleResponse($res);
|
675 |
}
|
702 |
public static function checksumAPI()
|
703 |
{
|
704 |
$url = 'https://api.wordpress.org/core/checksums/1.0/?version={version}&locale={locale}';
|
705 |
+
$custom = SucuriScanOption::getOption(':checksum_api');
|
706 |
|
707 |
+
if ($custom) {
|
708 |
$url = sprintf(
|
709 |
'https://api.github.com/repos/%s/git/trees/master?recursive=1',
|
710 |
$custom /* expect: username/repository */
|
712 |
}
|
713 |
|
714 |
$url = str_replace('{version}', SucuriScan::siteVersion(), $url);
|
715 |
+
$url = str_replace('{locale}', get_locale(), $url);
|
716 |
|
717 |
return $url;
|
718 |
}
|
750 |
*
|
751 |
* @see https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#_object_storage
|
752 |
*
|
753 |
+
* @param string $algorithm Either md5 or sha1.
|
754 |
+
* @param string $filename Absolute path to the given file.
|
755 |
+
* @return string Hash of the given file.
|
756 |
*/
|
757 |
public static function checksum($algorithm, $filename)
|
758 |
{
|
791 |
*/
|
792 |
public static function getOfficialChecksums()
|
793 |
{
|
|
|
794 |
$url = self::checksumAPI();
|
795 |
$version = SucuriScan::siteVersion();
|
796 |
$res = self::apiCall($url, 'GET', array());
|
808 |
$res = array('checksums' => array($version => $checksums));
|
809 |
}
|
810 |
|
811 |
+
if (!isset($res['checksums'])) {
|
812 |
+
return false;
|
813 |
+
}
|
814 |
+
|
815 |
+
/* checksums for a specific version */
|
816 |
+
if (isset($res['checksums'][$version])) {
|
817 |
+
return $res['checksums'][$version];
|
818 |
}
|
819 |
|
820 |
+
return $res['checksums'];
|
821 |
}
|
822 |
|
823 |
/**
|
863 |
$is_free_plugin = true;
|
864 |
$repository = $plugin_data['PluginURI'];
|
865 |
$offset = strpos($plugin_data['PluginURI'], '/plugins/');
|
866 |
+
$repository_name = substr($plugin_data['PluginURI'], $offset + 9);
|
867 |
|
868 |
if (strpos($repository_name, '/') !== false) {
|
869 |
$offset = strpos($repository_name, '/');
|
912 |
*
|
913 |
* The second filter, 'plugins_api', is the result that would be returned.
|
914 |
*
|
915 |
+
* @param string $plugin Frienly name of the plugin.
|
916 |
+
* @return array|bool Object on success, WP_Error on failure.
|
917 |
*/
|
918 |
public static function getRemotePluginData($plugin = '')
|
919 |
{
|
930 |
* @see https://i18n.svn.wordpress.org/
|
931 |
* @see https://core.svn.wordpress.org/tags/VERSION_NUMBER/
|
932 |
*
|
933 |
+
* @param string $filename Relative path of a core file.
|
934 |
+
* @return string|bool Original code for the core file, false otherwise.
|
935 |
*/
|
936 |
public static function getOriginalCoreFile($filename)
|
937 |
{
|
938 |
$version = self::siteVersion();
|
939 |
$url = 'https://core.svn.wordpress.org/tags/{version}/{filename}';
|
940 |
+
$custom = SucuriScanOption::getOption(':checksum_api');
|
941 |
|
942 |
+
if ($custom) {
|
943 |
$url = sprintf(
|
944 |
'https://raw.githubusercontent.com/%s/master/{filename}',
|
945 |
$custom /* expect: username/repository */
|
src/auditlogs.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the auditlogs.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,6 +24,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
/**
|
20 |
* Lists the logs collected by the API service.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
*/
|
22 |
class SucuriScanAuditLogs
|
23 |
{
|
@@ -55,6 +69,8 @@ class SucuriScanAuditLogs
|
|
55 |
* output it means that XDebug cannot cover the next line, leaving a report
|
56 |
* with a missing line in the coverage. Since the test case takes care of
|
57 |
* the functionality of this code we will assume that it is fully covered.
|
|
|
|
|
58 |
*/
|
59 |
public static function ajaxAuditLogs()
|
60 |
{
|
@@ -92,14 +108,16 @@ class SucuriScanAuditLogs
|
|
92 |
ob_end_clean();
|
93 |
|
94 |
/* report latency in the API calls */
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
|
|
98 |
}
|
99 |
|
100 |
/* explain missing API key */
|
101 |
if (!SucuriScanAPI::getPluginKey()) {
|
102 |
-
$response['status'] =
|
103 |
}
|
104 |
|
105 |
/* stop everything and report errors */
|
@@ -113,13 +131,12 @@ class SucuriScanAuditLogs
|
|
113 |
}
|
114 |
|
115 |
/* merge the logs from the queue system */
|
116 |
-
|
|
|
|
|
117 |
if (!$auditlogs) {
|
118 |
$auditlogs = $queuelogs;
|
119 |
} else {
|
120 |
-
$auditlogs['total_entries'] = isset($auditlogs['total_entries'])
|
121 |
-
? ($auditlogs['total_entries'] + $queuelogs['total_entries'])
|
122 |
-
: $queuelogs['total_entries'];
|
123 |
$auditlogs['output'] = array_merge(
|
124 |
$queuelogs['output'],
|
125 |
@$auditlogs['output']
|
@@ -128,102 +145,114 @@ class SucuriScanAuditLogs
|
|
128 |
$queuelogs['output_data'],
|
129 |
@$auditlogs['output_data']
|
130 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
132 |
}
|
133 |
|
134 |
-
if (is_array($auditlogs)
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
) {
|
140 |
-
$
|
141 |
-
$
|
142 |
-
|
143 |
-
|
144 |
-
$iterator_start = ($pageNumber - 1) * $maxPerPage;
|
145 |
-
$total_items = count($auditlogs['output_data']);
|
146 |
-
|
147 |
-
usort($auditlogs['output_data'], array('SucuriScanAuditLogs', 'sortByDate'));
|
148 |
-
|
149 |
-
for ($i = $iterator_start; $i < $total_items; $i++) {
|
150 |
-
if ($counter_i > $maxPerPage) {
|
151 |
-
break;
|
152 |
-
}
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
157 |
|
158 |
-
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
'AuditLog.Username' => $audit_log['username'],
|
165 |
-
'AuditLog.Address' => $audit_log['remote_addr'],
|
166 |
-
'AuditLog.Message' => $audit_log['message'],
|
167 |
-
'AuditLog.Extra' => '',
|
168 |
-
);
|
169 |
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
} elseif ($snippet_data['AuditLog.Date'] === $todaysDate) {
|
174 |
-
$previousDate = $snippet_data['AuditLog.Date'];
|
175 |
-
$snippet_data['AuditLog.Date'] = __('Today', SUCURISCAN_TEXTDOMAIN);
|
176 |
-
} else {
|
177 |
-
$previousDate = $snippet_data['AuditLog.Date'];
|
178 |
-
}
|
179 |
|
180 |
-
|
181 |
-
if (!empty($snippet_data['AuditLog.Date'])) {
|
182 |
-
$snippet_data['AuditLog.Date'] =
|
183 |
-
'<div class="sucuriscan-auditlog-date">'
|
184 |
-
. $snippet_data['AuditLog.Date']
|
185 |
-
. '</div>';
|
186 |
-
}
|
187 |
|
188 |
-
|
189 |
-
|
190 |
-
|
|
|
191 |
|
192 |
-
|
193 |
-
|
194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
|
196 |
-
|
197 |
-
|
|
|
|
|
|
|
198 |
|
199 |
-
|
200 |
-
|
201 |
-
|
|
|
|
|
|
|
202 |
}
|
203 |
|
204 |
-
$
|
205 |
-
$counter_i += 1;
|
206 |
}
|
207 |
|
208 |
-
|
|
|
|
|
|
|
209 |
|
210 |
-
|
211 |
-
|
|
|
212 |
|
213 |
-
|
214 |
-
$maxpages = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
215 |
-
}
|
216 |
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
}
|
225 |
-
} else {
|
226 |
-
$response['content'] = __('NoLogs', SUCURISCAN_TEXTDOMAIN);
|
227 |
}
|
228 |
|
229 |
$cache = new SucuriScanCache('auditqueue');
|
@@ -242,6 +271,8 @@ class SucuriScanAuditLogs
|
|
242 |
* output it means that XDebug cannot cover the next line, leaving a report
|
243 |
* with a missing line in the coverage. Since the test case takes care of
|
244 |
* the functionality of this code we will assume that it is fully covered.
|
|
|
|
|
245 |
*/
|
246 |
public static function ajaxAuditLogsSendLogs()
|
247 |
{
|
@@ -261,9 +292,9 @@ class SucuriScanAuditLogs
|
|
261 |
* queue is emptied, we will have to sort the entries in the list to keep
|
262 |
* the dates in sync.
|
263 |
*
|
264 |
-
* @param
|
265 |
-
* @param
|
266 |
-
* @return int
|
267 |
*/
|
268 |
public static function sortByDate($a, $b)
|
269 |
{
|
3 |
/**
|
4 |
* Code related to the auditlogs.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
/**
|
26 |
* Lists the logs collected by the API service.
|
27 |
+
*
|
28 |
+
* @category Library
|
29 |
+
* @package Sucuri
|
30 |
+
* @subpackage SucuriScanner
|
31 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
32 |
+
* @copyright 2010-2017 Sucuri Inc.
|
33 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
34 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
35 |
*/
|
36 |
class SucuriScanAuditLogs
|
37 |
{
|
69 |
* output it means that XDebug cannot cover the next line, leaving a report
|
70 |
* with a missing line in the coverage. Since the test case takes care of
|
71 |
* the functionality of this code we will assume that it is fully covered.
|
72 |
+
*
|
73 |
+
* @return void
|
74 |
*/
|
75 |
public static function ajaxAuditLogs()
|
76 |
{
|
108 |
ob_end_clean();
|
109 |
|
110 |
/* report latency in the API calls */
|
111 |
+
if (!is_array($auditlogs)) {
|
112 |
+
$response['status'] = 'API is not available; using local queue';
|
113 |
+
} else {
|
114 |
+
$response['status'] = sprintf('API %s secs', round($duration, 4));
|
115 |
+
}
|
116 |
}
|
117 |
|
118 |
/* explain missing API key */
|
119 |
if (!SucuriScanAPI::getPluginKey()) {
|
120 |
+
$response['status'] = 'API key is missing';
|
121 |
}
|
122 |
|
123 |
/* stop everything and report errors */
|
131 |
}
|
132 |
|
133 |
/* merge the logs from the queue system */
|
134 |
+
$queuelogs = SucuriScanAPI::getAuditLogsFromQueue();
|
135 |
+
|
136 |
+
if (is_array($queuelogs) && !empty($queuelogs)) {
|
137 |
if (!$auditlogs) {
|
138 |
$auditlogs = $queuelogs;
|
139 |
} else {
|
|
|
|
|
|
|
140 |
$auditlogs['output'] = array_merge(
|
141 |
$queuelogs['output'],
|
142 |
@$auditlogs['output']
|
145 |
$queuelogs['output_data'],
|
146 |
@$auditlogs['output_data']
|
147 |
);
|
148 |
+
|
149 |
+
if (isset($auditlogs['total_entries'])) {
|
150 |
+
$auditlogs['total_entries'] = $auditlogs['total_entries'] + $queuelogs['total_entries'];
|
151 |
+
} else {
|
152 |
+
$auditlogs['total_entries'] = $queuelogs['total_entries'];
|
153 |
+
}
|
154 |
}
|
155 |
}
|
156 |
|
157 |
+
if (!is_array($auditlogs)
|
158 |
+
|| !isset($auditlogs['output_data'])
|
159 |
+
|| !isset($auditlogs['total_entries'])
|
160 |
+
|| !is_array($auditlogs['output_data'])
|
161 |
+
|| !is_numeric($auditlogs['total_entries'])
|
162 |
) {
|
163 |
+
$response['content'] = 'There are no logs.';
|
164 |
+
wp_send_json($response, 200);
|
165 |
+
return;
|
166 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
|
168 |
+
$counter_i = 0;
|
169 |
+
$previousDate = '';
|
170 |
+
$outdata = (array) $auditlogs['output_data'];
|
171 |
+
$todaysDate = SucuriScan::datetime(null, 'M d, Y');
|
172 |
+
$iterator_start = ($pageNumber - 1) * $maxPerPage;
|
173 |
+
$show_password = SucuriScanOption::isEnabled(':notify_failed_password');
|
174 |
+
$total_items = count($outdata);
|
175 |
|
176 |
+
usort($outdata, array('SucuriScanAuditLogs', 'sortByDate'));
|
177 |
|
178 |
+
for ($i = $iterator_start; $i < $total_items; $i++) {
|
179 |
+
if ($counter_i > $maxPerPage) {
|
180 |
+
break;
|
181 |
+
}
|
|
|
|
|
|
|
|
|
|
|
182 |
|
183 |
+
if (!isset($outdata[$i])) {
|
184 |
+
continue;
|
185 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
|
187 |
+
$audit_log = (array) $outdata[$i];
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
|
189 |
+
if (!$show_password && strpos($audit_log['message'], ";\x20password:")) {
|
190 |
+
$idx = strpos($audit_log['message'], ";\x20password:");
|
191 |
+
$audit_log['message'] = substr($audit_log['message'], 0, $idx);
|
192 |
+
}
|
193 |
|
194 |
+
$snippet_data = array(
|
195 |
+
'AuditLog.Event' => $audit_log['event'],
|
196 |
+
'AuditLog.Time' => SucuriScan::datetime($audit_log['timestamp'], 'H:i'),
|
197 |
+
'AuditLog.Date' => SucuriScan::datetime($audit_log['timestamp'], 'M d, Y'),
|
198 |
+
'AuditLog.Username' => $audit_log['username'],
|
199 |
+
'AuditLog.Address' => $audit_log['remote_addr'],
|
200 |
+
'AuditLog.Message' => $audit_log['message'],
|
201 |
+
'AuditLog.Extra' => '',
|
202 |
+
);
|
203 |
+
|
204 |
+
/* determine if we need to print the date */
|
205 |
+
if ($snippet_data['AuditLog.Date'] === $previousDate) {
|
206 |
+
$snippet_data['AuditLog.Date'] = '';
|
207 |
+
} elseif ($snippet_data['AuditLog.Date'] === $todaysDate) {
|
208 |
+
$previousDate = $snippet_data['AuditLog.Date'];
|
209 |
+
$snippet_data['AuditLog.Date'] = 'Today';
|
210 |
+
} else {
|
211 |
+
$previousDate = $snippet_data['AuditLog.Date'];
|
212 |
+
}
|
213 |
|
214 |
+
/* decorate date if necessary */
|
215 |
+
if (!empty($snippet_data['AuditLog.Date'])) {
|
216 |
+
$snippet_data['AuditLog.Date'] = '<div class="sucuriscan-aud'
|
217 |
+
. 'itlog-date">' . $snippet_data['AuditLog.Date'] . '</div>';
|
218 |
+
}
|
219 |
|
220 |
+
/* print every file_list information item in a separate table */
|
221 |
+
if ($audit_log['file_list']) {
|
222 |
+
$snippet_data['AuditLog.Extra'] .= '<ul class="sucuriscan-list-as-table">';
|
223 |
+
|
224 |
+
foreach ($audit_log['file_list'] as $log_extra) {
|
225 |
+
$snippet_data['AuditLog.Extra'] .= '<li>' . SucuriScan::escape($log_extra) . '</li>';
|
226 |
}
|
227 |
|
228 |
+
$snippet_data['AuditLog.Extra'] .= '</ul>';
|
|
|
229 |
}
|
230 |
|
231 |
+
/* simplify the details of events with low metadata */
|
232 |
+
if (strpos($audit_log['message'], 'status has been changed')) {
|
233 |
+
$snippet_data['AuditLog.Extra'] = implode(",\x20", $audit_log['file_list']);
|
234 |
+
}
|
235 |
|
236 |
+
$response['content'] .= SucuriScanTemplate::getSnippet('auditlogs', $snippet_data);
|
237 |
+
$counter_i += 1;
|
238 |
+
}
|
239 |
|
240 |
+
$response['count'] = $counter_i;
|
|
|
|
|
241 |
|
242 |
+
if ($total_items > 1) {
|
243 |
+
$maxpages = ceil($auditlogs['total_entries'] / $maxPerPage);
|
244 |
+
|
245 |
+
if ($maxpages > SUCURISCAN_MAX_PAGINATION_BUTTONS) {
|
246 |
+
$maxpages = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
247 |
+
}
|
248 |
+
|
249 |
+
if ($maxpages > 1) {
|
250 |
+
$response['pagination'] = SucuriScanTemplate::pagination(
|
251 |
+
SucuriScanTemplate::getUrl(),
|
252 |
+
($maxPerPage * $maxpages),
|
253 |
+
$maxPerPage
|
254 |
+
);
|
255 |
}
|
|
|
|
|
256 |
}
|
257 |
|
258 |
$cache = new SucuriScanCache('auditqueue');
|
271 |
* output it means that XDebug cannot cover the next line, leaving a report
|
272 |
* with a missing line in the coverage. Since the test case takes care of
|
273 |
* the functionality of this code we will assume that it is fully covered.
|
274 |
+
*
|
275 |
+
* @return void
|
276 |
*/
|
277 |
public static function ajaxAuditLogsSendLogs()
|
278 |
{
|
292 |
* queue is emptied, we will have to sort the entries in the list to keep
|
293 |
* the dates in sync.
|
294 |
*
|
295 |
+
* @param array $a Data associated to a single log.
|
296 |
+
* @param array $b Data associated to another log.
|
297 |
+
* @return int Comparison between the dates of both logs.
|
298 |
*/
|
299 |
public static function sortByDate($a, $b)
|
300 |
{
|
src/cache.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the cache.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -28,6 +34,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
28 |
*
|
29 |
* [1] https://codex.wordpress.org/Class_Reference/WP_Object_Cache
|
30 |
* [2] https://codex.wordpress.org/Class_Reference/WP_Object_Cache#Persistent_Caching
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
*/
|
32 |
class SucuriScanCache extends SucuriScan
|
33 |
{
|
@@ -42,16 +56,16 @@ class SucuriScanCache extends SucuriScan
|
|
42 |
*
|
43 |
* [1] /public/data/sucuri-DATASTORE.php
|
44 |
*
|
45 |
-
* @var
|
46 |
*/
|
47 |
-
private $datastore
|
48 |
|
49 |
/**
|
50 |
* The full path of the datastore file.
|
51 |
*
|
52 |
* @var string
|
53 |
*/
|
54 |
-
private $datastore_path
|
55 |
|
56 |
/**
|
57 |
* Whether the datastore file is usable or not.
|
@@ -59,15 +73,15 @@ class SucuriScanCache extends SucuriScan
|
|
59 |
* This variable will only be TRUE if the datastore file specified exists, is
|
60 |
* writable and readable, in any other case it will always be FALSE.
|
61 |
*
|
62 |
-
* @var
|
63 |
*/
|
64 |
-
private $usable_datastore
|
65 |
|
66 |
/**
|
67 |
* Initializes the cache library.
|
68 |
*
|
69 |
-
* @param string $datastore
|
70 |
-
* @param bool
|
71 |
*/
|
72 |
public function __construct($datastore = '', $auto_create = true)
|
73 |
{
|
@@ -95,8 +109,8 @@ class SucuriScanCache extends SucuriScan
|
|
95 |
/**
|
96 |
* Default content of every datastore file.
|
97 |
*
|
98 |
-
* @param
|
99 |
-
* @return string
|
100 |
*/
|
101 |
private function datastoreInfo($finfo = array())
|
102 |
{
|
@@ -126,8 +140,8 @@ class SucuriScanCache extends SucuriScan
|
|
126 |
* user running the server, in case that it does not exists the method will
|
127 |
* tries to create it by itself with the right permissions to use it.
|
128 |
*
|
129 |
-
* @param
|
130 |
-
* @return string|bool
|
131 |
*/
|
132 |
private function datastoreFilePath($auto_create = false)
|
133 |
{
|
@@ -156,8 +170,8 @@ class SucuriScanCache extends SucuriScan
|
|
156 |
* key we will use a primitive string transformation technique to reduce the
|
157 |
* execution time, regular expressions are significantly slow.
|
158 |
*
|
159 |
-
* @param
|
160 |
-
* @return bool
|
161 |
*/
|
162 |
private function validKeyName($key = '')
|
163 |
{
|
@@ -187,8 +201,8 @@ class SucuriScanCache extends SucuriScan
|
|
187 |
/**
|
188 |
* Update the content of the datastore file with the new entries.
|
189 |
*
|
190 |
-
* @param
|
191 |
-
* @return bool
|
192 |
*/
|
193 |
private function saveNewEntries($finfo = array())
|
194 |
{
|
@@ -213,23 +227,24 @@ class SucuriScanCache extends SucuriScan
|
|
213 |
* and decoded data as the values of each entry. Duplicated key names will
|
214 |
* be merged automatically.
|
215 |
*
|
216 |
-
* @param
|
217 |
-
* @param
|
218 |
-
* @return array
|
219 |
*/
|
220 |
private function getDatastoreContent($assoc = false, $onlyInfo = false)
|
221 |
{
|
222 |
$object = array();
|
223 |
$object['info'] = array();
|
224 |
$object['entries'] = array();
|
|
|
225 |
|
226 |
-
if ($lines
|
227 |
foreach ($lines as $line) {
|
228 |
if (strpos($line, "//\x20") === 0
|
229 |
&& strpos($line, '=') !== false
|
230 |
-
&& $line[strlen($line)-1] === ';'
|
231 |
) {
|
232 |
-
$section = substr($line, 3, strlen($line)-4);
|
233 |
list($header, $value) = explode('=', $section, 2);
|
234 |
$object['info'][$header] = $value;
|
235 |
continue;
|
@@ -278,8 +293,8 @@ class SucuriScanCache extends SucuriScan
|
|
278 |
/**
|
279 |
* Get the total number of unique entries in the datastore file.
|
280 |
*
|
281 |
-
* @param
|
282 |
-
* @return int
|
283 |
*/
|
284 |
public function getCount($finfo = null)
|
285 |
{
|
@@ -296,13 +311,13 @@ class SucuriScanCache extends SucuriScan
|
|
296 |
* the caching process, any others besides this are just methods used to handle
|
297 |
* the data inside those files.
|
298 |
*
|
299 |
-
* @param
|
300 |
-
* @param
|
301 |
-
* @return bool
|
302 |
*/
|
303 |
public function dataHasExpired($lifetime = 0, $finfo = null)
|
304 |
{
|
305 |
-
if (
|
306 |
$meta = $this->getDatastoreInfo();
|
307 |
$finfo = array('info' => $meta);
|
308 |
}
|
@@ -324,9 +339,9 @@ class SucuriScanCache extends SucuriScan
|
|
324 |
* duplicated, but when getting the value of the same key later again it will
|
325 |
* return only the value of the first occurrence found in the file.
|
326 |
*
|
327 |
-
* @param
|
328 |
-
* @param
|
329 |
-
* @return bool
|
330 |
*/
|
331 |
public function add($key = '', $data = '')
|
332 |
{
|
@@ -336,9 +351,9 @@ class SucuriScanCache extends SucuriScan
|
|
336 |
/**
|
337 |
* Update the data of all the key names matching the one specified.
|
338 |
*
|
339 |
-
* @param
|
340 |
-
* @param
|
341 |
-
* @return bool
|
342 |
*/
|
343 |
public function set($key = '', $data = '')
|
344 |
{
|
@@ -355,10 +370,10 @@ class SucuriScanCache extends SucuriScan
|
|
355 |
/**
|
356 |
* Retrieve the first occurrence of the key found in the datastore file.
|
357 |
*
|
358 |
-
* @param
|
359 |
-
* @param
|
360 |
-
* @param
|
361 |
-
* @return mixed
|
362 |
*/
|
363 |
public function get($key = '', $lifetime = 0, $assoc = '')
|
364 |
{
|
@@ -380,9 +395,9 @@ class SucuriScanCache extends SucuriScan
|
|
380 |
/**
|
381 |
* Retrieve all the entries found in the datastore file.
|
382 |
*
|
383 |
-
* @param
|
384 |
-
* @param
|
385 |
-
* @return mixed
|
386 |
*/
|
387 |
public function getAll($lifetime = 0, $assoc = '')
|
388 |
{
|
@@ -398,8 +413,8 @@ class SucuriScanCache extends SucuriScan
|
|
398 |
/**
|
399 |
* Check whether a specific key exists in the datastore file.
|
400 |
*
|
401 |
-
* @param
|
402 |
-
* @return bool
|
403 |
*/
|
404 |
public function exists($key = '')
|
405 |
{
|
@@ -415,8 +430,8 @@ class SucuriScanCache extends SucuriScan
|
|
415 |
/**
|
416 |
* Delete any entry from the datastore file matching the key name specified.
|
417 |
*
|
418 |
-
* @param
|
419 |
-
* @return bool
|
420 |
*/
|
421 |
public function delete($key = '')
|
422 |
{
|
@@ -438,15 +453,17 @@ class SucuriScanCache extends SucuriScan
|
|
438 |
/**
|
439 |
* Replaces the entire content of the cache file.
|
440 |
*
|
441 |
-
* @param
|
442 |
-
* @return bool
|
443 |
*/
|
444 |
public function override($entries = array())
|
445 |
{
|
446 |
-
return $this->saveNewEntries(
|
447 |
-
|
448 |
-
|
449 |
-
|
|
|
|
|
450 |
}
|
451 |
|
452 |
/**
|
3 |
/**
|
4 |
* Code related to the cache.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
34 |
*
|
35 |
* [1] https://codex.wordpress.org/Class_Reference/WP_Object_Cache
|
36 |
* [2] https://codex.wordpress.org/Class_Reference/WP_Object_Cache#Persistent_Caching
|
37 |
+
*
|
38 |
+
* @category Library
|
39 |
+
* @package Sucuri
|
40 |
+
* @subpackage SucuriScanner
|
41 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
42 |
+
* @copyright 2010-2017 Sucuri Inc.
|
43 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
44 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
45 |
*/
|
46 |
class SucuriScanCache extends SucuriScan
|
47 |
{
|
56 |
*
|
57 |
* [1] /public/data/sucuri-DATASTORE.php
|
58 |
*
|
59 |
+
* @var string
|
60 |
*/
|
61 |
+
private $datastore;
|
62 |
|
63 |
/**
|
64 |
* The full path of the datastore file.
|
65 |
*
|
66 |
* @var string
|
67 |
*/
|
68 |
+
private $datastore_path;
|
69 |
|
70 |
/**
|
71 |
* Whether the datastore file is usable or not.
|
73 |
* This variable will only be TRUE if the datastore file specified exists, is
|
74 |
* writable and readable, in any other case it will always be FALSE.
|
75 |
*
|
76 |
+
* @var bool
|
77 |
*/
|
78 |
+
private $usable_datastore;
|
79 |
|
80 |
/**
|
81 |
* Initializes the cache library.
|
82 |
*
|
83 |
+
* @param string $datastore Name of the storage file.
|
84 |
+
* @param bool $auto_create Forces the creation of the storage file.
|
85 |
*/
|
86 |
public function __construct($datastore = '', $auto_create = true)
|
87 |
{
|
109 |
/**
|
110 |
* Default content of every datastore file.
|
111 |
*
|
112 |
+
* @param array $finfo Rainbow table with the key names and decoded values.
|
113 |
+
* @return string Default content of every datastore file.
|
114 |
*/
|
115 |
private function datastoreInfo($finfo = array())
|
116 |
{
|
140 |
* user running the server, in case that it does not exists the method will
|
141 |
* tries to create it by itself with the right permissions to use it.
|
142 |
*
|
143 |
+
* @param bool $auto_create Create the file is it does not exists.
|
144 |
+
* @return string|bool Absolute path to the storage file, false otherwise.
|
145 |
*/
|
146 |
private function datastoreFilePath($auto_create = false)
|
147 |
{
|
170 |
* key we will use a primitive string transformation technique to reduce the
|
171 |
* execution time, regular expressions are significantly slow.
|
172 |
*
|
173 |
+
* @param string $key Unique name for the data.
|
174 |
+
* @return bool True if the key is valid, false otherwise.
|
175 |
*/
|
176 |
private function validKeyName($key = '')
|
177 |
{
|
201 |
/**
|
202 |
* Update the content of the datastore file with the new entries.
|
203 |
*
|
204 |
+
* @param array $finfo Rainbow table with the key names and decoded values.
|
205 |
+
* @return bool TRUE if the operation finished successfully, FALSE otherwise.
|
206 |
*/
|
207 |
private function saveNewEntries($finfo = array())
|
208 |
{
|
227 |
* and decoded data as the values of each entry. Duplicated key names will
|
228 |
* be merged automatically.
|
229 |
*
|
230 |
+
* @param bool $assoc Force object to array conversion.
|
231 |
+
* @param bool $onlyInfo Returns the cache headers and no content.
|
232 |
+
* @return array Rainbow table with the key names and decoded values.
|
233 |
*/
|
234 |
private function getDatastoreContent($assoc = false, $onlyInfo = false)
|
235 |
{
|
236 |
$object = array();
|
237 |
$object['info'] = array();
|
238 |
$object['entries'] = array();
|
239 |
+
$lines = SucuriScanFileInfo::fileLines($this->datastore_path);
|
240 |
|
241 |
+
if (is_array($lines) && !empty($lines)) {
|
242 |
foreach ($lines as $line) {
|
243 |
if (strpos($line, "//\x20") === 0
|
244 |
&& strpos($line, '=') !== false
|
245 |
+
&& $line[strlen($line) - 1] === ';'
|
246 |
) {
|
247 |
+
$section = substr($line, 3, strlen($line) - 4);
|
248 |
list($header, $value) = explode('=', $section, 2);
|
249 |
$object['info'][$header] = $value;
|
250 |
continue;
|
293 |
/**
|
294 |
* Get the total number of unique entries in the datastore file.
|
295 |
*
|
296 |
+
* @param array $finfo Rainbow table with the key names and decoded values.
|
297 |
+
* @return int Total number of unique entries found in the datastore file.
|
298 |
*/
|
299 |
public function getCount($finfo = null)
|
300 |
{
|
311 |
* the caching process, any others besides this are just methods used to handle
|
312 |
* the data inside those files.
|
313 |
*
|
314 |
+
* @param int $lifetime Life time of the key in the datastore file.
|
315 |
+
* @param array $finfo Rainbow table with the key names and decoded values.
|
316 |
+
* @return bool TRUE if the life time of the data has expired, FALSE otherwise.
|
317 |
*/
|
318 |
public function dataHasExpired($lifetime = 0, $finfo = null)
|
319 |
{
|
320 |
+
if (!is_array($finfo)) {
|
321 |
$meta = $this->getDatastoreInfo();
|
322 |
$finfo = array('info' => $meta);
|
323 |
}
|
339 |
* duplicated, but when getting the value of the same key later again it will
|
340 |
* return only the value of the first occurrence found in the file.
|
341 |
*
|
342 |
+
* @param string $key Unique name for the data.
|
343 |
+
* @param mixed $data Data to associate to the key.
|
344 |
+
* @return bool True if the data was cached, false otherwise.
|
345 |
*/
|
346 |
public function add($key = '', $data = '')
|
347 |
{
|
351 |
/**
|
352 |
* Update the data of all the key names matching the one specified.
|
353 |
*
|
354 |
+
* @param string $key Unique name for the data.
|
355 |
+
* @param mixed $data Data to associate to the key.
|
356 |
+
* @return bool True if the cache data was updated, false otherwise.
|
357 |
*/
|
358 |
public function set($key = '', $data = '')
|
359 |
{
|
370 |
/**
|
371 |
* Retrieve the first occurrence of the key found in the datastore file.
|
372 |
*
|
373 |
+
* @param string $key Unique name for the data.
|
374 |
+
* @param int $lifetime Seconds before the data expires.
|
375 |
+
* @param string $assoc Force data to be converted to an array.
|
376 |
+
* @return mixed Data associated to the key.
|
377 |
*/
|
378 |
public function get($key = '', $lifetime = 0, $assoc = '')
|
379 |
{
|
395 |
/**
|
396 |
* Retrieve all the entries found in the datastore file.
|
397 |
*
|
398 |
+
* @param int $lifetime Life time of the key in the datastore file.
|
399 |
+
* @param string $assoc Force data to be converted to an array.
|
400 |
+
* @return mixed All the entries stored in the cache file.
|
401 |
*/
|
402 |
public function getAll($lifetime = 0, $assoc = '')
|
403 |
{
|
413 |
/**
|
414 |
* Check whether a specific key exists in the datastore file.
|
415 |
*
|
416 |
+
* @param string $key Unique name for the data.
|
417 |
+
* @return bool True if the data exists, false otherwise.
|
418 |
*/
|
419 |
public function exists($key = '')
|
420 |
{
|
430 |
/**
|
431 |
* Delete any entry from the datastore file matching the key name specified.
|
432 |
*
|
433 |
+
* @param string $key Unique name for the data.
|
434 |
+
* @return bool True if the data was deleted, false otherwise.
|
435 |
*/
|
436 |
public function delete($key = '')
|
437 |
{
|
453 |
/**
|
454 |
* Replaces the entire content of the cache file.
|
455 |
*
|
456 |
+
* @param array $entries New data for the cache.
|
457 |
+
* @return bool True if the cache was replaced.
|
458 |
*/
|
459 |
public function override($entries = array())
|
460 |
{
|
461 |
+
return $this->saveNewEntries(
|
462 |
+
array(
|
463 |
+
'info' => $this->getDatastoreInfo(),
|
464 |
+
'entries' => $entries,
|
465 |
+
)
|
466 |
+
);
|
467 |
}
|
468 |
|
469 |
/**
|
src/command.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the command.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -23,6 +29,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
23 |
* and folders using the built-in PHP class SplFileInfo. The SplFileInfo class
|
24 |
* offers a high-level object oriented interface to information for an individual
|
25 |
* file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
*/
|
27 |
class SucuriScanCommand extends SucuriScan
|
28 |
{
|
@@ -44,8 +58,8 @@ class SucuriScanCommand extends SucuriScan
|
|
44 |
/**
|
45 |
* Checks if an external command exists or not.
|
46 |
*
|
47 |
-
* @param
|
48 |
-
* @return bool
|
49 |
*/
|
50 |
public static function exists($cmd)
|
51 |
{
|
@@ -67,20 +81,24 @@ class SucuriScanCommand extends SucuriScan
|
|
67 |
/**
|
68 |
* Compares two files line by line.
|
69 |
*
|
70 |
-
* @param
|
71 |
-
* @param
|
72 |
-
* @return array
|
73 |
*/
|
74 |
public static function diff($a, $b)
|
75 |
{
|
76 |
-
$out = array();
|
77 |
|
78 |
if (self::exists('diff')) {
|
79 |
-
@exec(
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
|
|
84 |
}
|
85 |
|
86 |
return $out;
|
@@ -99,26 +117,27 @@ class SucuriScanCommand extends SucuriScan
|
|
99 |
* them in the dashboard. Some basic CSS classes will be attached to some of
|
100 |
* the elements in the code to facilitate the styling of the diff report.
|
101 |
*
|
102 |
-
* @param
|
103 |
-
* @return string|bool
|
104 |
*/
|
105 |
public static function diffHTML($filepath)
|
106 |
{
|
107 |
$checksums = SucuriScanAPI::getOfficialChecksums();
|
108 |
|
109 |
if (!$checksums) {
|
110 |
-
return SucuriScanInterface::error(
|
111 |
}
|
112 |
|
113 |
if (!array_key_exists($filepath, $checksums)) {
|
114 |
-
return SucuriScanInterface::error(
|
115 |
}
|
116 |
|
117 |
$output = ''; /* initialize empty with no differences */
|
118 |
$a = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-');
|
119 |
$b = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-');
|
|
|
120 |
|
121 |
-
if ($handle
|
122 |
@fwrite($handle, SucuriScanAPI::getOriginalCoreFile($filepath));
|
123 |
@copy(ABSPATH . '/' . $filepath, $b);
|
124 |
$output = self::diff($a, $b);
|
@@ -129,7 +148,7 @@ class SucuriScanCommand extends SucuriScan
|
|
129 |
@unlink($b); /* delete modified file */
|
130 |
|
131 |
if (!is_array($output) || empty($output)) {
|
132 |
-
return SucuriScanInterface::error(
|
133 |
}
|
134 |
|
135 |
$response = "<ul class='" . SUCURISCAN . "-diff-content'>\n";
|
3 |
/**
|
4 |
* Code related to the command.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
29 |
* and folders using the built-in PHP class SplFileInfo. The SplFileInfo class
|
30 |
* offers a high-level object oriented interface to information for an individual
|
31 |
* file.
|
32 |
+
*
|
33 |
+
* @category Library
|
34 |
+
* @package Sucuri
|
35 |
+
* @subpackage SucuriScanner
|
36 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
37 |
+
* @copyright 2010-2017 Sucuri Inc.
|
38 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
39 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
40 |
*/
|
41 |
class SucuriScanCommand extends SucuriScan
|
42 |
{
|
58 |
/**
|
59 |
* Checks if an external command exists or not.
|
60 |
*
|
61 |
+
* @param string $cmd Name of the external command.
|
62 |
+
* @return bool True if the command exists, false otherwise.
|
63 |
*/
|
64 |
public static function exists($cmd)
|
65 |
{
|
81 |
/**
|
82 |
* Compares two files line by line.
|
83 |
*
|
84 |
+
* @param string $a File path of the original file.
|
85 |
+
* @param string $b File path of the modified file.
|
86 |
+
* @return array Line-by-line changes (if any).
|
87 |
*/
|
88 |
public static function diff($a, $b)
|
89 |
{
|
90 |
+
$out = array();
|
91 |
|
92 |
if (self::exists('diff')) {
|
93 |
+
@exec(
|
94 |
+
sprintf(
|
95 |
+
'diff -u -- %s %s 2> /dev/null',
|
96 |
+
escapeshellarg($a),
|
97 |
+
escapeshellarg($b)
|
98 |
+
),
|
99 |
+
$out,
|
100 |
+
$err
|
101 |
+
);
|
102 |
}
|
103 |
|
104 |
return $out;
|
117 |
* them in the dashboard. Some basic CSS classes will be attached to some of
|
118 |
* the elements in the code to facilitate the styling of the diff report.
|
119 |
*
|
120 |
+
* @param string $filepath Relative path to the core WordPress file.
|
121 |
+
* @return string|bool HTML code with the diff report, false on failure.
|
122 |
*/
|
123 |
public static function diffHTML($filepath)
|
124 |
{
|
125 |
$checksums = SucuriScanAPI::getOfficialChecksums();
|
126 |
|
127 |
if (!$checksums) {
|
128 |
+
return SucuriScanInterface::error('Unsupported WordPress version.');
|
129 |
}
|
130 |
|
131 |
if (!array_key_exists($filepath, $checksums)) {
|
132 |
+
return SucuriScanInterface::error('Not an official WordPress file.');
|
133 |
}
|
134 |
|
135 |
$output = ''; /* initialize empty with no differences */
|
136 |
$a = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-');
|
137 |
$b = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-');
|
138 |
+
$handle = @fopen($a, 'w');
|
139 |
|
140 |
+
if ($handle) {
|
141 |
@fwrite($handle, SucuriScanAPI::getOriginalCoreFile($filepath));
|
142 |
@copy(ABSPATH . '/' . $filepath, $b);
|
143 |
$output = self::diff($a, $b);
|
148 |
@unlink($b); /* delete modified file */
|
149 |
|
150 |
if (!is_array($output) || empty($output)) {
|
151 |
+
return SucuriScanInterface::error('There are no differences.');
|
152 |
}
|
153 |
|
154 |
$response = "<ul class='" . SUCURISCAN . "-diff-content'>\n";
|
src/event.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the event.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -29,7 +35,13 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
29 |
* response to events is said to be event-driven, often with the goal of being
|
30 |
* interactive.
|
31 |
*
|
32 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
*/
|
34 |
class SucuriScanEvent extends SucuriScan
|
35 |
{
|
@@ -43,6 +55,8 @@ class SucuriScanEvent extends SucuriScan
|
|
43 |
* list with the checksum of the new file list, if there are differences we
|
44 |
* will assume that someone or something modified one or more files and send
|
45 |
* an email alsert about the incident.
|
|
|
|
|
46 |
*/
|
47 |
public static function installScheduledTask()
|
48 |
{
|
@@ -72,13 +86,13 @@ class SucuriScanEvent extends SucuriScan
|
|
72 |
|
73 |
foreach ($jobs as $unique => $info) {
|
74 |
$schedules[$unique] = sprintf(
|
75 |
-
|
76 |
$info['display'],
|
77 |
$info['interval']
|
78 |
);
|
79 |
}
|
80 |
|
81 |
-
$schedules['_oneoff'] =
|
82 |
|
83 |
return $schedules;
|
84 |
}
|
@@ -110,8 +124,8 @@ class SucuriScanEvent extends SucuriScan
|
|
110 |
/**
|
111 |
* Decides if the file system scanner can run or not.
|
112 |
*
|
113 |
-
* @param
|
114 |
-
* @return bool
|
115 |
*/
|
116 |
private static function runFileScanner($force_scan = false)
|
117 |
{
|
@@ -135,8 +149,8 @@ class SucuriScanEvent extends SucuriScan
|
|
135 |
* analyze them using the Sucuri Monitoring service, this will generate the
|
136 |
* audit logs for this site and be part of the integrity checks.
|
137 |
*
|
138 |
-
* @param
|
139 |
-
* @return bool
|
140 |
*/
|
141 |
public static function filesystemScan($force_scan = false)
|
142 |
{
|
@@ -169,10 +183,10 @@ class SucuriScanEvent extends SucuriScan
|
|
169 |
* in a failure. However, this procedure depends on the ability of the plugin
|
170 |
* to write the log into the queue when the previous request failed.
|
171 |
*
|
172 |
-
* @param
|
173 |
-
* @param
|
174 |
-
* @param
|
175 |
-
* @return bool
|
176 |
*/
|
177 |
private static function sendLogToAPI($message = '', $timestamp = '', $timeout = 1)
|
178 |
{
|
@@ -202,8 +216,8 @@ class SucuriScanEvent extends SucuriScan
|
|
202 |
* but it could be private and be mocked by the test bootstrap script. Take
|
203 |
* this in consideration during the static analysis of the code.
|
204 |
*
|
205 |
-
* @param
|
206 |
-
* @return bool
|
207 |
*/
|
208 |
public static function sendLogToQueue($message = '')
|
209 |
{
|
@@ -335,9 +349,9 @@ class SucuriScanEvent extends SucuriScan
|
|
335 |
/**
|
336 |
* Generates an audit event log (to be sent later).
|
337 |
*
|
338 |
-
* @param
|
339 |
-
* @param
|
340 |
-
* @return bool
|
341 |
*/
|
342 |
private static function reportEvent($severity = 0, $message = '')
|
343 |
{
|
@@ -354,7 +368,7 @@ class SucuriScanEvent extends SucuriScan
|
|
354 |
}
|
355 |
|
356 |
$severity = intval($severity);
|
357 |
-
$severity_name = 'Info';
|
358 |
$severities = array(
|
359 |
/* 0 */ 'Debug',
|
360 |
/* 1 */ 'Notice',
|
@@ -374,20 +388,22 @@ class SucuriScanEvent extends SucuriScan
|
|
374 |
$message = str_replace("\n", '', $message);
|
375 |
$message = str_replace("\t", '', $message);
|
376 |
|
377 |
-
return self::sendLogToQueue(
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
|
|
|
|
384 |
}
|
385 |
|
386 |
/**
|
387 |
* Reports a debug event on the website.
|
388 |
*
|
389 |
-
* @param
|
390 |
-
* @return bool
|
391 |
*/
|
392 |
public static function reportDebugEvent($message = '')
|
393 |
{
|
@@ -397,8 +413,8 @@ class SucuriScanEvent extends SucuriScan
|
|
397 |
/**
|
398 |
* Reports a notice event on the website.
|
399 |
*
|
400 |
-
* @param
|
401 |
-
* @return bool
|
402 |
*/
|
403 |
public static function reportNoticeEvent($message = '')
|
404 |
{
|
@@ -408,8 +424,8 @@ class SucuriScanEvent extends SucuriScan
|
|
408 |
/**
|
409 |
* Reports a info event on the website.
|
410 |
*
|
411 |
-
* @param
|
412 |
-
* @return bool
|
413 |
*/
|
414 |
public static function reportInfoEvent($message = '')
|
415 |
{
|
@@ -419,8 +435,8 @@ class SucuriScanEvent extends SucuriScan
|
|
419 |
/**
|
420 |
* Reports a warning event on the website.
|
421 |
*
|
422 |
-
* @param
|
423 |
-
* @return bool
|
424 |
*/
|
425 |
public static function reportWarningEvent($message = '')
|
426 |
{
|
@@ -430,8 +446,8 @@ class SucuriScanEvent extends SucuriScan
|
|
430 |
/**
|
431 |
* Reports a error event on the website.
|
432 |
*
|
433 |
-
* @param
|
434 |
-
* @return bool
|
435 |
*/
|
436 |
public static function reportErrorEvent($message = '')
|
437 |
{
|
@@ -441,45 +457,21 @@ class SucuriScanEvent extends SucuriScan
|
|
441 |
/**
|
442 |
* Reports a critical event on the website.
|
443 |
*
|
444 |
-
* @param
|
445 |
-
* @return bool
|
446 |
*/
|
447 |
public static function reportCriticalEvent($message = '')
|
448 |
{
|
449 |
return self::reportEvent(5, $message);
|
450 |
}
|
451 |
|
452 |
-
/**
|
453 |
-
* Reports a notice or error event for enable and disable actions.
|
454 |
-
*
|
455 |
-
* @param string $message Text witht the explanation of the event or action performed.
|
456 |
-
* @param string $action An optional text, hopefully either enabled or disabled.
|
457 |
-
* @return bool Either true or false depending on the success of the operation.
|
458 |
-
*/
|
459 |
-
public static function reportAutoEvent($message = '', $action = '')
|
460 |
-
{
|
461 |
-
$message = strip_tags($message);
|
462 |
-
|
463 |
-
/* auto-detect the action performed: enabled */
|
464 |
-
if (strpos($message, 'enabled') !== false) {
|
465 |
-
return self::reportNoticeEvent($message);
|
466 |
-
}
|
467 |
-
|
468 |
-
/* auto-detect the action performed: disabled */
|
469 |
-
if (strpos($message, 'disabled') !== false) {
|
470 |
-
return self::reportErrorEvent($message);
|
471 |
-
}
|
472 |
-
|
473 |
-
return self::reportInfoEvent($message);
|
474 |
-
}
|
475 |
-
|
476 |
/**
|
477 |
* Send a notification to the administrator of the specified events, only if
|
478 |
* the administrator accepted to receive alerts for this type of events.
|
479 |
*
|
480 |
-
* @param
|
481 |
-
* @param
|
482 |
-
* @return bool
|
483 |
*/
|
484 |
public static function notifyEvent($event = '', $content = '')
|
485 |
{
|
@@ -513,7 +505,20 @@ class SucuriScanEvent extends SucuriScan
|
|
513 |
case 'failed_login':
|
514 |
$settings_url = SucuriScanTemplate::getUrl('settings');
|
515 |
$content .= "\n" . sprintf(
|
516 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
517 |
$settings_url,
|
518 |
$settings_url
|
519 |
);
|
@@ -534,7 +539,7 @@ class SucuriScanEvent extends SucuriScan
|
|
534 |
$email_params['ForceHTML'] = true;
|
535 |
}
|
536 |
|
537 |
-
$title =
|
538 |
|
539 |
return SucuriScanMail::sendMail(
|
540 |
$email,
|
@@ -547,13 +552,13 @@ class SucuriScanEvent extends SucuriScan
|
|
547 |
/**
|
548 |
* Check whether an IP address is being trusted or not.
|
549 |
*
|
550 |
-
* @param
|
551 |
-
* @return bool
|
552 |
*/
|
553 |
-
public static function isTrustedIP($
|
554 |
{
|
555 |
-
if (!$
|
556 |
-
$
|
557 |
}
|
558 |
|
559 |
$cache = new SucuriScanCache('trustip', false);
|
@@ -564,7 +569,7 @@ class SucuriScanEvent extends SucuriScan
|
|
564 |
}
|
565 |
|
566 |
/* check if exact IP address match is whitelisted */
|
567 |
-
if (array_key_exists(md5($
|
568 |
return true;
|
569 |
}
|
570 |
|
@@ -578,31 +583,31 @@ class SucuriScanEvent extends SucuriScan
|
|
578 |
// Generate the regular expression for a specific CIDR range.
|
579 |
switch ($ip_info->cidr_range) {
|
580 |
case 24:
|
581 |
-
$ip_pattern =
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
|
|
586 |
break;
|
587 |
|
588 |
case 16:
|
589 |
-
$ip_pattern =
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
break;
|
595 |
|
596 |
case 8:
|
597 |
-
$ip_pattern =
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
. '\.[0-9]{1,3}$/';
|
602 |
break;
|
603 |
}
|
604 |
|
605 |
-
if ($ip_pattern && preg_match($ip_pattern, $
|
606 |
$is_trusted_ip = true;
|
607 |
break;
|
608 |
}
|
@@ -614,8 +619,8 @@ class SucuriScanEvent extends SucuriScan
|
|
614 |
/**
|
615 |
* Generate and set a new password for a specific user not in session.
|
616 |
*
|
617 |
-
* @param
|
618 |
-
* @return bool
|
619 |
*/
|
620 |
public static function setNewPassword($user_id = 0)
|
621 |
{
|
@@ -630,19 +635,22 @@ class SucuriScanEvent extends SucuriScan
|
|
630 |
$display_name = $user->display_name;
|
631 |
$new_password = wp_generate_password(15, true, false);
|
632 |
|
633 |
-
$message = SucuriScanTemplate::getSection(
|
634 |
-
'
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
|
|
|
|
|
|
639 |
|
640 |
/* Skip per hour alert limit and force text/html content-type */
|
641 |
$data_set = array('Force' => true, 'ForceHTML' => true);
|
642 |
|
643 |
$sent = SucuriScanMail::sendMail(
|
644 |
$user->user_email,
|
645 |
-
|
646 |
$message,
|
647 |
$data_set
|
648 |
);
|
@@ -667,7 +675,7 @@ class SucuriScanEvent extends SucuriScan
|
|
667 |
public static function setNewConfigKeys()
|
668 |
{
|
669 |
$new_wpconfig = '';
|
670 |
-
$config_path = self::
|
671 |
|
672 |
if (!$config_path) {
|
673 |
return false;
|
3 |
/**
|
4 |
* Code related to the event.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
35 |
* response to events is said to be event-driven, often with the goal of being
|
36 |
* interactive.
|
37 |
*
|
38 |
+
* @category Library
|
39 |
+
* @package Sucuri
|
40 |
+
* @subpackage SucuriScanner
|
41 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
42 |
+
* @copyright 2010-2017 Sucuri Inc.
|
43 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
44 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
45 |
*/
|
46 |
class SucuriScanEvent extends SucuriScan
|
47 |
{
|
55 |
* list with the checksum of the new file list, if there are differences we
|
56 |
* will assume that someone or something modified one or more files and send
|
57 |
* an email alsert about the incident.
|
58 |
+
*
|
59 |
+
* @return void
|
60 |
*/
|
61 |
public static function installScheduledTask()
|
62 |
{
|
86 |
|
87 |
foreach ($jobs as $unique => $info) {
|
88 |
$schedules[$unique] = sprintf(
|
89 |
+
'%s (every %d seconds)',
|
90 |
$info['display'],
|
91 |
$info['interval']
|
92 |
);
|
93 |
}
|
94 |
|
95 |
+
$schedules['_oneoff'] = 'Never (no execution)';
|
96 |
|
97 |
return $schedules;
|
98 |
}
|
124 |
/**
|
125 |
* Decides if the file system scanner can run or not.
|
126 |
*
|
127 |
+
* @param bool $force_scan Force the execution of the scanner.
|
128 |
+
* @return bool True if the scanner can run, false otherwise.
|
129 |
*/
|
130 |
private static function runFileScanner($force_scan = false)
|
131 |
{
|
149 |
* analyze them using the Sucuri Monitoring service, this will generate the
|
150 |
* audit logs for this site and be part of the integrity checks.
|
151 |
*
|
152 |
+
* @param bool $force_scan Whether the filesystem scan was forced by an administrator user or not.
|
153 |
+
* @return bool True if the filesystem scan was successful, false otherwise.
|
154 |
*/
|
155 |
public static function filesystemScan($force_scan = false)
|
156 |
{
|
183 |
* in a failure. However, this procedure depends on the ability of the plugin
|
184 |
* to write the log into the queue when the previous request failed.
|
185 |
*
|
186 |
+
* @param string $message Information about the event.
|
187 |
+
* @param string|int $timestamp Time when the event was triggered.
|
188 |
+
* @param int $timeout Maximum time in seconds to connect to the API.
|
189 |
+
* @return bool True if the event was logged, false otherwise.
|
190 |
*/
|
191 |
private static function sendLogToAPI($message = '', $timestamp = '', $timeout = 1)
|
192 |
{
|
216 |
* but it could be private and be mocked by the test bootstrap script. Take
|
217 |
* this in consideration during the static analysis of the code.
|
218 |
*
|
219 |
+
* @param string $message Information about the security event.
|
220 |
+
* @return bool True if the operation succeeded, false otherwise.
|
221 |
*/
|
222 |
public static function sendLogToQueue($message = '')
|
223 |
{
|
349 |
/**
|
350 |
* Generates an audit event log (to be sent later).
|
351 |
*
|
352 |
+
* @param int $severity Importance of the event that will be reported.
|
353 |
+
* @param string $message The explanation of the event.
|
354 |
+
* @return bool True if the event was logged, false otherwise.
|
355 |
*/
|
356 |
private static function reportEvent($severity = 0, $message = '')
|
357 |
{
|
368 |
}
|
369 |
|
370 |
$severity = intval($severity);
|
371 |
+
$severity_name = 'Info';
|
372 |
$severities = array(
|
373 |
/* 0 */ 'Debug',
|
374 |
/* 1 */ 'Notice',
|
388 |
$message = str_replace("\n", '', $message);
|
389 |
$message = str_replace("\t", '', $message);
|
390 |
|
391 |
+
return self::sendLogToQueue(
|
392 |
+
sprintf(
|
393 |
+
'%s:%s %s; %s',
|
394 |
+
$severity_name,
|
395 |
+
$username,
|
396 |
+
$remote_ip,
|
397 |
+
$message
|
398 |
+
)
|
399 |
+
);
|
400 |
}
|
401 |
|
402 |
/**
|
403 |
* Reports a debug event on the website.
|
404 |
*
|
405 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
406 |
+
* @return bool Either true or false depending on the success of the operation.
|
407 |
*/
|
408 |
public static function reportDebugEvent($message = '')
|
409 |
{
|
413 |
/**
|
414 |
* Reports a notice event on the website.
|
415 |
*
|
416 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
417 |
+
* @return bool Either true or false depending on the success of the operation.
|
418 |
*/
|
419 |
public static function reportNoticeEvent($message = '')
|
420 |
{
|
424 |
/**
|
425 |
* Reports a info event on the website.
|
426 |
*
|
427 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
428 |
+
* @return bool Either true or false depending on the success of the operation.
|
429 |
*/
|
430 |
public static function reportInfoEvent($message = '')
|
431 |
{
|
435 |
/**
|
436 |
* Reports a warning event on the website.
|
437 |
*
|
438 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
439 |
+
* @return bool Either true or false depending on the success of the operation.
|
440 |
*/
|
441 |
public static function reportWarningEvent($message = '')
|
442 |
{
|
446 |
/**
|
447 |
* Reports a error event on the website.
|
448 |
*
|
449 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
450 |
+
* @return bool Either true or false depending on the success of the operation.
|
451 |
*/
|
452 |
public static function reportErrorEvent($message = '')
|
453 |
{
|
457 |
/**
|
458 |
* Reports a critical event on the website.
|
459 |
*
|
460 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
461 |
+
* @return bool Either true or false depending on the success of the operation.
|
462 |
*/
|
463 |
public static function reportCriticalEvent($message = '')
|
464 |
{
|
465 |
return self::reportEvent(5, $message);
|
466 |
}
|
467 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
468 |
/**
|
469 |
* Send a notification to the administrator of the specified events, only if
|
470 |
* the administrator accepted to receive alerts for this type of events.
|
471 |
*
|
472 |
+
* @param string $event The name of the event that was triggered.
|
473 |
+
* @param string $content Body of the email that will be sent to the administrator.
|
474 |
+
* @return bool True if the email was apparently sent, false otherwise.
|
475 |
*/
|
476 |
public static function notifyEvent($event = '', $content = '')
|
477 |
{
|
505 |
case 'failed_login':
|
506 |
$settings_url = SucuriScanTemplate::getUrl('settings');
|
507 |
$content .= "\n" . sprintf(
|
508 |
+
"<br><br>\n\n<em>Explanation: Someone failed to login to y"
|
509 |
+
. "our site. If you are getting too many of these messages"
|
510 |
+
. ", it is likely your site is under a password guessing b"
|
511 |
+
. "rute-force attack [1]. You can disable the failed login"
|
512 |
+
. " alerts from here [2]. Alternatively, you can consider "
|
513 |
+
. "to install a firewall between your website and your vis"
|
514 |
+
. "itors to filter out these and other attacks, take a loo"
|
515 |
+
. "k at Sucuri Firewall [3].</em><br><br>\n\n[1] <a href='"
|
516 |
+
. "https://kb.sucuri.net/definitions/attacks/brute-force/p"
|
517 |
+
. "assword-guessing'>https://kb.sucuri.net/definitions/att"
|
518 |
+
. "acks/brute-force/password-guessing</a><br>\n[2] <a href"
|
519 |
+
. "='%s'>%s</a> <br>\n[3] <a href='https://sucuri.net/webs"
|
520 |
+
. "ite-firewall/?wpalert'>https://sucuri.net/website-firew"
|
521 |
+
. "all/</a><br>\n",
|
522 |
$settings_url,
|
523 |
$settings_url
|
524 |
);
|
539 |
$email_params['ForceHTML'] = true;
|
540 |
}
|
541 |
|
542 |
+
$title = ucwords(str_replace('_', "\x20", $event));
|
543 |
|
544 |
return SucuriScanMail::sendMail(
|
545 |
$email,
|
552 |
/**
|
553 |
* Check whether an IP address is being trusted or not.
|
554 |
*
|
555 |
+
* @param string $addr The supposed ip address that will be checked.
|
556 |
+
* @return bool True if the user IP is trusted, false otherwise.
|
557 |
*/
|
558 |
+
public static function isTrustedIP($addr = '')
|
559 |
{
|
560 |
+
if (!$addr) {
|
561 |
+
$addr = SucuriScan::getRemoteAddr();
|
562 |
}
|
563 |
|
564 |
$cache = new SucuriScanCache('trustip', false);
|
569 |
}
|
570 |
|
571 |
/* check if exact IP address match is whitelisted */
|
572 |
+
if (array_key_exists(md5($addr), $trusted_ips)) {
|
573 |
return true;
|
574 |
}
|
575 |
|
583 |
// Generate the regular expression for a specific CIDR range.
|
584 |
switch ($ip_info->cidr_range) {
|
585 |
case 24:
|
586 |
+
$ip_pattern = sprintf(
|
587 |
+
'/^%d\.%d\.%d\.[0-9]{1,3}$/',
|
588 |
+
intval($ip_parts[0]),
|
589 |
+
intval($ip_parts[1]),
|
590 |
+
intval($ip_parts[2])
|
591 |
+
);
|
592 |
break;
|
593 |
|
594 |
case 16:
|
595 |
+
$ip_pattern = sprintf(
|
596 |
+
'/^%d\.%d\.[0-9]{1,3}\.[0-9]{1,3}$/',
|
597 |
+
intval($ip_parts[0]),
|
598 |
+
intval($ip_parts[1])
|
599 |
+
);
|
600 |
break;
|
601 |
|
602 |
case 8:
|
603 |
+
$ip_pattern = sprintf(
|
604 |
+
'/^%d\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',
|
605 |
+
intval($ip_parts[0])
|
606 |
+
);
|
|
|
607 |
break;
|
608 |
}
|
609 |
|
610 |
+
if ($ip_pattern && preg_match($ip_pattern, $addr)) {
|
611 |
$is_trusted_ip = true;
|
612 |
break;
|
613 |
}
|
619 |
/**
|
620 |
* Generate and set a new password for a specific user not in session.
|
621 |
*
|
622 |
+
* @param int $user_id User account identifier.
|
623 |
+
* @return bool True if the process exit clean, false otherwise.
|
624 |
*/
|
625 |
public static function setNewPassword($user_id = 0)
|
626 |
{
|
635 |
$display_name = $user->display_name;
|
636 |
$new_password = wp_generate_password(15, true, false);
|
637 |
|
638 |
+
$message = SucuriScanTemplate::getSection(
|
639 |
+
'settings-posthack-reset-password-alert',
|
640 |
+
array(
|
641 |
+
'ResetPassword.UserName' => $user_login,
|
642 |
+
'ResetPassword.DisplayName' => $display_name,
|
643 |
+
'ResetPassword.Password' => $new_password,
|
644 |
+
'ResetPassword.Website' => $website,
|
645 |
+
)
|
646 |
+
);
|
647 |
|
648 |
/* Skip per hour alert limit and force text/html content-type */
|
649 |
$data_set = array('Force' => true, 'ForceHTML' => true);
|
650 |
|
651 |
$sent = SucuriScanMail::sendMail(
|
652 |
$user->user_email,
|
653 |
+
'Password Change',
|
654 |
$message,
|
655 |
$data_set
|
656 |
);
|
675 |
public static function setNewConfigKeys()
|
676 |
{
|
677 |
$new_wpconfig = '';
|
678 |
+
$config_path = self::getConfigPath();
|
679 |
|
680 |
if (!$config_path) {
|
681 |
return false;
|
src/fileinfo.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the fileinfo.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -23,6 +29,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
23 |
* and folders using the built-in PHP class SplFileInfo. The SplFileInfo class
|
24 |
* offers a high-level object oriented interface to information for an individual
|
25 |
* file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
*/
|
27 |
class SucuriScanFileInfo extends SucuriScan
|
28 |
{
|
@@ -31,7 +45,7 @@ class SucuriScanFileInfo extends SucuriScan
|
|
31 |
* be used to return the directory tree, this should be disabled when scanning a
|
32 |
* directory without the need to filter the items in the list.
|
33 |
*
|
34 |
-
* @var
|
35 |
*/
|
36 |
public $ignore_files;
|
37 |
|
@@ -40,7 +54,7 @@ class SucuriScanFileInfo extends SucuriScan
|
|
40 |
* be used to return the directory tree, this should be disabled when scanning a
|
41 |
* path without the need to filter the items in the list.
|
42 |
*
|
43 |
-
* @var
|
44 |
*/
|
45 |
public $ignore_directories;
|
46 |
|
@@ -57,7 +71,7 @@ class SucuriScanFileInfo extends SucuriScan
|
|
57 |
/**
|
58 |
* Whether the filesystem scanner should run recursively or not.
|
59 |
*
|
60 |
-
* @var
|
61 |
*/
|
62 |
public $run_recursively;
|
63 |
|
@@ -70,7 +84,7 @@ class SucuriScanFileInfo extends SucuriScan
|
|
70 |
* are ignored and that a folder may be empty some times there could be issues
|
71 |
* because the deletion will not reach these resources.
|
72 |
*
|
73 |
-
* @var
|
74 |
*/
|
75 |
public $skip_directories;
|
76 |
|
@@ -108,8 +122,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
108 |
*
|
109 |
* Note: This is an approach that is intentionally naive.
|
110 |
*
|
111 |
-
* @param
|
112 |
-
* @return True
|
113 |
*/
|
114 |
private function ignoreFile($path)
|
115 |
{
|
@@ -130,8 +144,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
130 |
*
|
131 |
* Note: This is an approach that is intentionally naive.
|
132 |
*
|
133 |
-
* @param
|
134 |
-
* @return True
|
135 |
*/
|
136 |
private function ignoreFolder($path)
|
137 |
{
|
@@ -149,8 +163,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
149 |
/**
|
150 |
* Ignores files specified by the admins.
|
151 |
*
|
152 |
-
* @param
|
153 |
-
* @return
|
154 |
*/
|
155 |
private function isIgnoredPath($path)
|
156 |
{
|
@@ -180,9 +194,9 @@ class SucuriScanFileInfo extends SucuriScan
|
|
180 |
* @see http://php.net/manual/en/class.directoryiterator.php
|
181 |
* @see http://php.net/manual/en/class.splfileinfo.php
|
182 |
*
|
183 |
-
* @param
|
184 |
-
* @param
|
185 |
-
* @return array
|
186 |
*/
|
187 |
public function getDirectoryTree($directory = '', $filterby = 'file')
|
188 |
{
|
@@ -196,10 +210,10 @@ class SucuriScanFileInfo extends SucuriScan
|
|
196 |
// @codeCoverageIgnoreStart
|
197 |
try {
|
198 |
if ($this->run_recursively) {
|
199 |
-
$flags = FilesystemIterator::KEY_AS_PATHNAME
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
$objects = new RecursiveIteratorIterator(
|
204 |
new RecursiveDirectoryIterator($directory, $flags),
|
205 |
RecursiveIteratorIterator::SELF_FIRST,
|
@@ -253,8 +267,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
253 |
* and md5sum of that file. Some folders and files will be ignored depending
|
254 |
* on some rules defined by the developer.
|
255 |
*
|
256 |
-
* @param
|
257 |
-
* @param
|
258 |
* @return array|string|bool List of files in this project.
|
259 |
*/
|
260 |
public function getDirectoryTreeMd5($directory = '', $as_array = false)
|
@@ -299,8 +313,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
299 |
/**
|
300 |
* Retrieves a list of unique directory paths.
|
301 |
*
|
302 |
-
* @param
|
303 |
-
* @return array
|
304 |
*/
|
305 |
public function getDirectoriesOnly($directory = '')
|
306 |
{
|
@@ -312,8 +326,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
312 |
/**
|
313 |
* Deletes a directory recursively.
|
314 |
*
|
315 |
-
* @param
|
316 |
-
* @return bool
|
317 |
*/
|
318 |
public function removeDirectoryTree($directory = '')
|
319 |
{
|
@@ -337,7 +351,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
337 |
$this->ignore_directories = false;
|
338 |
|
339 |
/* delete all the regular files and symbolic links */
|
340 |
-
|
|
|
341 |
foreach ($dir_tree as $filename) {
|
342 |
if (is_file($filename) || is_link($filename)) {
|
343 |
@unlink($filename);
|
@@ -346,7 +361,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
346 |
}
|
347 |
|
348 |
/* delete directories starting from the deepest level */
|
349 |
-
|
|
|
350 |
$dir_tree = array_unique($dir_tree);
|
351 |
usort($dir_tree, array('SucuriScanFileInfo', 'sortByLength'));
|
352 |
foreach ($dir_tree as $dir_path) {
|
@@ -363,9 +379,9 @@ class SucuriScanFileInfo extends SucuriScan
|
|
363 |
/**
|
364 |
* Evaluates the difference between the length of two strings.
|
365 |
*
|
366 |
-
* @param
|
367 |
-
* @param
|
368 |
-
* @return int
|
369 |
*/
|
370 |
public static function sortByLength($a, $b)
|
371 |
{
|
@@ -380,8 +396,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
380 |
* equals in order to avoid ambiguous results when the file exists, is
|
381 |
* readable, but is empty.
|
382 |
*
|
383 |
-
* @param
|
384 |
-
* @return string
|
385 |
*/
|
386 |
public static function fileContent($path = '')
|
387 |
{
|
@@ -393,8 +409,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
393 |
* new line characters from the end of each line, and skip empty lines from
|
394 |
* the list.
|
395 |
*
|
396 |
-
* @param
|
397 |
-
* @return array
|
398 |
*/
|
399 |
public static function fileLines($filepath = '')
|
400 |
{
|
@@ -404,8 +420,8 @@ class SucuriScanFileInfo extends SucuriScan
|
|
404 |
/**
|
405 |
* Tells whether the filename is a directory, symbolic link, or file.
|
406 |
*
|
407 |
-
* @param
|
408 |
-
* @return string
|
409 |
*/
|
410 |
public static function getResourceType($path = '')
|
411 |
{
|
3 |
/**
|
4 |
* Code related to the fileinfo.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
29 |
* and folders using the built-in PHP class SplFileInfo. The SplFileInfo class
|
30 |
* offers a high-level object oriented interface to information for an individual
|
31 |
* file.
|
32 |
+
*
|
33 |
+
* @category Library
|
34 |
+
* @package Sucuri
|
35 |
+
* @subpackage SucuriScanner
|
36 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
37 |
+
* @copyright 2010-2017 Sucuri Inc.
|
38 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
39 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
40 |
*/
|
41 |
class SucuriScanFileInfo extends SucuriScan
|
42 |
{
|
45 |
* be used to return the directory tree, this should be disabled when scanning a
|
46 |
* directory without the need to filter the items in the list.
|
47 |
*
|
48 |
+
* @var bool
|
49 |
*/
|
50 |
public $ignore_files;
|
51 |
|
54 |
* be used to return the directory tree, this should be disabled when scanning a
|
55 |
* path without the need to filter the items in the list.
|
56 |
*
|
57 |
+
* @var bool
|
58 |
*/
|
59 |
public $ignore_directories;
|
60 |
|
71 |
/**
|
72 |
* Whether the filesystem scanner should run recursively or not.
|
73 |
*
|
74 |
+
* @var bool
|
75 |
*/
|
76 |
public $run_recursively;
|
77 |
|
84 |
* are ignored and that a folder may be empty some times there could be issues
|
85 |
* because the deletion will not reach these resources.
|
86 |
*
|
87 |
+
* @var bool
|
88 |
*/
|
89 |
public $skip_directories;
|
90 |
|
122 |
*
|
123 |
* Note: This is an approach that is intentionally naive.
|
124 |
*
|
125 |
+
* @param string $path Path to the file.
|
126 |
+
* @return True if the file must be ignored.
|
127 |
*/
|
128 |
private function ignoreFile($path)
|
129 |
{
|
144 |
*
|
145 |
* Note: This is an approach that is intentionally naive.
|
146 |
*
|
147 |
+
* @param string $path Path to the folder.
|
148 |
+
* @return True if the folder must be ignored.
|
149 |
*/
|
150 |
private function ignoreFolder($path)
|
151 |
{
|
163 |
/**
|
164 |
* Ignores files specified by the admins.
|
165 |
*
|
166 |
+
* @param string $path Path to the file or directory.
|
167 |
+
* @return bool True if the path has to be ignored.
|
168 |
*/
|
169 |
private function isIgnoredPath($path)
|
170 |
{
|
194 |
* @see http://php.net/manual/en/class.directoryiterator.php
|
195 |
* @see http://php.net/manual/en/class.splfileinfo.php
|
196 |
*
|
197 |
+
* @param string $directory Where to execute the scanner.
|
198 |
+
* @param string $filterby Either "file" or "directory".
|
199 |
+
* @return array List of files in the specified directory.
|
200 |
*/
|
201 |
public function getDirectoryTree($directory = '', $filterby = 'file')
|
202 |
{
|
210 |
// @codeCoverageIgnoreStart
|
211 |
try {
|
212 |
if ($this->run_recursively) {
|
213 |
+
$flags = FilesystemIterator::KEY_AS_PATHNAME;
|
214 |
+
$flags |= FilesystemIterator::CURRENT_AS_FILEINFO;
|
215 |
+
$flags |= FilesystemIterator::SKIP_DOTS;
|
216 |
+
$flags |= FilesystemIterator::UNIX_PATHS;
|
217 |
$objects = new RecursiveIteratorIterator(
|
218 |
new RecursiveDirectoryIterator($directory, $flags),
|
219 |
RecursiveIteratorIterator::SELF_FIRST,
|
267 |
* and md5sum of that file. Some folders and files will be ignored depending
|
268 |
* on some rules defined by the developer.
|
269 |
*
|
270 |
+
* @param string $directory Where to execute the scanner.
|
271 |
+
* @param bool $as_array Return the file list as an array.
|
272 |
* @return array|string|bool List of files in this project.
|
273 |
*/
|
274 |
public function getDirectoryTreeMd5($directory = '', $as_array = false)
|
313 |
/**
|
314 |
* Retrieves a list of unique directory paths.
|
315 |
*
|
316 |
+
* @param string $directory Directory path to scan.
|
317 |
+
* @return array A list of unique directory paths.
|
318 |
*/
|
319 |
public function getDirectoriesOnly($directory = '')
|
320 |
{
|
326 |
/**
|
327 |
* Deletes a directory recursively.
|
328 |
*
|
329 |
+
* @param string $directory Path of the existing directory that will be removed.
|
330 |
+
* @return bool TRUE if all the files and folder inside the directory were removed.
|
331 |
*/
|
332 |
public function removeDirectoryTree($directory = '')
|
333 |
{
|
351 |
$this->ignore_directories = false;
|
352 |
|
353 |
/* delete all the regular files and symbolic links */
|
354 |
+
$dir_tree = $this->getDirectoryTree($directory, 'file');
|
355 |
+
if (is_array($dir_tree) && !empty($dir_tree)) {
|
356 |
foreach ($dir_tree as $filename) {
|
357 |
if (is_file($filename) || is_link($filename)) {
|
358 |
@unlink($filename);
|
361 |
}
|
362 |
|
363 |
/* delete directories starting from the deepest level */
|
364 |
+
$dir_tree = $this->getDirectoryTree($directory, 'directory');
|
365 |
+
if (is_array($dir_tree) && !empty($dir_tree)) {
|
366 |
$dir_tree = array_unique($dir_tree);
|
367 |
usort($dir_tree, array('SucuriScanFileInfo', 'sortByLength'));
|
368 |
foreach ($dir_tree as $dir_path) {
|
379 |
/**
|
380 |
* Evaluates the difference between the length of two strings.
|
381 |
*
|
382 |
+
* @param string $a First string of characters that will be measured.
|
383 |
+
* @param string $b Second string of characters that will be measured.
|
384 |
+
* @return int The difference in length between the two strings.
|
385 |
*/
|
386 |
public static function sortByLength($a, $b)
|
387 |
{
|
396 |
* equals in order to avoid ambiguous results when the file exists, is
|
397 |
* readable, but is empty.
|
398 |
*
|
399 |
+
* @param string $path Relative or absolute path of the file.
|
400 |
+
* @return string Content of the file, false if not accessible.
|
401 |
*/
|
402 |
public static function fileContent($path = '')
|
403 |
{
|
409 |
* new line characters from the end of each line, and skip empty lines from
|
410 |
* the list.
|
411 |
*
|
412 |
+
* @param string $filepath Path to the file.
|
413 |
+
* @return array An array where each element is a line in the file.
|
414 |
*/
|
415 |
public static function fileLines($filepath = '')
|
416 |
{
|
420 |
/**
|
421 |
* Tells whether the filename is a directory, symbolic link, or file.
|
422 |
*
|
423 |
+
* @param string $path Path to the file.
|
424 |
+
* @return string Type of resource: dir, link, file.
|
425 |
*/
|
426 |
public static function getResourceType($path = '')
|
427 |
{
|
src/firewall.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the firewall.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,15 +24,23 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
/**
|
20 |
* Defines methods to interact with Sucuri Firewall's API service.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
*/
|
22 |
class SucuriScanFirewall extends SucuriScanAPI
|
23 |
{
|
24 |
/**
|
25 |
* Check whether the firewall API key is valid or not.
|
26 |
*
|
27 |
-
* @param
|
28 |
-
* @param
|
29 |
-
* @return array|bool
|
30 |
*/
|
31 |
public static function isValidKey($api_key = '', $return_match = false)
|
32 |
{
|
@@ -70,20 +84,22 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
70 |
/**
|
71 |
* Call an action from the remote API interface of our firewall service.
|
72 |
*
|
73 |
-
* @param
|
74 |
-
* @param
|
75 |
-
* @return array|bool
|
76 |
*/
|
77 |
public static function apiCallFirewall($method = 'GET', $params = array())
|
78 |
{
|
79 |
-
$send_request =
|
|
|
|
|
|
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
$params['s'] = $api_key['s'];
|
87 |
}
|
88 |
|
89 |
if ($send_request) {
|
@@ -101,8 +117,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
101 |
* request to the remote API service and process its response, when successful
|
102 |
* it will return an array/object containing the public attributes of the site.
|
103 |
*
|
104 |
-
* @param
|
105 |
-
* @return array|bool
|
106 |
*/
|
107 |
public static function settings($api_key = false)
|
108 |
{
|
@@ -142,18 +158,18 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
142 |
|
143 |
if (self::isValidKey($api_key)) {
|
144 |
SucuriScanOption::updateOption($option_name, $api_key);
|
145 |
-
SucuriScanInterface::info(
|
146 |
SucuriScanOption::setRevProxy('enable');
|
147 |
SucuriScanOption::setAddrHeader('HTTP_X_SUCURI_CLIENTIP');
|
148 |
} else {
|
149 |
-
SucuriScanInterface::error(
|
150 |
}
|
151 |
}
|
152 |
|
153 |
// Delete the firewall API key from the plugin.
|
154 |
if (SucuriScanRequest::post(':delete_wafkey') !== false) {
|
155 |
SucuriScanOption::deleteOption($option_name);
|
156 |
-
SucuriScanInterface::info(
|
157 |
SucuriScanOption::setRevProxy('disable');
|
158 |
SucuriScanOption::setAddrHeader('REMOTE_ADDR');
|
159 |
}
|
@@ -175,33 +191,35 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
175 |
* text, for example changing numbers or variable names into a more explicit
|
176 |
* text so the administrator can understand the meaning of these settings.
|
177 |
*
|
178 |
-
* @param
|
179 |
-
* @return array
|
180 |
*/
|
181 |
public static function settingsExplanation($settings = array())
|
182 |
{
|
183 |
if (!is_array($settings)) {
|
184 |
-
return array(
|
185 |
}
|
186 |
|
187 |
$cache_modes = array(
|
188 |
-
'docache' =>
|
189 |
-
'sitecache' =>
|
190 |
-
'nocache' =>
|
191 |
-
'nocacheatall' =>
|
192 |
);
|
193 |
|
194 |
foreach ($settings as $keyname => $value) {
|
195 |
if ($keyname == 'proxy_active') {
|
196 |
-
$settings[$keyname] = ($value === 1)
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
200 |
if (array_key_exists($value, $cache_modes)) {
|
201 |
$settings[$keyname] = $cache_modes[$value];
|
202 |
} else {
|
203 |
-
$settings[$keyname] =
|
204 |
}
|
|
|
205 |
}
|
206 |
}
|
207 |
|
@@ -212,6 +230,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
212 |
* Returns the public firewall settings.
|
213 |
*
|
214 |
* @codeCoverageIgnore
|
|
|
|
|
215 |
*/
|
216 |
public static function getSettingsAjax()
|
217 |
{
|
@@ -230,7 +250,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
230 |
if (!$settings) {
|
231 |
if (empty($error)) {
|
232 |
ob_start();
|
233 |
-
SucuriScanInterface::error(
|
234 |
$response['error'] = ob_get_clean();
|
235 |
} else {
|
236 |
$response['error'] = $error;
|
@@ -258,12 +278,12 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
258 |
* the logs of previous days you will need to add a new parameter to the request
|
259 |
* URL named "date" with format yyyy-mm-dd.
|
260 |
*
|
261 |
-
* @param
|
262 |
-
* @param
|
263 |
-
* @param
|
264 |
-
* @param
|
265 |
-
* @param
|
266 |
-
* @return array|bool
|
267 |
*/
|
268 |
public static function auditlogs($api_key, $date = '', $query = '', $limit = 10, $offset = 0)
|
269 |
{
|
@@ -312,6 +332,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
312 |
* feature. The plugin will display a warning in this case.
|
313 |
*
|
314 |
* @codeCoverageIgnore
|
|
|
|
|
315 |
*/
|
316 |
public static function auditlogsAjax()
|
317 |
{
|
@@ -324,7 +346,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
324 |
|
325 |
if (!$api_key) {
|
326 |
ob_start();
|
327 |
-
SucuriScanInterface::error(
|
328 |
$response = ob_get_clean();
|
329 |
wp_send_json($response, 200);
|
330 |
}
|
@@ -360,7 +382,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
360 |
$response = self::auditlogsEntries($auditlogs['access_logs']);
|
361 |
|
362 |
if (empty($response)) {
|
363 |
-
$response = '<tr><td>
|
364 |
}
|
365 |
}
|
366 |
|
@@ -370,8 +392,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
370 |
/**
|
371 |
* Returns the security logs from the firewall in HTML.
|
372 |
*
|
373 |
-
* @param
|
374 |
-
* @return string
|
375 |
*/
|
376 |
public static function auditlogsEntries($entries = array())
|
377 |
{
|
@@ -432,10 +454,10 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
432 |
/**
|
433 |
* Get a list of years, months or days depending of the type specified.
|
434 |
*
|
435 |
-
* @param
|
436 |
-
* @param
|
437 |
-
* @param
|
438 |
-
* @return array|string
|
439 |
*/
|
440 |
public static function dates($type = '', $date = '', $in_html = true)
|
441 |
{
|
@@ -463,18 +485,18 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
463 |
case 'months':
|
464 |
$selected = $s_month;
|
465 |
$options = array(
|
466 |
-
'01' =>
|
467 |
-
'02' =>
|
468 |
-
'03' =>
|
469 |
-
'04' =>
|
470 |
-
'05' =>
|
471 |
-
'06' =>
|
472 |
-
'07' =>
|
473 |
-
'08' =>
|
474 |
-
'09' =>
|
475 |
-
'10' =>
|
476 |
-
'11' =>
|
477 |
-
'12' =>
|
478 |
);
|
479 |
break;
|
480 |
|
@@ -522,6 +544,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
522 |
* Returns the whitelisted and blacklisted IP addresses.
|
523 |
*
|
524 |
* @codeCoverageIgnore
|
|
|
|
|
525 |
*/
|
526 |
public static function ipAccessAjax()
|
527 |
{
|
@@ -540,7 +564,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
540 |
if (!$settings) {
|
541 |
if (empty($error)) {
|
542 |
ob_start();
|
543 |
-
SucuriScanInterface::error(
|
544 |
$response['error'] = ob_get_clean();
|
545 |
} else {
|
546 |
$response['error'] = $error;
|
@@ -560,6 +584,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
560 |
* Blacklists an IP address.
|
561 |
*
|
562 |
* @codeCoverageIgnore
|
|
|
|
|
563 |
*/
|
564 |
public static function blacklistAjax()
|
565 |
{
|
@@ -573,7 +599,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
573 |
|
574 |
if (!$params) {
|
575 |
ob_start();
|
576 |
-
SucuriScanInterface::error(
|
577 |
$response['msg'] = ob_get_clean();
|
578 |
wp_send_json($response, 200);
|
579 |
}
|
@@ -588,8 +614,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
588 |
$response['msg'] = implode(";\x20", $out['messages']);
|
589 |
|
590 |
if ($out['status'] == 1) {
|
591 |
-
SucuriScanEvent::reportInfoEvent(
|
592 |
-
'IP has been blacklisted: ' . $params['ip']);
|
593 |
}
|
594 |
}
|
595 |
|
@@ -600,6 +625,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
600 |
* Deletes an IP address from the blacklist.
|
601 |
*
|
602 |
* @codeCoverageIgnore
|
|
|
|
|
603 |
*/
|
604 |
public static function deblacklistAjax()
|
605 |
{
|
@@ -613,7 +640,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
613 |
if (!$params) {
|
614 |
ob_start();
|
615 |
$response['ok'] = false;
|
616 |
-
SucuriScanInterface::error(
|
617 |
$response['error'] = ob_get_clean();
|
618 |
wp_send_json($response, 200);
|
619 |
}
|
@@ -626,8 +653,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
626 |
$response['msg'] = implode(";\x20", $out['messages']);
|
627 |
|
628 |
if ($out['status'] == 1) {
|
629 |
-
SucuriScanEvent::reportInfoEvent(
|
630 |
-
'IP has been unblacklisted: ' . $params['ip']);
|
631 |
}
|
632 |
|
633 |
wp_send_json($response, 200);
|
@@ -636,12 +662,12 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
636 |
/**
|
637 |
* Flush the cache of the site(s) associated with the API key.
|
638 |
*
|
639 |
-
* @param
|
640 |
-
* @return string|bool
|
641 |
*/
|
642 |
public static function clearCache($api_key = false)
|
643 |
{
|
644 |
-
$params = array(
|
645 |
|
646 |
if (is_array($api_key)) {
|
647 |
$params = array_merge($params, $api_key);
|
@@ -663,9 +689,11 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
663 |
{
|
664 |
$params = array();
|
665 |
|
666 |
-
$params['FirewallAutoClearCache'] =
|
667 |
-
|
668 |
-
|
|
|
|
|
669 |
|
670 |
return SucuriScanTemplate::getSection('firewall-clearcache', $params);
|
671 |
}
|
@@ -679,9 +707,9 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
679 |
* of certain files is going to stay as it is due to the configuration on the
|
680 |
* edge of the servers.
|
681 |
*
|
682 |
-
* @
|
683 |
*/
|
684 |
-
public static function clearCacheHook(
|
685 |
{
|
686 |
if (SucuriScanOption::isEnabled(':auto_clear_cache')) {
|
687 |
ob_start();
|
@@ -694,6 +722,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
694 |
* Requests a cache flush to the firewall service.
|
695 |
*
|
696 |
* @codeCoverageIgnore
|
|
|
|
|
697 |
*/
|
698 |
public static function clearCacheAjax()
|
699 |
{
|
@@ -702,10 +732,11 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
702 |
}
|
703 |
|
704 |
ob_start();
|
705 |
-
SucuriScanInterface::error(
|
706 |
$response = ob_get_clean();
|
|
|
707 |
|
708 |
-
if ($api_key
|
709 |
$res = self::clearCache($api_key);
|
710 |
|
711 |
if (is_array($res) && isset($res['messages'])) {
|
@@ -724,6 +755,8 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
724 |
* Configures the status of the automatic cache flush.
|
725 |
*
|
726 |
* @codeCoverageIgnore
|
|
|
|
|
727 |
*/
|
728 |
public static function clearAutoCacheAjax()
|
729 |
{
|
3 |
/**
|
4 |
* Code related to the firewall.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
/**
|
26 |
* Defines methods to interact with Sucuri Firewall's API service.
|
27 |
+
*
|
28 |
+
* @category Library
|
29 |
+
* @package Sucuri
|
30 |
+
* @subpackage SucuriScanner
|
31 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
32 |
+
* @copyright 2010-2017 Sucuri Inc.
|
33 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
34 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
35 |
*/
|
36 |
class SucuriScanFirewall extends SucuriScanAPI
|
37 |
{
|
38 |
/**
|
39 |
* Check whether the firewall API key is valid or not.
|
40 |
*
|
41 |
+
* @param string $api_key The firewall API key.
|
42 |
+
* @param bool $return_match Whether the parts of the API key must be returned or not.
|
43 |
+
* @return array|bool True if the API key specified is valid, false otherwise.
|
44 |
*/
|
45 |
public static function isValidKey($api_key = '', $return_match = false)
|
46 |
{
|
84 |
/**
|
85 |
* Call an action from the remote API interface of our firewall service.
|
86 |
*
|
87 |
+
* @param string $method HTTP method that will be used to send the request.
|
88 |
+
* @param array $params HTTP request parameters (key-value array).
|
89 |
+
* @return array|bool HTTP response object.
|
90 |
*/
|
91 |
public static function apiCallFirewall($method = 'GET', $params = array())
|
92 |
{
|
93 |
+
$send_request = (bool) (isset($params['k']) && isset($params['s']));
|
94 |
+
|
95 |
+
if (!$send_request) {
|
96 |
+
$api_key = self::getKey();
|
97 |
|
98 |
+
if ($api_key) {
|
99 |
+
$send_request = true;
|
100 |
+
$params['k'] = $api_key['k'];
|
101 |
+
$params['s'] = $api_key['s'];
|
102 |
+
}
|
|
|
103 |
}
|
104 |
|
105 |
if ($send_request) {
|
117 |
* request to the remote API service and process its response, when successful
|
118 |
* it will return an array/object containing the public attributes of the site.
|
119 |
*
|
120 |
+
* @param array|bool $api_key The firewall API key.
|
121 |
+
* @return array|bool A hash with the settings of a firewall account.
|
122 |
*/
|
123 |
public static function settings($api_key = false)
|
124 |
{
|
158 |
|
159 |
if (self::isValidKey($api_key)) {
|
160 |
SucuriScanOption::updateOption($option_name, $api_key);
|
161 |
+
SucuriScanInterface::info('Firewall API key was successfully saved');
|
162 |
SucuriScanOption::setRevProxy('enable');
|
163 |
SucuriScanOption::setAddrHeader('HTTP_X_SUCURI_CLIENTIP');
|
164 |
} else {
|
165 |
+
SucuriScanInterface::error('Invalid firewall API key');
|
166 |
}
|
167 |
}
|
168 |
|
169 |
// Delete the firewall API key from the plugin.
|
170 |
if (SucuriScanRequest::post(':delete_wafkey') !== false) {
|
171 |
SucuriScanOption::deleteOption($option_name);
|
172 |
+
SucuriScanInterface::info('Firewall API key was successfully removed');
|
173 |
SucuriScanOption::setRevProxy('disable');
|
174 |
SucuriScanOption::setAddrHeader('REMOTE_ADDR');
|
175 |
}
|
191 |
* text, for example changing numbers or variable names into a more explicit
|
192 |
* text so the administrator can understand the meaning of these settings.
|
193 |
*
|
194 |
+
* @param array $settings A hash with the settings of a firewall account.
|
195 |
+
* @return array The explained version of the firewall settings.
|
196 |
*/
|
197 |
public static function settingsExplanation($settings = array())
|
198 |
{
|
199 |
if (!is_array($settings)) {
|
200 |
+
return array();
|
201 |
}
|
202 |
|
203 |
$cache_modes = array(
|
204 |
+
'docache' => 'enabled (recommended)',
|
205 |
+
'sitecache' => 'site caching (using your site headers)',
|
206 |
+
'nocache' => 'minimal (only for a few minutes)',
|
207 |
+
'nocacheatall' => 'caching disabled (use with caution)',
|
208 |
);
|
209 |
|
210 |
foreach ($settings as $keyname => $value) {
|
211 |
if ($keyname == 'proxy_active') {
|
212 |
+
$settings[$keyname] = ($value === 1) ? 'active' : 'not active';
|
213 |
+
continue;
|
214 |
+
}
|
215 |
+
|
216 |
+
if ($keyname == 'cache_mode') {
|
217 |
if (array_key_exists($value, $cache_modes)) {
|
218 |
$settings[$keyname] = $cache_modes[$value];
|
219 |
} else {
|
220 |
+
$settings[$keyname] = 'unknown';
|
221 |
}
|
222 |
+
continue;
|
223 |
}
|
224 |
}
|
225 |
|
230 |
* Returns the public firewall settings.
|
231 |
*
|
232 |
* @codeCoverageIgnore
|
233 |
+
*
|
234 |
+
* @return void
|
235 |
*/
|
236 |
public static function getSettingsAjax()
|
237 |
{
|
250 |
if (!$settings) {
|
251 |
if (empty($error)) {
|
252 |
ob_start();
|
253 |
+
SucuriScanInterface::error('Firewall API key was not found.');
|
254 |
$response['error'] = ob_get_clean();
|
255 |
} else {
|
256 |
$response['error'] = $error;
|
278 |
* the logs of previous days you will need to add a new parameter to the request
|
279 |
* URL named "date" with format yyyy-mm-dd.
|
280 |
*
|
281 |
+
* @param array|string $api_key The firewall API key.
|
282 |
+
* @param string $date Retrieve the data from this date.
|
283 |
+
* @param string $query Filter the data to match this query.
|
284 |
+
* @param int $limit Retrieve this maximum of data.
|
285 |
+
* @param int $offset Retrieve the data from this point.
|
286 |
+
* @return array|bool Objects with details of each blocked request.
|
287 |
*/
|
288 |
public static function auditlogs($api_key, $date = '', $query = '', $limit = 10, $offset = 0)
|
289 |
{
|
332 |
* feature. The plugin will display a warning in this case.
|
333 |
*
|
334 |
* @codeCoverageIgnore
|
335 |
+
*
|
336 |
+
* @return void
|
337 |
*/
|
338 |
public static function auditlogsAjax()
|
339 |
{
|
346 |
|
347 |
if (!$api_key) {
|
348 |
ob_start();
|
349 |
+
SucuriScanInterface::error('Firewall API key was not found.');
|
350 |
$response = ob_get_clean();
|
351 |
wp_send_json($response, 200);
|
352 |
}
|
382 |
$response = self::auditlogsEntries($auditlogs['access_logs']);
|
383 |
|
384 |
if (empty($response)) {
|
385 |
+
$response = '<tr><td>no data available.</td></tr>';
|
386 |
}
|
387 |
}
|
388 |
|
392 |
/**
|
393 |
* Returns the security logs from the firewall in HTML.
|
394 |
*
|
395 |
+
* @param array $entries Security logs retrieved from the Firewall API.
|
396 |
+
* @return string HTML with the information from the logs.
|
397 |
*/
|
398 |
public static function auditlogsEntries($entries = array())
|
399 |
{
|
454 |
/**
|
455 |
* Get a list of years, months or days depending of the type specified.
|
456 |
*
|
457 |
+
* @param string $type Either years, months or days.
|
458 |
+
* @param string $date Year, month and day selected from the request.
|
459 |
+
* @param bool $in_html Whether the list should be converted to a HTML select options or not.
|
460 |
+
* @return array|string Either an array with the expected values, or a HTML code.
|
461 |
*/
|
462 |
public static function dates($type = '', $date = '', $in_html = true)
|
463 |
{
|
485 |
case 'months':
|
486 |
$selected = $s_month;
|
487 |
$options = array(
|
488 |
+
'01' => 'January',
|
489 |
+
'02' => 'February',
|
490 |
+
'03' => 'March',
|
491 |
+
'04' => 'April',
|
492 |
+
'05' => 'May',
|
493 |
+
'06' => 'June',
|
494 |
+
'07' => 'July',
|
495 |
+
'08' => 'August',
|
496 |
+
'09' => 'September',
|
497 |
+
'10' => 'October',
|
498 |
+
'11' => 'November',
|
499 |
+
'12' => 'December',
|
500 |
);
|
501 |
break;
|
502 |
|
544 |
* Returns the whitelisted and blacklisted IP addresses.
|
545 |
*
|
546 |
* @codeCoverageIgnore
|
547 |
+
*
|
548 |
+
* @return void
|
549 |
*/
|
550 |
public static function ipAccessAjax()
|
551 |
{
|
564 |
if (!$settings) {
|
565 |
if (empty($error)) {
|
566 |
ob_start();
|
567 |
+
SucuriScanInterface::error('Firewall API key was not found.');
|
568 |
$response['error'] = ob_get_clean();
|
569 |
} else {
|
570 |
$response['error'] = $error;
|
584 |
* Blacklists an IP address.
|
585 |
*
|
586 |
* @codeCoverageIgnore
|
587 |
+
*
|
588 |
+
* @return void
|
589 |
*/
|
590 |
public static function blacklistAjax()
|
591 |
{
|
599 |
|
600 |
if (!$params) {
|
601 |
ob_start();
|
602 |
+
SucuriScanInterface::error('Firewall API key was not found.');
|
603 |
$response['msg'] = ob_get_clean();
|
604 |
wp_send_json($response, 200);
|
605 |
}
|
614 |
$response['msg'] = implode(";\x20", $out['messages']);
|
615 |
|
616 |
if ($out['status'] == 1) {
|
617 |
+
SucuriScanEvent::reportInfoEvent('IP has been blacklisted: ' . $params['ip']);
|
|
|
618 |
}
|
619 |
}
|
620 |
|
625 |
* Deletes an IP address from the blacklist.
|
626 |
*
|
627 |
* @codeCoverageIgnore
|
628 |
+
*
|
629 |
+
* @return void
|
630 |
*/
|
631 |
public static function deblacklistAjax()
|
632 |
{
|
640 |
if (!$params) {
|
641 |
ob_start();
|
642 |
$response['ok'] = false;
|
643 |
+
SucuriScanInterface::error('Firewall API key was not found.');
|
644 |
$response['error'] = ob_get_clean();
|
645 |
wp_send_json($response, 200);
|
646 |
}
|
653 |
$response['msg'] = implode(";\x20", $out['messages']);
|
654 |
|
655 |
if ($out['status'] == 1) {
|
656 |
+
SucuriScanEvent::reportInfoEvent('IP has been unblacklisted: ' . $params['ip']);
|
|
|
657 |
}
|
658 |
|
659 |
wp_send_json($response, 200);
|
662 |
/**
|
663 |
* Flush the cache of the site(s) associated with the API key.
|
664 |
*
|
665 |
+
* @param array|bool $api_key The firewall API key.
|
666 |
+
* @return string|bool Message explaining the result of the operation.
|
667 |
*/
|
668 |
public static function clearCache($api_key = false)
|
669 |
{
|
670 |
+
$params = array('a' => 'clear_cache');
|
671 |
|
672 |
if (is_array($api_key)) {
|
673 |
$params = array_merge($params, $api_key);
|
689 |
{
|
690 |
$params = array();
|
691 |
|
692 |
+
$params['FirewallAutoClearCache'] = 'data-status="disabled"';
|
693 |
+
|
694 |
+
if (SucuriScanOption::isEnabled(':auto_clear_cache')) {
|
695 |
+
$params['FirewallAutoClearCache'] = 'checked="checked"';
|
696 |
+
}
|
697 |
|
698 |
return SucuriScanTemplate::getSection('firewall-clearcache', $params);
|
699 |
}
|
707 |
* of certain files is going to stay as it is due to the configuration on the
|
708 |
* edge of the servers.
|
709 |
*
|
710 |
+
* @return void
|
711 |
*/
|
712 |
+
public static function clearCacheHook()
|
713 |
{
|
714 |
if (SucuriScanOption::isEnabled(':auto_clear_cache')) {
|
715 |
ob_start();
|
722 |
* Requests a cache flush to the firewall service.
|
723 |
*
|
724 |
* @codeCoverageIgnore
|
725 |
+
*
|
726 |
+
* @return void
|
727 |
*/
|
728 |
public static function clearCacheAjax()
|
729 |
{
|
732 |
}
|
733 |
|
734 |
ob_start();
|
735 |
+
SucuriScanInterface::error('Firewall API key was not found.');
|
736 |
$response = ob_get_clean();
|
737 |
+
$api_key = self::getKey();
|
738 |
|
739 |
+
if ($api_key) {
|
740 |
$res = self::clearCache($api_key);
|
741 |
|
742 |
if (is_array($res) && isset($res['messages'])) {
|
755 |
* Configures the status of the automatic cache flush.
|
756 |
*
|
757 |
* @codeCoverageIgnore
|
758 |
+
*
|
759 |
+
* @return void
|
760 |
*/
|
761 |
public static function clearAutoCacheAjax()
|
762 |
{
|
src/fsscanner.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the fsscanner.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -24,14 +30,22 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
24 |
* with the current content to establish what content has been updated. Updated
|
25 |
* content is then submitted to the remote server and it is stored for future
|
26 |
* analysis.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
*/
|
28 |
class SucuriScanFSScanner extends SucuriScan
|
29 |
{
|
30 |
/**
|
31 |
* Retrieve the last time when the filesystem scan was ran.
|
32 |
*
|
33 |
-
* @param
|
34 |
-
* @return string
|
35 |
*/
|
36 |
public static function getFilesystemRuntime($format = false)
|
37 |
{
|
@@ -51,8 +65,8 @@ class SucuriScanFSScanner extends SucuriScan
|
|
51 |
/**
|
52 |
* Add a new directory path to the list of ignored paths.
|
53 |
*
|
54 |
-
* @param
|
55 |
-
* @return bool
|
56 |
*/
|
57 |
public static function ignoreDirectory($path = '')
|
58 |
{
|
@@ -70,8 +84,8 @@ class SucuriScanFSScanner extends SucuriScan
|
|
70 |
/**
|
71 |
* Remove a directory path from the list of ignored paths.
|
72 |
*
|
73 |
-
* @param
|
74 |
-
* @return bool
|
75 |
*/
|
76 |
public static function unignoreDirectory($path = '')
|
77 |
{
|
@@ -81,25 +95,16 @@ class SucuriScanFSScanner extends SucuriScan
|
|
81 |
}
|
82 |
|
83 |
/**
|
84 |
-
*
|
85 |
-
*
|
86 |
-
* Retrieve a list of directory paths that will be ignored during the file
|
87 |
-
* system scans, any sub-directory and files inside these folders will be
|
88 |
-
* skipped automatically and will not be used to detect malware or modifications
|
89 |
-
* in the site.
|
90 |
*
|
91 |
-
* The
|
92 |
-
* by four (4) indexes which will facilitate the execution of common conditions
|
93 |
-
* in the implementation code.
|
94 |
*
|
95 |
-
*
|
96 |
-
*
|
97 |
-
*
|
98 |
-
*
|
99 |
-
* <li>ignored_at_list: Will contains a list of timestamps for when the directories were ignored.</li>
|
100 |
-
* </ul>
|
101 |
*
|
102 |
-
* @return array List of ignored
|
103 |
*/
|
104 |
public static function getIgnoredDirectories()
|
105 |
{
|
@@ -112,15 +117,13 @@ class SucuriScanFSScanner extends SucuriScan
|
|
112 |
|
113 |
$cache = new SucuriScanCache('ignorescanning');
|
114 |
$cache_lifetime = 0; // It is not necessary to expire this cache.
|
115 |
-
$
|
116 |
|
117 |
-
if ($
|
118 |
-
$response['raw'] = $
|
119 |
|
120 |
-
foreach ($
|
121 |
-
if (
|
122 |
-
&& array_key_exists('ignored_at', $data)
|
123 |
-
) {
|
124 |
$response['checksums'][] = $checksum;
|
125 |
$response['directories'][] = $data['directory_path'];
|
126 |
$response['ignored_at_list'][] = $data['ignored_at'];
|
@@ -130,41 +133,4 @@ class SucuriScanFSScanner extends SucuriScan
|
|
130 |
|
131 |
return $response;
|
132 |
}
|
133 |
-
|
134 |
-
/**
|
135 |
-
* Run file system scan and retrieve ignored folders.
|
136 |
-
*
|
137 |
-
* Run a file system scan and retrieve an array with two indexes, the first
|
138 |
-
* containing a list of ignored directory paths and their respective timestamps
|
139 |
-
* of when they were added by an administrator user, and the second containing a
|
140 |
-
* list of directories that are not being ignored.
|
141 |
-
*
|
142 |
-
* @return array List of ignored and not ignored directories.
|
143 |
-
*/
|
144 |
-
public static function getIgnoredDirectoriesLive()
|
145 |
-
{
|
146 |
-
$response = array(
|
147 |
-
'is_ignored' => array(),
|
148 |
-
'is_not_ignored' => array(),
|
149 |
-
);
|
150 |
-
|
151 |
-
// Get the ignored directories from the cache.
|
152 |
-
$ignored_directories = self::getIgnoredDirectories();
|
153 |
-
|
154 |
-
if ($ignored_directories) {
|
155 |
-
$response['is_ignored'] = $ignored_directories['raw'];
|
156 |
-
}
|
157 |
-
|
158 |
-
// Scan the project and file all directories.
|
159 |
-
$file_info = new SucuriScanFileInfo();
|
160 |
-
$file_info->ignore_files = true;
|
161 |
-
$file_info->ignore_directories = true;
|
162 |
-
$directory_list = $file_info->getDirectoriesOnly(ABSPATH);
|
163 |
-
|
164 |
-
if ($directory_list) {
|
165 |
-
$response['is_not_ignored'] = $directory_list;
|
166 |
-
}
|
167 |
-
|
168 |
-
return $response;
|
169 |
-
}
|
170 |
}
|
3 |
/**
|
4 |
* Code related to the fsscanner.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
30 |
* with the current content to establish what content has been updated. Updated
|
31 |
* content is then submitted to the remote server and it is stored for future
|
32 |
* analysis.
|
33 |
+
*
|
34 |
+
* @category Library
|
35 |
+
* @package Sucuri
|
36 |
+
* @subpackage SucuriScanner
|
37 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
38 |
+
* @copyright 2010-2017 Sucuri Inc.
|
39 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
40 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
41 |
*/
|
42 |
class SucuriScanFSScanner extends SucuriScan
|
43 |
{
|
44 |
/**
|
45 |
* Retrieve the last time when the filesystem scan was ran.
|
46 |
*
|
47 |
+
* @param bool $format Whether the timestamp must be formatted as date/time or not.
|
48 |
+
* @return string The timestamp of the runtime, or an string with the date/time.
|
49 |
*/
|
50 |
public static function getFilesystemRuntime($format = false)
|
51 |
{
|
65 |
/**
|
66 |
* Add a new directory path to the list of ignored paths.
|
67 |
*
|
68 |
+
* @param string $path The (full) absolute path of a directory.
|
69 |
+
* @return bool TRUE if the directory path was added to the list, FALSE otherwise.
|
70 |
*/
|
71 |
public static function ignoreDirectory($path = '')
|
72 |
{
|
84 |
/**
|
85 |
* Remove a directory path from the list of ignored paths.
|
86 |
*
|
87 |
+
* @param string $path The (full) absolute path of a directory.
|
88 |
+
* @return bool TRUE if the directory path was removed to the list, FALSE otherwise.
|
89 |
*/
|
90 |
public static function unignoreDirectory($path = '')
|
91 |
{
|
95 |
}
|
96 |
|
97 |
/**
|
98 |
+
* Returns a list of ignored directories.
|
|
|
|
|
|
|
|
|
|
|
99 |
*
|
100 |
+
* The method returns an array with the following keys:
|
|
|
|
|
101 |
*
|
102 |
+
* - raw: Contains the raw data from the local cache.
|
103 |
+
* - checksums: Contains the md5 of all the directories.
|
104 |
+
* - directories: Contains a list of directories.
|
105 |
+
* - ignored_at_list: Contains a list of timestamps.
|
|
|
|
|
106 |
*
|
107 |
+
* @return array List of ignored directories.
|
108 |
*/
|
109 |
public static function getIgnoredDirectories()
|
110 |
{
|
117 |
|
118 |
$cache = new SucuriScanCache('ignorescanning');
|
119 |
$cache_lifetime = 0; // It is not necessary to expire this cache.
|
120 |
+
$entries = $cache->getAll($cache_lifetime, 'array');
|
121 |
|
122 |
+
if ($entries) {
|
123 |
+
$response['raw'] = $entries;
|
124 |
|
125 |
+
foreach ($entries as $checksum => $data) {
|
126 |
+
if (isset($data['directory_path']) && isset($data['ignored_at'])) {
|
|
|
|
|
127 |
$response['checksums'][] = $checksum;
|
128 |
$response['directories'][] = $data['directory_path'];
|
129 |
$response['ignored_at_list'][] = $data['ignored_at'];
|
133 |
|
134 |
return $response;
|
135 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
}
|
src/globals.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the globals.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -69,102 +75,16 @@ if (defined('SUCURISCAN')) {
|
|
69 |
*
|
70 |
* @return array List of sub-pages of this plugin.
|
71 |
*/
|
72 |
-
function
|
73 |
{
|
74 |
return array(
|
75 |
-
'sucuriscan' =>
|
76 |
-
'sucuriscan_firewall' =>
|
77 |
-
'sucuriscan_lastlogins' =>
|
78 |
-
'sucuriscan_settings' =>
|
79 |
);
|
80 |
}
|
81 |
|
82 |
-
if (function_exists('load_plugin_textdomain')) {
|
83 |
-
/**
|
84 |
-
* Loads the language files for the entire interface.
|
85 |
-
*
|
86 |
-
* Internationalization is the process of developing your plugin so it
|
87 |
-
* can be translated into other languages. Localization describes the
|
88 |
-
* process of translating an internationalized plugin. Internationaliza-
|
89 |
-
* tion is often abbreviated as i18n (there are 18 letters between the
|
90 |
-
* i and the n) and localization is abbreviated as l10n (there are 10
|
91 |
-
* letters between the l and the n).
|
92 |
-
*
|
93 |
-
* @see https://codex.wordpress.org/I18n_for_WordPress_Developers
|
94 |
-
*/
|
95 |
-
function sucuriscan_load_plugin_textdomain()
|
96 |
-
{
|
97 |
-
global $locale;
|
98 |
-
|
99 |
-
$default_locale = 'en_US';
|
100 |
-
$pofile = sprintf(
|
101 |
-
'%s/languages/%s-%s.po',
|
102 |
-
SUCURISCAN_PLUGIN_PATH,
|
103 |
-
SUCURISCAN_TEXTDOMAIN,
|
104 |
-
$locale
|
105 |
-
);
|
106 |
-
$mofile = sprintf(
|
107 |
-
'%s/languages/%s-%s.mo',
|
108 |
-
SUCURISCAN_PLUGIN_PATH,
|
109 |
-
SUCURISCAN_TEXTDOMAIN,
|
110 |
-
$locale
|
111 |
-
);
|
112 |
-
|
113 |
-
/* attempt to import the English POT file into LOCALE */
|
114 |
-
if (!file_exists($pofile) || !file_exists($mofile)) {
|
115 |
-
$fallback = array(
|
116 |
-
'en_NZ' => 'en_US', /* English (New Zealand) */
|
117 |
-
'en_CA' => 'en_US', /* English (Canada) */
|
118 |
-
'en_ZA' => 'en_US', /* English (South Africa) */
|
119 |
-
'en_GB' => 'en_US', /* English (UK) */
|
120 |
-
'en_AU' => 'en_US', /* English (Australia) */
|
121 |
-
'es_AR' => 'es_ES', /* Español de Argentina */
|
122 |
-
'es_MX' => 'es_ES', /* Español de México */
|
123 |
-
'es_CO' => 'es_ES', /* Español de Colombia */
|
124 |
-
'es_GT' => 'es_ES', /* Español de Guatemala */
|
125 |
-
'es_VE' => 'es_ES', /* Español de Venezuela */
|
126 |
-
'es_CL' => 'es_ES', /* Español de Chile */
|
127 |
-
'es_PE' => 'es_ES', /* Español de Perú */
|
128 |
-
);
|
129 |
-
|
130 |
-
/* try to find a similar translation */
|
131 |
-
if (array_key_exists($locale, $fallback)) {
|
132 |
-
$default_locale = $fallback[$locale];
|
133 |
-
}
|
134 |
-
|
135 |
-
$en_pofile = sprintf(
|
136 |
-
'%s/languages/%s-%s.po',
|
137 |
-
SUCURISCAN_PLUGIN_PATH,
|
138 |
-
SUCURISCAN_TEXTDOMAIN,
|
139 |
-
$default_locale
|
140 |
-
);
|
141 |
-
$en_mofile = sprintf(
|
142 |
-
'%s/languages/%s-%s.mo',
|
143 |
-
SUCURISCAN_PLUGIN_PATH,
|
144 |
-
SUCURISCAN_TEXTDOMAIN,
|
145 |
-
$default_locale
|
146 |
-
);
|
147 |
-
|
148 |
-
@copy($en_pofile, $pofile);
|
149 |
-
@copy($en_mofile, $mofile);
|
150 |
-
}
|
151 |
-
|
152 |
-
/* fallback to English on language import failure */
|
153 |
-
if (!file_exists($pofile) || !file_exists($mofile)) {
|
154 |
-
$locale = $default_locale;
|
155 |
-
setlocale(LC_ALL, $default_locale);
|
156 |
-
}
|
157 |
-
|
158 |
-
load_plugin_textdomain(
|
159 |
-
SUCURISCAN_TEXTDOMAIN,
|
160 |
-
false, /* deprecated */
|
161 |
-
SUCURISCAN_PLUGIN_FOLDER . '/languages/'
|
162 |
-
);
|
163 |
-
}
|
164 |
-
|
165 |
-
add_action('init', 'sucuriscan_load_plugin_textdomain');
|
166 |
-
}
|
167 |
-
|
168 |
if (function_exists('add_action')) {
|
169 |
/**
|
170 |
* Display extension menu and submenu items in the correct interface.
|
@@ -174,10 +94,12 @@ if (defined('SUCURISCAN')) {
|
|
174 |
* administration panel of the subsites.
|
175 |
*
|
176 |
* @codeCoverageIgnore
|
|
|
|
|
177 |
*/
|
178 |
-
function
|
179 |
{
|
180 |
-
$pages =
|
181 |
|
182 |
add_menu_page(
|
183 |
'Sucuri Security',
|
@@ -201,7 +123,7 @@ if (defined('SUCURISCAN')) {
|
|
201 |
}
|
202 |
|
203 |
/* Attach HTTP request handlers for the internal plugin pages */
|
204 |
-
add_action($sucuriscan_action_prefix . 'admin_menu', '
|
205 |
|
206 |
/* Attach HTTP request handlers for the AJAX requests */
|
207 |
add_action('wp_ajax_sucuriscan_ajax', 'sucuriscan_ajax');
|
3 |
/**
|
4 |
* Code related to the globals.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
75 |
*
|
76 |
* @return array List of sub-pages of this plugin.
|
77 |
*/
|
78 |
+
function sucuriscanMainPages()
|
79 |
{
|
80 |
return array(
|
81 |
+
'sucuriscan' => 'Dashboard',
|
82 |
+
'sucuriscan_firewall' => 'Firewall (WAF)',
|
83 |
+
'sucuriscan_lastlogins' => 'Last Logins',
|
84 |
+
'sucuriscan_settings' => 'Settings',
|
85 |
);
|
86 |
}
|
87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
if (function_exists('add_action')) {
|
89 |
/**
|
90 |
* Display extension menu and submenu items in the correct interface.
|
94 |
* administration panel of the subsites.
|
95 |
*
|
96 |
* @codeCoverageIgnore
|
97 |
+
*
|
98 |
+
* @return void
|
99 |
*/
|
100 |
+
function sucuriscanAddMenuPage()
|
101 |
{
|
102 |
+
$pages = sucuriscanMainPages();
|
103 |
|
104 |
add_menu_page(
|
105 |
'Sucuri Security',
|
123 |
}
|
124 |
|
125 |
/* Attach HTTP request handlers for the internal plugin pages */
|
126 |
+
add_action($sucuriscan_action_prefix . 'admin_menu', 'sucuriscanAddMenuPage');
|
127 |
|
128 |
/* Attach HTTP request handlers for the AJAX requests */
|
129 |
add_action('wp_ajax_sucuriscan_ajax', 'sucuriscan_ajax');
|
src/hardening.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the hardening.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -33,6 +39,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
33 |
* scripts and tools like Bastille Linux, JASS for Solaris systems and
|
34 |
* Apache/PHP Hardener that can, for example, deactivate unneeded features in
|
35 |
* configuration files or perform various other protective measures.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
*/
|
37 |
class SucuriScanHardening extends SucuriScan
|
38 |
{
|
@@ -65,8 +79,8 @@ class SucuriScanHardening extends SucuriScan
|
|
65 |
* The permissions to modify the file are checked before anything else, this
|
66 |
* method is self-contained.
|
67 |
*
|
68 |
-
* @param
|
69 |
-
* @return bool
|
70 |
*/
|
71 |
public static function hardenDirectory($directory = '')
|
72 |
{
|
@@ -97,8 +111,8 @@ class SucuriScanHardening extends SucuriScan
|
|
97 |
* all files with certain extension in any mixed case. The file is truncated if
|
98 |
* after the operation its size is equals to zero.
|
99 |
*
|
100 |
-
* @param
|
101 |
-
* @return bool
|
102 |
*/
|
103 |
public static function unhardenDirectory($directory = '')
|
104 |
{
|
@@ -124,8 +138,8 @@ class SucuriScanHardening extends SucuriScan
|
|
124 |
/**
|
125 |
* Remove the hardening applied in previous versions.
|
126 |
*
|
127 |
-
* @param
|
128 |
-
* @return bool
|
129 |
*/
|
130 |
private static function fixPreviousHardening($directory = '')
|
131 |
{
|
@@ -147,8 +161,8 @@ class SucuriScanHardening extends SucuriScan
|
|
147 |
/**
|
148 |
* Check whether a directory is hardened or not.
|
149 |
*
|
150 |
-
* @param
|
151 |
-
* @return bool
|
152 |
*/
|
153 |
public static function isHardened($directory = '')
|
154 |
{
|
@@ -167,8 +181,8 @@ class SucuriScanHardening extends SucuriScan
|
|
167 |
/**
|
168 |
* Returns the path to the Apache access control file.
|
169 |
*
|
170 |
-
* @param
|
171 |
-
* @return string
|
172 |
*/
|
173 |
private static function htaccess($folder = '')
|
174 |
{
|
@@ -186,8 +200,8 @@ class SucuriScanHardening extends SucuriScan
|
|
186 |
* can send a direct request to it. The method will generate both the rules
|
187 |
* for Apache 2.4 and a compatibility conditional for older versions.
|
188 |
*
|
189 |
-
* @param
|
190 |
-
* @return string
|
191 |
*/
|
192 |
private static function whitelistRule($file = '')
|
193 |
{
|
@@ -217,20 +231,20 @@ class SucuriScanHardening extends SucuriScan
|
|
217 |
* admin can ignore this hardening in one or more files if direct access to
|
218 |
* it is required, as is the case with some 3rd-party plugins and themes.
|
219 |
*
|
220 |
-
* @param
|
221 |
-
* @param
|
222 |
-
* @return bool
|
223 |
*/
|
224 |
public static function whitelist($file = '', $folder = '')
|
225 |
{
|
226 |
$htaccess = self::htaccess($folder);
|
227 |
|
228 |
if (!file_exists($htaccess)) {
|
229 |
-
throw new Exception(
|
230 |
}
|
231 |
|
232 |
if (!is_writable($htaccess)) {
|
233 |
-
throw new Exception(
|
234 |
}
|
235 |
|
236 |
return (bool) @file_put_contents(
|
@@ -250,9 +264,9 @@ class SucuriScanHardening extends SucuriScan
|
|
250 |
* theme required it, they can decide to revert the whitelisting using this
|
251 |
* method which is executed by one of the tools in the settings page.
|
252 |
*
|
253 |
-
* @param
|
254 |
-
* @param
|
255 |
-
* @return bool
|
256 |
*/
|
257 |
public static function dewhitelist($file = '', $folder = '')
|
258 |
{
|
@@ -273,8 +287,8 @@ class SucuriScanHardening extends SucuriScan
|
|
273 |
/**
|
274 |
* Returns a list of whitelisted files in folder.
|
275 |
*
|
276 |
-
* @param
|
277 |
-
* @return array
|
278 |
*/
|
279 |
public static function getWhitelisted($folder = '')
|
280 |
{
|
@@ -282,6 +296,6 @@ class SucuriScanHardening extends SucuriScan
|
|
282 |
$content = SucuriScanFileInfo::fileContent($htaccess);
|
283 |
@preg_match_all('/<Files (\S+)>/', $content, $matches);
|
284 |
|
285 |
-
return $matches[1]
|
286 |
}
|
287 |
}
|
3 |
/**
|
4 |
* Code related to the hardening.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
39 |
* scripts and tools like Bastille Linux, JASS for Solaris systems and
|
40 |
* Apache/PHP Hardener that can, for example, deactivate unneeded features in
|
41 |
* configuration files or perform various other protective measures.
|
42 |
+
*
|
43 |
+
* @category Library
|
44 |
+
* @package Sucuri
|
45 |
+
* @subpackage SucuriScanner
|
46 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
47 |
+
* @copyright 2010-2017 Sucuri Inc.
|
48 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
49 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
50 |
*/
|
51 |
class SucuriScanHardening extends SucuriScan
|
52 |
{
|
79 |
* The permissions to modify the file are checked before anything else, this
|
80 |
* method is self-contained.
|
81 |
*
|
82 |
+
* @param string $directory Valid directory path where to place the access rules.
|
83 |
+
* @return bool True if the rules are successfully added, false otherwise.
|
84 |
*/
|
85 |
public static function hardenDirectory($directory = '')
|
86 |
{
|
111 |
* all files with certain extension in any mixed case. The file is truncated if
|
112 |
* after the operation its size is equals to zero.
|
113 |
*
|
114 |
+
* @param string $directory Valid directory path where to access rules are.
|
115 |
+
* @return bool True if the rules are successfully deleted, false otherwise.
|
116 |
*/
|
117 |
public static function unhardenDirectory($directory = '')
|
118 |
{
|
138 |
/**
|
139 |
* Remove the hardening applied in previous versions.
|
140 |
*
|
141 |
+
* @param string $directory Valid directory path.
|
142 |
+
* @return bool True if the access control file was fixed.
|
143 |
*/
|
144 |
private static function fixPreviousHardening($directory = '')
|
145 |
{
|
161 |
/**
|
162 |
* Check whether a directory is hardened or not.
|
163 |
*
|
164 |
+
* @param string $directory Valid directory path.
|
165 |
+
* @return bool True if the directory is hardened, false otherwise.
|
166 |
*/
|
167 |
public static function isHardened($directory = '')
|
168 |
{
|
181 |
/**
|
182 |
* Returns the path to the Apache access control file.
|
183 |
*
|
184 |
+
* @param string $folder Folder where the htaccess file is supposed to be.
|
185 |
+
* @return string Path to the htaccess file in the specified folder.
|
186 |
*/
|
187 |
private static function htaccess($folder = '')
|
188 |
{
|
200 |
* can send a direct request to it. The method will generate both the rules
|
201 |
* for Apache 2.4 and a compatibility conditional for older versions.
|
202 |
*
|
203 |
+
* @param string $file File to be ignored by the hardening.
|
204 |
+
* @return string Access control rules to whitelist the file.
|
205 |
*/
|
206 |
private static function whitelistRule($file = '')
|
207 |
{
|
231 |
* admin can ignore this hardening in one or more files if direct access to
|
232 |
* it is required, as is the case with some 3rd-party plugins and themes.
|
233 |
*
|
234 |
+
* @param string $file File to be ignored by the hardening.
|
235 |
+
* @param string $folder Folder hosting the specified file.
|
236 |
+
* @return bool True if the file has been whitelisted, false otherwise.
|
237 |
*/
|
238 |
public static function whitelist($file = '', $folder = '')
|
239 |
{
|
240 |
$htaccess = self::htaccess($folder);
|
241 |
|
242 |
if (!file_exists($htaccess)) {
|
243 |
+
throw new Exception('Access control file does not exists');
|
244 |
}
|
245 |
|
246 |
if (!is_writable($htaccess)) {
|
247 |
+
throw new Exception('Access control file is not writable');
|
248 |
}
|
249 |
|
250 |
return (bool) @file_put_contents(
|
264 |
* theme required it, they can decide to revert the whitelisting using this
|
265 |
* method which is executed by one of the tools in the settings page.
|
266 |
*
|
267 |
+
* @param string $file File to stop ignoring from the hardening.
|
268 |
+
* @param string $folder Folder hosting the specified file.
|
269 |
+
* @return bool True if the file has been dewhitelisted, false otherwise.
|
270 |
*/
|
271 |
public static function dewhitelist($file = '', $folder = '')
|
272 |
{
|
287 |
/**
|
288 |
* Returns a list of whitelisted files in folder.
|
289 |
*
|
290 |
+
* @param string $folder Directory to scan for whitelisted files.
|
291 |
+
* @return array List of whitelisted files, false on failure.
|
292 |
*/
|
293 |
public static function getWhitelisted($folder = '')
|
294 |
{
|
296 |
$content = SucuriScanFileInfo::fileContent($htaccess);
|
297 |
@preg_match_all('/<Files (\S+)>/', $content, $matches);
|
298 |
|
299 |
+
return $matches[1];
|
300 |
}
|
301 |
}
|
src/hook.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the hook.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -22,27 +28,38 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
22 |
* The term hooking covers a range of techniques used to alter or augment the
|
23 |
* behavior of an operating system, of applications, or of other software
|
24 |
* components by intercepting method calls or messages or events passed
|
25 |
-
* between software components. Code that handles such intercepted
|
|
|
26 |
*
|
27 |
* Hooking is used for many purposes, including debugging and extending
|
28 |
* functionality. Examples might include intercepting keyboard or mouse event
|
29 |
* messages before they reach an application, or intercepting operating system
|
30 |
* calls in order to monitor behavior or modify the method of an application
|
31 |
* or other component; it is also widely used in benchmarking programs.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
*/
|
33 |
class SucuriScanHook extends SucuriScanEvent
|
34 |
{
|
35 |
/**
|
36 |
* Send to Sucuri servers an alert notifying that an attachment was added to a post.
|
37 |
*
|
38 |
-
* @param
|
|
|
39 |
*/
|
40 |
public static function hookAttachmentAdd($id = 0)
|
41 |
{
|
42 |
$title = 'unknown';
|
43 |
$mime_type = 'unknown';
|
|
|
44 |
|
45 |
-
if ($data
|
46 |
$id = $data->ID;
|
47 |
$title = $data->post_title;
|
48 |
$mime_type = $data->post_mime_type;
|
@@ -56,7 +73,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
56 |
/**
|
57 |
* Send an alert notifying that a category was created.
|
58 |
*
|
59 |
-
* @param
|
|
|
60 |
*/
|
61 |
public static function hookCategoryCreate($id = 0)
|
62 |
{
|
@@ -67,10 +85,10 @@ class SucuriScanHook extends SucuriScanEvent
|
|
67 |
self::notifyEvent('post_publication', $message);
|
68 |
}
|
69 |
|
70 |
-
// TODO: Detect auto updates in core, themes, and plugin files.
|
71 |
-
|
72 |
/**
|
73 |
* Detects when the core files are updated.
|
|
|
|
|
74 |
*/
|
75 |
public static function hookCoreUpdate()
|
76 |
{
|
@@ -88,15 +106,17 @@ class SucuriScanHook extends SucuriScanEvent
|
|
88 |
/**
|
89 |
* Send an alert notifying that a new link was added to the bookmarks.
|
90 |
*
|
91 |
-
* @param
|
|
|
92 |
*/
|
93 |
public static function hookLinkAdd($id = 0)
|
94 |
{
|
95 |
$title = 'unknown';
|
96 |
$target = '_none';
|
97 |
$url = 'undefined/url';
|
|
|
98 |
|
99 |
-
if ($data
|
100 |
$title = $data->link_name;
|
101 |
$target = $data->link_target;
|
102 |
$url = $data->link_url;
|
@@ -116,15 +136,17 @@ class SucuriScanHook extends SucuriScanEvent
|
|
116 |
/**
|
117 |
* Send an alert notifying that a new link was added to the bookmarks.
|
118 |
*
|
119 |
-
* @param
|
|
|
120 |
*/
|
121 |
public static function hookLinkEdit($id = 0)
|
122 |
{
|
123 |
$title = 'unknown';
|
124 |
$target = '_none';
|
125 |
$url = 'undefined/url';
|
|
|
126 |
|
127 |
-
if ($data
|
128 |
$title = $data->link_name;
|
129 |
$target = $data->link_target;
|
130 |
$url = $data->link_url;
|
@@ -145,7 +167,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
145 |
* Send an alert notifying that an attempt to login into the
|
146 |
* administration panel failed.
|
147 |
*
|
148 |
-
* @param
|
|
|
149 |
*/
|
150 |
public static function hookLoginFailure($title = '')
|
151 |
{
|
@@ -166,7 +189,9 @@ class SucuriScanHook extends SucuriScanEvent
|
|
166 |
self::notifyEvent('failed_login', $message);
|
167 |
|
168 |
/* report brute-force attack if necessary */
|
169 |
-
|
|
|
|
|
170 |
$max_time = 3600; /* report logins in the last hour */
|
171 |
$maximum = SucuriScanOption::getOption(':maximum_failed_logins');
|
172 |
|
@@ -193,19 +218,16 @@ class SucuriScanHook extends SucuriScanEvent
|
|
193 |
* a brute-force attack (if it exists) because the time passed
|
194 |
* between the first and last login attempt is big enough to
|
195 |
* mitigate the attack.
|
196 |
-
*
|
197 |
-
* We will consider the current failed login event as the first
|
198 |
-
* entry of that file in case of future attempts during the next
|
199 |
-
* sixty minutes.
|
200 |
*/
|
201 |
sucuriscan_reset_failed_logins();
|
202 |
-
sucuriscan_log_failed_login($title, $password);
|
203 |
}
|
204 |
}
|
205 |
}
|
206 |
|
207 |
/**
|
208 |
* Detects usage of the password reset form.
|
|
|
|
|
209 |
*/
|
210 |
public static function hookLoginFormResetpass()
|
211 |
{
|
@@ -219,7 +241,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
219 |
* Send an alert notifying that an attempt to login into the
|
220 |
* administration panel was successful.
|
221 |
*
|
222 |
-
* @param
|
|
|
223 |
*/
|
224 |
public static function hookLoginSuccess($title = '')
|
225 |
{
|
@@ -236,6 +259,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
236 |
* will compare the value sent with the form with the value in the database
|
237 |
* and if there are differences will send an email alert notifying the admin
|
238 |
* about the changes.
|
|
|
|
|
239 |
*/
|
240 |
public static function hookOptionsManagement()
|
241 |
{
|
@@ -265,8 +290,7 @@ class SucuriScanHook extends SucuriScanEvent
|
|
265 |
}
|
266 |
|
267 |
/* identify the origin of the request */
|
268 |
-
$option_page = isset($_POST['option_page'])
|
269 |
-
? $_POST['option_page'] : 'options';
|
270 |
$page_referer = 'Common';
|
271 |
|
272 |
switch ($option_page) {
|
@@ -286,11 +310,13 @@ class SucuriScanHook extends SucuriScanEvent
|
|
286 |
|
287 |
if ($options_changed_count) {
|
288 |
$message = $page_referer . ' settings changed';
|
289 |
-
self::reportErrorEvent(
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
|
|
|
|
294 |
self::notifyEvent('settings_updated', $message . "<br>\n" . $options_changed_str);
|
295 |
}
|
296 |
}
|
@@ -299,8 +325,9 @@ class SucuriScanHook extends SucuriScanEvent
|
|
299 |
/**
|
300 |
* Sends an alert with information about a plugin that has been activated.
|
301 |
*
|
302 |
-
* @param
|
303 |
-
* @param
|
|
|
304 |
*/
|
305 |
public static function hookPluginActivate($plugin = '', $network_activation = '')
|
306 |
{
|
@@ -316,11 +343,12 @@ class SucuriScanHook extends SucuriScanEvent
|
|
316 |
* able to detect a deactivation if the plugin has been deleted via FTP or
|
317 |
* SSH or any file manager available in the hosting panel.
|
318 |
*
|
319 |
-
* @param
|
320 |
-
* @param
|
321 |
-
* @param
|
|
|
322 |
*/
|
323 |
-
private static function hookPluginChanges($action, $plugin = '', $
|
324 |
{
|
325 |
$filename = WP_PLUGIN_DIR . '/' . $plugin;
|
326 |
|
@@ -342,11 +370,12 @@ class SucuriScanHook extends SucuriScanEvent
|
|
342 |
}
|
343 |
|
344 |
$message = sprintf(
|
345 |
-
'Plugin %s: %s (v%s; %s)',
|
346 |
$action, /* activated or deactivated */
|
347 |
self::escape($info['Name']),
|
348 |
self::escape($info['Version']),
|
349 |
-
self::escape($plugin)
|
|
|
350 |
);
|
351 |
self::reportWarningEvent($message);
|
352 |
self::notifyEvent('plugin_' . $action, $message);
|
@@ -355,8 +384,9 @@ class SucuriScanHook extends SucuriScanEvent
|
|
355 |
/**
|
356 |
* Sends an alert with information about a plugin that has been deactivated.
|
357 |
*
|
358 |
-
* @param
|
359 |
-
* @param
|
|
|
360 |
*/
|
361 |
public static function hookPluginDeactivate($plugin = '', $network_activation = '')
|
362 |
{
|
@@ -365,6 +395,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
365 |
|
366 |
/**
|
367 |
* Detects when a plugin is deleted.
|
|
|
|
|
368 |
*/
|
369 |
public static function hookPluginDelete()
|
370 |
{
|
@@ -399,13 +431,14 @@ class SucuriScanHook extends SucuriScanEvent
|
|
399 |
|
400 |
// Report deleted plugins at once.
|
401 |
if (!empty($items_affected)) {
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
);
|
|
|
409 |
self::reportWarningEvent($message);
|
410 |
self::notifyEvent('plugin_deleted', $message);
|
411 |
}
|
@@ -414,6 +447,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
414 |
|
415 |
/**
|
416 |
* Detects when the plugin editor is used.
|
|
|
|
|
417 |
*/
|
418 |
public static function hookPluginEditor()
|
419 |
{
|
@@ -433,6 +468,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
433 |
|
434 |
/**
|
435 |
* Detects when a plugin is uploaded or installed.
|
|
|
|
|
436 |
*/
|
437 |
public static function hookPluginInstall()
|
438 |
{
|
@@ -455,17 +492,20 @@ class SucuriScanHook extends SucuriScanEvent
|
|
455 |
|
456 |
/**
|
457 |
* Detects when a plugin is updated or upgraded.
|
|
|
|
|
458 |
*/
|
459 |
public static function hookPluginUpdate()
|
460 |
{
|
461 |
// Plugin update request.
|
462 |
$plugin_update_actions = '(upgrade-plugin|do-plugin-upgrade|update-selected)';
|
463 |
|
464 |
-
if (current_user_can('update_plugins')
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
|
|
469 |
) {
|
470 |
$plugin_list = array();
|
471 |
$items_affected = array();
|
@@ -498,13 +538,14 @@ class SucuriScanHook extends SucuriScanEvent
|
|
498 |
|
499 |
// Report updated plugins at once.
|
500 |
if (!empty($items_affected)) {
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
);
|
|
|
508 |
self::reportWarningEvent($message);
|
509 |
self::notifyEvent('plugin_updated', $message);
|
510 |
}
|
@@ -524,32 +565,37 @@ class SucuriScanHook extends SucuriScanEvent
|
|
524 |
* this informaiton to send it to the API. We will delete the temporary data
|
525 |
* after the operation has succeeded.
|
526 |
*
|
527 |
-
* @param
|
|
|
528 |
*/
|
529 |
public static function hookPostBeforeDelete($id = 0)
|
530 |
{
|
531 |
-
|
532 |
-
$out = array(); /* data to cache */
|
533 |
-
$cache = new SucuriScanCache('hookdata');
|
534 |
|
535 |
-
|
536 |
-
|
537 |
-
$out['type'] = $data->post_type;
|
538 |
-
$out['status'] = $data->post_status;
|
539 |
-
$out['inserted'] = $data->post_date;
|
540 |
-
$out['modified'] = $data->post_modified;
|
541 |
-
$out['guid'] = $data->guid;
|
542 |
-
$out['title'] = empty($data->post_title)
|
543 |
-
? '(empty)' : $data->post_title;
|
544 |
-
|
545 |
-
$cache->add('post_' . $id, $out);
|
546 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
547 |
}
|
548 |
|
549 |
/**
|
550 |
* Send an alert notifying that a post was deleted.
|
551 |
*
|
552 |
-
* @param
|
|
|
553 |
*/
|
554 |
public static function hookPostDelete($id = 0)
|
555 |
{
|
@@ -570,9 +616,10 @@ class SucuriScanHook extends SucuriScanEvent
|
|
570 |
/**
|
571 |
* Sends an alert for transitions between post statuses.
|
572 |
*
|
573 |
-
* @param
|
574 |
-
* @param
|
575 |
-
* @param
|
|
|
576 |
*/
|
577 |
public static function hookPostStatus($new = '', $old = '', $post = null)
|
578 |
{
|
@@ -642,14 +689,16 @@ class SucuriScanHook extends SucuriScanEvent
|
|
642 |
/**
|
643 |
* Send an alert notifying that a post was moved to the trash.
|
644 |
*
|
645 |
-
* @param
|
|
|
646 |
*/
|
647 |
public static function hookPostTrash($id = 0)
|
648 |
{
|
649 |
$title = 'Unknown';
|
650 |
$status = 'none';
|
|
|
651 |
|
652 |
-
if ($data
|
653 |
$title = $data->post_title;
|
654 |
$status = $data->post_status;
|
655 |
}
|
@@ -666,15 +715,17 @@ class SucuriScanHook extends SucuriScanEvent
|
|
666 |
/**
|
667 |
* Send an alert notifying that a post or page is created or updated.
|
668 |
*
|
669 |
-
* @param
|
|
|
670 |
*/
|
671 |
private static function hookPublish($id = 0)
|
672 |
{
|
673 |
$title = 'Unknown';
|
674 |
$p_type = 'Publication';
|
675 |
$action = 'published';
|
|
|
676 |
|
677 |
-
if ($data
|
678 |
$title = $data->post_title;
|
679 |
$p_type = ucwords($data->post_type);
|
680 |
$action = 'updated';
|
@@ -684,7 +735,7 @@ class SucuriScanHook extends SucuriScanEvent
|
|
684 |
$action = 'created';
|
685 |
}
|
686 |
|
687 |
-
SucuriScanFirewall::clearCacheHook(
|
688 |
}
|
689 |
|
690 |
$message = sprintf(
|
@@ -701,7 +752,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
701 |
/**
|
702 |
* Detects when a page is created or updated.
|
703 |
*
|
704 |
-
* @param
|
|
|
705 |
*/
|
706 |
public static function hookPublishPage($id = 0)
|
707 |
{
|
@@ -711,7 +763,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
711 |
/**
|
712 |
* Detects when a post is created or updated via email.
|
713 |
*
|
714 |
-
* @param
|
|
|
715 |
*/
|
716 |
public static function hookPublishPhone($id = 0)
|
717 |
{
|
@@ -721,7 +774,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
721 |
/**
|
722 |
* Detects when a post is created or updated.
|
723 |
*
|
724 |
-
* @param
|
|
|
725 |
*/
|
726 |
public static function hookPublishPost($id = 0)
|
727 |
{
|
@@ -731,7 +785,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
731 |
/**
|
732 |
* Detects when a post is created or updated via XML-RPC.
|
733 |
*
|
734 |
-
* @param
|
|
|
735 |
*/
|
736 |
public static function hookPublishPostXMLRPC($id = 0)
|
737 |
{
|
@@ -742,7 +797,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
742 |
* Send an alert notifying that an attempt to retrieve the password
|
743 |
* of an user account was tried.
|
744 |
*
|
745 |
-
* @param
|
|
|
746 |
*/
|
747 |
public static function hookRetrievePassword($title = '')
|
748 |
{
|
@@ -753,6 +809,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
753 |
|
754 |
/**
|
755 |
* Detects when a theme is deleted.
|
|
|
|
|
756 |
*/
|
757 |
public static function hookThemeDelete()
|
758 |
{
|
@@ -772,6 +830,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
772 |
|
773 |
/**
|
774 |
* Detects when the theme editor is used.
|
|
|
|
|
775 |
*/
|
776 |
public static function hookThemeEditor()
|
777 |
{
|
@@ -792,6 +852,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
792 |
|
793 |
/**
|
794 |
* Detects when a theme is installed.
|
|
|
|
|
795 |
*/
|
796 |
public static function hookThemeInstall()
|
797 |
{
|
@@ -811,7 +873,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
811 |
/**
|
812 |
* Send an alert notifying that the theme of the site was changed.
|
813 |
*
|
814 |
-
* @param
|
|
|
815 |
*/
|
816 |
public static function hookThemeSwitch($title = '')
|
817 |
{
|
@@ -823,6 +886,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
823 |
|
824 |
/**
|
825 |
* Detects when a theme is automatically or manually updated.
|
|
|
|
|
826 |
*/
|
827 |
public static function hookThemeUpdate()
|
828 |
{
|
@@ -853,14 +918,15 @@ class SucuriScanHook extends SucuriScanEvent
|
|
853 |
}
|
854 |
|
855 |
// Report updated themes at once.
|
856 |
-
if (!empty($items_affected)) {
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
);
|
|
|
864 |
self::reportWarningEvent($message);
|
865 |
self::notifyEvent('theme_updated', $message);
|
866 |
}
|
@@ -870,7 +936,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
870 |
/**
|
871 |
* Send an alert notifying that a user account was deleted.
|
872 |
*
|
873 |
-
* @param
|
|
|
874 |
*/
|
875 |
public static function hookUserDelete($id = 0)
|
876 |
{
|
@@ -880,15 +947,17 @@ class SucuriScanHook extends SucuriScanEvent
|
|
880 |
/**
|
881 |
* Send an alert notifying that a new user account was created.
|
882 |
*
|
883 |
-
* @param
|
|
|
884 |
*/
|
885 |
public static function hookUserRegister($id = 0)
|
886 |
{
|
887 |
$title = 'unknown';
|
888 |
$email = 'user@domain.com';
|
889 |
$roles = 'none';
|
|
|
890 |
|
891 |
-
if ($data
|
892 |
$title = $data->user_login;
|
893 |
$email = $data->user_email;
|
894 |
$roles = @implode(', ', $data->roles);
|
@@ -907,6 +976,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
907 |
|
908 |
/**
|
909 |
* Detects when a widget is added.
|
|
|
|
|
910 |
*/
|
911 |
public static function hookWidgetAdd()
|
912 |
{
|
@@ -915,6 +986,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
915 |
|
916 |
/**
|
917 |
* Detects when a widget is added.
|
|
|
|
|
918 |
*/
|
919 |
private static function hookWidgetChanges()
|
920 |
{
|
@@ -950,6 +1023,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
950 |
|
951 |
/**
|
952 |
* Detects when a widget is deleted.
|
|
|
|
|
953 |
*/
|
954 |
public static function hookWidgetDelete()
|
955 |
{
|
3 |
/**
|
4 |
* Code related to the hook.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
28 |
* The term hooking covers a range of techniques used to alter or augment the
|
29 |
* behavior of an operating system, of applications, or of other software
|
30 |
* components by intercepting method calls or messages or events passed
|
31 |
+
* between software components. Code that handles such intercepted function
|
32 |
+
* methods, events or messages is called a "hook".
|
33 |
*
|
34 |
* Hooking is used for many purposes, including debugging and extending
|
35 |
* functionality. Examples might include intercepting keyboard or mouse event
|
36 |
* messages before they reach an application, or intercepting operating system
|
37 |
* calls in order to monitor behavior or modify the method of an application
|
38 |
* or other component; it is also widely used in benchmarking programs.
|
39 |
+
*
|
40 |
+
* @category Library
|
41 |
+
* @package Sucuri
|
42 |
+
* @subpackage SucuriScanner
|
43 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
44 |
+
* @copyright 2010-2017 Sucuri Inc.
|
45 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
46 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
47 |
*/
|
48 |
class SucuriScanHook extends SucuriScanEvent
|
49 |
{
|
50 |
/**
|
51 |
* Send to Sucuri servers an alert notifying that an attachment was added to a post.
|
52 |
*
|
53 |
+
* @param int $id The post identifier.
|
54 |
+
* @return void
|
55 |
*/
|
56 |
public static function hookAttachmentAdd($id = 0)
|
57 |
{
|
58 |
$title = 'unknown';
|
59 |
$mime_type = 'unknown';
|
60 |
+
$data = get_post($id);
|
61 |
|
62 |
+
if ($data) {
|
63 |
$id = $data->ID;
|
64 |
$title = $data->post_title;
|
65 |
$mime_type = $data->post_mime_type;
|
73 |
/**
|
74 |
* Send an alert notifying that a category was created.
|
75 |
*
|
76 |
+
* @param int $id The identifier of the category created.
|
77 |
+
* @return void
|
78 |
*/
|
79 |
public static function hookCategoryCreate($id = 0)
|
80 |
{
|
85 |
self::notifyEvent('post_publication', $message);
|
86 |
}
|
87 |
|
|
|
|
|
88 |
/**
|
89 |
* Detects when the core files are updated.
|
90 |
+
*
|
91 |
+
* @return void
|
92 |
*/
|
93 |
public static function hookCoreUpdate()
|
94 |
{
|
106 |
/**
|
107 |
* Send an alert notifying that a new link was added to the bookmarks.
|
108 |
*
|
109 |
+
* @param int $id Identifier of the new link created;
|
110 |
+
* @return void
|
111 |
*/
|
112 |
public static function hookLinkAdd($id = 0)
|
113 |
{
|
114 |
$title = 'unknown';
|
115 |
$target = '_none';
|
116 |
$url = 'undefined/url';
|
117 |
+
$data = get_bookmark($id);
|
118 |
|
119 |
+
if ($data) {
|
120 |
$title = $data->link_name;
|
121 |
$target = $data->link_target;
|
122 |
$url = $data->link_url;
|
136 |
/**
|
137 |
* Send an alert notifying that a new link was added to the bookmarks.
|
138 |
*
|
139 |
+
* @param int $id Identifier of the new link created;
|
140 |
+
* @return void
|
141 |
*/
|
142 |
public static function hookLinkEdit($id = 0)
|
143 |
{
|
144 |
$title = 'unknown';
|
145 |
$target = '_none';
|
146 |
$url = 'undefined/url';
|
147 |
+
$data = get_bookmark($id);
|
148 |
|
149 |
+
if ($data) {
|
150 |
$title = $data->link_name;
|
151 |
$target = $data->link_target;
|
152 |
$url = $data->link_url;
|
167 |
* Send an alert notifying that an attempt to login into the
|
168 |
* administration panel failed.
|
169 |
*
|
170 |
+
* @param string $title The name of the user account involved in the transaction.
|
171 |
+
* @return void
|
172 |
*/
|
173 |
public static function hookLoginFailure($title = '')
|
174 |
{
|
189 |
self::notifyEvent('failed_login', $message);
|
190 |
|
191 |
/* report brute-force attack if necessary */
|
192 |
+
$logins = sucuriscan_get_failed_logins();
|
193 |
+
|
194 |
+
if (is_array($logins) && !empty($logins)) {
|
195 |
$max_time = 3600; /* report logins in the last hour */
|
196 |
$maximum = SucuriScanOption::getOption(':maximum_failed_logins');
|
197 |
|
218 |
* a brute-force attack (if it exists) because the time passed
|
219 |
* between the first and last login attempt is big enough to
|
220 |
* mitigate the attack.
|
|
|
|
|
|
|
|
|
221 |
*/
|
222 |
sucuriscan_reset_failed_logins();
|
|
|
223 |
}
|
224 |
}
|
225 |
}
|
226 |
|
227 |
/**
|
228 |
* Detects usage of the password reset form.
|
229 |
+
*
|
230 |
+
* @return void
|
231 |
*/
|
232 |
public static function hookLoginFormResetpass()
|
233 |
{
|
241 |
* Send an alert notifying that an attempt to login into the
|
242 |
* administration panel was successful.
|
243 |
*
|
244 |
+
* @param string $title User account involved in the transaction.
|
245 |
+
* @return void
|
246 |
*/
|
247 |
public static function hookLoginSuccess($title = '')
|
248 |
{
|
259 |
* will compare the value sent with the form with the value in the database
|
260 |
* and if there are differences will send an email alert notifying the admin
|
261 |
* about the changes.
|
262 |
+
*
|
263 |
+
* @return void
|
264 |
*/
|
265 |
public static function hookOptionsManagement()
|
266 |
{
|
290 |
}
|
291 |
|
292 |
/* identify the origin of the request */
|
293 |
+
$option_page = isset($_POST['option_page']) ? $_POST['option_page'] : 'options';
|
|
|
294 |
$page_referer = 'Common';
|
295 |
|
296 |
switch ($option_page) {
|
310 |
|
311 |
if ($options_changed_count) {
|
312 |
$message = $page_referer . ' settings changed';
|
313 |
+
self::reportErrorEvent(
|
314 |
+
sprintf(
|
315 |
+
'%s: (multiple entries): %s',
|
316 |
+
$message,
|
317 |
+
rtrim($options_changed_simple, ',')
|
318 |
+
)
|
319 |
+
);
|
320 |
self::notifyEvent('settings_updated', $message . "<br>\n" . $options_changed_str);
|
321 |
}
|
322 |
}
|
325 |
/**
|
326 |
* Sends an alert with information about a plugin that has been activated.
|
327 |
*
|
328 |
+
* @param string $plugin Name of the plugin.
|
329 |
+
* @param string $network_activation Whether the activation was global or not.
|
330 |
+
* @return void
|
331 |
*/
|
332 |
public static function hookPluginActivate($plugin = '', $network_activation = '')
|
333 |
{
|
343 |
* able to detect a deactivation if the plugin has been deleted via FTP or
|
344 |
* SSH or any file manager available in the hosting panel.
|
345 |
*
|
346 |
+
* @param string $action Activated or deactivated.
|
347 |
+
* @param string $plugin Short name of the plugin file.
|
348 |
+
* @param string $network Whether the action is global or not.
|
349 |
+
* @return void
|
350 |
*/
|
351 |
+
private static function hookPluginChanges($action, $plugin = '', $network = '')
|
352 |
{
|
353 |
$filename = WP_PLUGIN_DIR . '/' . $plugin;
|
354 |
|
370 |
}
|
371 |
|
372 |
$message = sprintf(
|
373 |
+
'Plugin %s: %s (v%s; %s%s)',
|
374 |
$action, /* activated or deactivated */
|
375 |
self::escape($info['Name']),
|
376 |
self::escape($info['Version']),
|
377 |
+
self::escape($plugin),
|
378 |
+
($network ? '; network' : '')
|
379 |
);
|
380 |
self::reportWarningEvent($message);
|
381 |
self::notifyEvent('plugin_' . $action, $message);
|
384 |
/**
|
385 |
* Sends an alert with information about a plugin that has been deactivated.
|
386 |
*
|
387 |
+
* @param string $plugin Name of the plugin.
|
388 |
+
* @param string $network_activation Whether the deactivation was global or not.
|
389 |
+
* @return void
|
390 |
*/
|
391 |
public static function hookPluginDeactivate($plugin = '', $network_activation = '')
|
392 |
{
|
395 |
|
396 |
/**
|
397 |
* Detects when a plugin is deleted.
|
398 |
+
*
|
399 |
+
* @return void
|
400 |
*/
|
401 |
public static function hookPluginDelete()
|
402 |
{
|
431 |
|
432 |
// Report deleted plugins at once.
|
433 |
if (!empty($items_affected)) {
|
434 |
+
if (count($items_affected) > 1) {
|
435 |
+
$message = 'Plugins deleted: (multiple entries):';
|
436 |
+
} else {
|
437 |
+
$message = 'Plugin deleted:';
|
438 |
+
}
|
439 |
+
|
440 |
+
$message .= "\x20" . @implode(',', $items_affected);
|
441 |
+
|
442 |
self::reportWarningEvent($message);
|
443 |
self::notifyEvent('plugin_deleted', $message);
|
444 |
}
|
447 |
|
448 |
/**
|
449 |
* Detects when the plugin editor is used.
|
450 |
+
*
|
451 |
+
* @return void
|
452 |
*/
|
453 |
public static function hookPluginEditor()
|
454 |
{
|
468 |
|
469 |
/**
|
470 |
* Detects when a plugin is uploaded or installed.
|
471 |
+
*
|
472 |
+
* @return void
|
473 |
*/
|
474 |
public static function hookPluginInstall()
|
475 |
{
|
492 |
|
493 |
/**
|
494 |
* Detects when a plugin is updated or upgraded.
|
495 |
+
*
|
496 |
+
* @return void
|
497 |
*/
|
498 |
public static function hookPluginUpdate()
|
499 |
{
|
500 |
// Plugin update request.
|
501 |
$plugin_update_actions = '(upgrade-plugin|do-plugin-upgrade|update-selected)';
|
502 |
|
503 |
+
if (!current_user_can('update_plugins')) {
|
504 |
+
return;
|
505 |
+
}
|
506 |
+
|
507 |
+
if (SucuriScanRequest::getOrPost('action', $plugin_update_actions)
|
508 |
+
|| SucuriScanRequest::getOrPost('action2', $plugin_update_actions)
|
509 |
) {
|
510 |
$plugin_list = array();
|
511 |
$items_affected = array();
|
538 |
|
539 |
// Report updated plugins at once.
|
540 |
if (!empty($items_affected)) {
|
541 |
+
if (count($items_affected) > 1) {
|
542 |
+
$message = 'Plugins updated: (multiple entries):';
|
543 |
+
} else {
|
544 |
+
$message = 'Plugin updated:';
|
545 |
+
}
|
546 |
+
|
547 |
+
$message .= "\x20" . @implode(',', $items_affected);
|
548 |
+
|
549 |
self::reportWarningEvent($message);
|
550 |
self::notifyEvent('plugin_updated', $message);
|
551 |
}
|
565 |
* this informaiton to send it to the API. We will delete the temporary data
|
566 |
* after the operation has succeeded.
|
567 |
*
|
568 |
+
* @param int $id The identifier of the post deleted.
|
569 |
+
* @return void
|
570 |
*/
|
571 |
public static function hookPostBeforeDelete($id = 0)
|
572 |
{
|
573 |
+
$data = get_post($id);
|
|
|
|
|
574 |
|
575 |
+
if (!$data) {
|
576 |
+
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
577 |
}
|
578 |
+
|
579 |
+
$out = array(); /* data to cache */
|
580 |
+
$cache = new SucuriScanCache('hookdata');
|
581 |
+
|
582 |
+
$out['id'] = $data->ID;
|
583 |
+
$out['author'] = $data->post_author;
|
584 |
+
$out['type'] = $data->post_type;
|
585 |
+
$out['status'] = $data->post_status;
|
586 |
+
$out['inserted'] = $data->post_date;
|
587 |
+
$out['modified'] = $data->post_modified;
|
588 |
+
$out['guid'] = $data->guid;
|
589 |
+
$out['title'] = empty($data->post_title) ? '(empty)' : $data->post_title;
|
590 |
+
|
591 |
+
$cache->add('post_' . $id, $out);
|
592 |
}
|
593 |
|
594 |
/**
|
595 |
* Send an alert notifying that a post was deleted.
|
596 |
*
|
597 |
+
* @param int $id The identifier of the post deleted.
|
598 |
+
* @return void
|
599 |
*/
|
600 |
public static function hookPostDelete($id = 0)
|
601 |
{
|
616 |
/**
|
617 |
* Sends an alert for transitions between post statuses.
|
618 |
*
|
619 |
+
* @param string $new New post status.
|
620 |
+
* @param string $old Old post status.
|
621 |
+
* @param mixed $post Post data.
|
622 |
+
* @return void
|
623 |
*/
|
624 |
public static function hookPostStatus($new = '', $old = '', $post = null)
|
625 |
{
|
689 |
/**
|
690 |
* Send an alert notifying that a post was moved to the trash.
|
691 |
*
|
692 |
+
* @param int $id The identifier of the trashed post.
|
693 |
+
* @return void
|
694 |
*/
|
695 |
public static function hookPostTrash($id = 0)
|
696 |
{
|
697 |
$title = 'Unknown';
|
698 |
$status = 'none';
|
699 |
+
$data = get_post($id);
|
700 |
|
701 |
+
if ($data) {
|
702 |
$title = $data->post_title;
|
703 |
$status = $data->post_status;
|
704 |
}
|
715 |
/**
|
716 |
* Send an alert notifying that a post or page is created or updated.
|
717 |
*
|
718 |
+
* @param int $id The identifier of the post or page published.
|
719 |
+
* @return void
|
720 |
*/
|
721 |
private static function hookPublish($id = 0)
|
722 |
{
|
723 |
$title = 'Unknown';
|
724 |
$p_type = 'Publication';
|
725 |
$action = 'published';
|
726 |
+
$data = get_post($id);
|
727 |
|
728 |
+
if ($data) {
|
729 |
$title = $data->post_title;
|
730 |
$p_type = ucwords($data->post_type);
|
731 |
$action = 'updated';
|
735 |
$action = 'created';
|
736 |
}
|
737 |
|
738 |
+
SucuriScanFirewall::clearCacheHook();
|
739 |
}
|
740 |
|
741 |
$message = sprintf(
|
752 |
/**
|
753 |
* Detects when a page is created or updated.
|
754 |
*
|
755 |
+
* @param int $id The identifier of the post or page published.
|
756 |
+
* @return void
|
757 |
*/
|
758 |
public static function hookPublishPage($id = 0)
|
759 |
{
|
763 |
/**
|
764 |
* Detects when a post is created or updated via email.
|
765 |
*
|
766 |
+
* @param int $id The identifier of the post or page published.
|
767 |
+
* @return void
|
768 |
*/
|
769 |
public static function hookPublishPhone($id = 0)
|
770 |
{
|
774 |
/**
|
775 |
* Detects when a post is created or updated.
|
776 |
*
|
777 |
+
* @param int $id The identifier of the post or page published.
|
778 |
+
* @return void
|
779 |
*/
|
780 |
public static function hookPublishPost($id = 0)
|
781 |
{
|
785 |
/**
|
786 |
* Detects when a post is created or updated via XML-RPC.
|
787 |
*
|
788 |
+
* @param int $id The identifier of the post or page published.
|
789 |
+
* @return void
|
790 |
*/
|
791 |
public static function hookPublishPostXMLRPC($id = 0)
|
792 |
{
|
797 |
* Send an alert notifying that an attempt to retrieve the password
|
798 |
* of an user account was tried.
|
799 |
*
|
800 |
+
* @param string $title The name of the user account involved in the trasaction.
|
801 |
+
* @return void
|
802 |
*/
|
803 |
public static function hookRetrievePassword($title = '')
|
804 |
{
|
809 |
|
810 |
/**
|
811 |
* Detects when a theme is deleted.
|
812 |
+
*
|
813 |
+
* @return void
|
814 |
*/
|
815 |
public static function hookThemeDelete()
|
816 |
{
|
830 |
|
831 |
/**
|
832 |
* Detects when the theme editor is used.
|
833 |
+
*
|
834 |
+
* @return void
|
835 |
*/
|
836 |
public static function hookThemeEditor()
|
837 |
{
|
852 |
|
853 |
/**
|
854 |
* Detects when a theme is installed.
|
855 |
+
*
|
856 |
+
* @return void
|
857 |
*/
|
858 |
public static function hookThemeInstall()
|
859 |
{
|
873 |
/**
|
874 |
* Send an alert notifying that the theme of the site was changed.
|
875 |
*
|
876 |
+
* @param string $title The name of the new theme selected to used through out the site.
|
877 |
+
* @return void
|
878 |
*/
|
879 |
public static function hookThemeSwitch($title = '')
|
880 |
{
|
886 |
|
887 |
/**
|
888 |
* Detects when a theme is automatically or manually updated.
|
889 |
+
*
|
890 |
+
* @return void
|
891 |
*/
|
892 |
public static function hookThemeUpdate()
|
893 |
{
|
918 |
}
|
919 |
|
920 |
// Report updated themes at once.
|
921 |
+
if (is_array($items_affected) && !empty($items_affected)) {
|
922 |
+
if (count($items_affected) > 1) {
|
923 |
+
$message = 'Themes updated: (multiple entries):';
|
924 |
+
} else {
|
925 |
+
$message = 'Theme updated:';
|
926 |
+
}
|
927 |
+
|
928 |
+
$message .= "\x20" . implode(',', $items_affected);
|
929 |
+
|
930 |
self::reportWarningEvent($message);
|
931 |
self::notifyEvent('theme_updated', $message);
|
932 |
}
|
936 |
/**
|
937 |
* Send an alert notifying that a user account was deleted.
|
938 |
*
|
939 |
+
* @param int $id The identifier of the user account deleted.
|
940 |
+
* @return void
|
941 |
*/
|
942 |
public static function hookUserDelete($id = 0)
|
943 |
{
|
947 |
/**
|
948 |
* Send an alert notifying that a new user account was created.
|
949 |
*
|
950 |
+
* @param int $id The identifier of the new user account created.
|
951 |
+
* @return void
|
952 |
*/
|
953 |
public static function hookUserRegister($id = 0)
|
954 |
{
|
955 |
$title = 'unknown';
|
956 |
$email = 'user@domain.com';
|
957 |
$roles = 'none';
|
958 |
+
$data = get_userdata($id);
|
959 |
|
960 |
+
if ($data) {
|
961 |
$title = $data->user_login;
|
962 |
$email = $data->user_email;
|
963 |
$roles = @implode(', ', $data->roles);
|
976 |
|
977 |
/**
|
978 |
* Detects when a widget is added.
|
979 |
+
*
|
980 |
+
* @return void
|
981 |
*/
|
982 |
public static function hookWidgetAdd()
|
983 |
{
|
986 |
|
987 |
/**
|
988 |
* Detects when a widget is added.
|
989 |
+
*
|
990 |
+
* @return void
|
991 |
*/
|
992 |
private static function hookWidgetChanges()
|
993 |
{
|
1023 |
|
1024 |
/**
|
1025 |
* Detects when a widget is deleted.
|
1026 |
+
*
|
1027 |
+
* @return void
|
1028 |
*/
|
1029 |
public static function hookWidgetDelete()
|
1030 |
{
|
src/installer-skin.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the installer-skin.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,8 +24,8 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
if (class_exists('SucuriScanInterface') && class_exists('SucuriScanRequest')) {
|
20 |
if (SucuriScanRequest::post('form_action') == 'reset_plugin') {
|
21 |
-
include_once
|
22 |
-
include_once
|
23 |
|
24 |
/**
|
25 |
* Plugin Installer Skin for WordPress Plugin Installer.
|
@@ -30,16 +36,23 @@ if (class_exists('SucuriScanInterface') && class_exists('SucuriScanRequest')) {
|
|
30 |
* process immediately and we will not be able to disregard these logs
|
31 |
* after the operation has finished.
|
32 |
*
|
33 |
-
* @see WP_Upgrader_Skin
|
34 |
-
*
|
35 |
* @codeCoverageIgnore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
*/
|
37 |
class SucuriScanPluginInstallerSkin extends Plugin_Installer_Skin
|
38 |
{
|
39 |
/**
|
40 |
* Reports the progress of the plugin installation.
|
41 |
*
|
42 |
-
* @param
|
|
|
43 |
*/
|
44 |
public function feedback($string = '')
|
45 |
{
|
3 |
/**
|
4 |
* Code related to the installer-skin.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
if (class_exists('SucuriScanInterface') && class_exists('SucuriScanRequest')) {
|
26 |
if (SucuriScanRequest::post('form_action') == 'reset_plugin') {
|
27 |
+
include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php';
|
28 |
+
include_once ABSPATH . '/wp-admin/includes/plugin-install.php';
|
29 |
|
30 |
/**
|
31 |
* Plugin Installer Skin for WordPress Plugin Installer.
|
36 |
* process immediately and we will not be able to disregard these logs
|
37 |
* after the operation has finished.
|
38 |
*
|
|
|
|
|
39 |
* @codeCoverageIgnore
|
40 |
+
*
|
41 |
+
* @category Library
|
42 |
+
* @package Sucuri
|
43 |
+
* @subpackage SucuriScanner
|
44 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
45 |
+
* @copyright 2010-2017 Sucuri Inc.
|
46 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
47 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
48 |
*/
|
49 |
class SucuriScanPluginInstallerSkin extends Plugin_Installer_Skin
|
50 |
{
|
51 |
/**
|
52 |
* Reports the progress of the plugin installation.
|
53 |
*
|
54 |
+
* @param string $string Message to send to the buffer.
|
55 |
+
* @return void
|
56 |
*/
|
57 |
public function feedback($string = '')
|
58 |
{
|
src/integrity.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the integrity.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -23,6 +29,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
23 |
* in the root directory, wp-admin and wp-includes will be compared against the
|
24 |
* files distributed with the current WordPress version; all files with
|
25 |
* inconsistencies will be listed here.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
*/
|
27 |
class SucuriScanIntegrity
|
28 |
{
|
@@ -64,6 +78,8 @@ class SucuriScanIntegrity
|
|
64 |
* output it means that XDebug cannot cover the next line, leaving a report
|
65 |
* with a missing line in the coverage. Since the test case takes care of
|
66 |
* the functionality of this code we will assume that it is fully covered.
|
|
|
|
|
67 |
*/
|
68 |
public static function ajaxIntegrity()
|
69 |
{
|
@@ -80,6 +96,8 @@ class SucuriScanIntegrity
|
|
80 |
* Process the HTTP requests sent by the form submissions originated in the
|
81 |
* integrity page, all forms must have a nonce field that will be checked
|
82 |
* against the one generated in the template render function.
|
|
|
|
|
83 |
*/
|
84 |
private static function pageIntegritySubmission()
|
85 |
{
|
@@ -92,12 +110,12 @@ class SucuriScanIntegrity
|
|
92 |
|
93 |
/* skip if the user didn't confirm the operation */
|
94 |
if (SucuriScanRequest::post(':process_form') != 1) {
|
95 |
-
return SucuriScanInterface::error(
|
96 |
}
|
97 |
|
98 |
/* skip if the requested action is not currently supported */
|
99 |
if ($action !== 'fixed' && $action !== 'delete' && $action !== 'restore') {
|
100 |
-
return SucuriScanInterface::error(
|
101 |
}
|
102 |
|
103 |
/* process the HTTP request */
|
@@ -114,7 +132,7 @@ class SucuriScanIntegrity
|
|
114 |
|
115 |
/* skip if no files were selected */
|
116 |
if (!$core_files) {
|
117 |
-
return SucuriScanInterface::error(
|
118 |
}
|
119 |
|
120 |
/* process files until the maximum execution time is reached */
|
@@ -143,11 +161,7 @@ class SucuriScanIntegrity
|
|
143 |
|
144 |
$full_path = ABSPATH . '/' . $file_path;
|
145 |
|
146 |
-
if ($action === 'fixed' && (
|
147 |
-
$status_type === 'added'
|
148 |
-
|| $status_type === 'removed'
|
149 |
-
|| $status_type === 'modified'
|
150 |
-
)) {
|
151 |
$cache_key = md5($file_path);
|
152 |
$cache_value = array(
|
153 |
'file_path' => $file_path,
|
@@ -162,11 +176,10 @@ class SucuriScanIntegrity
|
|
162 |
continue;
|
163 |
}
|
164 |
|
165 |
-
if ($action === 'restore' && (
|
166 |
-
$
|
167 |
-
|
168 |
-
|
169 |
-
if ($content = SucuriScanAPI::getOriginalCoreFile($file_path)) {
|
170 |
$basedir = dirname($full_path);
|
171 |
|
172 |
if (!file_exists($basedir)) {
|
@@ -192,14 +205,9 @@ class SucuriScanIntegrity
|
|
192 |
|
193 |
/* report files affected as a single event */
|
194 |
if (!empty($files_affected)) {
|
195 |
-
$
|
196 |
-
|
197 |
-
|
198 |
-
$message = sprintf(
|
199 |
-
$message_tpl,
|
200 |
-
$action_titles[$action],
|
201 |
-
@implode(',', $files_affected)
|
202 |
-
);
|
203 |
|
204 |
switch ($action) {
|
205 |
case 'restore':
|
@@ -217,22 +225,26 @@ class SucuriScanIntegrity
|
|
217 |
}
|
218 |
|
219 |
if ($displayTimeoutAlert) {
|
220 |
-
SucuriScanInterface::error(
|
221 |
}
|
222 |
|
223 |
if ($files_processed != $files_selected) {
|
224 |
-
return SucuriScanInterface::error(
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
|
|
|
|
229 |
}
|
230 |
|
231 |
-
return SucuriScanInterface::info(
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
|
|
|
|
236 |
}
|
237 |
|
238 |
/**
|
@@ -247,8 +259,8 @@ class SucuriScanIntegrity
|
|
247 |
*
|
248 |
* The website owner will receive an email alert with this information.
|
249 |
*
|
250 |
-
* @param
|
251 |
-
* @return string|bool
|
252 |
*/
|
253 |
public static function getIntegrityStatus($send_email = false)
|
254 |
{
|
@@ -306,11 +318,11 @@ class SucuriScanIntegrity
|
|
306 |
$visibility = 'visible';
|
307 |
|
308 |
if ($list_type === 'added') {
|
309 |
-
$error =
|
310 |
} elseif ($list_type === 'modified') {
|
311 |
-
$error =
|
312 |
} elseif ($list_type === 'removed') {
|
313 |
-
$error =
|
314 |
}
|
315 |
}
|
316 |
|
@@ -319,18 +331,22 @@ class SucuriScanIntegrity
|
|
319 |
$file_size_human = SucuriScan::humanFileSize($file_size);
|
320 |
}
|
321 |
|
|
|
|
|
322 |
// Generate the HTML code from the snippet template for this file.
|
323 |
-
$params['Integrity.List'] .=
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
|
|
|
|
334 |
$affected_files++;
|
335 |
$counter++;
|
336 |
}
|
@@ -344,12 +360,14 @@ class SucuriScanIntegrity
|
|
344 |
}
|
345 |
|
346 |
if ($send_email === true) {
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
|
|
|
|
353 |
}
|
354 |
|
355 |
ob_start();
|
@@ -359,9 +377,8 @@ class SucuriScanIntegrity
|
|
359 |
|
360 |
$params['Integrity.DiffUtility'] = SucuriScanIntegrity::diffUtility();
|
361 |
|
362 |
-
|
363 |
-
|
364 |
-
: SucuriScanTemplate::getSection('integrity-incorrect', $params);
|
365 |
}
|
366 |
|
367 |
/**
|
@@ -382,12 +399,15 @@ class SucuriScanIntegrity
|
|
382 |
|
383 |
$params = array();
|
384 |
|
385 |
-
$params['DiffUtility.Modal'] = SucuriScanTemplate::getModal(
|
386 |
-
'
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
|
|
|
|
|
|
391 |
|
392 |
return SucuriScanTemplate::getSection('integrity-diff-utility', $params);
|
393 |
}
|
@@ -406,6 +426,8 @@ class SucuriScanIntegrity
|
|
406 |
* output it means that XDebug cannot cover the next line, leaving a report
|
407 |
* with a missing line in the coverage. Since the test case takes care of
|
408 |
* the functionality of this code we will assume that it is fully covered.
|
|
|
|
|
409 |
*/
|
410 |
public static function ajaxIntegrityDiffUtility()
|
411 |
{
|
@@ -415,7 +437,7 @@ class SucuriScanIntegrity
|
|
415 |
|
416 |
ob_start();
|
417 |
$filename = SucuriScanRequest::post('filepath');
|
418 |
-
|
419 |
$response = ob_get_clean();
|
420 |
|
421 |
wp_send_json($response, 200);
|
@@ -425,9 +447,9 @@ class SucuriScanIntegrity
|
|
425 |
* Retrieve a list of md5sum and last modification time of all the files in the
|
426 |
* folder specified. This is a recursive function.
|
427 |
*
|
428 |
-
* @param
|
429 |
-
* @param
|
430 |
-
* @return array
|
431 |
*/
|
432 |
private static function integrityTree($dir = './', $recursive = false)
|
433 |
{
|
@@ -457,10 +479,12 @@ class SucuriScanIntegrity
|
|
457 |
*/
|
458 |
private static function checkIntegrityIntegrity()
|
459 |
{
|
|
|
460 |
$latest_hashes = SucuriScanAPI::getOfficialChecksums();
|
461 |
-
|
462 |
-
|
463 |
-
|
|
|
464 |
|
465 |
// @codeCoverageIgnoreStart
|
466 |
if (!$latest_hashes) {
|
@@ -568,13 +592,11 @@ class SucuriScanIntegrity
|
|
568 |
/**
|
569 |
* Ignore irrelevant files and directories from the integrity checking.
|
570 |
*
|
571 |
-
* @param
|
572 |
-
* @return bool
|
573 |
*/
|
574 |
private static function ignoreIntegrityFilepath($path = '')
|
575 |
{
|
576 |
-
global $wp_local_package;
|
577 |
-
|
578 |
$irrelevant = array(
|
579 |
'php.ini',
|
580 |
'.htaccess',
|
@@ -621,7 +643,7 @@ class SucuriScanIntegrity
|
|
621 |
* specifying the language that will be used in the admin panel, site
|
622 |
* options, and emails.
|
623 |
*/
|
624 |
-
if (
|
625 |
$irrelevant[] = 'wp-includes/version.php';
|
626 |
$irrelevant[] = 'wp-config-sample.php';
|
627 |
}
|
3 |
/**
|
4 |
* Code related to the integrity.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
29 |
* in the root directory, wp-admin and wp-includes will be compared against the
|
30 |
* files distributed with the current WordPress version; all files with
|
31 |
* inconsistencies will be listed here.
|
32 |
+
*
|
33 |
+
* @category Library
|
34 |
+
* @package Sucuri
|
35 |
+
* @subpackage SucuriScanner
|
36 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
37 |
+
* @copyright 2010-2017 Sucuri Inc.
|
38 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
39 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
40 |
*/
|
41 |
class SucuriScanIntegrity
|
42 |
{
|
78 |
* output it means that XDebug cannot cover the next line, leaving a report
|
79 |
* with a missing line in the coverage. Since the test case takes care of
|
80 |
* the functionality of this code we will assume that it is fully covered.
|
81 |
+
*
|
82 |
+
* @return void
|
83 |
*/
|
84 |
public static function ajaxIntegrity()
|
85 |
{
|
96 |
* Process the HTTP requests sent by the form submissions originated in the
|
97 |
* integrity page, all forms must have a nonce field that will be checked
|
98 |
* against the one generated in the template render function.
|
99 |
+
*
|
100 |
+
* @return void
|
101 |
*/
|
102 |
private static function pageIntegritySubmission()
|
103 |
{
|
110 |
|
111 |
/* skip if the user didn't confirm the operation */
|
112 |
if (SucuriScanRequest::post(':process_form') != 1) {
|
113 |
+
return SucuriScanInterface::error('You need to confirm that you understand the risk of this operation.');
|
114 |
}
|
115 |
|
116 |
/* skip if the requested action is not currently supported */
|
117 |
if ($action !== 'fixed' && $action !== 'delete' && $action !== 'restore') {
|
118 |
+
return SucuriScanInterface::error('Requested action is not supported.');
|
119 |
}
|
120 |
|
121 |
/* process the HTTP request */
|
132 |
|
133 |
/* skip if no files were selected */
|
134 |
if (!$core_files) {
|
135 |
+
return SucuriScanInterface::error('Nothing was selected from the list.');
|
136 |
}
|
137 |
|
138 |
/* process files until the maximum execution time is reached */
|
161 |
|
162 |
$full_path = ABSPATH . '/' . $file_path;
|
163 |
|
164 |
+
if ($action === 'fixed' && ($status_type === 'added' || $status_type === 'removed' || $status_type === 'modified')) {
|
|
|
|
|
|
|
|
|
165 |
$cache_key = md5($file_path);
|
166 |
$cache_value = array(
|
167 |
'file_path' => $file_path,
|
176 |
continue;
|
177 |
}
|
178 |
|
179 |
+
if ($action === 'restore' && ($status_type === 'removed' || $status_type === 'modified')) {
|
180 |
+
$content = SucuriScanAPI::getOriginalCoreFile($file_path);
|
181 |
+
|
182 |
+
if ($content) {
|
|
|
183 |
$basedir = dirname($full_path);
|
184 |
|
185 |
if (!file_exists($basedir)) {
|
205 |
|
206 |
/* report files affected as a single event */
|
207 |
if (!empty($files_affected)) {
|
208 |
+
$message = $action_titles[$action] . ':';
|
209 |
+
$message .= count($files_affected) > 1 ? "\x20(multiple entries):\x20" : '';
|
210 |
+
$message .= @implode(',', $files_affected);
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
switch ($action) {
|
213 |
case 'restore':
|
225 |
}
|
226 |
|
227 |
if ($displayTimeoutAlert) {
|
228 |
+
SucuriScanInterface::error('Server is not fast enough to process this action; maximum execution time reached');
|
229 |
}
|
230 |
|
231 |
if ($files_processed != $files_selected) {
|
232 |
+
return SucuriScanInterface::error(
|
233 |
+
sprintf(
|
234 |
+
'Only <b>%d</b> out of <b>%d</b> files were processed.',
|
235 |
+
$files_processed,
|
236 |
+
$files_selected
|
237 |
+
)
|
238 |
+
);
|
239 |
}
|
240 |
|
241 |
+
return SucuriScanInterface::info(
|
242 |
+
sprintf(
|
243 |
+
'<b>%d</b> out of <b>%d</b> files were successfully processed.',
|
244 |
+
$files_processed,
|
245 |
+
$files_selected
|
246 |
+
)
|
247 |
+
);
|
248 |
}
|
249 |
|
250 |
/**
|
259 |
*
|
260 |
* The website owner will receive an email alert with this information.
|
261 |
*
|
262 |
+
* @param bool $send_email Send an email alert to the admins.
|
263 |
+
* @return string|bool HTML with information about the integrity.
|
264 |
*/
|
265 |
public static function getIntegrityStatus($send_email = false)
|
266 |
{
|
318 |
$visibility = 'visible';
|
319 |
|
320 |
if ($list_type === 'added') {
|
321 |
+
$error = 'The plugin has no permission to delete this file because it was created by a different system user who has more privileges than your account. Please use FTP to delete it.';
|
322 |
} elseif ($list_type === 'modified') {
|
323 |
+
$error = 'The plugin has no permission to restore this file because it was modified by a different system user who has more privileges than your account. Please use FTP to restore it.';
|
324 |
} elseif ($list_type === 'removed') {
|
325 |
+
$error = 'The plugin has no permission to restore this file because its directory is owned by a different system user who has more privileges than your account. Please use FTP to restore it.';
|
326 |
}
|
327 |
}
|
328 |
|
331 |
$file_size_human = SucuriScan::humanFileSize($file_size);
|
332 |
}
|
333 |
|
334 |
+
$modified_at = $file_info['modified_at'] ? SucuriScan::datetime($file_info['modified_at']) : '';
|
335 |
+
|
336 |
// Generate the HTML code from the snippet template for this file.
|
337 |
+
$params['Integrity.List'] .= SucuriScanTemplate::getSnippet(
|
338 |
+
'integrity-incorrect',
|
339 |
+
array(
|
340 |
+
'Integrity.StatusType' => $list_type,
|
341 |
+
'Integrity.FilePath' => $file_path,
|
342 |
+
'Integrity.FileSize' => $file_size,
|
343 |
+
'Integrity.FileSizeHuman' => $file_size_human,
|
344 |
+
'Integrity.FileSizeNumber' => number_format($file_size),
|
345 |
+
'Integrity.ModifiedAt' => $modified_at,
|
346 |
+
'Integrity.ErrorVisibility' => $visibility,
|
347 |
+
'Integrity.ErrorMessage' => $error,
|
348 |
+
)
|
349 |
+
);
|
350 |
$affected_files++;
|
351 |
$counter++;
|
352 |
}
|
360 |
}
|
361 |
|
362 |
if ($send_email === true) {
|
363 |
+
if ($affected_files > 0) {
|
364 |
+
return SucuriScanEvent::notifyEvent(
|
365 |
+
'scan_checksums', /* send alert with a list of affected files */
|
366 |
+
SucuriScanTemplate::getSection('integrity-notification', $params)
|
367 |
+
);
|
368 |
+
}
|
369 |
+
|
370 |
+
return false;
|
371 |
}
|
372 |
|
373 |
ob_start();
|
377 |
|
378 |
$params['Integrity.DiffUtility'] = SucuriScanIntegrity::diffUtility();
|
379 |
|
380 |
+
$template = ($affected_files === 0) ? 'correct' : 'incorrect';
|
381 |
+
return SucuriScanTemplate::getSection('integrity-' . $template, $params);
|
|
|
382 |
}
|
383 |
|
384 |
/**
|
399 |
|
400 |
$params = array();
|
401 |
|
402 |
+
$params['DiffUtility.Modal'] = SucuriScanTemplate::getModal(
|
403 |
+
'none',
|
404 |
+
array(
|
405 |
+
'Title' => 'WordPress Integrity Diff Utility',
|
406 |
+
'Content' => '' /* empty */,
|
407 |
+
'Identifier' => 'diff-utility',
|
408 |
+
'Visibility' => 'hidden',
|
409 |
+
)
|
410 |
+
);
|
411 |
|
412 |
return SucuriScanTemplate::getSection('integrity-diff-utility', $params);
|
413 |
}
|
426 |
* output it means that XDebug cannot cover the next line, leaving a report
|
427 |
* with a missing line in the coverage. Since the test case takes care of
|
428 |
* the functionality of this code we will assume that it is fully covered.
|
429 |
+
*
|
430 |
+
* @return void
|
431 |
*/
|
432 |
public static function ajaxIntegrityDiffUtility()
|
433 |
{
|
437 |
|
438 |
ob_start();
|
439 |
$filename = SucuriScanRequest::post('filepath');
|
440 |
+
echo SucuriScanCommand::diffHTML($filename);
|
441 |
$response = ob_get_clean();
|
442 |
|
443 |
wp_send_json($response, 200);
|
447 |
* Retrieve a list of md5sum and last modification time of all the files in the
|
448 |
* folder specified. This is a recursive function.
|
449 |
*
|
450 |
+
* @param string $dir The base path where the scanning will start.
|
451 |
+
* @param bool $recursive Either TRUE or FALSE if the scan should be performed recursively.
|
452 |
+
* @return array List of arrays containing the md5sum and last modification time of the files found.
|
453 |
*/
|
454 |
private static function integrityTree($dir = './', $recursive = false)
|
455 |
{
|
479 |
*/
|
480 |
private static function checkIntegrityIntegrity()
|
481 |
{
|
482 |
+
$base_content_dir = '';
|
483 |
$latest_hashes = SucuriScanAPI::getOfficialChecksums();
|
484 |
+
|
485 |
+
if (defined('WP_CONTENT_DIR')) {
|
486 |
+
$base_content_dir = basename(rtrim(WP_CONTENT_DIR, '/'));
|
487 |
+
}
|
488 |
|
489 |
// @codeCoverageIgnoreStart
|
490 |
if (!$latest_hashes) {
|
592 |
/**
|
593 |
* Ignore irrelevant files and directories from the integrity checking.
|
594 |
*
|
595 |
+
* @param string $path File path that will be compared.
|
596 |
+
* @return bool True if the file should be ignored, false otherwise.
|
597 |
*/
|
598 |
private static function ignoreIntegrityFilepath($path = '')
|
599 |
{
|
|
|
|
|
600 |
$irrelevant = array(
|
601 |
'php.ini',
|
602 |
'.htaccess',
|
643 |
* specifying the language that will be used in the admin panel, site
|
644 |
* options, and emails.
|
645 |
*/
|
646 |
+
if (@$GLOBALS['wp_local_package'] != 'en_US') {
|
647 |
$irrelevant[] = 'wp-includes/version.php';
|
648 |
$irrelevant[] = 'wp-config-sample.php';
|
649 |
}
|
src/interface.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the interface.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -22,18 +28,22 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
22 |
* Define all the required variables, script, styles, and basic functions needed
|
23 |
* when the site is loaded, not even the administrator panel but also the front
|
24 |
* page, some bug-fixes will/are applied here for sites behind a proxy, and
|
25 |
-
* sites with old versions of the premium plugin (
|
26 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
*/
|
28 |
class SucuriScanInterface
|
29 |
{
|
30 |
/**
|
31 |
* Initialization code for the plugin.
|
32 |
*
|
33 |
-
*
|
34 |
-
* execution of other functions will be generated. Things like the real IP
|
35 |
-
* address of the client when it has been forwarded or it's behind an external
|
36 |
-
* service like a Proxy.
|
37 |
*/
|
38 |
public static function initialize()
|
39 |
{
|
@@ -48,16 +58,16 @@ class SucuriScanInterface
|
|
48 |
/**
|
49 |
* Define which javascript and css files will be loaded in the header of the
|
50 |
* plugin pages, only when the administrator panel is accessed.
|
|
|
|
|
51 |
*/
|
52 |
public static function enqueueScripts()
|
53 |
{
|
54 |
-
$asset = substr(md5(microtime(true)), 0, 7);
|
55 |
-
|
56 |
wp_register_style(
|
57 |
'sucuriscan1',
|
58 |
SUCURISCAN_URL . '/inc/css/styles.css',
|
59 |
array(/* empty */),
|
60 |
-
|
61 |
);
|
62 |
wp_enqueue_style('sucuriscan1');
|
63 |
|
@@ -65,7 +75,7 @@ class SucuriScanInterface
|
|
65 |
'sucuriscan1',
|
66 |
SUCURISCAN_URL . '/inc/js/scripts.js',
|
67 |
array(/* empty */),
|
68 |
-
|
69 |
);
|
70 |
wp_enqueue_script('sucuriscan1');
|
71 |
|
@@ -74,7 +84,7 @@ class SucuriScanInterface
|
|
74 |
'sucuriscan3',
|
75 |
SUCURISCAN_URL . '/inc/css/flags.min.css',
|
76 |
array(/* empty */),
|
77 |
-
|
78 |
);
|
79 |
wp_enqueue_style('sucuriscan3');
|
80 |
}
|
@@ -85,6 +95,8 @@ class SucuriScanInterface
|
|
85 |
* 1.6.0) all the functionality of the others will be merged here, this will
|
86 |
* remove duplicated functionality, duplicated bugs and/or duplicated
|
87 |
* maintenance reports allowing us to focus in one unique project.
|
|
|
|
|
88 |
*/
|
89 |
public static function handleOldPlugins()
|
90 |
{
|
@@ -121,6 +133,8 @@ class SucuriScanInterface
|
|
121 |
/**
|
122 |
* Create a folder in the WordPress upload directory where the plugin will
|
123 |
* store all the temporal or dynamic information.
|
|
|
|
|
124 |
*/
|
125 |
public static function createStorageFolder()
|
126 |
{
|
@@ -156,6 +170,8 @@ class SucuriScanInterface
|
|
156 |
* for the current user in session which usually needs to be granted admin
|
157 |
* privileges to access the plugin's tools. It also checks if the required
|
158 |
* SPL library is available and if the settings file is writable.
|
|
|
|
|
159 |
*/
|
160 |
public static function startupChecks()
|
161 |
{
|
@@ -165,16 +181,18 @@ class SucuriScanInterface
|
|
165 |
|
166 |
if (!SucuriScanFileInfo::isSplAvailable()) {
|
167 |
/* display a warning when system dependencies are not met */
|
168 |
-
self::error(
|
169 |
}
|
170 |
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
|
|
|
|
175 |
$filename /* absolute path of the settings file */
|
176 |
-
)
|
177 |
-
|
178 |
}
|
179 |
}
|
180 |
|
@@ -187,6 +205,8 @@ class SucuriScanInterface
|
|
187 |
* will execute certain actions and/or display some messages.
|
188 |
*
|
189 |
* @codeCoverageIgnore
|
|
|
|
|
190 |
*/
|
191 |
public static function noticeAfterUpdate()
|
192 |
{
|
@@ -211,7 +231,7 @@ class SucuriScanInterface
|
|
211 |
* the new code.
|
212 |
*/
|
213 |
if (SucuriScanOption::isDisabled(':api_service')) {
|
214 |
-
self::info(
|
215 |
}
|
216 |
|
217 |
/**
|
@@ -224,19 +244,21 @@ class SucuriScanInterface
|
|
224 |
*
|
225 |
* @date Featured added at - May 01, 2017
|
226 |
*/
|
227 |
-
self::info(
|
228 |
}
|
229 |
|
230 |
/**
|
231 |
* Check whether a user has the permissions to see a page from the plugin.
|
232 |
*
|
233 |
* @codeCoverageIgnore
|
|
|
|
|
234 |
*/
|
235 |
public static function checkPageVisibility()
|
236 |
{
|
237 |
if (!function_exists('current_user_can') || !current_user_can('manage_options')) {
|
238 |
SucuriScan::throwException('Access denied; cannot manage options');
|
239 |
-
wp_die(
|
240 |
}
|
241 |
}
|
242 |
|
@@ -257,7 +279,17 @@ class SucuriScanInterface
|
|
257 |
|
258 |
if (!$nonce_value || !wp_verify_nonce($nonce_value, $nonce_name)) {
|
259 |
SucuriScan::throwException('Nonce is invalid');
|
260 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
return false;
|
262 |
}
|
263 |
}
|
@@ -270,8 +302,9 @@ class SucuriScanInterface
|
|
270 |
*
|
271 |
* @codeCoverageIgnore
|
272 |
*
|
273 |
-
* @param
|
274 |
-
* @param
|
|
|
275 |
*/
|
276 |
private static function adminNotice($type = 'updated', $message = '')
|
277 |
{
|
@@ -300,18 +333,22 @@ class SucuriScanInterface
|
|
300 |
|
301 |
SucuriScan::throwException($message, $type);
|
302 |
|
303 |
-
echo SucuriScanTemplate::getSection(
|
304 |
-
'
|
305 |
-
|
306 |
-
|
307 |
-
|
|
|
|
|
|
|
308 |
}
|
309 |
}
|
310 |
|
311 |
/**
|
312 |
* Prints a HTML alert of type ERROR in the WordPress admin interface.
|
313 |
*
|
314 |
-
* @param
|
|
|
315 |
*/
|
316 |
public static function error($msg = '')
|
317 |
{
|
@@ -322,7 +359,8 @@ class SucuriScanInterface
|
|
322 |
/**
|
323 |
* Prints a HTML alert of type INFO in the WordPress admin interface.
|
324 |
*
|
325 |
-
* @param
|
|
|
326 |
*/
|
327 |
public static function info($msg = '')
|
328 |
{
|
3 |
/**
|
4 |
* Code related to the interface.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
28 |
* Define all the required variables, script, styles, and basic functions needed
|
29 |
* when the site is loaded, not even the administrator panel but also the front
|
30 |
* page, some bug-fixes will/are applied here for sites behind a proxy, and
|
31 |
+
* sites with old versions of the premium plugin (deprecated on July, 2014).
|
32 |
+
*
|
33 |
+
* @category Library
|
34 |
+
* @package Sucuri
|
35 |
+
* @subpackage SucuriScanner
|
36 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
37 |
+
* @copyright 2010-2017 Sucuri Inc.
|
38 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
39 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
40 |
*/
|
41 |
class SucuriScanInterface
|
42 |
{
|
43 |
/**
|
44 |
* Initialization code for the plugin.
|
45 |
*
|
46 |
+
* @return void
|
|
|
|
|
|
|
47 |
*/
|
48 |
public static function initialize()
|
49 |
{
|
58 |
/**
|
59 |
* Define which javascript and css files will be loaded in the header of the
|
60 |
* plugin pages, only when the administrator panel is accessed.
|
61 |
+
*
|
62 |
+
* @return void
|
63 |
*/
|
64 |
public static function enqueueScripts()
|
65 |
{
|
|
|
|
|
66 |
wp_register_style(
|
67 |
'sucuriscan1',
|
68 |
SUCURISCAN_URL . '/inc/css/styles.css',
|
69 |
array(/* empty */),
|
70 |
+
'3eeb7af'
|
71 |
);
|
72 |
wp_enqueue_style('sucuriscan1');
|
73 |
|
75 |
'sucuriscan1',
|
76 |
SUCURISCAN_URL . '/inc/js/scripts.js',
|
77 |
array(/* empty */),
|
78 |
+
'81f6bb4'
|
79 |
);
|
80 |
wp_enqueue_script('sucuriscan1');
|
81 |
|
84 |
'sucuriscan3',
|
85 |
SUCURISCAN_URL . '/inc/css/flags.min.css',
|
86 |
array(/* empty */),
|
87 |
+
substr(md5(time()), 0, 7)
|
88 |
);
|
89 |
wp_enqueue_style('sucuriscan3');
|
90 |
}
|
95 |
* 1.6.0) all the functionality of the others will be merged here, this will
|
96 |
* remove duplicated functionality, duplicated bugs and/or duplicated
|
97 |
* maintenance reports allowing us to focus in one unique project.
|
98 |
+
*
|
99 |
+
* @return void
|
100 |
*/
|
101 |
public static function handleOldPlugins()
|
102 |
{
|
133 |
/**
|
134 |
* Create a folder in the WordPress upload directory where the plugin will
|
135 |
* store all the temporal or dynamic information.
|
136 |
+
*
|
137 |
+
* @return void
|
138 |
*/
|
139 |
public static function createStorageFolder()
|
140 |
{
|
170 |
* for the current user in session which usually needs to be granted admin
|
171 |
* privileges to access the plugin's tools. It also checks if the required
|
172 |
* SPL library is available and if the settings file is writable.
|
173 |
+
*
|
174 |
+
* @return void
|
175 |
*/
|
176 |
public static function startupChecks()
|
177 |
{
|
181 |
|
182 |
if (!SucuriScanFileInfo::isSplAvailable()) {
|
183 |
/* display a warning when system dependencies are not met */
|
184 |
+
self::error('The plugin requires PHP 5 >= 5.3.0 - OR - PHP 7');
|
185 |
}
|
186 |
|
187 |
+
$filename = SucuriScanOption::optionsFilePath();
|
188 |
+
|
189 |
+
if (!is_writable($filename)) {
|
190 |
+
self::error(
|
191 |
+
sprintf(
|
192 |
+
'Storage is not writable: <code>%s</code>',
|
193 |
$filename /* absolute path of the settings file */
|
194 |
+
)
|
195 |
+
);
|
196 |
}
|
197 |
}
|
198 |
|
205 |
* will execute certain actions and/or display some messages.
|
206 |
*
|
207 |
* @codeCoverageIgnore
|
208 |
+
*
|
209 |
+
* @return void
|
210 |
*/
|
211 |
public static function noticeAfterUpdate()
|
212 |
{
|
231 |
* the new code.
|
232 |
*/
|
233 |
if (SucuriScanOption::isDisabled(':api_service')) {
|
234 |
+
self::info('API service communication is disabled, if you just updated the plugin this might be a good opportunity to test this feature once again with the new code. Enable it again from the "API Service" panel located in the settings page.');
|
235 |
}
|
236 |
|
237 |
/**
|
244 |
*
|
245 |
* @date Featured added at - May 01, 2017
|
246 |
*/
|
247 |
+
self::info('Do you want to get vulnerability disclosures? Subscribe to our newsletter <a href="http://sucuri.hs-sites.com/subscribe-to-security" target="_blank" rel="noopener">here</a>');
|
248 |
}
|
249 |
|
250 |
/**
|
251 |
* Check whether a user has the permissions to see a page from the plugin.
|
252 |
*
|
253 |
* @codeCoverageIgnore
|
254 |
+
*
|
255 |
+
* @return void
|
256 |
*/
|
257 |
public static function checkPageVisibility()
|
258 |
{
|
259 |
if (!function_exists('current_user_can') || !current_user_can('manage_options')) {
|
260 |
SucuriScan::throwException('Access denied; cannot manage options');
|
261 |
+
wp_die('Access denied by Sucuri Inc.');
|
262 |
}
|
263 |
}
|
264 |
|
279 |
|
280 |
if (!$nonce_value || !wp_verify_nonce($nonce_value, $nonce_name)) {
|
281 |
SucuriScan::throwException('Nonce is invalid');
|
282 |
+
self::error(
|
283 |
+
'WordPress CSRF verification failed. The submitted form is'
|
284 |
+
. ' missing an important unique code that prevents automat'
|
285 |
+
. 'ed unwated access, go back and try again. If you did no'
|
286 |
+
. 't submit a form, this error message could be an indicat'
|
287 |
+
. 'ion of an incompatibility between this plugin and anoth'
|
288 |
+
. 'er add-on; one of them is inserting data into the globa'
|
289 |
+
. 'l POST variable when the HTTP request is coming via GET'
|
290 |
+
. '. Disable them one by one (while reloading this page) t'
|
291 |
+
. 'o find the culprit.'
|
292 |
+
);
|
293 |
return false;
|
294 |
}
|
295 |
}
|
302 |
*
|
303 |
* @codeCoverageIgnore
|
304 |
*
|
305 |
+
* @param string $type The type of alert, it can be either Updated or Error.
|
306 |
+
* @param string $message The message that will be printed in the alert.
|
307 |
+
* @return void
|
308 |
*/
|
309 |
private static function adminNotice($type = 'updated', $message = '')
|
310 |
{
|
333 |
|
334 |
SucuriScan::throwException($message, $type);
|
335 |
|
336 |
+
echo SucuriScanTemplate::getSection(
|
337 |
+
'notification-admin',
|
338 |
+
array(
|
339 |
+
'AlertType' => $type,
|
340 |
+
'AlertUnique' => rand(100, 999),
|
341 |
+
'AlertMessage' => $message,
|
342 |
+
)
|
343 |
+
);
|
344 |
}
|
345 |
}
|
346 |
|
347 |
/**
|
348 |
* Prints a HTML alert of type ERROR in the WordPress admin interface.
|
349 |
*
|
350 |
+
* @param string $msg The message that will be printed in the alert.
|
351 |
+
* @return void
|
352 |
*/
|
353 |
public static function error($msg = '')
|
354 |
{
|
359 |
/**
|
360 |
* Prints a HTML alert of type INFO in the WordPress admin interface.
|
361 |
*
|
362 |
+
* @param string $msg The message that will be printed in the alert.
|
363 |
+
* @return void
|
364 |
*/
|
365 |
public static function info($msg = '')
|
366 |
{
|
src/lastlogins-blocked.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the lastlogins-blocked.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -28,6 +34,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
28 |
* in the Firewall service and it also provides a better filtering mechanism for
|
29 |
* any other suspicious login attempt. We will encourage people to leverage the
|
30 |
* power of the Firewall.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
*/
|
32 |
class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
33 |
{
|
@@ -47,7 +61,7 @@ class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
|
47 |
|
48 |
if (is_array($unblockUsers) && !empty($unblockUsers)) {
|
49 |
self::unblock($unblockUsers);
|
50 |
-
SucuriScanInterface::info(
|
51 |
}
|
52 |
}
|
53 |
|
@@ -56,13 +70,15 @@ class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
|
56 |
|
57 |
if (is_array($blocked) && !empty($blocked)) {
|
58 |
foreach ($blocked as $data) {
|
59 |
-
$output['BlockedUsers.List'] .=
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
66 |
}
|
67 |
|
68 |
$output['BlockedUsers.NoItemsVisibility'] = 'hidden';
|
@@ -74,7 +90,8 @@ class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
|
74 |
/**
|
75 |
* Blocks one or more usernames.
|
76 |
*
|
77 |
-
* @param
|
|
|
78 |
*/
|
79 |
public static function block($users = array())
|
80 |
{
|
@@ -104,7 +121,8 @@ class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
|
104 |
/**
|
105 |
* Unblocks one or more usernames.
|
106 |
*
|
107 |
-
* @param
|
|
|
108 |
*/
|
109 |
public static function unblock($users = array())
|
110 |
{
|
@@ -129,43 +147,47 @@ class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
|
129 |
* check to see if the username has been blocked by an admin and proceed
|
130 |
* according to the expected behavior. Either we will stop the request right
|
131 |
* here or let it propagate to the authentication checker.
|
|
|
|
|
132 |
*/
|
133 |
public static function blockUserLogin()
|
134 |
{
|
135 |
-
if (class_exists('SucuriScanRequest')
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
) {
|
138 |
-
$
|
139 |
-
$
|
140 |
-
|
141 |
-
if (
|
142 |
-
|
143 |
-
$blocked = $cache->getAll();
|
144 |
-
$cache_key = md5($username);
|
145 |
-
|
146 |
-
if (is_array($blocked)
|
147 |
-
&& is_string($cache_key)
|
148 |
-
&& array_key_exists($cache_key, $blocked)
|
149 |
-
) {
|
150 |
-
$blocked[$cache_key]->last_attempt = time();
|
151 |
-
$cache->set($cache_key, $blocked[$cache_key]);
|
152 |
-
|
153 |
-
if (!headers_sent()) {
|
154 |
-
header('HTTP/1.1 403 Forbidden');
|
155 |
-
}
|
156 |
-
|
157 |
-
exit(0);
|
158 |
-
}
|
159 |
}
|
|
|
|
|
160 |
}
|
161 |
}
|
162 |
|
163 |
/**
|
164 |
* Finds the first login attempt of a specific username.
|
165 |
*
|
166 |
-
* @param
|
167 |
-
* @param
|
168 |
-
* @return int
|
169 |
*/
|
170 |
private static function firstAttempt($logs, $user)
|
171 |
{
|
@@ -187,9 +209,9 @@ class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
|
187 |
/**
|
188 |
* Finds the last login attempt of a specific username.
|
189 |
*
|
190 |
-
* @param
|
191 |
-
* @param
|
192 |
-
* @return int
|
193 |
*/
|
194 |
private static function lastAttempt($logs, $user)
|
195 |
{
|
3 |
/**
|
4 |
* Code related to the lastlogins-blocked.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
34 |
* in the Firewall service and it also provides a better filtering mechanism for
|
35 |
* any other suspicious login attempt. We will encourage people to leverage the
|
36 |
* power of the Firewall.
|
37 |
+
*
|
38 |
+
* @category Library
|
39 |
+
* @package Sucuri
|
40 |
+
* @subpackage SucuriScanner
|
41 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
42 |
+
* @copyright 2010-2017 Sucuri Inc.
|
43 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
44 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
45 |
*/
|
46 |
class SucuriScanBlockedUsers extends SucuriScanLastLogins
|
47 |
{
|
61 |
|
62 |
if (is_array($unblockUsers) && !empty($unblockUsers)) {
|
63 |
self::unblock($unblockUsers);
|
64 |
+
SucuriScanInterface::info('Selected user accounts were unblocked');
|
65 |
}
|
66 |
}
|
67 |
|
70 |
|
71 |
if (is_array($blocked) && !empty($blocked)) {
|
72 |
foreach ($blocked as $data) {
|
73 |
+
$output['BlockedUsers.List'] .= SucuriScanTemplate::getSnippet(
|
74 |
+
'lastlogins-blockedusers',
|
75 |
+
array(
|
76 |
+
'BlockedUsers.Username' => $data->username,
|
77 |
+
'BlockedUsers.BlockedAt' => self::datetime($data->blocked_at),
|
78 |
+
'BlockedUsers.FirstAttempt' => self::datetime($data->first_attempt),
|
79 |
+
'BlockedUsers.LastAttempt' => self::datetime($data->last_attempt),
|
80 |
+
)
|
81 |
+
);
|
82 |
}
|
83 |
|
84 |
$output['BlockedUsers.NoItemsVisibility'] = 'hidden';
|
90 |
/**
|
91 |
* Blocks one or more usernames.
|
92 |
*
|
93 |
+
* @param array $users List of usernames.
|
94 |
+
* @return void
|
95 |
*/
|
96 |
public static function block($users = array())
|
97 |
{
|
121 |
/**
|
122 |
* Unblocks one or more usernames.
|
123 |
*
|
124 |
+
* @param array $users List of usernames.
|
125 |
+
* @return void
|
126 |
*/
|
127 |
public static function unblock($users = array())
|
128 |
{
|
147 |
* check to see if the username has been blocked by an admin and proceed
|
148 |
* according to the expected behavior. Either we will stop the request right
|
149 |
* here or let it propagate to the authentication checker.
|
150 |
+
*
|
151 |
+
* @return void
|
152 |
*/
|
153 |
public static function blockUserLogin()
|
154 |
{
|
155 |
+
if (!class_exists('SucuriScanRequest') || !class_exists('SucuriScanCache')) {
|
156 |
+
return;
|
157 |
+
}
|
158 |
+
|
159 |
+
$username = SucuriScanRequest::post('log');
|
160 |
+
$password = SucuriScanRequest::post('pwd');
|
161 |
+
|
162 |
+
if ($username === false || $password === false) {
|
163 |
+
return;
|
164 |
+
}
|
165 |
+
|
166 |
+
$cache = new SucuriScanCache('blockedusers');
|
167 |
+
$blocked = $cache->getAll();
|
168 |
+
$cache_key = md5($username);
|
169 |
+
|
170 |
+
if (is_array($blocked)
|
171 |
+
&& is_string($cache_key)
|
172 |
+
&& array_key_exists($cache_key, $blocked)
|
173 |
) {
|
174 |
+
$blocked[$cache_key]->last_attempt = time();
|
175 |
+
$cache->set($cache_key, $blocked[$cache_key]);
|
176 |
+
|
177 |
+
if (!headers_sent()) {
|
178 |
+
header('HTTP/1.1 403 Forbidden');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
}
|
180 |
+
|
181 |
+
exit(0);
|
182 |
}
|
183 |
}
|
184 |
|
185 |
/**
|
186 |
* Finds the first login attempt of a specific username.
|
187 |
*
|
188 |
+
* @param array $logs List of failed login attempts.
|
189 |
+
* @param string $user Username to be inspected.
|
190 |
+
* @return int Timestamp of the first login attempt.
|
191 |
*/
|
192 |
private static function firstAttempt($logs, $user)
|
193 |
{
|
209 |
/**
|
210 |
* Finds the last login attempt of a specific username.
|
211 |
*
|
212 |
+
* @param array $logs List of failed login attempts.
|
213 |
+
* @param string $user Username to be inspected.
|
214 |
+
* @return int Timestamp of the last login attempt.
|
215 |
*/
|
216 |
private static function lastAttempt($logs, $user)
|
217 |
{
|
src/lastlogins-failed.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the lastlogins-failed.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -38,7 +44,7 @@ function sucuriscan_failed_logins_panel()
|
|
38 |
|
39 |
if (is_array($blockUsers) && !empty($blockUsers)) {
|
40 |
SucuriScanBlockedUsers::block($blockUsers);
|
41 |
-
SucuriScanInterface::info(
|
42 |
}
|
43 |
}
|
44 |
|
@@ -51,6 +57,7 @@ function sucuriscan_failed_logins_panel()
|
|
51 |
$max_failed_logins = SucuriScanOption::getOption(':maximum_failed_logins');
|
52 |
$notify_bruteforce_attack = SucuriScanOption::getOption(':notify_bruteforce_attack');
|
53 |
$failed_logins = sucuriscan_get_all_failed_logins($page_offset, $max_per_page);
|
|
|
54 |
|
55 |
if ($failed_logins) {
|
56 |
$counter = 0;
|
@@ -74,16 +81,22 @@ function sucuriscan_failed_logins_panel()
|
|
74 |
$wrong_user_password_color = 'info';
|
75 |
}
|
76 |
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
'
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
$counter++;
|
89 |
}
|
@@ -121,9 +134,9 @@ function sucuriscan_failed_logins_panel()
|
|
121 |
*
|
122 |
* @see sucuriscan_reset_failed_logins()
|
123 |
*
|
124 |
-
* @param
|
125 |
-
* @param
|
126 |
-
* @return string|false
|
127 |
*/
|
128 |
function sucuriscan_failed_logins_datastore_path($get_old_logs = false, $reset = false)
|
129 |
{
|
@@ -157,8 +170,8 @@ function sucuriscan_failed_logins_default_content()
|
|
157 |
/**
|
158 |
* Returns failed logins data including old entries.
|
159 |
*
|
160 |
-
* @param
|
161 |
-
* @param
|
162 |
* @return array|false Failed logins data.
|
163 |
*/
|
164 |
function sucuriscan_get_all_failed_logins($offset = 0, $limit = -1)
|
@@ -195,10 +208,10 @@ function sucuriscan_get_all_failed_logins($offset = 0, $limit = -1)
|
|
195 |
* with the report) or reset the file after considering it a normal behavior of
|
196 |
* the site.
|
197 |
*
|
198 |
-
* @param
|
199 |
-
* @param
|
200 |
-
* @param
|
201 |
-
* @return array|false
|
202 |
*/
|
203 |
function sucuriscan_get_failed_logins($get_old_logs = false, $offset = 0, $limit = -1)
|
204 |
{
|
@@ -286,7 +299,7 @@ function sucuriscan_get_failed_logins($get_old_logs = false, $offset = 0, $limit
|
|
286 |
|
287 |
if (!is_array($first)) {
|
288 |
/* In case the JSON is not decoded yet */
|
289 |
-
$first= @json_decode($first, true);
|
290 |
}
|
291 |
|
292 |
$failed_logins['last_attempt'] = $last['attempt_time'];
|
@@ -301,29 +314,33 @@ function sucuriscan_get_failed_logins($get_old_logs = false, $offset = 0, $limit
|
|
301 |
* this entry will contain the username, timestamp of the login attempt, remote
|
302 |
* address of the computer sending the request, and the user-agent.
|
303 |
*
|
304 |
-
* @param
|
305 |
-
* @param
|
306 |
-
* @return bool
|
307 |
*/
|
308 |
function sucuriscan_log_failed_login($user_login = '', $wrong_password = '')
|
309 |
{
|
310 |
-
|
311 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
312 |
'user_login' => $user_login,
|
313 |
'user_password' => $wrong_password,
|
314 |
'attempt_time' => time(),
|
315 |
'remote_addr' => SucuriScan::getRemoteAddr(),
|
316 |
'user_agent' => SucuriScan::getUserAgent(),
|
317 |
-
)
|
318 |
-
|
319 |
-
return (bool) @file_put_contents(
|
320 |
-
$storage,
|
321 |
-
$login_data . "\n",
|
322 |
-
FILE_APPEND
|
323 |
-
);
|
324 |
-
}
|
325 |
|
326 |
-
return
|
|
|
|
|
|
|
|
|
327 |
}
|
328 |
|
329 |
/**
|
@@ -332,64 +349,68 @@ function sucuriscan_log_failed_login($user_login = '', $wrong_password = '')
|
|
332 |
* in HTML code to send as a report via email according to the plugin settings
|
333 |
* for the email alerts.
|
334 |
*
|
335 |
-
* @param
|
336 |
-
* @return bool
|
337 |
*/
|
338 |
function sucuriscan_report_failed_logins($failed_logins = array())
|
339 |
{
|
340 |
-
if (
|
341 |
-
|
342 |
-
$
|
|
|
|
|
|
|
343 |
|
344 |
-
|
345 |
-
|
346 |
|
347 |
-
|
348 |
-
|
349 |
-
$table_html .= '<tr>';
|
350 |
-
$table_html .= '<th>' . __('Username', SUCURISCAN_TEXTDOMAIN) . '</th>';
|
351 |
-
$table_html .= '<th>' . __('Password', SUCURISCAN_TEXTDOMAIN) . '</th>';
|
352 |
-
$table_html .= '<th>' . __('RemoteAddr', SUCURISCAN_TEXTDOMAIN) . '</th>';
|
353 |
-
$table_html .= '<th>' . __('AttemptTimestamp', SUCURISCAN_TEXTDOMAIN) . '</th>';
|
354 |
-
$table_html .= '<th>' . __('AttemptDatetime', SUCURISCAN_TEXTDOMAIN) . '</th>';
|
355 |
-
$table_html .= '</tr>';
|
356 |
-
$table_html .= '</thead>';
|
357 |
|
358 |
-
|
359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
$table_html .= '<td>' . esc_attr($login_data['user_login']) . '</td>';
|
367 |
-
$table_html .= '<td>' . esc_attr($login_data['user_password']) . '</td>';
|
368 |
-
$table_html .= '<td>' . esc_attr($login_data['remote_addr']) . '</td>';
|
369 |
-
$table_html .= '<td>' . esc_attr($login_data['attempt_time']) . '</td>';
|
370 |
-
$table_html .= '<td>' . esc_attr($login_data['attempt_date']) . '</td>';
|
371 |
-
$table_html .= '</tr>';
|
372 |
-
} else {
|
373 |
-
$mail_content .= "\n";
|
374 |
-
$mail_content .= __('Username', SUCURISCAN_TEXTDOMAIN) . ":\x20" . $login_data['user_login'] . "\n";
|
375 |
-
$mail_content .= __('Password', SUCURISCAN_TEXTDOMAIN) . ":\x20" . $login_data['user_password'] . "\n";
|
376 |
-
$mail_content .= __('RemoteAddr', SUCURISCAN_TEXTDOMAIN) . ":\x20" . $login_data['remote_addr'] . "\n";
|
377 |
-
$mail_content .= __('AttemptTimestamp', SUCURISCAN_TEXTDOMAIN) . ":\x20" . $login_data['attempt_time'] . "\n";
|
378 |
-
$mail_content .= __('AttemptDatetime', SUCURISCAN_TEXTDOMAIN) . ":\x20" . $login_data['attempt_date'] . "\n";
|
379 |
-
}
|
380 |
-
}
|
381 |
|
382 |
if ($prettify_mails) {
|
383 |
-
$table_html .= '
|
384 |
-
$table_html .= '</
|
385 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
386 |
}
|
|
|
387 |
|
388 |
-
|
389 |
-
|
|
|
|
|
|
|
390 |
|
391 |
-
|
392 |
-
|
|
|
393 |
}
|
394 |
|
395 |
return false;
|
3 |
/**
|
4 |
* Code related to the lastlogins-failed.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
44 |
|
45 |
if (is_array($blockUsers) && !empty($blockUsers)) {
|
46 |
SucuriScanBlockedUsers::block($blockUsers);
|
47 |
+
SucuriScanInterface::info('Selected user accounts were blocked');
|
48 |
}
|
49 |
}
|
50 |
|
57 |
$max_failed_logins = SucuriScanOption::getOption(':maximum_failed_logins');
|
58 |
$notify_bruteforce_attack = SucuriScanOption::getOption(':notify_bruteforce_attack');
|
59 |
$failed_logins = sucuriscan_get_all_failed_logins($page_offset, $max_per_page);
|
60 |
+
$show_password = SucuriScanOption::isEnabled(':notify_failed_password');
|
61 |
|
62 |
if ($failed_logins) {
|
63 |
$counter = 0;
|
81 |
$wrong_user_password_color = 'info';
|
82 |
}
|
83 |
|
84 |
+
if (!$show_password) {
|
85 |
+
$wrong_user_password = 'hidden';
|
86 |
+
}
|
87 |
+
|
88 |
+
$template_variables['FailedLogins.List'] .= SucuriScanTemplate::getSnippet(
|
89 |
+
'lastlogins-failedlogins',
|
90 |
+
array(
|
91 |
+
'FailedLogins.Num' => $login_data['attempt_count'],
|
92 |
+
'FailedLogins.Username' => $login_data['user_login'],
|
93 |
+
'FailedLogins.RemoteAddr' => $login_data['remote_addr'],
|
94 |
+
'FailedLogins.UserAgent' => $login_data['user_agent'],
|
95 |
+
'FailedLogins.Password' => $wrong_user_password,
|
96 |
+
'FailedLogins.PasswordColor' => $wrong_user_password_color,
|
97 |
+
'FailedLogins.Datetime' => SucuriScan::datetime($login_data['attempt_time']),
|
98 |
+
)
|
99 |
+
);
|
100 |
|
101 |
$counter++;
|
102 |
}
|
134 |
*
|
135 |
* @see sucuriscan_reset_failed_logins()
|
136 |
*
|
137 |
+
* @param bool $get_old_logs Whether the old logs will be retrieved or not.
|
138 |
+
* @param bool $reset Whether the file will be resetted or not.
|
139 |
+
* @return string|false Absolute path to the file.
|
140 |
*/
|
141 |
function sucuriscan_failed_logins_datastore_path($get_old_logs = false, $reset = false)
|
142 |
{
|
170 |
/**
|
171 |
* Returns failed logins data including old entries.
|
172 |
*
|
173 |
+
* @param int $offset Initial index to start the array.
|
174 |
+
* @param int $limit Number of items in the returned array.
|
175 |
* @return array|false Failed logins data.
|
176 |
*/
|
177 |
function sucuriscan_get_all_failed_logins($offset = 0, $limit = -1)
|
208 |
* with the report) or reset the file after considering it a normal behavior of
|
209 |
* the site.
|
210 |
*
|
211 |
+
* @param bool $get_old_logs Whether the old logs will be retrieved or not.
|
212 |
+
* @param int $offset Array index from where to start collecting the data.
|
213 |
+
* @param int $limit Number of items to insert into the returned array.
|
214 |
+
* @return array|false Information and entries gathered from the failed logins datastore file.
|
215 |
*/
|
216 |
function sucuriscan_get_failed_logins($get_old_logs = false, $offset = 0, $limit = -1)
|
217 |
{
|
299 |
|
300 |
if (!is_array($first)) {
|
301 |
/* In case the JSON is not decoded yet */
|
302 |
+
$first = @json_decode($first, true);
|
303 |
}
|
304 |
|
305 |
$failed_logins['last_attempt'] = $last['attempt_time'];
|
314 |
* this entry will contain the username, timestamp of the login attempt, remote
|
315 |
* address of the computer sending the request, and the user-agent.
|
316 |
*
|
317 |
+
* @param string $user_login Information from the current failed login event.
|
318 |
+
* @param string $wrong_password Wrong password used during the supposed attack.
|
319 |
+
* @return bool Whether the information of the current failed login event was stored or not.
|
320 |
*/
|
321 |
function sucuriscan_log_failed_login($user_login = '', $wrong_password = '')
|
322 |
{
|
323 |
+
$storage = sucuriscan_failed_logins_datastore_path();
|
324 |
+
|
325 |
+
if (!$storage) {
|
326 |
+
return false;
|
327 |
+
}
|
328 |
+
|
329 |
+
$login_data = json_encode(
|
330 |
+
array(
|
331 |
'user_login' => $user_login,
|
332 |
'user_password' => $wrong_password,
|
333 |
'attempt_time' => time(),
|
334 |
'remote_addr' => SucuriScan::getRemoteAddr(),
|
335 |
'user_agent' => SucuriScan::getUserAgent(),
|
336 |
+
)
|
337 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
338 |
|
339 |
+
return (bool) @file_put_contents(
|
340 |
+
$storage,
|
341 |
+
$login_data . "\n",
|
342 |
+
FILE_APPEND
|
343 |
+
);
|
344 |
}
|
345 |
|
346 |
/**
|
349 |
* in HTML code to send as a report via email according to the plugin settings
|
350 |
* for the email alerts.
|
351 |
*
|
352 |
+
* @param array $failed_logins Information gathered from the failed logins.
|
353 |
+
* @return bool Whether the report was sent via email or not.
|
354 |
*/
|
355 |
function sucuriscan_report_failed_logins($failed_logins = array())
|
356 |
{
|
357 |
+
if (!$failed_logins
|
358 |
+
|| !isset($failed_logins['count'])
|
359 |
+
|| $failed_logins['count'] < 1
|
360 |
+
) {
|
361 |
+
return false;
|
362 |
+
}
|
363 |
|
364 |
+
$mail_content = '';
|
365 |
+
$prettify_mails = SucuriScanMail::prettifyMails();
|
366 |
|
367 |
+
if ($prettify_mails) {
|
368 |
+
$table_html = '<table border="1" cellspacing="0" cellpadding="0">';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
|
370 |
+
// Add the table headers.
|
371 |
+
$table_html .= '<thead>';
|
372 |
+
$table_html .= '<tr>';
|
373 |
+
$table_html .= '<th>' . 'Username' . '</th>';
|
374 |
+
$table_html .= '<th>' . 'Password' . '</th>';
|
375 |
+
$table_html .= '<th>' . 'IP Address' . '</th>';
|
376 |
+
$table_html .= '<th>' . 'Attempt Timestamp' . '</th>';
|
377 |
+
$table_html .= '<th>' . 'Attempt Date/Time' . '</th>';
|
378 |
+
$table_html .= '</tr>';
|
379 |
+
$table_html .= '</thead>';
|
380 |
|
381 |
+
$table_html .= '<tbody>';
|
382 |
+
}
|
383 |
+
|
384 |
+
foreach ($failed_logins['entries'] as $login_data) {
|
385 |
+
$login_data['attempt_date'] = SucuriScan::datetime($login_data['attempt_time']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
386 |
|
387 |
if ($prettify_mails) {
|
388 |
+
$table_html .= '<tr>';
|
389 |
+
$table_html .= '<td>' . esc_attr($login_data['user_login']) . '</td>';
|
390 |
+
$table_html .= '<td>' . esc_attr($login_data['user_password']) . '</td>';
|
391 |
+
$table_html .= '<td>' . esc_attr($login_data['remote_addr']) . '</td>';
|
392 |
+
$table_html .= '<td>' . esc_attr($login_data['attempt_time']) . '</td>';
|
393 |
+
$table_html .= '<td>' . esc_attr($login_data['attempt_date']) . '</td>';
|
394 |
+
$table_html .= '</tr>';
|
395 |
+
} else {
|
396 |
+
$mail_content .= "\n";
|
397 |
+
$mail_content .= 'Username' . ":\x20" . $login_data['user_login'] . "\n";
|
398 |
+
$mail_content .= 'Password' . ":\x20" . $login_data['user_password'] . "\n";
|
399 |
+
$mail_content .= 'IP Address' . ":\x20" . $login_data['remote_addr'] . "\n";
|
400 |
+
$mail_content .= 'Attempt Timestamp' . ":\x20" . $login_data['attempt_time'] . "\n";
|
401 |
+
$mail_content .= 'Attempt Date/Time' . ":\x20" . $login_data['attempt_date'] . "\n";
|
402 |
}
|
403 |
+
}
|
404 |
|
405 |
+
if ($prettify_mails) {
|
406 |
+
$table_html .= '</tbody>';
|
407 |
+
$table_html .= '</table>';
|
408 |
+
$mail_content = $table_html;
|
409 |
+
}
|
410 |
|
411 |
+
if (SucuriScanEvent::notifyEvent('bruteforce_attack', $mail_content)) {
|
412 |
+
sucuriscan_reset_failed_logins();
|
413 |
+
return true;
|
414 |
}
|
415 |
|
416 |
return false;
|
src/lastlogins-loggedin.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the lastlogins-loggedin.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -38,15 +44,18 @@ function sucuriscan_loggedin_users_panel()
|
|
38 |
$logged_in_user['last_activity_datetime'] = SucuriScan::datetime($logged_in_user['last_activity']);
|
39 |
$logged_in_user['user_registered_datetime'] = SucuriScan::datetime(strtotime($logged_in_user['user_registered']));
|
40 |
|
41 |
-
$params['LoggedInUsers.List'] .= SucuriScanTemplate::getSnippet(
|
42 |
-
'
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
50 |
}
|
51 |
}
|
52 |
|
@@ -104,8 +113,9 @@ function sucuriscan_save_online_users($logged_in_users = array())
|
|
104 |
|
105 |
if (!function_exists('sucuriscan_unset_online_user_on_logout')) {
|
106 |
/**
|
107 |
-
* Remove a logged in user from the list
|
108 |
-
*
|
|
|
109 |
*/
|
110 |
function sucuriscan_unset_online_user_on_logout()
|
111 |
{
|
@@ -123,9 +133,9 @@ if (!function_exists('sucuriscan_unset_online_user_on_logout')) {
|
|
123 |
* Remove a logged in user from the list of registered users in session using
|
124 |
* the user identifier and the ip address of the last computer used to login.
|
125 |
*
|
126 |
-
* @param
|
127 |
-
* @param
|
128 |
-
* @return bool
|
129 |
*/
|
130 |
function sucuriscan_unset_online_user($user_id = 0, $remote_addr = '')
|
131 |
{
|
@@ -150,8 +160,9 @@ if (!function_exists('sucuriscan_set_online_user')) {
|
|
150 |
/**
|
151 |
* Add an user account to the list of registered users in session.
|
152 |
*
|
153 |
-
* @param
|
154 |
-
* @param
|
|
|
155 |
*/
|
156 |
function sucuriscan_set_online_user($user_login = '', $user = false)
|
157 |
{
|
3 |
/**
|
4 |
* Code related to the lastlogins-loggedin.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
44 |
$logged_in_user['last_activity_datetime'] = SucuriScan::datetime($logged_in_user['last_activity']);
|
45 |
$logged_in_user['user_registered_datetime'] = SucuriScan::datetime(strtotime($logged_in_user['user_registered']));
|
46 |
|
47 |
+
$params['LoggedInUsers.List'] .= SucuriScanTemplate::getSnippet(
|
48 |
+
'lastlogins-loggedin',
|
49 |
+
array(
|
50 |
+
'LoggedInUsers.Id' => $logged_in_user['user_id'],
|
51 |
+
'LoggedInUsers.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $logged_in_user['user_id']),
|
52 |
+
'LoggedInUsers.UserLogin' => $logged_in_user['user_login'],
|
53 |
+
'LoggedInUsers.UserEmail' => $logged_in_user['user_email'],
|
54 |
+
'LoggedInUsers.LastActivity' => $logged_in_user['last_activity_datetime'],
|
55 |
+
'LoggedInUsers.Registered' => $logged_in_user['user_registered_datetime'],
|
56 |
+
'LoggedInUsers.RemoteAddr' => $logged_in_user['remote_addr'],
|
57 |
+
)
|
58 |
+
);
|
59 |
}
|
60 |
}
|
61 |
|
113 |
|
114 |
if (!function_exists('sucuriscan_unset_online_user_on_logout')) {
|
115 |
/**
|
116 |
+
* Remove a logged in user from the list.
|
117 |
+
*
|
118 |
+
* @return void
|
119 |
*/
|
120 |
function sucuriscan_unset_online_user_on_logout()
|
121 |
{
|
133 |
* Remove a logged in user from the list of registered users in session using
|
134 |
* the user identifier and the ip address of the last computer used to login.
|
135 |
*
|
136 |
+
* @param int $user_id User ID of the account that will be logged out.
|
137 |
+
* @param string $remote_addr IP address of the computer where the user logged in.
|
138 |
+
* @return bool True on success, false otherwise.
|
139 |
*/
|
140 |
function sucuriscan_unset_online_user($user_id = 0, $remote_addr = '')
|
141 |
{
|
160 |
/**
|
161 |
* Add an user account to the list of registered users in session.
|
162 |
*
|
163 |
+
* @param string $user_login The name of the user account that just logged in the site.
|
164 |
+
* @param bool $user The WordPress object containing all the information associated to the user.
|
165 |
+
* @return void
|
166 |
*/
|
167 |
function sucuriscan_set_online_user($user_login = '', $user = false)
|
168 |
{
|
src/lastlogins.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the lastlogins.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,6 +24,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
/**
|
20 |
* Placeholder for the last logins interface.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
*/
|
22 |
class SucuriScanLastLogins extends SucuriScan
|
23 |
{
|
@@ -27,6 +41,8 @@ class SucuriScanLastLogins extends SucuriScan
|
|
27 |
* List all the user administrator accounts.
|
28 |
*
|
29 |
* @see https://codex.wordpress.org/Class_Reference/WP_User_Query
|
|
|
|
|
30 |
*/
|
31 |
function sucuriscan_lastlogins_admins()
|
32 |
{
|
@@ -44,7 +60,7 @@ function sucuriscan_lastlogins_admins()
|
|
44 |
'AdminUsers.Username' => $admin->user_login,
|
45 |
'AdminUsers.Email' => $admin->user_email,
|
46 |
'AdminUsers.LastLogins' => '',
|
47 |
-
'AdminUsers.RegisteredAt' =>
|
48 |
'AdminUsers.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $admin->ID),
|
49 |
'AdminUsers.NoLastLogins' => 'visible',
|
50 |
'AdminUsers.NoLastLoginsTable' => 'hidden',
|
@@ -56,20 +72,22 @@ function sucuriscan_lastlogins_admins()
|
|
56 |
) {
|
57 |
$user_snippet['AdminUsers.NoLastLogins'] = 'hidden';
|
58 |
$user_snippet['AdminUsers.NoLastLoginsTable'] = 'visible';
|
59 |
-
$user_snippet['AdminUsers.RegisteredAt'] =
|
60 |
|
61 |
foreach ($last_logins['entries'] as $i => $lastlogin) {
|
62 |
if ($i === 0) {
|
63 |
$user_snippet['AdminUsers.RegisteredAt'] = SucuriScan::datetime(
|
64 |
-
$lastlogin
|
65 |
);
|
66 |
}
|
67 |
|
68 |
-
$user_snippet['AdminUsers.LastLogins'] .=
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
|
|
|
|
73 |
}
|
74 |
}
|
75 |
|
@@ -103,10 +121,12 @@ function sucuriscan_lastlogins_all()
|
|
103 |
|
104 |
if (!sucuriscan_lastlogins_datastore_is_writable()) {
|
105 |
$fpath = SucuriScan::escape(sucuriscan_lastlogins_datastore_filepath());
|
106 |
-
SucuriScanInterface::error(sprintf(
|
107 |
}
|
108 |
|
109 |
-
|
|
|
|
|
110 |
$params['UserList.Total'] = $last_logins['total'];
|
111 |
|
112 |
if ($last_logins['total'] > $max_per_page) {
|
@@ -119,24 +139,24 @@ function sucuriscan_lastlogins_all()
|
|
119 |
|
120 |
foreach ($last_logins['entries'] as $user) {
|
121 |
$user_dataset = array(
|
122 |
-
'UserList.Number' => $user
|
123 |
-
'UserList.UserId' => $user
|
124 |
-
'UserList.Username' =>
|
125 |
'UserList.Displayname' => '',
|
126 |
'UserList.Email' => '',
|
127 |
'UserList.Registered' => '',
|
128 |
-
'UserList.RemoteAddr' => $user
|
129 |
-
'UserList.Hostname' => $user
|
130 |
-
'UserList.Datetime' => $user
|
131 |
-
'UserList.TimeAgo' => SucuriScan::humanTime($user
|
132 |
-
'UserList.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $user
|
133 |
);
|
134 |
|
135 |
-
if ($user
|
136 |
-
$user_dataset['UserList.Username'] = $user
|
137 |
-
$user_dataset['UserList.Displayname'] = $user
|
138 |
-
$user_dataset['UserList.Email'] = $user
|
139 |
-
$user_dataset['UserList.Registered'] = $user
|
140 |
}
|
141 |
|
142 |
$params['UserList'] .= SucuriScanTemplate::getSnippet('lastlogins-all', $user_dataset);
|
@@ -177,11 +197,7 @@ function sucuriscan_lastlogins_datastore_exists()
|
|
177 |
@file_put_contents($fpath, "<?php exit(0); ?>\n", LOCK_EX);
|
178 |
}
|
179 |
|
180 |
-
|
181 |
-
return $fpath;
|
182 |
-
}
|
183 |
-
|
184 |
-
return false;
|
185 |
}
|
186 |
|
187 |
/**
|
@@ -228,29 +244,35 @@ if (!function_exists('sucuri_set_lastlogin')) {
|
|
228 |
/**
|
229 |
* Add a new user session to the list of last user logins.
|
230 |
*
|
231 |
-
* @param
|
|
|
232 |
*/
|
233 |
function sucuriscan_set_lastlogin($user_login = '')
|
234 |
{
|
235 |
-
|
236 |
-
$current_user = get_user_by('login', $user_login);
|
237 |
-
$remote_addr = SucuriScan::getRemoteAddr();
|
238 |
-
|
239 |
-
$login_info = array(
|
240 |
-
'user_id' => $current_user->ID,
|
241 |
-
'user_login' => $current_user->user_login,
|
242 |
-
'user_remoteaddr' => $remote_addr,
|
243 |
-
'user_hostname' => @gethostbyaddr($remote_addr),
|
244 |
-
'user_lastlogin' => current_time('mysql')
|
245 |
-
);
|
246 |
|
247 |
-
|
248 |
-
|
249 |
-
json_encode($login_info) . "\n",
|
250 |
-
FILE_APPEND
|
251 |
-
);
|
252 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
}
|
|
|
254 |
add_action('wp_login', 'sucuriscan_set_lastlogin', 50);
|
255 |
}
|
256 |
|
@@ -260,10 +282,10 @@ if (!function_exists('sucuri_set_lastlogin')) {
|
|
260 |
* The results of this operation can be filtered by specific user identifiers,
|
261 |
* or limiting the quantity of entries.
|
262 |
*
|
263 |
-
* @param
|
264 |
-
* @param
|
265 |
-
* @param
|
266 |
-
* @return array|bool
|
267 |
*/
|
268 |
function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0)
|
269 |
{
|
@@ -305,6 +327,7 @@ function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0)
|
|
305 |
*
|
306 |
* @var object
|
307 |
*/
|
|
|
308 |
$current_user = wp_get_current_user();
|
309 |
$is_admin_user = (bool) current_user_can('manage_options');
|
310 |
|
@@ -332,24 +355,11 @@ function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0)
|
|
332 |
continue;
|
333 |
}
|
334 |
|
335 |
-
// Get the WP_User object and add extra information from the last-login data.
|
336 |
$last_login['user_exists'] = false;
|
337 |
-
$
|
338 |
-
|
339 |
-
if ($user_account) {
|
340 |
-
$last_login['user_exists'] = true;
|
341 |
-
|
342 |
-
foreach ($user_account->data as $var_name => $var_value) {
|
343 |
-
$last_login[ $var_name ] = $var_value;
|
344 |
-
|
345 |
-
if ($var_name == 'user_registered') {
|
346 |
-
$last_login['user_registered_timestamp'] = strtotime($var_value);
|
347 |
-
}
|
348 |
-
}
|
349 |
-
}
|
350 |
|
351 |
$last_login['line_num'] = $i + 1;
|
352 |
-
$last_logins['entries'][] =
|
353 |
$parsed_lines += 1;
|
354 |
|
355 |
if ($limit > 0 && $parsed_lines >= $limit) {
|
@@ -357,6 +367,34 @@ function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0)
|
|
357 |
}
|
358 |
}
|
359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
return $last_logins;
|
361 |
}
|
362 |
|
@@ -365,10 +403,10 @@ if (!function_exists('sucuri_login_redirect')) {
|
|
365 |
* Hook for the wp-login action to redirect the user to a specific URL after
|
366 |
* his successfully login to the administrator interface.
|
367 |
*
|
368 |
-
* @param
|
369 |
-
* @param
|
370 |
-
* @param
|
371 |
-
* @return string
|
372 |
*/
|
373 |
function sucuriscan_login_redirect($redirect_to = '', $request = null, $user = false)
|
374 |
{
|
@@ -392,6 +430,8 @@ if (!function_exists('sucuri_login_redirect')) {
|
|
392 |
if (!function_exists('sucuri_get_user_lastlogin')) {
|
393 |
/**
|
394 |
* Display the last user login at the top of the admin interface.
|
|
|
|
|
395 |
*/
|
396 |
function sucuriscan_get_user_lastlogin()
|
397 |
{
|
@@ -399,8 +439,6 @@ if (!function_exists('sucuri_get_user_lastlogin')) {
|
|
399 |
&& SucuriScanRequest::get(':lastlogin', '1')
|
400 |
) {
|
401 |
$current_user = wp_get_current_user();
|
402 |
-
|
403 |
-
// Select the penultimate entry, not the last one.
|
404 |
$last_logins = sucuriscan_get_logins(2, 0, $current_user->ID);
|
405 |
|
406 |
if ($last_logins
|
@@ -410,10 +448,11 @@ if (!function_exists('sucuri_get_user_lastlogin')) {
|
|
410 |
$row = $last_logins['entries'][1];
|
411 |
$page_url = SucuriScanTemplate::getUrl('lastlogins');
|
412 |
$message = sprintf(
|
413 |
-
|
414 |
-
|
415 |
-
SucuriScan::
|
416 |
-
SucuriScan::escape($row
|
|
|
417 |
SucuriScan::escape($page_url)
|
418 |
);
|
419 |
SucuriScanInterface::info($message);
|
@@ -421,5 +460,6 @@ if (!function_exists('sucuri_get_user_lastlogin')) {
|
|
421 |
}
|
422 |
}
|
423 |
|
|
|
424 |
add_action('admin_notices', 'sucuriscan_get_user_lastlogin');
|
425 |
}
|
3 |
/**
|
4 |
* Code related to the lastlogins.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
/**
|
26 |
* Placeholder for the last logins interface.
|
27 |
+
*
|
28 |
+
* @category Library
|
29 |
+
* @package Sucuri
|
30 |
+
* @subpackage SucuriScanner
|
31 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
32 |
+
* @copyright 2010-2017 Sucuri Inc.
|
33 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
34 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
35 |
*/
|
36 |
class SucuriScanLastLogins extends SucuriScan
|
37 |
{
|
41 |
* List all the user administrator accounts.
|
42 |
*
|
43 |
* @see https://codex.wordpress.org/Class_Reference/WP_User_Query
|
44 |
+
*
|
45 |
+
* @return void
|
46 |
*/
|
47 |
function sucuriscan_lastlogins_admins()
|
48 |
{
|
60 |
'AdminUsers.Username' => $admin->user_login,
|
61 |
'AdminUsers.Email' => $admin->user_email,
|
62 |
'AdminUsers.LastLogins' => '',
|
63 |
+
'AdminUsers.RegisteredAt' => 'unknown',
|
64 |
'AdminUsers.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $admin->ID),
|
65 |
'AdminUsers.NoLastLogins' => 'visible',
|
66 |
'AdminUsers.NoLastLoginsTable' => 'hidden',
|
72 |
) {
|
73 |
$user_snippet['AdminUsers.NoLastLogins'] = 'hidden';
|
74 |
$user_snippet['AdminUsers.NoLastLoginsTable'] = 'visible';
|
75 |
+
$user_snippet['AdminUsers.RegisteredAt'] = 'unknown';
|
76 |
|
77 |
foreach ($last_logins['entries'] as $i => $lastlogin) {
|
78 |
if ($i === 0) {
|
79 |
$user_snippet['AdminUsers.RegisteredAt'] = SucuriScan::datetime(
|
80 |
+
$lastlogin['user_registered_timestamp']
|
81 |
);
|
82 |
}
|
83 |
|
84 |
+
$user_snippet['AdminUsers.LastLogins'] .= SucuriScanTemplate::getSnippet(
|
85 |
+
'lastlogins-admins-lastlogin',
|
86 |
+
array(
|
87 |
+
'AdminUsers.RemoteAddr' => $lastlogin['user_remoteaddr'],
|
88 |
+
'AdminUsers.Datetime' => SucuriScan::datetime($lastlogin['user_lastlogin_timestamp']),
|
89 |
+
)
|
90 |
+
);
|
91 |
}
|
92 |
}
|
93 |
|
121 |
|
122 |
if (!sucuriscan_lastlogins_datastore_is_writable()) {
|
123 |
$fpath = SucuriScan::escape(sucuriscan_lastlogins_datastore_filepath());
|
124 |
+
SucuriScanInterface::error(sprintf('Last-logins data file is not writable: <code>%s</code>', $fpath));
|
125 |
}
|
126 |
|
127 |
+
$last_logins = sucuriscan_get_logins($max_per_page, $offset);
|
128 |
+
|
129 |
+
if (is_array($last_logins) && !empty($last_logins)) {
|
130 |
$params['UserList.Total'] = $last_logins['total'];
|
131 |
|
132 |
if ($last_logins['total'] > $max_per_page) {
|
139 |
|
140 |
foreach ($last_logins['entries'] as $user) {
|
141 |
$user_dataset = array(
|
142 |
+
'UserList.Number' => $user['line_num'],
|
143 |
+
'UserList.UserId' => $user['user_id'],
|
144 |
+
'UserList.Username' => 'unknown',
|
145 |
'UserList.Displayname' => '',
|
146 |
'UserList.Email' => '',
|
147 |
'UserList.Registered' => '',
|
148 |
+
'UserList.RemoteAddr' => $user['user_remoteaddr'],
|
149 |
+
'UserList.Hostname' => $user['user_hostname'],
|
150 |
+
'UserList.Datetime' => $user['user_lastlogin'],
|
151 |
+
'UserList.TimeAgo' => SucuriScan::humanTime($user['user_lastlogin_timestamp']),
|
152 |
+
'UserList.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $user['user_id']),
|
153 |
);
|
154 |
|
155 |
+
if ($user['user_exists']) {
|
156 |
+
$user_dataset['UserList.Username'] = $user['user_login'];
|
157 |
+
$user_dataset['UserList.Displayname'] = $user['display_name'];
|
158 |
+
$user_dataset['UserList.Email'] = $user['user_email'];
|
159 |
+
$user_dataset['UserList.Registered'] = $user['user_registered'];
|
160 |
}
|
161 |
|
162 |
$params['UserList'] .= SucuriScanTemplate::getSnippet('lastlogins-all', $user_dataset);
|
197 |
@file_put_contents($fpath, "<?php exit(0); ?>\n", LOCK_EX);
|
198 |
}
|
199 |
|
200 |
+
return file_exists($fpath) ? $fpath : false;
|
|
|
|
|
|
|
|
|
201 |
}
|
202 |
|
203 |
/**
|
244 |
/**
|
245 |
* Add a new user session to the list of last user logins.
|
246 |
*
|
247 |
+
* @param string $user_login User account involved in the operation.
|
248 |
+
* @return void
|
249 |
*/
|
250 |
function sucuriscan_set_lastlogin($user_login = '')
|
251 |
{
|
252 |
+
$filename = sucuriscan_lastlogins_datastore_is_writable();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
|
254 |
+
if (!is_string($filename)) {
|
255 |
+
return false;
|
|
|
|
|
|
|
256 |
}
|
257 |
+
|
258 |
+
$current_user = get_user_by('login', $user_login);
|
259 |
+
$remote_addr = SucuriScan::getRemoteAddr();
|
260 |
+
|
261 |
+
$login_info = array(
|
262 |
+
'user_id' => $current_user->ID,
|
263 |
+
'user_login' => $current_user->user_login,
|
264 |
+
'user_remoteaddr' => $remote_addr,
|
265 |
+
'user_hostname' => @gethostbyaddr($remote_addr),
|
266 |
+
'user_lastlogin' => current_time('mysql')
|
267 |
+
);
|
268 |
+
|
269 |
+
@file_put_contents(
|
270 |
+
$filename,
|
271 |
+
json_encode($login_info) . "\n",
|
272 |
+
FILE_APPEND
|
273 |
+
);
|
274 |
}
|
275 |
+
|
276 |
add_action('wp_login', 'sucuriscan_set_lastlogin', 50);
|
277 |
}
|
278 |
|
282 |
* The results of this operation can be filtered by specific user identifiers,
|
283 |
* or limiting the quantity of entries.
|
284 |
*
|
285 |
+
* @param int $limit How many entries will be returned from the operation.
|
286 |
+
* @param int $offset Initial point where the logs will be start counting.
|
287 |
+
* @param int $user_id Optional user identifier to filter the results.
|
288 |
+
* @return array|bool All user logins, false on failure.
|
289 |
*/
|
290 |
function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0)
|
291 |
{
|
327 |
*
|
328 |
* @var object
|
329 |
*/
|
330 |
+
$user_ids = array();
|
331 |
$current_user = wp_get_current_user();
|
332 |
$is_admin_user = (bool) current_user_can('manage_options');
|
333 |
|
355 |
continue;
|
356 |
}
|
357 |
|
|
|
358 |
$last_login['user_exists'] = false;
|
359 |
+
$user_ids[] = $last_login['user_id'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
|
361 |
$last_login['line_num'] = $i + 1;
|
362 |
+
$last_logins['entries'][] = $last_login;
|
363 |
$parsed_lines += 1;
|
364 |
|
365 |
if ($limit > 0 && $parsed_lines >= $limit) {
|
367 |
}
|
368 |
}
|
369 |
|
370 |
+
/* no need for database query */
|
371 |
+
if (empty($user_ids)) {
|
372 |
+
return $last_logins;
|
373 |
+
}
|
374 |
+
|
375 |
+
/* extra information for the unique user accounts */
|
376 |
+
$user_ids = array_unique($user_ids);
|
377 |
+
$dbquery = new WP_User_Query(array('include' => $user_ids));
|
378 |
+
|
379 |
+
if ($dbquery) {
|
380 |
+
$results = $dbquery->get_results();
|
381 |
+
|
382 |
+
foreach ($last_logins['entries'] as $key => $entry) {
|
383 |
+
foreach ($results as $dbentry) {
|
384 |
+
if ($entry['user_id'] === $dbentry->ID) {
|
385 |
+
$last_logins['entries'][$key]['user_exists'] = true;
|
386 |
+
$last_logins['entries'][$key]['user_nicename'] = $dbentry->user_nicename;
|
387 |
+
$last_logins['entries'][$key]['user_email'] = $dbentry->user_email;
|
388 |
+
$last_logins['entries'][$key]['user_url'] = $dbentry->user_url;
|
389 |
+
$last_logins['entries'][$key]['user_status'] = $dbentry->user_status;
|
390 |
+
$last_logins['entries'][$key]['display_name'] = $dbentry->display_name;
|
391 |
+
$last_logins['entries'][$key]['user_registered'] = $dbentry->user_registered;
|
392 |
+
$last_logins['entries'][$key]['user_registered_timestamp'] = strtotime($dbentry->user_registered);
|
393 |
+
}
|
394 |
+
}
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
return $last_logins;
|
399 |
}
|
400 |
|
403 |
* Hook for the wp-login action to redirect the user to a specific URL after
|
404 |
* his successfully login to the administrator interface.
|
405 |
*
|
406 |
+
* @param string $redirect_to The redirect destination URL.
|
407 |
+
* @param mixed $request The requested redirect destination URL passed as a parameter.
|
408 |
+
* @param bool $user WP_User object if login was successful, WP_Error object otherwise.
|
409 |
+
* @return string URL where the browser must be redirected to.
|
410 |
*/
|
411 |
function sucuriscan_login_redirect($redirect_to = '', $request = null, $user = false)
|
412 |
{
|
430 |
if (!function_exists('sucuri_get_user_lastlogin')) {
|
431 |
/**
|
432 |
* Display the last user login at the top of the admin interface.
|
433 |
+
*
|
434 |
+
* @return void
|
435 |
*/
|
436 |
function sucuriscan_get_user_lastlogin()
|
437 |
{
|
439 |
&& SucuriScanRequest::get(':lastlogin', '1')
|
440 |
) {
|
441 |
$current_user = wp_get_current_user();
|
|
|
|
|
442 |
$last_logins = sucuriscan_get_logins(2, 0, $current_user->ID);
|
443 |
|
444 |
if ($last_logins
|
448 |
$row = $last_logins['entries'][1];
|
449 |
$page_url = SucuriScanTemplate::getUrl('lastlogins');
|
450 |
$message = sprintf(
|
451 |
+
'Last login was at <b>%s</b> from <b>%s</b> <em>(%s)</em> '
|
452 |
+
. '<a href="%s" target="_self">view all logs</a>',
|
453 |
+
SucuriScan::datetime($row['user_lastlogin_timestamp']),
|
454 |
+
SucuriScan::escape($row['user_remoteaddr']),
|
455 |
+
SucuriScan::escape($row['user_hostname']),
|
456 |
SucuriScan::escape($page_url)
|
457 |
);
|
458 |
SucuriScanInterface::info($message);
|
460 |
}
|
461 |
}
|
462 |
|
463 |
+
add_action('network_admin_notices', 'sucuriscan_get_user_lastlogin');
|
464 |
add_action('admin_notices', 'sucuriscan_get_user_lastlogin');
|
465 |
}
|
src/mail.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the mail.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -23,6 +29,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
23 |
* will check if the site is being compromised, in which case a notification
|
24 |
* will be sent to the site email address (an address that can be configured in
|
25 |
* the settings page).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
*/
|
27 |
class SucuriScanMail extends SucuriScanOption
|
28 |
{
|
@@ -39,11 +53,11 @@ class SucuriScanMail extends SucuriScanOption
|
|
39 |
/**
|
40 |
* Send a message to a specific email address.
|
41 |
*
|
42 |
-
* @param
|
43 |
-
* @param
|
44 |
-
* @param
|
45 |
-
* @param
|
46 |
-
* @return bool
|
47 |
*/
|
48 |
public static function sendMail($email = '', $subject = '', $message = '', $data_set = array())
|
49 |
{
|
@@ -101,8 +115,8 @@ class SucuriScanMail extends SucuriScanOption
|
|
101 |
/**
|
102 |
* Generate a subject for the email alerts.
|
103 |
*
|
104 |
-
* @param
|
105 |
-
* @return string
|
106 |
*/
|
107 |
private static function getEmailSubject($event = '')
|
108 |
{
|
@@ -117,8 +131,8 @@ class SucuriScanMail extends SucuriScanOption
|
|
117 |
|| strpos($subject, ':email') !== false
|
118 |
) {
|
119 |
$user = wp_get_current_user();
|
120 |
-
$username =
|
121 |
-
$eaddress =
|
122 |
|
123 |
if ($user instanceof WP_User
|
124 |
&& isset($user->user_login)
|
@@ -138,10 +152,10 @@ class SucuriScanMail extends SucuriScanOption
|
|
138 |
/**
|
139 |
* Generate a HTML version of the message that will be sent through an email.
|
140 |
*
|
141 |
-
* @param
|
142 |
-
* @param
|
143 |
-
* @param
|
144 |
-
* @return string
|
145 |
*/
|
146 |
private static function prettifyMail($subject = '', $message = '', $data_set = array())
|
147 |
{
|
@@ -160,7 +174,7 @@ class SucuriScanMail extends SucuriScanOption
|
|
160 |
&& !empty($user->user_login)
|
161 |
) {
|
162 |
$display_name = sprintf(
|
163 |
-
|
164 |
$user->display_name,
|
165 |
$user->user_login
|
166 |
);
|
@@ -186,7 +200,7 @@ class SucuriScanMail extends SucuriScanOption
|
|
186 |
}
|
187 |
}
|
188 |
|
189 |
-
$params['TemplateTitle'] =
|
190 |
$params['Subject'] = $subject;
|
191 |
$params['Website'] = $website;
|
192 |
$params['RemoteAddress'] = self::getRemoteAddr();
|
3 |
/**
|
4 |
* Code related to the mail.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
29 |
* will check if the site is being compromised, in which case a notification
|
30 |
* will be sent to the site email address (an address that can be configured in
|
31 |
* the settings page).
|
32 |
+
*
|
33 |
+
* @category Library
|
34 |
+
* @package Sucuri
|
35 |
+
* @subpackage SucuriScanner
|
36 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
37 |
+
* @copyright 2010-2017 Sucuri Inc.
|
38 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
39 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
40 |
*/
|
41 |
class SucuriScanMail extends SucuriScanOption
|
42 |
{
|
53 |
/**
|
54 |
* Send a message to a specific email address.
|
55 |
*
|
56 |
+
* @param string $email The email address of the recipient that will receive the message.
|
57 |
+
* @param string $subject The reason of the message that will be sent.
|
58 |
+
* @param string $message Body of the message that will be sent.
|
59 |
+
* @param array $data_set Optional parameter to add more information to the notification.
|
60 |
+
* @return bool Whether the email contents were sent successfully.
|
61 |
*/
|
62 |
public static function sendMail($email = '', $subject = '', $message = '', $data_set = array())
|
63 |
{
|
115 |
/**
|
116 |
* Generate a subject for the email alerts.
|
117 |
*
|
118 |
+
* @param string $event The reason of the message that will be sent.
|
119 |
+
* @return string A text with the subject for the email alert.
|
120 |
*/
|
121 |
private static function getEmailSubject($event = '')
|
122 |
{
|
131 |
|| strpos($subject, ':email') !== false
|
132 |
) {
|
133 |
$user = wp_get_current_user();
|
134 |
+
$username = 'unknown';
|
135 |
+
$eaddress = 'unknown';
|
136 |
|
137 |
if ($user instanceof WP_User
|
138 |
&& isset($user->user_login)
|
152 |
/**
|
153 |
* Generate a HTML version of the message that will be sent through an email.
|
154 |
*
|
155 |
+
* @param string $subject The reason of the message that will be sent.
|
156 |
+
* @param string $message Body of the message that will be sent.
|
157 |
+
* @param array $data_set Optional parameter to add more information to the notification.
|
158 |
+
* @return string The message formatted in a HTML template.
|
159 |
*/
|
160 |
private static function prettifyMail($subject = '', $message = '', $data_set = array())
|
161 |
{
|
174 |
&& !empty($user->user_login)
|
175 |
) {
|
176 |
$display_name = sprintf(
|
177 |
+
'User: %s (%s)',
|
178 |
$user->display_name,
|
179 |
$user->user_login
|
180 |
);
|
200 |
}
|
201 |
}
|
202 |
|
203 |
+
$params['TemplateTitle'] = 'Sucuri Alert';
|
204 |
$params['Subject'] = $subject;
|
205 |
$params['Website'] = $website;
|
206 |
$params['RemoteAddress'] = self::getRemoteAddr();
|
src/option.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the option.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -36,8 +42,15 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
36 |
* apply network-wide and the data is stored in the wp_sitemeta table under the
|
37 |
* given custom name.
|
38 |
*
|
39 |
-
* @
|
40 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
*/
|
42 |
class SucuriScanOption extends SucuriScanRequest
|
43 |
{
|
@@ -63,8 +76,6 @@ class SucuriScanOption extends SucuriScanRequest
|
|
63 |
'sucuriscan_emails_per_hour' => 5,
|
64 |
'sucuriscan_emails_sent' => 0,
|
65 |
'sucuriscan_ignored_events' => '',
|
66 |
-
'sucuriscan_integrity_startup' => '',
|
67 |
-
'sucuriscan_language' => 'en_US',
|
68 |
'sucuriscan_last_email_at' => time(),
|
69 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
70 |
'sucuriscan_maximum_failed_logins' => 30,
|
@@ -123,8 +134,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
123 |
/**
|
124 |
* Retrieve the default values for some specific options.
|
125 |
*
|
126 |
-
* @param
|
127 |
-
* @return mixed
|
128 |
*/
|
129 |
private static function getDefaultOptions($option = '')
|
130 |
{
|
@@ -135,10 +146,7 @@ class SucuriScanOption extends SucuriScanRequest
|
|
135 |
$admin_email = get_option('admin_email');
|
136 |
$default['sucuriscan_account'] = $admin_email;
|
137 |
$default['sucuriscan_notify_to'] = $admin_email;
|
138 |
-
|
139 |
-
$default['sucuriscan_email_subject'] =
|
140 |
-
__('SucuriAlert', SUCURISCAN_TEXTDOMAIN)
|
141 |
-
. ', :domain, :event, :remoteaddr';
|
142 |
}
|
143 |
|
144 |
return @$default[$option];
|
@@ -196,8 +204,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
196 |
/**
|
197 |
* Write new options into the external options file.
|
198 |
*
|
199 |
-
* @param
|
200 |
-
* @return bool
|
201 |
*/
|
202 |
public static function writeNewOptions($options = array())
|
203 |
{
|
@@ -212,9 +220,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
212 |
* Returns data from the settings file or the database.
|
213 |
*
|
214 |
* To facilitate the development, you can prefix the name of the key in the
|
215 |
-
* request (when accessing it) with a single colon, this method will
|
216 |
-
*
|
217 |
-
* plugin.
|
218 |
*
|
219 |
* NOTE: The SucuriScanCache library is a better interface to read the
|
220 |
* content of a configuration file following the same standard in the other
|
@@ -225,8 +232,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
225 |
*
|
226 |
* @see https://developer.wordpress.org/reference/functions/get_option/
|
227 |
*
|
228 |
-
* @param
|
229 |
-
* @return mixed
|
230 |
*/
|
231 |
public static function getOption($option = '')
|
232 |
{
|
@@ -270,8 +277,18 @@ class SucuriScanOption extends SucuriScanRequest
|
|
270 |
}
|
271 |
}
|
272 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
if (strpos($option, SUCURISCAN . '_') === 0) {
|
274 |
-
|
|
|
|
|
275 |
}
|
276 |
|
277 |
return false;
|
@@ -287,9 +304,9 @@ class SucuriScanOption extends SucuriScanRequest
|
|
287 |
*
|
288 |
* @see https://developer.wordpress.org/reference/functions/update_option/
|
289 |
*
|
290 |
-
* @param
|
291 |
-
* @param
|
292 |
-
* @return bool
|
293 |
*/
|
294 |
public static function updateOption($option = '', $value = '')
|
295 |
{
|
@@ -311,8 +328,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
311 |
*
|
312 |
* @see https://developer.wordpress.org/reference/functions/delete_option/
|
313 |
*
|
314 |
-
* @param
|
315 |
-
* @return bool
|
316 |
*/
|
317 |
public static function deleteOption($option = '')
|
318 |
{
|
@@ -334,8 +351,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
334 |
/**
|
335 |
* Check whether a setting is enabled or not.
|
336 |
*
|
337 |
-
* @param
|
338 |
-
* @return bool
|
339 |
*/
|
340 |
public static function isEnabled($option = '')
|
341 |
{
|
@@ -345,8 +362,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
345 |
/**
|
346 |
* Check whether a setting is disabled or not.
|
347 |
*
|
348 |
-
* @param
|
349 |
-
* @return bool
|
350 |
*/
|
351 |
public static function isDisabled($option = '')
|
352 |
{
|
@@ -358,21 +375,21 @@ class SucuriScanOption extends SucuriScanRequest
|
|
358 |
* containing the word "transient" are excluded from the results, this method
|
359 |
* compatible with multisite instances.
|
360 |
*
|
361 |
-
* @return array All the options stored by Wordpress in the database
|
362 |
*/
|
363 |
private static function getSiteOptions()
|
364 |
{
|
365 |
-
global $wpdb;
|
366 |
-
|
367 |
$settings = array();
|
368 |
-
$results = $wpdb->get_results(
|
369 |
-
"SELECT * FROM {$wpdb->options}
|
370 |
-
WHERE option_name NOT LIKE '%_transient_%'
|
371 |
-
ORDER BY option_id ASC"
|
372 |
-
);
|
373 |
|
374 |
-
|
375 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
}
|
377 |
|
378 |
$external = self::getAllOptions();
|
@@ -388,8 +405,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
388 |
* Check what Wordpress options were changed comparing the values in the database
|
389 |
* with the values sent through a simple request using a GET or POST method.
|
390 |
*
|
391 |
-
* @param
|
392 |
-
* @return array
|
393 |
*/
|
394 |
public static function whatOptionsWereChanged($request = array())
|
395 |
{
|
@@ -510,8 +527,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
510 |
/**
|
511 |
* Check whether an event is being ignored to send alerts or not.
|
512 |
*
|
513 |
-
* @param
|
514 |
-
* @return bool
|
515 |
*/
|
516 |
public static function isIgnoredEvent($event = '')
|
517 |
{
|
@@ -521,25 +538,6 @@ class SucuriScanOption extends SucuriScanRequest
|
|
521 |
return array_key_exists($event, $ignored);
|
522 |
}
|
523 |
|
524 |
-
/**
|
525 |
-
* Add a new post type to the list of ignored events to send alerts.
|
526 |
-
*
|
527 |
-
* @param string $event_name Unique post-type name.
|
528 |
-
* @return bool Whether the event was ignored or not.
|
529 |
-
*/
|
530 |
-
public static function addIgnoredEvent($event_name = '')
|
531 |
-
{
|
532 |
-
$ignored = self::getIgnoredEvents();
|
533 |
-
|
534 |
-
if (array_key_exists($event_name, $ignored)) {
|
535 |
-
return false; /* skip if the post-type was already ignored */
|
536 |
-
}
|
537 |
-
|
538 |
-
$ignored[$event_name] = time(); /* add post-type to the list */
|
539 |
-
|
540 |
-
return self::updateOption(':ignored_events', @json_encode($ignored));
|
541 |
-
}
|
542 |
-
|
543 |
/**
|
544 |
* Get a list of the post types ignored to receive email alerts when the
|
545 |
* "new site content" hook is triggered.
|
@@ -549,36 +547,12 @@ class SucuriScanOption extends SucuriScanRequest
|
|
549 |
public static function getIgnoredEvents()
|
550 |
{
|
551 |
$post_types = self::getOption(':ignored_events');
|
552 |
-
$post_types_arr = false;
|
553 |
|
554 |
if (is_string($post_types)) {
|
555 |
-
$
|
556 |
-
}
|
557 |
-
|
558 |
-
if (!is_array($post_types_arr)) {
|
559 |
-
$post_types_arr = array();
|
560 |
-
}
|
561 |
-
|
562 |
-
return $post_types_arr;
|
563 |
-
}
|
564 |
-
|
565 |
-
/**
|
566 |
-
* Remove a post type from the list of ignored events to send alerts.
|
567 |
-
*
|
568 |
-
* @param string $event Unique post-type name.
|
569 |
-
* @return bool Whether the event was removed from the list or not.
|
570 |
-
*/
|
571 |
-
public static function removeIgnoredEvent($event = '')
|
572 |
-
{
|
573 |
-
$ignored = self::getIgnoredEvents();
|
574 |
-
|
575 |
-
if (!array_key_exists($event, $ignored)) {
|
576 |
-
return false;
|
577 |
}
|
578 |
|
579 |
-
|
580 |
-
|
581 |
-
return self::updateOption(':ignored_events', @json_encode($ignored));
|
582 |
}
|
583 |
|
584 |
/**
|
@@ -631,8 +605,9 @@ class SucuriScanOption extends SucuriScanRequest
|
|
631 |
* firewall page is activated as it assumes that the proxy is creating a
|
632 |
* custom HTTP header for the real IP.
|
633 |
*
|
634 |
-
* @param
|
635 |
-
* @param
|
|
|
636 |
*/
|
637 |
public static function setRevProxy($action = 'disable', $silent = false)
|
638 |
{
|
@@ -652,17 +627,20 @@ class SucuriScanOption extends SucuriScanRequest
|
|
652 |
return true;
|
653 |
}
|
654 |
|
655 |
-
return SucuriScanInterface::info(
|
656 |
-
|
657 |
-
|
658 |
-
|
|
|
|
|
659 |
}
|
660 |
|
661 |
/**
|
662 |
* Change the HTTP header to retrieve the real IP address.
|
663 |
*
|
664 |
-
* @param
|
665 |
-
* @param
|
|
|
666 |
*/
|
667 |
public static function setAddrHeader($header = 'REMOTE_ADDR', $silent = false)
|
668 |
{
|
@@ -670,7 +648,7 @@ class SucuriScanOption extends SucuriScanRequest
|
|
670 |
$allowed = SucuriScan::allowedHttpHeaders(true);
|
671 |
|
672 |
if (!array_key_exists($header, $allowed)) {
|
673 |
-
return SucuriScanInterface::error(
|
674 |
}
|
675 |
|
676 |
$message = sprintf('HTTP header was set to %s', $header);
|
@@ -684,9 +662,11 @@ class SucuriScanOption extends SucuriScanRequest
|
|
684 |
return true;
|
685 |
}
|
686 |
|
687 |
-
return SucuriScanInterface::info(
|
688 |
-
|
689 |
-
|
690 |
-
|
|
|
|
|
691 |
}
|
692 |
}
|
3 |
/**
|
4 |
* Code related to the option.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
42 |
* apply network-wide and the data is stored in the wp_sitemeta table under the
|
43 |
* given custom name.
|
44 |
*
|
45 |
+
* @category Library
|
46 |
+
* @package Sucuri
|
47 |
+
* @subpackage SucuriScanner
|
48 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
49 |
+
* @copyright 2010-2017 Sucuri Inc.
|
50 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
51 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
52 |
+
* @see https://codex.wordpress.org/Option_Reference
|
53 |
+
* @see https://codex.wordpress.org/Options_API
|
54 |
*/
|
55 |
class SucuriScanOption extends SucuriScanRequest
|
56 |
{
|
76 |
'sucuriscan_emails_per_hour' => 5,
|
77 |
'sucuriscan_emails_sent' => 0,
|
78 |
'sucuriscan_ignored_events' => '',
|
|
|
|
|
79 |
'sucuriscan_last_email_at' => time(),
|
80 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
81 |
'sucuriscan_maximum_failed_logins' => 30,
|
134 |
/**
|
135 |
* Retrieve the default values for some specific options.
|
136 |
*
|
137 |
+
* @param string $option List of options, or single option name.
|
138 |
+
* @return mixed The default values for the specified options.
|
139 |
*/
|
140 |
private static function getDefaultOptions($option = '')
|
141 |
{
|
146 |
$admin_email = get_option('admin_email');
|
147 |
$default['sucuriscan_account'] = $admin_email;
|
148 |
$default['sucuriscan_notify_to'] = $admin_email;
|
149 |
+
$default['sucuriscan_email_subject'] = 'Sucuri Alert, :domain, :event, :remoteaddr';
|
|
|
|
|
|
|
150 |
}
|
151 |
|
152 |
return @$default[$option];
|
204 |
/**
|
205 |
* Write new options into the external options file.
|
206 |
*
|
207 |
+
* @param array $options Array with plugins options.
|
208 |
+
* @return bool True if the new options were saved, false otherwise.
|
209 |
*/
|
210 |
public static function writeNewOptions($options = array())
|
211 |
{
|
220 |
* Returns data from the settings file or the database.
|
221 |
*
|
222 |
* To facilitate the development, you can prefix the name of the key in the
|
223 |
+
* request (when accessing it) with a single colon, this method will automa-
|
224 |
+
* tically replace that character with the unique identifier of the plugin.
|
|
|
225 |
*
|
226 |
* NOTE: The SucuriScanCache library is a better interface to read the
|
227 |
* content of a configuration file following the same standard in the other
|
232 |
*
|
233 |
* @see https://developer.wordpress.org/reference/functions/get_option/
|
234 |
*
|
235 |
+
* @param string $option Name of the option.
|
236 |
+
* @return mixed Value associated to the option.
|
237 |
*/
|
238 |
public static function getOption($option = '')
|
239 |
{
|
277 |
}
|
278 |
}
|
279 |
|
280 |
+
/**
|
281 |
+
* Cache default value to stop querying the database.
|
282 |
+
*
|
283 |
+
* The option was not found in the database either, we will return the
|
284 |
+
* data from the array of default values hardcoded in the source code,
|
285 |
+
* then will attempt to write the default value into the flat settings
|
286 |
+
* file to stop querying the database in subsequent requests.
|
287 |
+
*/
|
288 |
if (strpos($option, SUCURISCAN . '_') === 0) {
|
289 |
+
$value = self::getDefaultOptions($option);
|
290 |
+
self::updateOption($option, $value);
|
291 |
+
return $value;
|
292 |
}
|
293 |
|
294 |
return false;
|
304 |
*
|
305 |
* @see https://developer.wordpress.org/reference/functions/update_option/
|
306 |
*
|
307 |
+
* @param string $option Name of the option.
|
308 |
+
* @param mixed $value New value for the option.
|
309 |
+
* @return bool True if option has been updated, false otherwise.
|
310 |
*/
|
311 |
public static function updateOption($option = '', $value = '')
|
312 |
{
|
328 |
*
|
329 |
* @see https://developer.wordpress.org/reference/functions/delete_option/
|
330 |
*
|
331 |
+
* @param string $option Name of the option to be deleted.
|
332 |
+
* @return bool True if option is successfully deleted, false otherwise.
|
333 |
*/
|
334 |
public static function deleteOption($option = '')
|
335 |
{
|
351 |
/**
|
352 |
* Check whether a setting is enabled or not.
|
353 |
*
|
354 |
+
* @param string $option Name of the option to be deleted.
|
355 |
+
* @return bool True if the option is enabled, false otherwise.
|
356 |
*/
|
357 |
public static function isEnabled($option = '')
|
358 |
{
|
362 |
/**
|
363 |
* Check whether a setting is disabled or not.
|
364 |
*
|
365 |
+
* @param string $option Name of the option to be deleted.
|
366 |
+
* @return bool True if the option is disabled, false otherwise.
|
367 |
*/
|
368 |
public static function isDisabled($option = '')
|
369 |
{
|
375 |
* containing the word "transient" are excluded from the results, this method
|
376 |
* compatible with multisite instances.
|
377 |
*
|
378 |
+
* @return array All the options stored by Wordpress in the database.
|
379 |
*/
|
380 |
private static function getSiteOptions()
|
381 |
{
|
|
|
|
|
382 |
$settings = array();
|
|
|
|
|
|
|
|
|
|
|
383 |
|
384 |
+
if (array_key_exists('wpdb', $GLOBALS)) {
|
385 |
+
$results = $GLOBALS['wpdb']->get_results(
|
386 |
+
'SELECT * FROM ' . $GLOBALS['wpdb']->options . ' WHERE opti'
|
387 |
+
. 'on_name NOT LIKE "%_transient_%" ORDER BY option_id ASC'
|
388 |
+
);
|
389 |
+
|
390 |
+
foreach ($results as $row) {
|
391 |
+
$settings[$row->option_name] = $row->option_value;
|
392 |
+
}
|
393 |
}
|
394 |
|
395 |
$external = self::getAllOptions();
|
405 |
* Check what Wordpress options were changed comparing the values in the database
|
406 |
* with the values sent through a simple request using a GET or POST method.
|
407 |
*
|
408 |
+
* @param array $request The content of the global variable GET or POST considering SERVER[REQUEST_METHOD].
|
409 |
+
* @return array A list of all the options that were changes through this request.
|
410 |
*/
|
411 |
public static function whatOptionsWereChanged($request = array())
|
412 |
{
|
527 |
/**
|
528 |
* Check whether an event is being ignored to send alerts or not.
|
529 |
*
|
530 |
+
* @param string $event Unique post-type name.
|
531 |
+
* @return bool Whether an event is being ignored or not.
|
532 |
*/
|
533 |
public static function isIgnoredEvent($event = '')
|
534 |
{
|
538 |
return array_key_exists($event, $ignored);
|
539 |
}
|
540 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
/**
|
542 |
* Get a list of the post types ignored to receive email alerts when the
|
543 |
* "new site content" hook is triggered.
|
547 |
public static function getIgnoredEvents()
|
548 |
{
|
549 |
$post_types = self::getOption(':ignored_events');
|
|
|
550 |
|
551 |
if (is_string($post_types)) {
|
552 |
+
$post_types = @json_decode($post_types, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
553 |
}
|
554 |
|
555 |
+
return (array) $post_types;
|
|
|
|
|
556 |
}
|
557 |
|
558 |
/**
|
605 |
* firewall page is activated as it assumes that the proxy is creating a
|
606 |
* custom HTTP header for the real IP.
|
607 |
*
|
608 |
+
* @param string $action Enable or disable the reverse proxy.
|
609 |
+
* @param bool $silent Hide admin notices on success.
|
610 |
+
* @return void
|
611 |
*/
|
612 |
public static function setRevProxy($action = 'disable', $silent = false)
|
613 |
{
|
627 |
return true;
|
628 |
}
|
629 |
|
630 |
+
return SucuriScanInterface::info(
|
631 |
+
sprintf(
|
632 |
+
'Reverse proxy support was set to <b>%s</b>',
|
633 |
+
$action_d /* either enabled or disabled */
|
634 |
+
)
|
635 |
+
);
|
636 |
}
|
637 |
|
638 |
/**
|
639 |
* Change the HTTP header to retrieve the real IP address.
|
640 |
*
|
641 |
+
* @param string $header Valid HTTP header name.
|
642 |
+
* @param bool $silent Hide admin notices on success.
|
643 |
+
* @return void
|
644 |
*/
|
645 |
public static function setAddrHeader($header = 'REMOTE_ADDR', $silent = false)
|
646 |
{
|
648 |
$allowed = SucuriScan::allowedHttpHeaders(true);
|
649 |
|
650 |
if (!array_key_exists($header, $allowed)) {
|
651 |
+
return SucuriScanInterface::error('HTTP header is not allowed');
|
652 |
}
|
653 |
|
654 |
$message = sprintf('HTTP header was set to %s', $header);
|
662 |
return true;
|
663 |
}
|
664 |
|
665 |
+
return SucuriScanInterface::info(
|
666 |
+
sprintf(
|
667 |
+
'HTTP header was set to <code>%s</code>',
|
668 |
+
$header /* one of the allowed HTTP headers */
|
669 |
+
)
|
670 |
+
);
|
671 |
}
|
672 |
}
|
src/pagehandler.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the pagehandler.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,6 +24,8 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
/**
|
20 |
* Renders the content of the plugin's dashboard page.
|
|
|
|
|
21 |
*/
|
22 |
function sucuriscan_page()
|
23 |
{
|
@@ -32,12 +40,12 @@ function sucuriscan_page()
|
|
32 |
$params['AuditLogs'] = SucuriScanAuditLogs::pageAuditLogs();
|
33 |
|
34 |
/* load data for the SiteCheck section */
|
35 |
-
$params['SiteCheck.iFramesTitle'] =
|
36 |
-
$params['SiteCheck.LinksTitle'] =
|
37 |
-
$params['SiteCheck.ScriptsTitle'] =
|
38 |
-
$params['SiteCheck.iFramesContent'] =
|
39 |
-
$params['SiteCheck.LinksContent'] =
|
40 |
-
$params['SiteCheck.ScriptsContent'] =
|
41 |
$params['SiteCheck.Malware'] = '<div id="sucuriscan-malware"></div>';
|
42 |
$params['SiteCheck.Blacklist'] = '<div id="sucuriscan-blacklist"></div>';
|
43 |
$params['SiteCheck.Recommendations'] = '<div id="sucuriscan-recommendations"></div>';
|
@@ -47,6 +55,8 @@ function sucuriscan_page()
|
|
47 |
|
48 |
/**
|
49 |
* Renders the content of the plugin's firewall page.
|
|
|
|
|
50 |
*/
|
51 |
function sucuriscan_firewall_page()
|
52 |
{
|
@@ -64,6 +74,8 @@ function sucuriscan_firewall_page()
|
|
64 |
|
65 |
/**
|
66 |
* Renders the content of the plugin's last logins page.
|
|
|
|
|
67 |
*/
|
68 |
function sucuriscan_lastlogins_page()
|
69 |
{
|
@@ -77,9 +89,9 @@ function sucuriscan_lastlogins_page()
|
|
77 |
|
78 |
if (@unlink($file_path)) {
|
79 |
sucuriscan_lastlogins_datastore_exists();
|
80 |
-
SucuriScanInterface::info(
|
81 |
} else {
|
82 |
-
SucuriScanInterface::error(
|
83 |
}
|
84 |
}
|
85 |
|
@@ -97,6 +109,8 @@ function sucuriscan_lastlogins_page()
|
|
97 |
|
98 |
/**
|
99 |
* Renders the content of the plugin's settings page.
|
|
|
|
|
100 |
*/
|
101 |
function sucuriscan_settings_page()
|
102 |
{
|
@@ -120,7 +134,6 @@ function sucuriscan_settings_page()
|
|
120 |
/* settings - scanner */
|
121 |
$params['Settings.Scanner.Cronjobs'] = SucuriScanSettingsScanner::cronjobs($nonce);
|
122 |
$params['Settings.Scanner.IntegrityDiffUtility'] = SucuriScanSettingsIntegrity::diffUtility($nonce);
|
123 |
-
$params['Settings.Scanner.IntegrityLanguage'] = SucuriScanSettingsIntegrity::language($nonce);
|
124 |
$params['Settings.Scanner.IntegrityCache'] = SucuriScanSettingsIntegrity::cache($nonce);
|
125 |
$params['Settings.Scanner.IgnoreFolders'] = SucuriScanSettingsScanner::ignoreFolders($nonce);
|
126 |
|
@@ -168,6 +181,8 @@ function sucuriscan_settings_page()
|
|
168 |
|
169 |
/**
|
170 |
* Handles all the AJAX plugin's requests.
|
|
|
|
|
171 |
*/
|
172 |
function sucuriscan_ajax()
|
173 |
{
|
@@ -190,7 +205,6 @@ function sucuriscan_ajax()
|
|
190 |
SucuriScanSettingsPosthack::getPluginsAjax();
|
191 |
SucuriScanSettingsPosthack::resetPasswordAjax();
|
192 |
SucuriScanSettingsPosthack::resetPluginAjax();
|
193 |
-
SucuriScanSettingsScanner::ignoreFoldersAjax();
|
194 |
}
|
195 |
|
196 |
wp_send_json(array('ok' => false, 'error' => 'invalid ajax action'), 200);
|
3 |
/**
|
4 |
* Code related to the pagehandler.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
/**
|
26 |
* Renders the content of the plugin's dashboard page.
|
27 |
+
*
|
28 |
+
* @return void
|
29 |
*/
|
30 |
function sucuriscan_page()
|
31 |
{
|
40 |
$params['AuditLogs'] = SucuriScanAuditLogs::pageAuditLogs();
|
41 |
|
42 |
/* load data for the SiteCheck section */
|
43 |
+
$params['SiteCheck.iFramesTitle'] = 'iFrames';
|
44 |
+
$params['SiteCheck.LinksTitle'] = 'Links';
|
45 |
+
$params['SiteCheck.ScriptsTitle'] = 'Scripts';
|
46 |
+
$params['SiteCheck.iFramesContent'] = 'Loading...';
|
47 |
+
$params['SiteCheck.LinksContent'] = 'Loading...';
|
48 |
+
$params['SiteCheck.ScriptsContent'] = 'Loading...';
|
49 |
$params['SiteCheck.Malware'] = '<div id="sucuriscan-malware"></div>';
|
50 |
$params['SiteCheck.Blacklist'] = '<div id="sucuriscan-blacklist"></div>';
|
51 |
$params['SiteCheck.Recommendations'] = '<div id="sucuriscan-recommendations"></div>';
|
55 |
|
56 |
/**
|
57 |
* Renders the content of the plugin's firewall page.
|
58 |
+
*
|
59 |
+
* @return void
|
60 |
*/
|
61 |
function sucuriscan_firewall_page()
|
62 |
{
|
74 |
|
75 |
/**
|
76 |
* Renders the content of the plugin's last logins page.
|
77 |
+
*
|
78 |
+
* @return void
|
79 |
*/
|
80 |
function sucuriscan_lastlogins_page()
|
81 |
{
|
89 |
|
90 |
if (@unlink($file_path)) {
|
91 |
sucuriscan_lastlogins_datastore_exists();
|
92 |
+
SucuriScanInterface::info('Last-Logins logs were successfully reset.');
|
93 |
} else {
|
94 |
+
SucuriScanInterface::error('Could not reset the last-logins data file.');
|
95 |
}
|
96 |
}
|
97 |
|
109 |
|
110 |
/**
|
111 |
* Renders the content of the plugin's settings page.
|
112 |
+
*
|
113 |
+
* @return void
|
114 |
*/
|
115 |
function sucuriscan_settings_page()
|
116 |
{
|
134 |
/* settings - scanner */
|
135 |
$params['Settings.Scanner.Cronjobs'] = SucuriScanSettingsScanner::cronjobs($nonce);
|
136 |
$params['Settings.Scanner.IntegrityDiffUtility'] = SucuriScanSettingsIntegrity::diffUtility($nonce);
|
|
|
137 |
$params['Settings.Scanner.IntegrityCache'] = SucuriScanSettingsIntegrity::cache($nonce);
|
138 |
$params['Settings.Scanner.IgnoreFolders'] = SucuriScanSettingsScanner::ignoreFolders($nonce);
|
139 |
|
181 |
|
182 |
/**
|
183 |
* Handles all the AJAX plugin's requests.
|
184 |
+
*
|
185 |
+
* @return void
|
186 |
*/
|
187 |
function sucuriscan_ajax()
|
188 |
{
|
205 |
SucuriScanSettingsPosthack::getPluginsAjax();
|
206 |
SucuriScanSettingsPosthack::resetPasswordAjax();
|
207 |
SucuriScanSettingsPosthack::resetPluginAjax();
|
|
|
208 |
}
|
209 |
|
210 |
wp_send_json(array('ok' => false, 'error' => 'invalid ajax action'), 200);
|
src/request.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the request.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -23,6 +29,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
23 |
* HTTP request, generally after a form submission or while loading a URL. Use
|
24 |
* these methods at most instead of accessing an index in the global PHP
|
25 |
* variables _POST, _GET, _REQUEST since they may come with insecure data.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
*/
|
27 |
class SucuriScanRequest extends SucuriScan
|
28 |
{
|
@@ -33,9 +47,9 @@ class SucuriScanRequest extends SucuriScan
|
|
33 |
* will return False if the value doesn't matches what the RegExp defined.
|
34 |
* Very useful to whitelist user input besides form validations.
|
35 |
*
|
36 |
-
* @param
|
37 |
-
* @param
|
38 |
-
* @param
|
39 |
* @return array|string|bool Value from the global _GET or _POST variable.
|
40 |
*/
|
41 |
private static function request($list = array(), $key = '', $pattern = '')
|
@@ -80,9 +94,9 @@ class SucuriScanRequest extends SucuriScan
|
|
80 |
* Returns the value stored in a specific index in the global _GET variable,
|
81 |
* you can specify a pattern as the second argument to match allowed values.
|
82 |
*
|
83 |
-
* @param
|
84 |
-
* @param
|
85 |
-
* @return array|string
|
86 |
*/
|
87 |
public static function get($key = '', $pattern = '')
|
88 |
{
|
@@ -93,9 +107,9 @@ class SucuriScanRequest extends SucuriScan
|
|
93 |
* Returns the value stored in a specific index in the global _POST variable,
|
94 |
* you can specify a pattern as the second argument to match allowed values.
|
95 |
*
|
96 |
-
* @param
|
97 |
-
* @param
|
98 |
-
* @return array|string
|
99 |
*/
|
100 |
public static function post($key = '', $pattern = '')
|
101 |
{
|
@@ -106,9 +120,9 @@ class SucuriScanRequest extends SucuriScan
|
|
106 |
* Returns the value stored in a specific index in the global _REQUEST variable,
|
107 |
* you can specify a pattern as the second argument to match allowed values.
|
108 |
*
|
109 |
-
* @param
|
110 |
-
* @param
|
111 |
-
* @return array|string
|
112 |
*/
|
113 |
public static function getOrPost($key = '', $pattern = '')
|
114 |
{
|
3 |
/**
|
4 |
* Code related to the request.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
29 |
* HTTP request, generally after a form submission or while loading a URL. Use
|
30 |
* these methods at most instead of accessing an index in the global PHP
|
31 |
* variables _POST, _GET, _REQUEST since they may come with insecure data.
|
32 |
+
*
|
33 |
+
* @category Library
|
34 |
+
* @package Sucuri
|
35 |
+
* @subpackage SucuriScanner
|
36 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
37 |
+
* @copyright 2010-2017 Sucuri Inc.
|
38 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
39 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
40 |
*/
|
41 |
class SucuriScanRequest extends SucuriScan
|
42 |
{
|
47 |
* will return False if the value doesn't matches what the RegExp defined.
|
48 |
* Very useful to whitelist user input besides form validations.
|
49 |
*
|
50 |
+
* @param array $list The array where the specified key will be searched.
|
51 |
+
* @param string $key Name of the variable contained in _POST.
|
52 |
+
* @param string $pattern Optional pattern to match allowed values.
|
53 |
* @return array|string|bool Value from the global _GET or _POST variable.
|
54 |
*/
|
55 |
private static function request($list = array(), $key = '', $pattern = '')
|
94 |
* Returns the value stored in a specific index in the global _GET variable,
|
95 |
* you can specify a pattern as the second argument to match allowed values.
|
96 |
*
|
97 |
+
* @param string $key Name of the variable contained in _GET.
|
98 |
+
* @param string $pattern Optional pattern to match allowed values.
|
99 |
+
* @return array|string Value from the global _GET variable.
|
100 |
*/
|
101 |
public static function get($key = '', $pattern = '')
|
102 |
{
|
107 |
* Returns the value stored in a specific index in the global _POST variable,
|
108 |
* you can specify a pattern as the second argument to match allowed values.
|
109 |
*
|
110 |
+
* @param string $key Name of the variable contained in _POST.
|
111 |
+
* @param string $pattern Optional pattern to match allowed values.
|
112 |
+
* @return array|string Value from the global _POST variable.
|
113 |
*/
|
114 |
public static function post($key = '', $pattern = '')
|
115 |
{
|
120 |
* Returns the value stored in a specific index in the global _REQUEST variable,
|
121 |
* you can specify a pattern as the second argument to match allowed values.
|
122 |
*
|
123 |
+
* @param string $key Name of the variable contained in _REQUEST.
|
124 |
+
* @param string $pattern Optional pattern to match allowed values.
|
125 |
+
* @return array|string Value from the global _REQUEST variable.
|
126 |
*/
|
127 |
public static function getOrPost($key = '', $pattern = '')
|
128 |
{
|
src/settings-alerts.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-alerts.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -24,8 +30,8 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
24 |
* is usually the email of the website owner. The plugin allows to add more
|
25 |
* emails to the list so the alerts are sent to other people.
|
26 |
*
|
27 |
-
* @param
|
28 |
-
* @return string
|
29 |
*/
|
30 |
function sucuriscan_settings_alerts_recipients($nonce)
|
31 |
{
|
@@ -47,14 +53,14 @@ function sucuriscan_settings_alerts_recipients($nonce)
|
|
47 |
|
48 |
if (SucuriScan::isValidEmail($new_email)) {
|
49 |
$emails[] = $new_email;
|
50 |
-
$message = sprintf(
|
51 |
|
52 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
53 |
SucuriScanEvent::reportInfoEvent('The email alerts will be sent to: ' . $new_email);
|
54 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
55 |
SucuriScanInterface::info($message);
|
56 |
} else {
|
57 |
-
SucuriScanInterface::error(
|
58 |
}
|
59 |
}
|
60 |
|
@@ -73,7 +79,7 @@ function sucuriscan_settings_alerts_recipients($nonce)
|
|
73 |
|
74 |
if (!empty($deleted_emails)) {
|
75 |
$deleted_emails_str = implode(",\x20", $deleted_emails);
|
76 |
-
$message = sprintf(
|
77 |
|
78 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
79 |
SucuriScanEvent::reportInfoEvent('These emails will stop receiving alerts: ' . $deleted_emails_str);
|
@@ -91,17 +97,18 @@ function sucuriscan_settings_alerts_recipients($nonce)
|
|
91 |
sprintf('Test email alert sent at %s', SucuriScan::datetime()),
|
92 |
array('Force' => true)
|
93 |
);
|
94 |
-
|
|
|
95 |
}
|
96 |
}
|
97 |
|
98 |
|
99 |
foreach ($emails as $email) {
|
100 |
if (!empty($email)) {
|
101 |
-
$params['Alerts.Recipients'] .=
|
102 |
-
|
103 |
-
'Recipient.Email' => $email
|
104 |
-
)
|
105 |
}
|
106 |
}
|
107 |
|
@@ -127,30 +134,34 @@ function sucuriscan_settings_alerts_trustedips()
|
|
127 |
|
128 |
if (SucuriScanInterface::checkNonce()) {
|
129 |
// Trust and IP address to ignore alerts for a subnet.
|
130 |
-
|
|
|
|
|
131 |
if (SucuriScan::isValidIP($trust_ip) || SucuriScan::isValidCIDR($trust_ip)) {
|
132 |
$ip_info = SucuriScan::getIPInfo($trust_ip);
|
133 |
$ip_info['added_at'] = time();
|
134 |
$cache_key = md5($ip_info['remote_addr']);
|
135 |
|
136 |
if ($cache->exists($cache_key)) {
|
137 |
-
SucuriScanInterface::error(
|
138 |
} elseif ($cache->add($cache_key, $ip_info)) {
|
139 |
SucuriScanEvent::reportWarningEvent('IP has been trusted: ' . $trust_ip);
|
140 |
-
SucuriScanInterface::info(sprintf(
|
141 |
} else {
|
142 |
-
SucuriScanInterface::error(
|
143 |
}
|
144 |
}
|
145 |
}
|
146 |
|
147 |
// Trust and IP address to ignore alerts for a subnet.
|
148 |
-
|
|
|
|
|
149 |
foreach ($del_trust_ip as $cache_key) {
|
150 |
$cache->delete($cache_key);
|
151 |
}
|
152 |
|
153 |
-
SucuriScanInterface::info(
|
154 |
}
|
155 |
}
|
156 |
|
@@ -162,13 +173,15 @@ function sucuriscan_settings_alerts_trustedips()
|
|
162 |
$ip_info->cidr_format = 'n/a';
|
163 |
}
|
164 |
|
165 |
-
$params['TrustedIPs.List'] .=
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
172 |
}
|
173 |
|
174 |
$params['TrustedIPs.NoItems.Visibility'] = 'hidden';
|
@@ -191,20 +204,20 @@ function sucuriscan_settings_alerts_subject($nonce)
|
|
191 |
'Alerts.CustomValue' => '',
|
192 |
);
|
193 |
|
194 |
-
$header = __('SucuriAlert', SUCURISCAN_TEXTDOMAIN);
|
195 |
-
|
196 |
$subjects = array(
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
);
|
204 |
|
205 |
// Process form submission to change the alert settings.
|
206 |
if ($nonce) {
|
207 |
-
|
|
|
|
|
208 |
$current_value = SucuriScanOption::getOption(':email_subject');
|
209 |
$new_subject = false;
|
210 |
|
@@ -225,7 +238,7 @@ function sucuriscan_settings_alerts_subject($nonce)
|
|
225 |
) {
|
226 |
$new_subject = trim($custom_subject);
|
227 |
} else {
|
228 |
-
SucuriScanInterface::error(
|
229 |
}
|
230 |
} elseif (is_array($subjects) && in_array($email_subject, $subjects)) {
|
231 |
$new_subject = trim($email_subject);
|
@@ -238,7 +251,7 @@ function sucuriscan_settings_alerts_subject($nonce)
|
|
238 |
SucuriScanOption::updateOption(':email_subject', $new_subject);
|
239 |
SucuriScanEvent::reportInfoEvent($message);
|
240 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
241 |
-
SucuriScanInterface::info(
|
242 |
}
|
243 |
}
|
244 |
}
|
@@ -256,12 +269,14 @@ function sucuriscan_settings_alerts_subject($nonce)
|
|
256 |
$checked = '';
|
257 |
}
|
258 |
|
259 |
-
$params['Alerts.Subject'] .=
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
|
|
|
|
265 |
}
|
266 |
|
267 |
if ($is_official_subject === false) {
|
@@ -285,18 +300,20 @@ function sucuriscan_settings_alerts_perhour($nonce)
|
|
285 |
$params['Alerts.PerHour'] = '';
|
286 |
|
287 |
$emails_per_hour = array(
|
288 |
-
'5' =>
|
289 |
-
'10' =>
|
290 |
-
'20' =>
|
291 |
-
'40' =>
|
292 |
-
'80' =>
|
293 |
-
'160' =>
|
294 |
-
'unlimited' =>
|
295 |
);
|
296 |
|
297 |
if ($nonce) {
|
298 |
// Update the value for the maximum emails per hour.
|
299 |
-
|
|
|
|
|
300 |
if (array_key_exists($per_hour, $emails_per_hour)) {
|
301 |
$per_hour_label = strtolower($emails_per_hour[$per_hour]);
|
302 |
$message = 'Maximum alerts per hour set to <code>' . $per_hour_label . '</code>';
|
@@ -304,9 +321,9 @@ function sucuriscan_settings_alerts_perhour($nonce)
|
|
304 |
SucuriScanOption::updateOption(':emails_per_hour', $per_hour);
|
305 |
SucuriScanEvent::reportInfoEvent($message);
|
306 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
307 |
-
SucuriScanInterface::info(
|
308 |
} else {
|
309 |
-
SucuriScanInterface::error(
|
310 |
}
|
311 |
}
|
312 |
}
|
@@ -330,28 +347,31 @@ function sucuriscan_settings_alerts_bruteforce($nonce)
|
|
330 |
$params['Alerts.BruteForce'] = '';
|
331 |
|
332 |
$max_failed_logins = array(
|
333 |
-
'30' =>
|
334 |
-
'60' =>
|
335 |
-
'120' =>
|
336 |
-
'240' =>
|
337 |
-
'480' =>
|
338 |
);
|
339 |
|
340 |
if ($nonce) {
|
341 |
// Update the maximum failed logins per hour before consider it a brute-force attack.
|
342 |
-
|
|
|
|
|
343 |
if (array_key_exists($maximum, $max_failed_logins)) {
|
344 |
$message = 'Consider brute-force attack after <code>' . $maximum . '</code> failed logins per hour';
|
345 |
|
346 |
SucuriScanOption::updateOption(':maximum_failed_logins', $maximum);
|
347 |
SucuriScanEvent::reportInfoEvent($message);
|
348 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
349 |
-
SucuriScanInterface::info(
|
350 |
-
|
351 |
-
|
352 |
-
|
|
|
353 |
} else {
|
354 |
-
SucuriScanInterface::error(
|
355 |
}
|
356 |
}
|
357 |
}
|
@@ -376,32 +396,32 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
376 |
$params['Alerts.NoAlertsVisibility'] = 'hidden';
|
377 |
|
378 |
$notify_options = array(
|
379 |
-
'sucuriscan_notify_plugin_change' => 'setting:' .
|
380 |
-
'sucuriscan_prettify_mails' => 'setting:' .
|
381 |
-
'sucuriscan_use_wpmail' => 'setting:' .
|
382 |
-
'sucuriscan_lastlogin_redirection' => 'setting:' .
|
383 |
-
'sucuriscan_notify_scan_checksums' => 'setting:' .
|
384 |
-
'sucuriscan_notify_available_updates' => 'setting:' .
|
385 |
-
'sucuriscan_notify_user_registration' => 'user:' .
|
386 |
-
'sucuriscan_notify_success_login' => 'user:' .
|
387 |
-
'sucuriscan_notify_failed_login' => 'user:' .
|
388 |
-
'sucuriscan_notify_failed_password' => 'user:' .
|
389 |
-
'sucuriscan_notify_bruteforce_attack' => 'user:' .
|
390 |
-
'sucuriscan_notify_post_publication' => 'setting:' .
|
391 |
-
'sucuriscan_notify_website_updated' => 'setting:' .
|
392 |
-
'sucuriscan_notify_settings_updated' => 'setting:' .
|
393 |
-
'sucuriscan_notify_theme_editor' => 'setting:' .
|
394 |
-
'sucuriscan_notify_plugin_installed' => 'plugin:' .
|
395 |
-
'sucuriscan_notify_plugin_activated' => 'plugin:' .
|
396 |
-
'sucuriscan_notify_plugin_deactivated' => 'plugin:' .
|
397 |
-
'sucuriscan_notify_plugin_updated' => 'plugin:' .
|
398 |
-
'sucuriscan_notify_plugin_deleted' => 'plugin:' .
|
399 |
-
'sucuriscan_notify_widget_added' => 'widget:' .
|
400 |
-
'sucuriscan_notify_widget_deleted' => 'widget:' .
|
401 |
-
'sucuriscan_notify_theme_installed' => 'theme:' .
|
402 |
-
'sucuriscan_notify_theme_activated' => 'theme:' .
|
403 |
-
'sucuriscan_notify_theme_updated' => 'theme:' .
|
404 |
-
'sucuriscan_notify_theme_deleted' => 'theme:' .
|
405 |
);
|
406 |
|
407 |
/**
|
@@ -421,6 +441,7 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
421 |
$params['Alerts.NoAlertsVisibility'] = 'visible';
|
422 |
unset($notify_options['sucuriscan_notify_success_login']);
|
423 |
unset($notify_options['sucuriscan_notify_failed_login']);
|
|
|
424 |
}
|
425 |
|
426 |
// Process form submission to change the alert settings.
|
@@ -429,6 +450,11 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
429 |
if (SucuriScanRequest::post(':save_alert_events') !== false) {
|
430 |
$ucounter = 0;
|
431 |
|
|
|
|
|
|
|
|
|
|
|
432 |
foreach ($notify_options as $alert_type => $alert_label) {
|
433 |
$option_value = SucuriScanRequest::post($alert_type, '(1|0)');
|
434 |
|
@@ -449,7 +475,7 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
449 |
|
450 |
SucuriScanEvent::reportInfoEvent($message);
|
451 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
452 |
-
SucuriScanInterface::info(
|
453 |
}
|
454 |
}
|
455 |
}
|
@@ -463,7 +489,7 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
463 |
/* identify the optional icon */
|
464 |
$offset = strpos($alert_label, ':');
|
465 |
$alert_group = substr($alert_label, 0, $offset);
|
466 |
-
$alert_label = substr($alert_label, $offset+1);
|
467 |
|
468 |
switch ($alert_group) {
|
469 |
case 'user':
|
@@ -487,13 +513,15 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
487 |
break;
|
488 |
}
|
489 |
|
490 |
-
$params['Alerts.Events'] .=
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
|
|
|
|
497 |
}
|
498 |
|
499 |
return SucuriScanTemplate::getSection('settings-alerts-events', $params);
|
@@ -506,82 +534,78 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
506 |
*/
|
507 |
function sucuriscan_settings_alerts_ignore_posts()
|
508 |
{
|
509 |
-
$params = array(
|
510 |
-
|
511 |
-
|
512 |
-
|
|
|
|
|
513 |
|
514 |
if (SucuriScanInterface::checkNonce()) {
|
515 |
// Ignore a new event for email alerts.
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
527 |
}
|
528 |
-
} elseif ($action == 'remove') {
|
529 |
-
SucuriScanOption::removeIgnoredEvent($ignore_rule);
|
530 |
-
SucuriScanInterface::info(__('PostTypeUnignored', SUCURISCAN_TEXTDOMAIN));
|
531 |
-
SucuriScanEvent::reportNoticeEvent('Changes in <code>' . $ignore_rule . '</code> post-type will not be ignored');
|
532 |
}
|
|
|
|
|
|
|
|
|
533 |
}
|
534 |
}
|
535 |
|
536 |
/* notifications are post updates are disabled; print error */
|
537 |
if (SucuriScanOption::isDisabled(':notify_post_publication')) {
|
538 |
-
$params['
|
539 |
-
$params['
|
540 |
-
'<tr><td colspan="4">%s</td></tr>',
|
541 |
-
__('NoData', SUCURISCAN_TEXTDOMAIN)
|
542 |
-
);
|
543 |
|
544 |
return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params);
|
545 |
}
|
546 |
|
547 |
-
$post_types = SucuriScanOption::getPostTypes();
|
548 |
-
$ignored_events = SucuriScanOption::getIgnoredEvents();
|
549 |
-
|
550 |
-
/* include custom non-registered post-types */
|
551 |
-
foreach ($ignored_events as $event => $time) {
|
552 |
-
if (!array_key_exists($event, $post_types)) {
|
553 |
-
$post_types[$event] = $event;
|
554 |
-
}
|
555 |
-
}
|
556 |
-
|
557 |
/* Check which post-types are being ignored */
|
558 |
foreach ($post_types as $post_type) {
|
559 |
-
$
|
|
|
|
|
560 |
|
561 |
if (array_key_exists($post_type, $ignored_events)) {
|
562 |
-
$
|
563 |
-
$
|
564 |
-
$is_ignored_class = 'danger';
|
565 |
-
$button_action = 'remove';
|
566 |
-
$button_text = __('PostTypeIgnore', SUCURISCAN_TEXTDOMAIN);
|
567 |
-
} else {
|
568 |
-
$is_ignored_text = __('No', SUCURISCAN_TEXTDOMAIN);
|
569 |
-
$was_ignored_at = '--';
|
570 |
-
$is_ignored_class = 'success';
|
571 |
-
$button_action = 'add';
|
572 |
-
$button_text = __('PostTypeUnignore', SUCURISCAN_TEXTDOMAIN);
|
573 |
}
|
574 |
|
575 |
-
$params['
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
));
|
585 |
}
|
586 |
|
587 |
return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params);
|
3 |
/**
|
4 |
* Code related to the settings-alerts.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
30 |
* is usually the email of the website owner. The plugin allows to add more
|
31 |
* emails to the list so the alerts are sent to other people.
|
32 |
*
|
33 |
+
* @param bool $nonce True if the CSRF protection worked, false otherwise.
|
34 |
+
* @return string HTML for the email alert recipients.
|
35 |
*/
|
36 |
function sucuriscan_settings_alerts_recipients($nonce)
|
37 |
{
|
53 |
|
54 |
if (SucuriScan::isValidEmail($new_email)) {
|
55 |
$emails[] = $new_email;
|
56 |
+
$message = sprintf('The email alerts will be sent to: <code>%s</code>', $new_email);
|
57 |
|
58 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
59 |
SucuriScanEvent::reportInfoEvent('The email alerts will be sent to: ' . $new_email);
|
60 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
61 |
SucuriScanInterface::info($message);
|
62 |
} else {
|
63 |
+
SucuriScanInterface::error('Email format not supported.');
|
64 |
}
|
65 |
}
|
66 |
|
79 |
|
80 |
if (!empty($deleted_emails)) {
|
81 |
$deleted_emails_str = implode(",\x20", $deleted_emails);
|
82 |
+
$message = sprintf('These emails will stop receiving alerts: <code>%s</code>', $deleted_emails_str);
|
83 |
|
84 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
85 |
SucuriScanEvent::reportInfoEvent('These emails will stop receiving alerts: ' . $deleted_emails_str);
|
97 |
sprintf('Test email alert sent at %s', SucuriScan::datetime()),
|
98 |
array('Force' => true)
|
99 |
);
|
100 |
+
|
101 |
+
SucuriScanInterface::info('A test alert was sent to your email, check your inbox');
|
102 |
}
|
103 |
}
|
104 |
|
105 |
|
106 |
foreach ($emails as $email) {
|
107 |
if (!empty($email)) {
|
108 |
+
$params['Alerts.Recipients'] .= SucuriScanTemplate::getSnippet(
|
109 |
+
'settings-alerts-recipients',
|
110 |
+
array('Recipient.Email' => $email)
|
111 |
+
);
|
112 |
}
|
113 |
}
|
114 |
|
134 |
|
135 |
if (SucuriScanInterface::checkNonce()) {
|
136 |
// Trust and IP address to ignore alerts for a subnet.
|
137 |
+
$trust_ip = SucuriScanRequest::post(':trust_ip');
|
138 |
+
|
139 |
+
if ($trust_ip) {
|
140 |
if (SucuriScan::isValidIP($trust_ip) || SucuriScan::isValidCIDR($trust_ip)) {
|
141 |
$ip_info = SucuriScan::getIPInfo($trust_ip);
|
142 |
$ip_info['added_at'] = time();
|
143 |
$cache_key = md5($ip_info['remote_addr']);
|
144 |
|
145 |
if ($cache->exists($cache_key)) {
|
146 |
+
SucuriScanInterface::error('The IP specified address was already added.');
|
147 |
} elseif ($cache->add($cache_key, $ip_info)) {
|
148 |
SucuriScanEvent::reportWarningEvent('IP has been trusted: ' . $trust_ip);
|
149 |
+
SucuriScanInterface::info(sprintf('Events generated from this IP will be ignored: <code>%s</code>', $trust_ip));
|
150 |
} else {
|
151 |
+
SucuriScanInterface::error('The IP address could not be added to the trusted list');
|
152 |
}
|
153 |
}
|
154 |
}
|
155 |
|
156 |
// Trust and IP address to ignore alerts for a subnet.
|
157 |
+
$del_trust_ip = SucuriScanRequest::post(':del_trust_ip', '_array');
|
158 |
+
|
159 |
+
if ($del_trust_ip) {
|
160 |
foreach ($del_trust_ip as $cache_key) {
|
161 |
$cache->delete($cache_key);
|
162 |
}
|
163 |
|
164 |
+
SucuriScanInterface::info('The selected IP addresses were successfully deleted.');
|
165 |
}
|
166 |
}
|
167 |
|
173 |
$ip_info->cidr_format = 'n/a';
|
174 |
}
|
175 |
|
176 |
+
$params['TrustedIPs.List'] .= SucuriScanTemplate::getSnippet(
|
177 |
+
'settings-alerts-trustedips',
|
178 |
+
array(
|
179 |
+
'TrustIP.CacheKey' => $cache_key,
|
180 |
+
'TrustIP.RemoteAddr' => SucuriScan::escape($ip_info->remote_addr),
|
181 |
+
'TrustIP.CIDRFormat' => SucuriScan::escape($ip_info->cidr_format),
|
182 |
+
'TrustIP.AddedAt' => SucuriScan::datetime($ip_info->added_at),
|
183 |
+
)
|
184 |
+
);
|
185 |
}
|
186 |
|
187 |
$params['TrustedIPs.NoItems.Visibility'] = 'hidden';
|
204 |
'Alerts.CustomValue' => '',
|
205 |
);
|
206 |
|
|
|
|
|
207 |
$subjects = array(
|
208 |
+
'Sucuri Alert, :domain, :event',
|
209 |
+
'Sucuri Alert, :domain, :event, :remoteaddr',
|
210 |
+
'Sucuri Alert, :domain, :event, :username',
|
211 |
+
'Sucuri Alert, :domain, :event, :email',
|
212 |
+
'Sucuri Alert, :event, :remoteaddr',
|
213 |
+
'Sucuri Alert, :event',
|
214 |
);
|
215 |
|
216 |
// Process form submission to change the alert settings.
|
217 |
if ($nonce) {
|
218 |
+
$email_subject = SucuriScanRequest::post(':email_subject');
|
219 |
+
|
220 |
+
if ($email_subject) {
|
221 |
$current_value = SucuriScanOption::getOption(':email_subject');
|
222 |
$new_subject = false;
|
223 |
|
238 |
) {
|
239 |
$new_subject = trim($custom_subject);
|
240 |
} else {
|
241 |
+
SucuriScanInterface::error('Invalid characters in the email subject.');
|
242 |
}
|
243 |
} elseif (is_array($subjects) && in_array($email_subject, $subjects)) {
|
244 |
$new_subject = trim($email_subject);
|
251 |
SucuriScanOption::updateOption(':email_subject', $new_subject);
|
252 |
SucuriScanEvent::reportInfoEvent($message);
|
253 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
254 |
+
SucuriScanInterface::info('The email subject has been successfully updated');
|
255 |
}
|
256 |
}
|
257 |
}
|
269 |
$checked = '';
|
270 |
}
|
271 |
|
272 |
+
$params['Alerts.Subject'] .= SucuriScanTemplate::getSnippet(
|
273 |
+
'settings-alerts-subject',
|
274 |
+
array(
|
275 |
+
'EmailSubject.Name' => $subject_format,
|
276 |
+
'EmailSubject.Value' => $subject_format,
|
277 |
+
'EmailSubject.Checked' => $checked,
|
278 |
+
)
|
279 |
+
);
|
280 |
}
|
281 |
|
282 |
if ($is_official_subject === false) {
|
300 |
$params['Alerts.PerHour'] = '';
|
301 |
|
302 |
$emails_per_hour = array(
|
303 |
+
'5' => 'Maximum 5 per hour',
|
304 |
+
'10' => 'Maximum 10 per hour',
|
305 |
+
'20' => 'Maximum 20 per hour',
|
306 |
+
'40' => 'Maximum 40 per hour',
|
307 |
+
'80' => 'Maximum 80 per hour',
|
308 |
+
'160' => 'Maximum 160 per hour',
|
309 |
+
'unlimited' => 'Unlimited alerts per hour',
|
310 |
);
|
311 |
|
312 |
if ($nonce) {
|
313 |
// Update the value for the maximum emails per hour.
|
314 |
+
$per_hour = SucuriScanRequest::post(':emails_per_hour');
|
315 |
+
|
316 |
+
if ($per_hour) {
|
317 |
if (array_key_exists($per_hour, $emails_per_hour)) {
|
318 |
$per_hour_label = strtolower($emails_per_hour[$per_hour]);
|
319 |
$message = 'Maximum alerts per hour set to <code>' . $per_hour_label . '</code>';
|
321 |
SucuriScanOption::updateOption(':emails_per_hour', $per_hour);
|
322 |
SucuriScanEvent::reportInfoEvent($message);
|
323 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
324 |
+
SucuriScanInterface::info('The maximum number of alerts per hour has been updated');
|
325 |
} else {
|
326 |
+
SucuriScanInterface::error('Error updating the maximum number of alerts per hour');
|
327 |
}
|
328 |
}
|
329 |
}
|
347 |
$params['Alerts.BruteForce'] = '';
|
348 |
|
349 |
$max_failed_logins = array(
|
350 |
+
'30' => '30 failed logins per hour',
|
351 |
+
'60' => '60 failed logins per hour',
|
352 |
+
'120' => '120 failed logins per hour',
|
353 |
+
'240' => '240 failed logins per hour',
|
354 |
+
'480' => '480 failed logins per hour',
|
355 |
);
|
356 |
|
357 |
if ($nonce) {
|
358 |
// Update the maximum failed logins per hour before consider it a brute-force attack.
|
359 |
+
$maximum = SucuriScanRequest::post(':maximum_failed_logins');
|
360 |
+
|
361 |
+
if ($maximum) {
|
362 |
if (array_key_exists($maximum, $max_failed_logins)) {
|
363 |
$message = 'Consider brute-force attack after <code>' . $maximum . '</code> failed logins per hour';
|
364 |
|
365 |
SucuriScanOption::updateOption(':maximum_failed_logins', $maximum);
|
366 |
SucuriScanEvent::reportInfoEvent($message);
|
367 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
368 |
+
SucuriScanInterface::info(
|
369 |
+
'The plugin will assume that your website is under a brute'
|
370 |
+
. '-force attack after ' . $maximum . ' failed logins are '
|
371 |
+
. 'detected during the same hour'
|
372 |
+
);
|
373 |
} else {
|
374 |
+
SucuriScanInterface::error('Invalid number of failed logins per hour');
|
375 |
}
|
376 |
}
|
377 |
}
|
396 |
$params['Alerts.NoAlertsVisibility'] = 'hidden';
|
397 |
|
398 |
$notify_options = array(
|
399 |
+
'sucuriscan_notify_plugin_change' => 'setting:' . 'Receive email alerts for changes in the settings of the Sucuri plugin',
|
400 |
+
'sucuriscan_prettify_mails' => 'setting:' . 'Receive email alerts in HTML <em>(there may be issues with some mail services)</em>',
|
401 |
+
'sucuriscan_use_wpmail' => 'setting:' . 'Use WordPress functions to send mails <em>(uncheck to use native PHP functions)</em>',
|
402 |
+
'sucuriscan_lastlogin_redirection' => 'setting:' . 'Allow redirection after login to report the last-login information',
|
403 |
+
'sucuriscan_notify_scan_checksums' => 'setting:' . 'Receive email alerts for core integrity checks',
|
404 |
+
'sucuriscan_notify_available_updates' => 'setting:' . 'Receive email alerts for available updates',
|
405 |
+
'sucuriscan_notify_user_registration' => 'user:' . 'Receive email alerts for new user registration',
|
406 |
+
'sucuriscan_notify_success_login' => 'user:' . 'Receive email alerts for successful login attempts',
|
407 |
+
'sucuriscan_notify_failed_login' => 'user:' . 'Receive email alerts for failed login attempts <em>(you may receive tons of emails)</em>',
|
408 |
+
'sucuriscan_notify_failed_password' => 'user:' . 'Receive email alerts for failed login attempts including the submitted password',
|
409 |
+
'sucuriscan_notify_bruteforce_attack' => 'user:' . 'Receive email alerts for password guessing attacks <em>(summary of failed logins per hour)</em>',
|
410 |
+
'sucuriscan_notify_post_publication' => 'setting:' . 'Receive email alerts for changes in the post status <em>(configure from Ignore Posts Changes)</em>',
|
411 |
+
'sucuriscan_notify_website_updated' => 'setting:' . 'Receive email alerts when the WordPress version is updated',
|
412 |
+
'sucuriscan_notify_settings_updated' => 'setting:' . 'Receive email alerts when your website settings are updated',
|
413 |
+
'sucuriscan_notify_theme_editor' => 'setting:' . 'Receive email alerts when a file is modified with theme/plugin editor',
|
414 |
+
'sucuriscan_notify_plugin_installed' => 'plugin:' . 'Receive email alerts when a <b>plugin is installed</b>',
|
415 |
+
'sucuriscan_notify_plugin_activated' => 'plugin:' . 'Receive email alerts when a <b>plugin is activated</b>',
|
416 |
+
'sucuriscan_notify_plugin_deactivated' => 'plugin:' . 'Receive email alerts when a <b>plugin is deactivated</b>',
|
417 |
+
'sucuriscan_notify_plugin_updated' => 'plugin:' . 'Receive email alerts when a <b>plugin is updated</b>',
|
418 |
+
'sucuriscan_notify_plugin_deleted' => 'plugin:' . 'Receive email alerts when a <b>plugin is deleted</b>',
|
419 |
+
'sucuriscan_notify_widget_added' => 'widget:' . 'Receive email alerts when a <b>widget is added</b> to a sidebar',
|
420 |
+
'sucuriscan_notify_widget_deleted' => 'widget:' . 'Receive email alerts when a <b>widget is deleted</b> from a sidebar',
|
421 |
+
'sucuriscan_notify_theme_installed' => 'theme:' . 'Receive email alerts when a <b>theme is installed</b>',
|
422 |
+
'sucuriscan_notify_theme_activated' => 'theme:' . 'Receive email alerts when a <b>theme is activated</b>',
|
423 |
+
'sucuriscan_notify_theme_updated' => 'theme:' . 'Receive email alerts when a <b>theme is updated</b>',
|
424 |
+
'sucuriscan_notify_theme_deleted' => 'theme:' . 'Receive email alerts when a <b>theme is deleted</b>',
|
425 |
);
|
426 |
|
427 |
/**
|
441 |
$params['Alerts.NoAlertsVisibility'] = 'visible';
|
442 |
unset($notify_options['sucuriscan_notify_success_login']);
|
443 |
unset($notify_options['sucuriscan_notify_failed_login']);
|
444 |
+
unset($notify_options['sucuriscan_notify_failed_password']);
|
445 |
}
|
446 |
|
447 |
// Process form submission to change the alert settings.
|
450 |
if (SucuriScanRequest::post(':save_alert_events') !== false) {
|
451 |
$ucounter = 0;
|
452 |
|
453 |
+
/* disable password tracker for failed logins as well */
|
454 |
+
if (SucuriScanRequest::post(':notify_failed_login') === '0') {
|
455 |
+
$_POST['sucuriscan_notify_failed_password'] = '0';
|
456 |
+
}
|
457 |
+
|
458 |
foreach ($notify_options as $alert_type => $alert_label) {
|
459 |
$option_value = SucuriScanRequest::post($alert_type, '(1|0)');
|
460 |
|
475 |
|
476 |
SucuriScanEvent::reportInfoEvent($message);
|
477 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
478 |
+
SucuriScanInterface::info('The alert settings have been updated');
|
479 |
}
|
480 |
}
|
481 |
}
|
489 |
/* identify the optional icon */
|
490 |
$offset = strpos($alert_label, ':');
|
491 |
$alert_group = substr($alert_label, 0, $offset);
|
492 |
+
$alert_label = substr($alert_label, $offset + 1);
|
493 |
|
494 |
switch ($alert_group) {
|
495 |
case 'user':
|
513 |
break;
|
514 |
}
|
515 |
|
516 |
+
$params['Alerts.Events'] .= SucuriScanTemplate::getSnippet(
|
517 |
+
'settings-alerts-events',
|
518 |
+
array(
|
519 |
+
'Event.Name' => $alert_type,
|
520 |
+
'Event.Checked' => $checked,
|
521 |
+
'Event.Label' => $alert_label,
|
522 |
+
'Event.LabelIcon' => $alert_icon,
|
523 |
+
)
|
524 |
+
);
|
525 |
}
|
526 |
|
527 |
return SucuriScanTemplate::getSection('settings-alerts-events', $params);
|
534 |
*/
|
535 |
function sucuriscan_settings_alerts_ignore_posts()
|
536 |
{
|
537 |
+
$params = array();
|
538 |
+
$post_types = SucuriScanOption::getPostTypes();
|
539 |
+
$ignored_events = SucuriScanOption::getIgnoredEvents();
|
540 |
+
|
541 |
+
$params['PostTypes.List'] = '';
|
542 |
+
$params['PostTypes.ErrorVisibility'] = 'hidden';
|
543 |
|
544 |
if (SucuriScanInterface::checkNonce()) {
|
545 |
// Ignore a new event for email alerts.
|
546 |
+
$action = SucuriScanRequest::post(':ignorerule_action');
|
547 |
+
$ignore_rule = SucuriScanRequest::post(':ignorerule');
|
548 |
+
$selected_types = SucuriScanRequest::post(':posttypes', '_array');
|
549 |
+
|
550 |
+
if ($action === 'add') {
|
551 |
+
if (!preg_match('/^[a-z_\-]+$/', $ignore_rule)) {
|
552 |
+
SucuriScanInterface::error('Only lowercase letters, underscores and hyphens are allowed.');
|
553 |
+
} elseif (array_key_exists($ignore_rule, $ignored_events)) {
|
554 |
+
SucuriScanInterface::error('The post-type is already being ignored (duplicate).');
|
555 |
+
} else {
|
556 |
+
$ignored_events[$ignore_rule] = time();
|
557 |
+
|
558 |
+
SucuriScanInterface::info('Post-type has been successfully ignored.');
|
559 |
+
SucuriScanOption::updateOption(':ignored_events', $ignored_events);
|
560 |
+
SucuriScanEvent::reportWarningEvent('Changes in <code>' . $ignore_rule . '</code> post-type will be ignored');
|
561 |
+
}
|
562 |
+
}
|
563 |
+
|
564 |
+
if ($action === 'batch') {
|
565 |
+
/* reset current data to start all over again */
|
566 |
+
$ignored_events = array();
|
567 |
+
$timestamp = time();
|
568 |
+
|
569 |
+
foreach ($post_types as $post_type) {
|
570 |
+
if (!in_array($post_type, $selected_types)) {
|
571 |
+
$ignored_events[$post_type] = $timestamp;
|
572 |
}
|
|
|
|
|
|
|
|
|
573 |
}
|
574 |
+
|
575 |
+
SucuriScanInterface::info('List of monitored post-types has been updated.');
|
576 |
+
SucuriScanOption::updateOption(':ignored_events', $ignored_events);
|
577 |
+
SucuriScanEvent::reportWarningEvent('List of monitored post-types has been updated');
|
578 |
}
|
579 |
}
|
580 |
|
581 |
/* notifications are post updates are disabled; print error */
|
582 |
if (SucuriScanOption::isDisabled(':notify_post_publication')) {
|
583 |
+
$params['PostTypes.ErrorVisibility'] = 'visible';
|
584 |
+
$params['PostTypes.List'] = '<tr><td colspan="4">no data available</td></tr>';
|
|
|
|
|
|
|
585 |
|
586 |
return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params);
|
587 |
}
|
588 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
589 |
/* Check which post-types are being ignored */
|
590 |
foreach ($post_types as $post_type) {
|
591 |
+
$was_ignored_at = '--';
|
592 |
+
$selected = 'checked="checked"';
|
593 |
+
$post_type_title = ucwords(str_replace('_', "\x20", $post_type));
|
594 |
|
595 |
if (array_key_exists($post_type, $ignored_events)) {
|
596 |
+
$was_ignored_at = SucuriScan::datetime($ignored_events[$post_type]);
|
597 |
+
$selected = ''; /* uncheck the HTML checkbox */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
598 |
}
|
599 |
|
600 |
+
$params['PostTypes.List'] .= SucuriScanTemplate::getSnippet(
|
601 |
+
'settings-alerts-ignore-posts',
|
602 |
+
array(
|
603 |
+
'PostTypes.Selected' => $selected,
|
604 |
+
'PostTypes.UniqueID' => $post_type,
|
605 |
+
'PostTypes.Title' => $post_type_title,
|
606 |
+
'PostTypes.IgnoredAt' => $was_ignored_at,
|
607 |
+
)
|
608 |
+
);
|
|
|
609 |
}
|
610 |
|
611 |
return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params);
|
src/settings-apiservice.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-apiservice.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -27,8 +33,8 @@ function sucuriscan_settings_apiservice_status($nonce)
|
|
27 |
$params = array();
|
28 |
|
29 |
$params['ApiStatus.StatusNum'] = '1';
|
30 |
-
$params['ApiStatus.Status'] =
|
31 |
-
$params['ApiStatus.SwitchText'] =
|
32 |
$params['ApiStatus.SwitchValue'] = 'disable';
|
33 |
$params['ApiStatus.WarningVisibility'] = 'visible';
|
34 |
$params['ApiStatus.ErrorVisibility'] = 'hidden';
|
@@ -36,14 +42,16 @@ function sucuriscan_settings_apiservice_status($nonce)
|
|
36 |
|
37 |
if ($nonce) {
|
38 |
// Enable or disable the API service communication.
|
39 |
-
|
|
|
|
|
40 |
$action_d = $api_service . 'd';
|
41 |
$message = 'API service communication was <code>' . $action_d . '</code>';
|
42 |
|
43 |
SucuriScanEvent::reportInfoEvent($message);
|
44 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
45 |
SucuriScanOption::updateOption(':api_service', $action_d);
|
46 |
-
SucuriScanInterface::info(
|
47 |
}
|
48 |
}
|
49 |
|
@@ -51,8 +59,8 @@ function sucuriscan_settings_apiservice_status($nonce)
|
|
51 |
|
52 |
if ($api_service === 'disabled') {
|
53 |
$params['ApiStatus.StatusNum'] = '0';
|
54 |
-
$params['ApiStatus.Status'] =
|
55 |
-
$params['ApiStatus.SwitchText'] =
|
56 |
$params['ApiStatus.SwitchValue'] = 'enable';
|
57 |
$params['ApiStatus.WarningVisibility'] = 'hidden';
|
58 |
$params['ApiStatus.ErrorVisibility'] = 'visible';
|
@@ -119,14 +127,14 @@ function sucuriscan_settings_apiservice_checksums($nonce)
|
|
119 |
$message = 'Core integrity API changed: ' . SucuriScanAPI::checksumAPI();
|
120 |
SucuriScanEvent::reportInfoEvent($message);
|
121 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
122 |
-
SucuriScanInterface::info(
|
123 |
} else {
|
124 |
SucuriScanOption::deleteOption(':checksum_api');
|
125 |
|
126 |
$message = 'Core integrity API changed: ' . SucuriScanAPI::checksumAPI();
|
127 |
SucuriScanEvent::reportInfoEvent($message);
|
128 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
129 |
-
SucuriScanInterface::info(
|
130 |
}
|
131 |
}
|
132 |
|
3 |
/**
|
4 |
* Code related to the settings-apiservice.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
33 |
$params = array();
|
34 |
|
35 |
$params['ApiStatus.StatusNum'] = '1';
|
36 |
+
$params['ApiStatus.Status'] = 'Enabled';
|
37 |
+
$params['ApiStatus.SwitchText'] = 'Disable';
|
38 |
$params['ApiStatus.SwitchValue'] = 'disable';
|
39 |
$params['ApiStatus.WarningVisibility'] = 'visible';
|
40 |
$params['ApiStatus.ErrorVisibility'] = 'hidden';
|
42 |
|
43 |
if ($nonce) {
|
44 |
// Enable or disable the API service communication.
|
45 |
+
$api_service = SucuriScanRequest::post(':api_service', '(en|dis)able');
|
46 |
+
|
47 |
+
if ($api_service) {
|
48 |
$action_d = $api_service . 'd';
|
49 |
$message = 'API service communication was <code>' . $action_d . '</code>';
|
50 |
|
51 |
SucuriScanEvent::reportInfoEvent($message);
|
52 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
53 |
SucuriScanOption::updateOption(':api_service', $action_d);
|
54 |
+
SucuriScanInterface::info('The status of the API service has been changed');
|
55 |
}
|
56 |
}
|
57 |
|
59 |
|
60 |
if ($api_service === 'disabled') {
|
61 |
$params['ApiStatus.StatusNum'] = '0';
|
62 |
+
$params['ApiStatus.Status'] = 'Disabled';
|
63 |
+
$params['ApiStatus.SwitchText'] = 'Enable';
|
64 |
$params['ApiStatus.SwitchValue'] = 'enable';
|
65 |
$params['ApiStatus.WarningVisibility'] = 'hidden';
|
66 |
$params['ApiStatus.ErrorVisibility'] = 'visible';
|
127 |
$message = 'Core integrity API changed: ' . SucuriScanAPI::checksumAPI();
|
128 |
SucuriScanEvent::reportInfoEvent($message);
|
129 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
130 |
+
SucuriScanInterface::info('The URL to retrieve the WordPress checksums has been changed');
|
131 |
} else {
|
132 |
SucuriScanOption::deleteOption(':checksum_api');
|
133 |
|
134 |
$message = 'Core integrity API changed: ' . SucuriScanAPI::checksumAPI();
|
135 |
SucuriScanEvent::reportInfoEvent($message);
|
136 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
137 |
+
SucuriScanInterface::info('The URL to retrieve the WordPress checksums has been changed');
|
138 |
}
|
139 |
}
|
140 |
|
src/settings-general.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-general.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -31,13 +37,13 @@ function sucuriscan_settings_general_resetoptions($nonce)
|
|
31 |
if (intval($process) === 1) {
|
32 |
$message = 'Local security logs, hardening and settings were deleted';
|
33 |
|
34 |
-
|
35 |
|
36 |
SucuriScanEvent::reportCriticalEvent($message);
|
37 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
38 |
-
SucuriScanInterface::info(
|
39 |
} else {
|
40 |
-
SucuriScanInterface::error(
|
41 |
}
|
42 |
}
|
43 |
|
@@ -62,19 +68,22 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
62 |
|
63 |
if ($nonce) {
|
64 |
// Remove API key from the local storage.
|
|
|
65 |
if (SucuriScanRequest::post(':remove_api_key') !== false
|
66 |
&& SucuriScanAPI::setPluginKey('') !== false
|
67 |
) {
|
68 |
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
|
69 |
|
|
|
70 |
SucuriScanEvent::reportCriticalEvent('Sucuri API key has been deleted.');
|
71 |
SucuriScanEvent::notifyEvent('plugin_change', 'Sucuri API key removed');
|
72 |
-
SucuriScanInterface::info('Sucuri API key has been deleted <code>'
|
73 |
-
. SucuriScan::escape(SucuriScanAPI::getPluginKey()) . '</code>');
|
74 |
}
|
75 |
|
76 |
// Save API key after it was recovered by the administrator.
|
77 |
-
|
|
|
|
|
78 |
SucuriScanAPI::setPluginKey($api_key, true);
|
79 |
SucuriScanEvent::installScheduledTask();
|
80 |
SucuriScanEvent::reportInfoEvent('Sucuri API key was added manually.');
|
@@ -88,9 +97,10 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
88 |
if ($user_obj && user_can($user_obj, 'administrator')) {
|
89 |
// Send request to generate new API key or display form to set manually.
|
90 |
if (SucuriScanAPI::registerSite($user_obj->user_email)) {
|
91 |
-
$api_registered_modal = SucuriScanTemplate::getModal(
|
92 |
-
'
|
93 |
-
|
|
|
94 |
} else {
|
95 |
$display_manual_key_form = true;
|
96 |
}
|
@@ -111,9 +121,10 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
111 |
$api_key = SucuriScanAPI::getPluginKey();
|
112 |
|
113 |
if (SucuriScanRequest::get('recover') !== false) {
|
114 |
-
$api_recovery_modal = SucuriScanTemplate::getModal(
|
115 |
-
'
|
116 |
-
|
|
|
117 |
}
|
118 |
|
119 |
// Check whether the domain name is valid or not.
|
@@ -123,7 +134,7 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
123 |
$invalid_domain = (bool) ($domain_address === $clean_domain);
|
124 |
}
|
125 |
|
126 |
-
$params['APIKey'] = (!$api_key ?
|
127 |
$params['APIKey.RecoverVisibility'] = SucuriScanTemplate::visibility(!$api_key);
|
128 |
$params['APIKey.ManualKeyFormVisibility'] = SucuriScanTemplate::visibility($display_manual_key_form);
|
129 |
$params['APIKey.RemoveVisibility'] = SucuriScanTemplate::visibility((bool) $api_key);
|
@@ -164,7 +175,9 @@ function sucuriscan_settings_general_datastorage($nonce)
|
|
164 |
$params['Storage.Path'] = SucuriScan::dataStorePath();
|
165 |
|
166 |
if ($nonce) {
|
167 |
-
|
|
|
|
|
168 |
$deleted = 0;
|
169 |
|
170 |
foreach ($filenames as $filename) {
|
@@ -187,11 +200,13 @@ function sucuriscan_settings_general_datastorage($nonce)
|
|
187 |
}
|
188 |
}
|
189 |
|
190 |
-
SucuriScanInterface::info(
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
|
|
|
|
195 |
}
|
196 |
}
|
197 |
|
@@ -200,20 +215,20 @@ function sucuriscan_settings_general_datastorage($nonce)
|
|
200 |
$fname = ($name ? sprintf('sucuri-%s.php', $name) : '');
|
201 |
$fpath = SucuriScan::dataStorePath($fname);
|
202 |
$disabled = 'disabled="disabled"';
|
203 |
-
$iswritable =
|
204 |
-
$exists =
|
205 |
$labelExistence = 'danger';
|
206 |
$labelWritability = 'default';
|
207 |
|
208 |
if (file_exists($fpath)) {
|
209 |
$fsize = @filesize($fpath);
|
210 |
-
$exists =
|
211 |
$labelExistence = 'success';
|
212 |
$labelWritability = 'danger';
|
213 |
|
214 |
if (is_writable($fpath)) {
|
215 |
$disabled = ''; /* Allow file deletion */
|
216 |
-
$iswritable =
|
217 |
$labelWritability = 'success';
|
218 |
}
|
219 |
}
|
@@ -228,8 +243,8 @@ function sucuriscan_settings_general_datastorage($nonce)
|
|
228 |
$params['Storage.Writability'] = $labelWritability;
|
229 |
|
230 |
if (is_dir($fpath)) {
|
|
|
231 |
$params['Storage.DisabledInput'] = 'disabled="disabled"';
|
232 |
-
$params['Storage.Filesize'] = '' /* empty */;
|
233 |
}
|
234 |
|
235 |
$params['Storage.Files'] .= SucuriScanTemplate::getSnippet('settings-general-datastorage', $params);
|
@@ -274,8 +289,8 @@ function sucuriscan_settings_general_selfhosting($nonce)
|
|
274 |
$params = array();
|
275 |
|
276 |
$params['SelfHosting.DisabledVisibility'] = 'visible';
|
277 |
-
$params['SelfHosting.Status'] =
|
278 |
-
$params['SelfHosting.SwitchText'] =
|
279 |
$params['SelfHosting.SwitchValue'] = 'disable';
|
280 |
$params['SelfHosting.FpathVisibility'] = 'hidden';
|
281 |
$params['SelfHosting.Fpath'] = '';
|
@@ -286,29 +301,29 @@ function sucuriscan_settings_general_selfhosting($nonce)
|
|
286 |
|
287 |
if ($monitor_fpath !== false) {
|
288 |
if (empty($monitor_fpath)) {
|
289 |
-
$message = 'Log exporter was disabled
|
290 |
|
291 |
SucuriScanEvent::reportInfoEvent($message);
|
292 |
SucuriScanOption::deleteOption(':selfhosting_fpath');
|
293 |
SucuriScanOption::updateOption(':selfhosting_monitor', 'disabled');
|
294 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
295 |
-
SucuriScanInterface::info(
|
296 |
} elseif (strpos($monitor_fpath, $_SERVER['DOCUMENT_ROOT']) !== false) {
|
297 |
-
SucuriScanInterface::error(
|
298 |
} elseif (file_exists($monitor_fpath)) {
|
299 |
-
SucuriScanInterface::error(
|
300 |
} elseif (!is_writable(dirname($monitor_fpath))) {
|
301 |
-
SucuriScanInterface::error(
|
302 |
} else {
|
303 |
@file_put_contents($monitor_fpath, '', LOCK_EX);
|
304 |
|
305 |
-
$message = 'Log exporter file path was set
|
306 |
|
307 |
SucuriScanEvent::reportInfoEvent($message);
|
308 |
SucuriScanOption::updateOption(':selfhosting_monitor', 'enabled');
|
309 |
SucuriScanOption::updateOption(':selfhosting_fpath', $monitor_fpath);
|
310 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
311 |
-
SucuriScanInterface::info(
|
312 |
}
|
313 |
}
|
314 |
}
|
@@ -317,8 +332,8 @@ function sucuriscan_settings_general_selfhosting($nonce)
|
|
317 |
$monitor_fpath = SucuriScanOption::getOption(':selfhosting_fpath');
|
318 |
|
319 |
if ($monitor === 'disabled') {
|
320 |
-
$params['SelfHosting.Status'] =
|
321 |
-
$params['SelfHosting.SwitchText'] =
|
322 |
$params['SelfHosting.SwitchValue'] = 'enable';
|
323 |
}
|
324 |
|
@@ -340,8 +355,8 @@ function sucuriscan_settings_general_selfhosting($nonce)
|
|
340 |
function sucuriscan_settings_general_reverseproxy($nonce)
|
341 |
{
|
342 |
$params = array(
|
343 |
-
'ReverseProxyStatus' =>
|
344 |
-
'ReverseProxySwitchText' =>
|
345 |
'ReverseProxySwitchValue' => 'disable',
|
346 |
);
|
347 |
|
@@ -361,8 +376,8 @@ function sucuriscan_settings_general_reverseproxy($nonce)
|
|
361 |
}
|
362 |
|
363 |
if (SucuriScanOption::isDisabled(':revproxy')) {
|
364 |
-
$params['ReverseProxyStatus'] =
|
365 |
-
$params['ReverseProxySwitchText'] =
|
366 |
$params['ReverseProxySwitchValue'] = 'enable';
|
367 |
}
|
368 |
|
@@ -378,17 +393,17 @@ function sucuriscan_settings_general_reverseproxy($nonce)
|
|
378 |
function sucuriscan_settings_general_ipdiscoverer($nonce)
|
379 |
{
|
380 |
$params = array(
|
381 |
-
'TopLevelDomain' =>
|
382 |
-
'WebsiteHostName' =>
|
383 |
-
'WebsiteHostAddress' =>
|
384 |
-
'IsUsingFirewall' =>
|
385 |
-
'WebsiteURL' =>
|
386 |
'RemoteAddress' => '127.0.0.1',
|
387 |
'RemoteAddressHeader' => 'INVALID',
|
388 |
'AddrHeaderOptions' => '',
|
389 |
/* Switch form information. */
|
390 |
-
'DnsLookupsStatus' =>
|
391 |
-
'DnsLookupsSwitchText' =>
|
392 |
'DnsLookupsSwitchValue' => 'disable',
|
393 |
);
|
394 |
|
@@ -407,7 +422,7 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
407 |
SucuriScanOption::updateOption(':dns_lookups', $action_d);
|
408 |
SucuriScanEvent::reportInfoEvent($message);
|
409 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
410 |
-
SucuriScanInterface::info(
|
411 |
}
|
412 |
|
413 |
if ($addr_header) {
|
@@ -422,8 +437,8 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
422 |
}
|
423 |
|
424 |
if (SucuriScanOption::isDisabled(':dns_lookups')) {
|
425 |
-
$params['DnsLookupsStatus'] =
|
426 |
-
$params['DnsLookupsSwitchText'] =
|
427 |
$params['DnsLookupsSwitchValue'] = 'enable';
|
428 |
}
|
429 |
|
@@ -440,9 +455,7 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
440 |
$allowed_headers, /* list is limited to a few options */
|
441 |
SucuriScanOption::getOption(':addr_header')
|
442 |
);
|
443 |
-
$params['IsUsingFirewall'] =
|
444 |
-
? __('Active', SUCURISCAN_TEXTDOMAIN)
|
445 |
-
: __('NotActive', SUCURISCAN_TEXTDOMAIN));
|
446 |
|
447 |
if ($base_domain !== $proxy_info['http_host']) {
|
448 |
$params['TopLevelDomain'] = sprintf('%s (%s)', $params['TopLevelDomain'], $base_domain);
|
@@ -472,7 +485,6 @@ function sucuriscan_settings_general_importexport($nonce)
|
|
472 |
':email_subject',
|
473 |
':emails_per_hour',
|
474 |
':ignored_events',
|
475 |
-
':language',
|
476 |
':lastlogin_redirection',
|
477 |
':maximum_failed_logins',
|
478 |
':notify_available_updates',
|
@@ -537,16 +549,18 @@ function sucuriscan_settings_general_importexport($nonce)
|
|
537 |
$count++;
|
538 |
}
|
539 |
|
540 |
-
SucuriScanInterface::info(
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
|
|
|
|
545 |
} else {
|
546 |
-
SucuriScanInterface::error(
|
547 |
}
|
548 |
} else {
|
549 |
-
SucuriScanInterface::error(
|
550 |
}
|
551 |
}
|
552 |
|
@@ -598,7 +612,7 @@ function sucuriscan_settings_general_timezone($nonce)
|
|
598 |
SucuriScanOption::updateOption(':timezone', $timezone);
|
599 |
SucuriScanEvent::reportInfoEvent($message);
|
600 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
601 |
-
SucuriScanInterface::info(
|
602 |
}
|
603 |
}
|
604 |
|
3 |
/**
|
4 |
* Code related to the settings-general.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
37 |
if (intval($process) === 1) {
|
38 |
$message = 'Local security logs, hardening and settings were deleted';
|
39 |
|
40 |
+
sucuriscanResetAndDeactivate(); /* simulate plugin deactivation */
|
41 |
|
42 |
SucuriScanEvent::reportCriticalEvent($message);
|
43 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
44 |
+
SucuriScanInterface::info('Local security logs, hardening and settings were deleted');
|
45 |
} else {
|
46 |
+
SucuriScanInterface::error('You need to confirm that you understand the risk of this operation.');
|
47 |
}
|
48 |
}
|
49 |
|
68 |
|
69 |
if ($nonce) {
|
70 |
// Remove API key from the local storage.
|
71 |
+
$api_key = SucuriScanAPI::getPluginKey();
|
72 |
if (SucuriScanRequest::post(':remove_api_key') !== false
|
73 |
&& SucuriScanAPI::setPluginKey('') !== false
|
74 |
) {
|
75 |
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
|
76 |
|
77 |
+
$api_key = SucuriScan::escape($api_key);
|
78 |
SucuriScanEvent::reportCriticalEvent('Sucuri API key has been deleted.');
|
79 |
SucuriScanEvent::notifyEvent('plugin_change', 'Sucuri API key removed');
|
80 |
+
SucuriScanInterface::info('Sucuri API key has been deleted <code>' . $api_key . '</code>');
|
|
|
81 |
}
|
82 |
|
83 |
// Save API key after it was recovered by the administrator.
|
84 |
+
$api_key = SucuriScanRequest::post(':manual_api_key');
|
85 |
+
|
86 |
+
if ($api_key) {
|
87 |
SucuriScanAPI::setPluginKey($api_key, true);
|
88 |
SucuriScanEvent::installScheduledTask();
|
89 |
SucuriScanEvent::reportInfoEvent('Sucuri API key was added manually.');
|
97 |
if ($user_obj && user_can($user_obj, 'administrator')) {
|
98 |
// Send request to generate new API key or display form to set manually.
|
99 |
if (SucuriScanAPI::registerSite($user_obj->user_email)) {
|
100 |
+
$api_registered_modal = SucuriScanTemplate::getModal(
|
101 |
+
'settings-apiregistered',
|
102 |
+
array('Title' => 'Site registered successfully')
|
103 |
+
);
|
104 |
} else {
|
105 |
$display_manual_key_form = true;
|
106 |
}
|
121 |
$api_key = SucuriScanAPI::getPluginKey();
|
122 |
|
123 |
if (SucuriScanRequest::get('recover') !== false) {
|
124 |
+
$api_recovery_modal = SucuriScanTemplate::getModal(
|
125 |
+
'settings-apirecovery',
|
126 |
+
array('Title' => 'Plugin API Key Recovery')
|
127 |
+
);
|
128 |
}
|
129 |
|
130 |
// Check whether the domain name is valid or not.
|
134 |
$invalid_domain = (bool) ($domain_address === $clean_domain);
|
135 |
}
|
136 |
|
137 |
+
$params['APIKey'] = (!$api_key ? '(not set)' : $api_key);
|
138 |
$params['APIKey.RecoverVisibility'] = SucuriScanTemplate::visibility(!$api_key);
|
139 |
$params['APIKey.ManualKeyFormVisibility'] = SucuriScanTemplate::visibility($display_manual_key_form);
|
140 |
$params['APIKey.RemoveVisibility'] = SucuriScanTemplate::visibility((bool) $api_key);
|
175 |
$params['Storage.Path'] = SucuriScan::dataStorePath();
|
176 |
|
177 |
if ($nonce) {
|
178 |
+
$filenames = SucuriScanRequest::post(':filename', '_array');
|
179 |
+
|
180 |
+
if ($filenames) {
|
181 |
$deleted = 0;
|
182 |
|
183 |
foreach ($filenames as $filename) {
|
200 |
}
|
201 |
}
|
202 |
|
203 |
+
SucuriScanInterface::info(
|
204 |
+
sprintf(
|
205 |
+
'%d out of %d files has been deleted',
|
206 |
+
$deleted,
|
207 |
+
count($filenames)
|
208 |
+
)
|
209 |
+
);
|
210 |
}
|
211 |
}
|
212 |
|
215 |
$fname = ($name ? sprintf('sucuri-%s.php', $name) : '');
|
216 |
$fpath = SucuriScan::dataStorePath($fname);
|
217 |
$disabled = 'disabled="disabled"';
|
218 |
+
$iswritable = 'Not Writable';
|
219 |
+
$exists = 'Does Not Exist';
|
220 |
$labelExistence = 'danger';
|
221 |
$labelWritability = 'default';
|
222 |
|
223 |
if (file_exists($fpath)) {
|
224 |
$fsize = @filesize($fpath);
|
225 |
+
$exists = 'Exists';
|
226 |
$labelExistence = 'success';
|
227 |
$labelWritability = 'danger';
|
228 |
|
229 |
if (is_writable($fpath)) {
|
230 |
$disabled = ''; /* Allow file deletion */
|
231 |
+
$iswritable = 'Writable';
|
232 |
$labelWritability = 'success';
|
233 |
}
|
234 |
}
|
243 |
$params['Storage.Writability'] = $labelWritability;
|
244 |
|
245 |
if (is_dir($fpath)) {
|
246 |
+
$params['Storage.Filesize'] = '';
|
247 |
$params['Storage.DisabledInput'] = 'disabled="disabled"';
|
|
|
248 |
}
|
249 |
|
250 |
$params['Storage.Files'] .= SucuriScanTemplate::getSnippet('settings-general-datastorage', $params);
|
289 |
$params = array();
|
290 |
|
291 |
$params['SelfHosting.DisabledVisibility'] = 'visible';
|
292 |
+
$params['SelfHosting.Status'] = 'Enabled';
|
293 |
+
$params['SelfHosting.SwitchText'] = 'Disable';
|
294 |
$params['SelfHosting.SwitchValue'] = 'disable';
|
295 |
$params['SelfHosting.FpathVisibility'] = 'hidden';
|
296 |
$params['SelfHosting.Fpath'] = '';
|
301 |
|
302 |
if ($monitor_fpath !== false) {
|
303 |
if (empty($monitor_fpath)) {
|
304 |
+
$message = 'Log exporter was disabled';
|
305 |
|
306 |
SucuriScanEvent::reportInfoEvent($message);
|
307 |
SucuriScanOption::deleteOption(':selfhosting_fpath');
|
308 |
SucuriScanOption::updateOption(':selfhosting_monitor', 'disabled');
|
309 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
310 |
+
SucuriScanInterface::info('The log exporter feature has been disabled');
|
311 |
} elseif (strpos($monitor_fpath, $_SERVER['DOCUMENT_ROOT']) !== false) {
|
312 |
+
SucuriScanInterface::error('File should not be publicly accessible.');
|
313 |
} elseif (file_exists($monitor_fpath)) {
|
314 |
+
SucuriScanInterface::error('File already exists and will not be overwritten.');
|
315 |
} elseif (!is_writable(dirname($monitor_fpath))) {
|
316 |
+
SucuriScanInterface::error('File parent directory is not writable.');
|
317 |
} else {
|
318 |
@file_put_contents($monitor_fpath, '', LOCK_EX);
|
319 |
|
320 |
+
$message = 'Log exporter file path was correctly set';
|
321 |
|
322 |
SucuriScanEvent::reportInfoEvent($message);
|
323 |
SucuriScanOption::updateOption(':selfhosting_monitor', 'enabled');
|
324 |
SucuriScanOption::updateOption(':selfhosting_fpath', $monitor_fpath);
|
325 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
326 |
+
SucuriScanInterface::info('The log exporter feature has been enabled and the data file was successfully set.');
|
327 |
}
|
328 |
}
|
329 |
}
|
332 |
$monitor_fpath = SucuriScanOption::getOption(':selfhosting_fpath');
|
333 |
|
334 |
if ($monitor === 'disabled') {
|
335 |
+
$params['SelfHosting.Status'] = 'Disabled';
|
336 |
+
$params['SelfHosting.SwitchText'] = 'Enable';
|
337 |
$params['SelfHosting.SwitchValue'] = 'enable';
|
338 |
}
|
339 |
|
355 |
function sucuriscan_settings_general_reverseproxy($nonce)
|
356 |
{
|
357 |
$params = array(
|
358 |
+
'ReverseProxyStatus' => 'Enabled',
|
359 |
+
'ReverseProxySwitchText' => 'Disable',
|
360 |
'ReverseProxySwitchValue' => 'disable',
|
361 |
);
|
362 |
|
376 |
}
|
377 |
|
378 |
if (SucuriScanOption::isDisabled(':revproxy')) {
|
379 |
+
$params['ReverseProxyStatus'] = 'Disabled';
|
380 |
+
$params['ReverseProxySwitchText'] = 'Enable';
|
381 |
$params['ReverseProxySwitchValue'] = 'enable';
|
382 |
}
|
383 |
|
393 |
function sucuriscan_settings_general_ipdiscoverer($nonce)
|
394 |
{
|
395 |
$params = array(
|
396 |
+
'TopLevelDomain' => 'unknown',
|
397 |
+
'WebsiteHostName' => 'unknown',
|
398 |
+
'WebsiteHostAddress' => 'unknown',
|
399 |
+
'IsUsingFirewall' => 'unknown',
|
400 |
+
'WebsiteURL' => 'unknown',
|
401 |
'RemoteAddress' => '127.0.0.1',
|
402 |
'RemoteAddressHeader' => 'INVALID',
|
403 |
'AddrHeaderOptions' => '',
|
404 |
/* Switch form information. */
|
405 |
+
'DnsLookupsStatus' => 'Enabled',
|
406 |
+
'DnsLookupsSwitchText' => 'Disable',
|
407 |
'DnsLookupsSwitchValue' => 'disable',
|
408 |
);
|
409 |
|
422 |
SucuriScanOption::updateOption(':dns_lookups', $action_d);
|
423 |
SucuriScanEvent::reportInfoEvent($message);
|
424 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
425 |
+
SucuriScanInterface::info('The status of the DNS lookups for the reverse proxy detection has been changed');
|
426 |
}
|
427 |
|
428 |
if ($addr_header) {
|
437 |
}
|
438 |
|
439 |
if (SucuriScanOption::isDisabled(':dns_lookups')) {
|
440 |
+
$params['DnsLookupsStatus'] = 'Disabled';
|
441 |
+
$params['DnsLookupsSwitchText'] = 'Enable';
|
442 |
$params['DnsLookupsSwitchValue'] = 'enable';
|
443 |
}
|
444 |
|
455 |
$allowed_headers, /* list is limited to a few options */
|
456 |
SucuriScanOption::getOption(':addr_header')
|
457 |
);
|
458 |
+
$params['IsUsingFirewall'] = $proxy_info['status'] ? 'active' : 'not active';
|
|
|
|
|
459 |
|
460 |
if ($base_domain !== $proxy_info['http_host']) {
|
461 |
$params['TopLevelDomain'] = sprintf('%s (%s)', $params['TopLevelDomain'], $base_domain);
|
485 |
':email_subject',
|
486 |
':emails_per_hour',
|
487 |
':ignored_events',
|
|
|
488 |
':lastlogin_redirection',
|
489 |
':maximum_failed_logins',
|
490 |
':notify_available_updates',
|
549 |
$count++;
|
550 |
}
|
551 |
|
552 |
+
SucuriScanInterface::info(
|
553 |
+
sprintf(
|
554 |
+
'%d out of %d option have been successfully imported',
|
555 |
+
$count,
|
556 |
+
$total
|
557 |
+
)
|
558 |
+
);
|
559 |
} else {
|
560 |
+
SucuriScanInterface::error('Data is incorrectly encoded');
|
561 |
}
|
562 |
} else {
|
563 |
+
SucuriScanInterface::error('You need to confirm that you understand the risk of this operation.');
|
564 |
}
|
565 |
}
|
566 |
|
612 |
SucuriScanOption::updateOption(':timezone', $timezone);
|
613 |
SucuriScanEvent::reportInfoEvent($message);
|
614 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
615 |
+
SucuriScanInterface::info('The timezone for the date and time in the audit logs has been changed');
|
616 |
}
|
617 |
}
|
618 |
|
src/settings-hardening.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-hardening.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,6 +24,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
/**
|
20 |
* Renders the content of the plugin's hardening page.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
*/
|
22 |
class SucuriScanHardeningPage extends SucuriScan
|
23 |
{
|
@@ -26,8 +40,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
26 |
* a specific part of the WordPress installation, if the Status variable is
|
27 |
* set as a positive integer the button is shown as "unharden".
|
28 |
*
|
29 |
-
* @param
|
30 |
-
* @return string
|
31 |
*/
|
32 |
private static function drawSection($args = array())
|
33 |
{
|
@@ -58,8 +72,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
58 |
/**
|
59 |
* Checks if the request has a valid nonce to prevent a CSRF.
|
60 |
*
|
61 |
-
* @param
|
62 |
-
* @return bool
|
63 |
*/
|
64 |
private static function processRequest($function)
|
65 |
{
|
@@ -76,26 +90,36 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
76 |
* (brute force attempts, DDoS, SQL injections, etc) and helping it remain
|
77 |
* malware and blacklist free. This test checks if your site is using Sucuri
|
78 |
* Firewall to protect your site.
|
|
|
|
|
79 |
*/
|
80 |
public static function firewall()
|
81 |
{
|
82 |
$params = array();
|
83 |
|
84 |
if (self::processRequest(__FUNCTION__)) {
|
85 |
-
SucuriScanInterface::error(
|
|
|
|
|
|
|
|
|
86 |
}
|
87 |
|
88 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
89 |
-
$params['Hardening.Title'] =
|
90 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
91 |
|
92 |
if (!SucuriScan::isBehindFirewall()) {
|
93 |
$params['Hardening.Status'] = 0;
|
94 |
-
$params['Hardening.FieldText'] =
|
95 |
} else {
|
96 |
$params['Hardening.Status'] = 1;
|
97 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
98 |
-
$params['Hardening.FieldText'] =
|
99 |
}
|
100 |
|
101 |
return self::drawSection($params);
|
@@ -109,6 +133,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
109 |
* source code are made public, if there were security fixes then someone
|
110 |
* with malicious intent can use this information to attack any site that
|
111 |
* has not been upgraded.
|
|
|
|
|
112 |
*/
|
113 |
public static function wpversion()
|
114 |
{
|
@@ -118,13 +144,17 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
118 |
|
119 |
$params['URL.Settings'] = admin_url('update-core.php');
|
120 |
$params['Hardening.Status'] = 0;
|
121 |
-
$params['Hardening.FieldText'] =
|
122 |
-
$params['Hardening.Title'] =
|
123 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
124 |
|
125 |
if (isset($updates[0]) && $updates[0] instanceof stdClass) {
|
126 |
if ($updates[0]->response == 'latest' || $updates[0]->response == 'development') {
|
127 |
-
$params['Hardening.FieldText'] =
|
128 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
129 |
$params['Hardening.Status'] = 1;
|
130 |
}
|
@@ -147,26 +177,32 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
147 |
* of life and is no longer supported.
|
148 |
*
|
149 |
* @see http://php.net/supported-versions.php
|
|
|
|
|
150 |
*/
|
151 |
public static function phpversion()
|
152 |
{
|
153 |
$params = array();
|
154 |
|
155 |
if (self::processRequest(__FUNCTION__)) {
|
156 |
-
SucuriScanInterface::error(
|
|
|
|
|
|
|
|
|
157 |
}
|
158 |
|
159 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
160 |
-
$params['Hardening.Title'] =
|
161 |
-
$params['Hardening.Description'] = sprintf(
|
162 |
|
163 |
if (intval(version_compare(PHP_VERSION, '5.6.0') >= 0)) {
|
164 |
$params['Hardening.Status'] = 1;
|
165 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
166 |
-
$params['Hardening.FieldText'] =
|
167 |
} else {
|
168 |
$params['Hardening.Status'] = 0;
|
169 |
-
$params['Hardening.FieldText'] =
|
170 |
}
|
171 |
|
172 |
return self::drawSection($params);
|
@@ -176,22 +212,32 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
176 |
* Notify the state of the hardening for the removal of the Generator tag in
|
177 |
* HTML code printed by WordPress to show the current version number of the
|
178 |
* installation.
|
|
|
|
|
179 |
*/
|
180 |
public static function wpgenerator()
|
181 |
{
|
182 |
$params = array();
|
183 |
|
184 |
-
$params['Hardening.Title'] =
|
185 |
$params['Hardening.Status'] = 1;
|
186 |
-
$params['Hardening.FieldText'] =
|
187 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
188 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
|
190 |
return self::drawSection($params);
|
191 |
}
|
192 |
|
193 |
/**
|
194 |
* Offers information to apply a hardening to an Nginx installation.
|
|
|
|
|
195 |
*/
|
196 |
public static function nginxphp()
|
197 |
{
|
@@ -202,14 +248,25 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
202 |
$params = array();
|
203 |
|
204 |
if (self::processRequest(__FUNCTION__)) {
|
205 |
-
SucuriScanInterface::error(
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
}
|
207 |
|
208 |
-
$params['Hardening.Title'] =
|
209 |
$params['Hardening.Status'] = 2;
|
210 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
211 |
-
$params['Hardening.FieldText'] =
|
212 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
|
|
213 |
|
214 |
return self::drawSection($params);
|
215 |
}
|
@@ -220,6 +277,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
220 |
* A htaccess file is placed in the upload folder denying the access to any php
|
221 |
* file that could be uploaded through a vulnerability in a Plugin, Theme or
|
222 |
* WordPress itself.
|
|
|
|
|
223 |
*/
|
224 |
public static function wpuploads()
|
225 |
{
|
@@ -235,9 +294,9 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
235 |
|
236 |
if ($result === true) {
|
237 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the uploads directory');
|
238 |
-
SucuriScanInterface::info(
|
239 |
} else {
|
240 |
-
SucuriScanInterface::error(
|
241 |
}
|
242 |
}
|
243 |
|
@@ -246,27 +305,32 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
246 |
|
247 |
if ($result === true) {
|
248 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the uploads directory');
|
249 |
-
SucuriScanInterface::info(
|
250 |
} else {
|
251 |
-
SucuriScanInterface::error(
|
252 |
}
|
253 |
}
|
254 |
|
255 |
-
$params['Hardening.Title'] =
|
256 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
|
|
257 |
|
258 |
if (SucuriScan::isBehindFirewall()) {
|
259 |
$params['Hardening.Status'] = 1;
|
260 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
261 |
-
$params['Hardening.FieldText'] =
|
262 |
} elseif (SucuriScanHardening::isHardened($folder)) {
|
263 |
$params['Hardening.Status'] = 1;
|
264 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
265 |
-
$params['Hardening.FieldText'] =
|
266 |
} else {
|
267 |
$params['Hardening.Status'] = 0;
|
268 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
269 |
-
$params['Hardening.FieldText'] =
|
270 |
}
|
271 |
|
272 |
return self::drawSection($params);
|
@@ -278,6 +342,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
278 |
* A htaccess file is placed in the content folder denying the access to any php
|
279 |
* file that could be uploaded through a vulnerability in a Plugin, Theme or
|
280 |
* WordPress itself.
|
|
|
|
|
281 |
*/
|
282 |
public static function wpcontent()
|
283 |
{
|
@@ -292,9 +358,9 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
292 |
|
293 |
if ($result === true) {
|
294 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the content directory');
|
295 |
-
SucuriScanInterface::info(
|
296 |
} else {
|
297 |
-
SucuriScanInterface::error(
|
298 |
}
|
299 |
}
|
300 |
|
@@ -303,27 +369,32 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
303 |
|
304 |
if ($result === true) {
|
305 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the content directory');
|
306 |
-
SucuriScanInterface::info(
|
307 |
} else {
|
308 |
-
SucuriScanInterface::error(
|
309 |
}
|
310 |
}
|
311 |
|
312 |
-
$params['Hardening.Title'] =
|
313 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
|
|
314 |
|
315 |
if (SucuriScan::isBehindFirewall()) {
|
316 |
$params['Hardening.Status'] = 1;
|
317 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
318 |
-
$params['Hardening.FieldText'] =
|
319 |
} elseif (SucuriScanHardening::isHardened(WP_CONTENT_DIR)) {
|
320 |
$params['Hardening.Status'] = 1;
|
321 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
322 |
-
$params['Hardening.FieldText'] =
|
323 |
} else {
|
324 |
$params['Hardening.Status'] = 0;
|
325 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
326 |
-
$params['Hardening.FieldText'] =
|
327 |
}
|
328 |
|
329 |
return self::drawSection($params);
|
@@ -336,6 +407,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
336 |
* file that could be uploaded through a vulnerability in a Plugin, Theme or
|
337 |
* WordPress itself, there are some exceptions for some specific files that must
|
338 |
* be available publicly.
|
|
|
|
|
339 |
*/
|
340 |
public static function wpincludes()
|
341 |
{
|
@@ -354,12 +427,12 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
354 |
SucuriScanHardening::whitelist('wp-tinymce.php', 'wp-includes');
|
355 |
SucuriScanHardening::whitelist('ms-files.php', 'wp-includes');
|
356 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the library directory');
|
357 |
-
SucuriScanInterface::info(
|
358 |
} catch (Exception $e) {
|
359 |
SucuriScanInterface::error($e->getMessage());
|
360 |
}
|
361 |
} else {
|
362 |
-
SucuriScanInterface::error(
|
363 |
}
|
364 |
}
|
365 |
|
@@ -370,27 +443,32 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
370 |
SucuriScanHardening::dewhitelist('wp-tinymce.php', 'wp-includes');
|
371 |
SucuriScanHardening::dewhitelist('ms-files.php', 'wp-includes');
|
372 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the library directory');
|
373 |
-
SucuriScanInterface::info(
|
374 |
} else {
|
375 |
-
SucuriScanInterface::error(
|
376 |
}
|
377 |
}
|
378 |
|
379 |
-
$params['Hardening.Title'] =
|
380 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
|
|
381 |
|
382 |
if (SucuriScan::isBehindFirewall()) {
|
383 |
$params['Hardening.Status'] = 1;
|
384 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
385 |
-
$params['Hardening.FieldText'] =
|
386 |
} elseif (SucuriScanHardening::isHardened($folder)) {
|
387 |
$params['Hardening.Status'] = 1;
|
388 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
389 |
-
$params['Hardening.FieldText'] =
|
390 |
} else {
|
391 |
$params['Hardening.Status'] = 0;
|
392 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
393 |
-
$params['Hardening.FieldText'] =
|
394 |
}
|
395 |
|
396 |
return self::drawSection($params);
|
@@ -400,34 +478,36 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
400 |
* Check whether the "readme.html" file is still available in the root of the
|
401 |
* site or not, which can lead to an attacker to know which version number of
|
402 |
* Wordpress is being used and search for possible vulnerabilities.
|
|
|
|
|
403 |
*/
|
404 |
public static function readme()
|
405 |
{
|
406 |
$params = array();
|
407 |
|
408 |
-
// TODO: Create an option to automatically delete this after WP upgrade.
|
409 |
if (self::processRequest(__FUNCTION__)) {
|
410 |
if (@unlink(ABSPATH . '/readme.html') === false) {
|
411 |
-
SucuriScanInterface::error(
|
412 |
-
__('HardeningReadmeApplyFailure', SUCURISCAN_TEXTDOMAIN),
|
413 |
-
ABSPATH /* root of the WordPress installation */
|
414 |
-
));
|
415 |
} else {
|
416 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the <code>readme.html</code> file');
|
417 |
-
SucuriScanInterface::info(
|
418 |
}
|
419 |
}
|
420 |
|
421 |
-
$params['Hardening.Title'] =
|
422 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
|
|
423 |
|
424 |
if (file_exists(ABSPATH . '/readme.html')) {
|
425 |
$params['Hardening.Status'] = 0;
|
426 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
427 |
-
$params['Hardening.FieldText'] =
|
428 |
} else {
|
429 |
$params['Hardening.Status'] = 1;
|
430 |
-
$params['Hardening.FieldText'] =
|
431 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
432 |
}
|
433 |
|
@@ -435,32 +515,39 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
435 |
}
|
436 |
|
437 |
/**
|
438 |
-
* Check whether the main
|
439 |
-
*
|
|
|
|
|
440 |
*/
|
441 |
public static function adminuser()
|
442 |
{
|
443 |
$params = array();
|
444 |
|
445 |
-
$user_query = new WP_User_Query(
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
|
|
|
|
450 |
$results = $user_query->get_results();
|
451 |
|
452 |
$params['URL.Settings'] = admin_url('users.php?role=administrator');
|
453 |
-
$params['Hardening.Title'] =
|
454 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
455 |
|
456 |
if (count($results) === 0) {
|
457 |
$params['Hardening.Status'] = 1;
|
458 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
459 |
-
$params['Hardening.FieldText'] =
|
460 |
} else {
|
461 |
$params['Hardening.Status'] = 0;
|
462 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
463 |
-
$params['Hardening.FieldText'] =
|
464 |
}
|
465 |
|
466 |
return self::drawSection($params);
|
@@ -468,6 +555,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
468 |
|
469 |
/**
|
470 |
* Enable or disable the user of the built-in Wordpress file editor.
|
|
|
|
|
471 |
*/
|
472 |
public static function fileeditor()
|
473 |
{
|
@@ -475,12 +564,12 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
475 |
$fileEditorWasDisabled = (bool) (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT);
|
476 |
|
477 |
if (self::processRequest(__FUNCTION__)) {
|
478 |
-
$config = SucuriScan::
|
479 |
|
480 |
if (!$config) {
|
481 |
-
SucuriScanInterface::error(
|
482 |
} elseif (!is_writable($config)) {
|
483 |
-
SucuriScanInterface::error(
|
484 |
} else {
|
485 |
$content = SucuriScanFileInfo::fileContent($config);
|
486 |
$lines = explode("\n", $content);
|
@@ -501,17 +590,17 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
501 |
$content = implode("\n", $newlines);
|
502 |
@file_put_contents($config, $content, LOCK_EX);
|
503 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the plugin and theme editor');
|
504 |
-
SucuriScanInterface::info(
|
505 |
}
|
506 |
}
|
507 |
|
508 |
if (self::processRequest(__FUNCTION__ . '_revert')) {
|
509 |
-
$config = SucuriScan::
|
510 |
|
511 |
if (!$config) {
|
512 |
-
SucuriScanInterface::error(
|
513 |
} elseif (!is_writable($config)) {
|
514 |
-
SucuriScanInterface::error(
|
515 |
} else {
|
516 |
$content = SucuriScanFileInfo::fileContent($config);
|
517 |
$lines = explode("\n", $content);
|
@@ -528,28 +617,38 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
528 |
}
|
529 |
|
530 |
if (!$hardeningWasReverted) {
|
531 |
-
SucuriScanInterface::error(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
532 |
} else {
|
533 |
$fileEditorWasDisabled = false;
|
534 |
$content = implode("\n", $newlines);
|
535 |
@file_put_contents($config, $content, LOCK_EX);
|
536 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the plugin and theme editor');
|
537 |
-
SucuriScanInterface::info(
|
538 |
}
|
539 |
}
|
540 |
}
|
541 |
|
542 |
-
$params['Hardening.Title'] =
|
543 |
-
$params['Hardening.Description'] =
|
|
|
|
|
|
|
544 |
|
545 |
if ($fileEditorWasDisabled) {
|
546 |
$params['Hardening.Status'] = 1;
|
547 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
548 |
-
$params['Hardening.FieldText'] =
|
549 |
} else {
|
550 |
$params['Hardening.Status'] = 0;
|
551 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
552 |
-
$params['Hardening.FieldText'] =
|
553 |
}
|
554 |
|
555 |
return self::drawSection($params);
|
@@ -563,6 +662,8 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
563 |
* contained in such directory, 3rd-party plugins and themes that makes use
|
564 |
* of these direct requests will stop working. The admins will want to allow
|
565 |
* direct access to certain PHP files.
|
|
|
|
|
566 |
*/
|
567 |
public static function whitelistPHPFiles()
|
568 |
{
|
@@ -578,45 +679,54 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
578 |
|
579 |
if (SucuriScanInterface::checkNonce()) {
|
580 |
// Add a new file to the hardening whitelist.
|
581 |
-
|
|
|
|
|
582 |
$folder = SucuriScanRequest::post(':hardening_folder');
|
583 |
|
584 |
if (in_array($folder, $allowed_folders)) {
|
585 |
try {
|
586 |
SucuriScanHardening::whitelist($fwhite, $folder);
|
587 |
-
SucuriScanInterface::info(
|
588 |
} catch (Exception $e) {
|
589 |
SucuriScanInterface::error($e->getMessage());
|
590 |
}
|
591 |
} else {
|
592 |
-
SucuriScanInterface::error(
|
593 |
}
|
594 |
}
|
595 |
|
596 |
// Remove a file from the hardening whitelist.
|
597 |
-
|
|
|
|
|
598 |
foreach ($rmfwhite as $fpath) {
|
599 |
$fpath = str_replace('/.*/', '|', $fpath);
|
600 |
$parts = explode('|', $fpath, 2);
|
601 |
SucuriScanHardening::dewhitelist($parts[1], $parts[0]);
|
602 |
}
|
603 |
|
604 |
-
SucuriScanInterface::info(
|
605 |
}
|
606 |
}
|
607 |
|
608 |
// Read the access control file and retrieve the whitelisted files.
|
609 |
foreach ($allowed_folders as $folder) {
|
610 |
-
|
|
|
|
|
611 |
$params['HardeningWhitelist.NoItemsVisibility'] = 'hidden';
|
612 |
|
613 |
foreach ($files as $file) {
|
614 |
$fregexp = sprintf('%s/.*/%s', $folder, $file);
|
615 |
-
$html = SucuriScanTemplate::getSnippet(
|
616 |
-
'
|
617 |
-
|
618 |
-
|
619 |
-
|
|
|
|
|
|
|
620 |
$params['HardeningWhitelist.List'] .= $html;
|
621 |
}
|
622 |
}
|
3 |
/**
|
4 |
* Code related to the settings-hardening.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
/**
|
26 |
* Renders the content of the plugin's hardening page.
|
27 |
+
*
|
28 |
+
* @category Library
|
29 |
+
* @package Sucuri
|
30 |
+
* @subpackage SucuriScanner
|
31 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
32 |
+
* @copyright 2010-2017 Sucuri Inc.
|
33 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
34 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
35 |
*/
|
36 |
class SucuriScanHardeningPage extends SucuriScan
|
37 |
{
|
40 |
* a specific part of the WordPress installation, if the Status variable is
|
41 |
* set as a positive integer the button is shown as "unharden".
|
42 |
*
|
43 |
+
* @param array $args Array with template variables to replace.
|
44 |
+
* @return string HTML code with the replaced template variables.
|
45 |
*/
|
46 |
private static function drawSection($args = array())
|
47 |
{
|
72 |
/**
|
73 |
* Checks if the request has a valid nonce to prevent a CSRF.
|
74 |
*
|
75 |
+
* @param string $function Name of the action that was executed.
|
76 |
+
* @return bool True if the request has a valid CSRF protection.
|
77 |
*/
|
78 |
private static function processRequest($function)
|
79 |
{
|
90 |
* (brute force attempts, DDoS, SQL injections, etc) and helping it remain
|
91 |
* malware and blacklist free. This test checks if your site is using Sucuri
|
92 |
* Firewall to protect your site.
|
93 |
+
*
|
94 |
+
* @return string HTML code with the replaced template variables.
|
95 |
*/
|
96 |
public static function firewall()
|
97 |
{
|
98 |
$params = array();
|
99 |
|
100 |
if (self::processRequest(__FUNCTION__)) {
|
101 |
+
SucuriScanInterface::error(
|
102 |
+
'The firewall is a premium service that you need purchase at -'
|
103 |
+
. ' <a href="https://goo.gl/qfNkMq" target="_blank">Sucuri Fir'
|
104 |
+
. 'ewall</a>'
|
105 |
+
);
|
106 |
}
|
107 |
|
108 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
109 |
+
$params['Hardening.Title'] = 'Website Firewall Protection';
|
110 |
+
$params['Hardening.Description'] = 'A WAF is a protection layer for yo'
|
111 |
+
. 'ur web site, blocking all sort of attacks (brute force attempts, DD'
|
112 |
+
. 'oS, SQL injections, etc) and helping it remain malware and blacklis'
|
113 |
+
. 't free. This test checks if your site is using Sucuri Firewall to p'
|
114 |
+
. 'rotect your site.';
|
115 |
|
116 |
if (!SucuriScan::isBehindFirewall()) {
|
117 |
$params['Hardening.Status'] = 0;
|
118 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
119 |
} else {
|
120 |
$params['Hardening.Status'] = 1;
|
121 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
122 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
123 |
}
|
124 |
|
125 |
return self::drawSection($params);
|
133 |
* source code are made public, if there were security fixes then someone
|
134 |
* with malicious intent can use this information to attack any site that
|
135 |
* has not been upgraded.
|
136 |
+
*
|
137 |
+
* @return HTML with the information about this hardening option.
|
138 |
*/
|
139 |
public static function wpversion()
|
140 |
{
|
144 |
|
145 |
$params['URL.Settings'] = admin_url('update-core.php');
|
146 |
$params['Hardening.Status'] = 0;
|
147 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
148 |
+
$params['Hardening.Title'] = 'Verify WordPress Version';
|
149 |
+
$params['Hardening.Description'] = 'Why keep your site updated? WordPr'
|
150 |
+
. 'ess is an open-source project which means that with every update th'
|
151 |
+
. 'e details of the changes made to the source code are made public, i'
|
152 |
+
. 'f there were security fixes then someone with malicious intent can '
|
153 |
+
. 'use this information to attack any site that has not been upgraded.';
|
154 |
|
155 |
if (isset($updates[0]) && $updates[0] instanceof stdClass) {
|
156 |
if ($updates[0]->response == 'latest' || $updates[0]->response == 'development') {
|
157 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
158 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
159 |
$params['Hardening.Status'] = 1;
|
160 |
}
|
177 |
* of life and is no longer supported.
|
178 |
*
|
179 |
* @see http://php.net/supported-versions.php
|
180 |
+
*
|
181 |
+
* @return HTML with the information about this hardening option.
|
182 |
*/
|
183 |
public static function phpversion()
|
184 |
{
|
185 |
$params = array();
|
186 |
|
187 |
if (self::processRequest(__FUNCTION__)) {
|
188 |
+
SucuriScanInterface::error(
|
189 |
+
'Ask your hosting provider to install an updated version of PH'
|
190 |
+
. 'P - <a href="http://php.net/supported-versions.php" target='
|
191 |
+
. '"_blank" rel="noopener">List of PHP Supported Versions</a>'
|
192 |
+
);
|
193 |
}
|
194 |
|
195 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
196 |
+
$params['Hardening.Title'] = 'Verify PHP Version';
|
197 |
+
$params['Hardening.Description'] = sprintf('PHP %s is installed.', PHP_VERSION);
|
198 |
|
199 |
if (intval(version_compare(PHP_VERSION, '5.6.0') >= 0)) {
|
200 |
$params['Hardening.Status'] = 1;
|
201 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
202 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
203 |
} else {
|
204 |
$params['Hardening.Status'] = 0;
|
205 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
206 |
}
|
207 |
|
208 |
return self::drawSection($params);
|
212 |
* Notify the state of the hardening for the removal of the Generator tag in
|
213 |
* HTML code printed by WordPress to show the current version number of the
|
214 |
* installation.
|
215 |
+
*
|
216 |
+
* @return HTML with the information about this hardening option.
|
217 |
*/
|
218 |
public static function wpgenerator()
|
219 |
{
|
220 |
$params = array();
|
221 |
|
222 |
+
$params['Hardening.Title'] = 'Remove WordPress Version';
|
223 |
$params['Hardening.Status'] = 1;
|
224 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
225 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
226 |
+
$params['Hardening.Description'] = 'It checks if your WordPress versio'
|
227 |
+
. 'n is being leaked to the public via a HTML meta-tag. Many web vulne'
|
228 |
+
. 'rability scanners use this to determine which version of the code i'
|
229 |
+
. 's running in your website. They use this to find disclosed vulnerab'
|
230 |
+
. 'ilities associated to this version number. A vulnerability scanner '
|
231 |
+
. 'can still guess which version of WordPress is installed by comparin'
|
232 |
+
. 'g the checksum of some static files.';
|
233 |
|
234 |
return self::drawSection($params);
|
235 |
}
|
236 |
|
237 |
/**
|
238 |
* Offers information to apply a hardening to an Nginx installation.
|
239 |
+
*
|
240 |
+
* @return HTML with the information about this hardening option.
|
241 |
*/
|
242 |
public static function nginxphp()
|
243 |
{
|
248 |
$params = array();
|
249 |
|
250 |
if (self::processRequest(__FUNCTION__)) {
|
251 |
+
SucuriScanInterface::error(
|
252 |
+
'Read the official WordPress guidelines to learn how to restri'
|
253 |
+
. 'ct access to PHP files in sensitive directories - <a href="'
|
254 |
+
. 'https://codex.wordpress.org/Nginx#Global_restrictions_file"'
|
255 |
+
. ' target="_blank" rel="noopener">Nginx Global Restrictions F'
|
256 |
+
. 'or WordPress</a>'
|
257 |
+
);
|
258 |
}
|
259 |
|
260 |
+
$params['Hardening.Title'] = 'Block of Certain PHP Files';
|
261 |
$params['Hardening.Status'] = 2;
|
262 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
263 |
+
$params['Hardening.FieldText'] = 'Check Hardening';
|
264 |
+
$params['Hardening.Description'] = 'Block the execution of PHP files i'
|
265 |
+
. 'n sensitive directories. Be careful while applying this hardening o'
|
266 |
+
. 'ption as there are many plugins and theme which rely on the ability'
|
267 |
+
. ' to execute PHP files in the content directory to generate images o'
|
268 |
+
. 'r save temporary data. Use the "Whitelist PHP Files" tool to add ex'
|
269 |
+
. 'ceptions to individual files.';
|
270 |
|
271 |
return self::drawSection($params);
|
272 |
}
|
277 |
* A htaccess file is placed in the upload folder denying the access to any php
|
278 |
* file that could be uploaded through a vulnerability in a Plugin, Theme or
|
279 |
* WordPress itself.
|
280 |
+
*
|
281 |
+
* @return HTML with the information about this hardening option.
|
282 |
*/
|
283 |
public static function wpuploads()
|
284 |
{
|
294 |
|
295 |
if ($result === true) {
|
296 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the uploads directory');
|
297 |
+
SucuriScanInterface::info('Hardening applied to the uploads directory');
|
298 |
} else {
|
299 |
+
SucuriScanInterface::error('Error hardening directory, check the permissions.');
|
300 |
}
|
301 |
}
|
302 |
|
305 |
|
306 |
if ($result === true) {
|
307 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the uploads directory');
|
308 |
+
SucuriScanInterface::info('Hardening reverted in the uploads directory');
|
309 |
} else {
|
310 |
+
SucuriScanInterface::error('Access file is not writable, check the permissions.');
|
311 |
}
|
312 |
}
|
313 |
|
314 |
+
$params['Hardening.Title'] = 'Block PHP Files in Uploads Directory';
|
315 |
+
$params['Hardening.Description'] = 'Block the execution of PHP files i'
|
316 |
+
. 'n sensitive directories. Be careful while applying this hardening o'
|
317 |
+
. 'ption as there are many plugins and theme which rely on the ability'
|
318 |
+
. ' to execute PHP files in the content directory to generate images o'
|
319 |
+
. 'r save temporary data. Use the "Whitelist PHP Files" tool to add ex'
|
320 |
+
. 'ceptions to individual files.';
|
321 |
|
322 |
if (SucuriScan::isBehindFirewall()) {
|
323 |
$params['Hardening.Status'] = 1;
|
324 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
325 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
326 |
} elseif (SucuriScanHardening::isHardened($folder)) {
|
327 |
$params['Hardening.Status'] = 1;
|
328 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
329 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
330 |
} else {
|
331 |
$params['Hardening.Status'] = 0;
|
332 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
333 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
334 |
}
|
335 |
|
336 |
return self::drawSection($params);
|
342 |
* A htaccess file is placed in the content folder denying the access to any php
|
343 |
* file that could be uploaded through a vulnerability in a Plugin, Theme or
|
344 |
* WordPress itself.
|
345 |
+
*
|
346 |
+
* @return HTML with the information about this hardening option.
|
347 |
*/
|
348 |
public static function wpcontent()
|
349 |
{
|
358 |
|
359 |
if ($result === true) {
|
360 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the content directory');
|
361 |
+
SucuriScanInterface::info('Hardening applied to the content directory');
|
362 |
} else {
|
363 |
+
SucuriScanInterface::error('Error hardening directory, check the permissions.');
|
364 |
}
|
365 |
}
|
366 |
|
369 |
|
370 |
if ($result === true) {
|
371 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the content directory');
|
372 |
+
SucuriScanInterface::info('Hardening reverted in the content directory');
|
373 |
} else {
|
374 |
+
SucuriScanInterface::error('Access file is not writable, check the permissions.');
|
375 |
}
|
376 |
}
|
377 |
|
378 |
+
$params['Hardening.Title'] = 'Block PHP Files in WP-CONTENT Directory';
|
379 |
+
$params['Hardening.Description'] = 'Block the execution of PHP files i'
|
380 |
+
. 'n sensitive directories. Be careful while applying this hardening o'
|
381 |
+
. 'ption as there are many plugins and theme which rely on the ability'
|
382 |
+
. ' to execute PHP files in the content directory to generate images o'
|
383 |
+
. 'r save temporary data. Use the "Whitelist PHP Files" tool to add ex'
|
384 |
+
. 'ceptions to individual files.';
|
385 |
|
386 |
if (SucuriScan::isBehindFirewall()) {
|
387 |
$params['Hardening.Status'] = 1;
|
388 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
389 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
390 |
} elseif (SucuriScanHardening::isHardened(WP_CONTENT_DIR)) {
|
391 |
$params['Hardening.Status'] = 1;
|
392 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
393 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
394 |
} else {
|
395 |
$params['Hardening.Status'] = 0;
|
396 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
397 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
398 |
}
|
399 |
|
400 |
return self::drawSection($params);
|
407 |
* file that could be uploaded through a vulnerability in a Plugin, Theme or
|
408 |
* WordPress itself, there are some exceptions for some specific files that must
|
409 |
* be available publicly.
|
410 |
+
*
|
411 |
+
* @return HTML with the information about this hardening option.
|
412 |
*/
|
413 |
public static function wpincludes()
|
414 |
{
|
427 |
SucuriScanHardening::whitelist('wp-tinymce.php', 'wp-includes');
|
428 |
SucuriScanHardening::whitelist('ms-files.php', 'wp-includes');
|
429 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the library directory');
|
430 |
+
SucuriScanInterface::info('Hardening applied to the library directory');
|
431 |
} catch (Exception $e) {
|
432 |
SucuriScanInterface::error($e->getMessage());
|
433 |
}
|
434 |
} else {
|
435 |
+
SucuriScanInterface::error('Error hardening directory, check the permissions.');
|
436 |
}
|
437 |
}
|
438 |
|
443 |
SucuriScanHardening::dewhitelist('wp-tinymce.php', 'wp-includes');
|
444 |
SucuriScanHardening::dewhitelist('ms-files.php', 'wp-includes');
|
445 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the library directory');
|
446 |
+
SucuriScanInterface::info('Hardening reverted in the library directory');
|
447 |
} else {
|
448 |
+
SucuriScanInterface::error('Access file is not writable, check the permissions.');
|
449 |
}
|
450 |
}
|
451 |
|
452 |
+
$params['Hardening.Title'] = 'Block PHP Files in WP-INCLUDES Directory';
|
453 |
+
$params['Hardening.Description'] = 'Block the execution of PHP files i'
|
454 |
+
. 'n sensitive directories. Be careful while applying this hardening o'
|
455 |
+
. 'ption as there are many plugins and theme which rely on the ability'
|
456 |
+
. ' to execute PHP files in the content directory to generate images o'
|
457 |
+
. 'r save temporary data. Use the "Whitelist PHP Files" tool to add ex'
|
458 |
+
. 'ceptions to individual files.';
|
459 |
|
460 |
if (SucuriScan::isBehindFirewall()) {
|
461 |
$params['Hardening.Status'] = 1;
|
462 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
463 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
464 |
} elseif (SucuriScanHardening::isHardened($folder)) {
|
465 |
$params['Hardening.Status'] = 1;
|
466 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
467 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
468 |
} else {
|
469 |
$params['Hardening.Status'] = 0;
|
470 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
471 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
472 |
}
|
473 |
|
474 |
return self::drawSection($params);
|
478 |
* Check whether the "readme.html" file is still available in the root of the
|
479 |
* site or not, which can lead to an attacker to know which version number of
|
480 |
* Wordpress is being used and search for possible vulnerabilities.
|
481 |
+
*
|
482 |
+
* @return HTML with the information about this hardening option.
|
483 |
*/
|
484 |
public static function readme()
|
485 |
{
|
486 |
$params = array();
|
487 |
|
|
|
488 |
if (self::processRequest(__FUNCTION__)) {
|
489 |
if (@unlink(ABSPATH . '/readme.html') === false) {
|
490 |
+
SucuriScanInterface::error('Cannot delete <code>' . ABSPATH . '/readme.html</code>');
|
|
|
|
|
|
|
491 |
} else {
|
492 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the <code>readme.html</code> file');
|
493 |
+
SucuriScanInterface::info('Hardening applied to the <code>readme.html</code> file');
|
494 |
}
|
495 |
}
|
496 |
|
497 |
+
$params['Hardening.Title'] = 'Information Leakage';
|
498 |
+
$params['Hardening.Description'] = 'Checks if the WordPress README fil'
|
499 |
+
. 'e still exists in the website. The information in this file can be '
|
500 |
+
. 'used by malicious users to pin-point which disclosed vulnerabilitie'
|
501 |
+
. 's are associated to the website. Be aware that WordPress recreates '
|
502 |
+
. 'this file automatically with every update.';
|
503 |
|
504 |
if (file_exists(ABSPATH . '/readme.html')) {
|
505 |
$params['Hardening.Status'] = 0;
|
506 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
507 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
508 |
} else {
|
509 |
$params['Hardening.Status'] = 1;
|
510 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
511 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
512 |
}
|
513 |
|
515 |
}
|
516 |
|
517 |
/**
|
518 |
+
* Check whether the main admin user still has the default name "admin" or
|
519 |
+
* not, which can lead to an attacker to perform a brute force attack.
|
520 |
+
*
|
521 |
+
* @return HTML with the information about this hardening option.
|
522 |
*/
|
523 |
public static function adminuser()
|
524 |
{
|
525 |
$params = array();
|
526 |
|
527 |
+
$user_query = new WP_User_Query(
|
528 |
+
array(
|
529 |
+
'search' => 'admin',
|
530 |
+
'fields' => array('ID', 'user_login'),
|
531 |
+
'search_columns' => array('user_login'),
|
532 |
+
)
|
533 |
+
);
|
534 |
$results = $user_query->get_results();
|
535 |
|
536 |
$params['URL.Settings'] = admin_url('users.php?role=administrator');
|
537 |
+
$params['Hardening.Title'] = 'Default Admin Account';
|
538 |
+
$params['Hardening.Description'] = 'Check if the primary user account '
|
539 |
+
. 'still uses the name "admin". This allows malicious users to easily '
|
540 |
+
. 'identify which account has the highest privileges to target an atta'
|
541 |
+
. 'ck.';
|
542 |
|
543 |
if (count($results) === 0) {
|
544 |
$params['Hardening.Status'] = 1;
|
545 |
$params['Hardening.FieldAttrs'] = 'disabled';
|
546 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
547 |
} else {
|
548 |
$params['Hardening.Status'] = 0;
|
549 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
550 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
551 |
}
|
552 |
|
553 |
return self::drawSection($params);
|
555 |
|
556 |
/**
|
557 |
* Enable or disable the user of the built-in Wordpress file editor.
|
558 |
+
*
|
559 |
+
* @return HTML with the information about this hardening option.
|
560 |
*/
|
561 |
public static function fileeditor()
|
562 |
{
|
564 |
$fileEditorWasDisabled = (bool) (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT);
|
565 |
|
566 |
if (self::processRequest(__FUNCTION__)) {
|
567 |
+
$config = SucuriScan::getConfigPath();
|
568 |
|
569 |
if (!$config) {
|
570 |
+
SucuriScanInterface::error('WordPress configuration file was not found.');
|
571 |
} elseif (!is_writable($config)) {
|
572 |
+
SucuriScanInterface::error('WordPress configuration file is not writable.');
|
573 |
} else {
|
574 |
$content = SucuriScanFileInfo::fileContent($config);
|
575 |
$lines = explode("\n", $content);
|
590 |
$content = implode("\n", $newlines);
|
591 |
@file_put_contents($config, $content, LOCK_EX);
|
592 |
SucuriScanEvent::reportNoticeEvent('Hardening applied to the plugin and theme editor');
|
593 |
+
SucuriScanInterface::info('Hardening applied to the plugin and theme editor');
|
594 |
}
|
595 |
}
|
596 |
|
597 |
if (self::processRequest(__FUNCTION__ . '_revert')) {
|
598 |
+
$config = SucuriScan::getConfigPath();
|
599 |
|
600 |
if (!$config) {
|
601 |
+
SucuriScanInterface::error('WordPress configuration file was not found.');
|
602 |
} elseif (!is_writable($config)) {
|
603 |
+
SucuriScanInterface::error('WordPress configuration file is not writable.');
|
604 |
} else {
|
605 |
$content = SucuriScanFileInfo::fileContent($config);
|
606 |
$lines = explode("\n", $content);
|
617 |
}
|
618 |
|
619 |
if (!$hardeningWasReverted) {
|
620 |
+
SucuriScanInterface::error(
|
621 |
+
'File Editor was not disabled using this tool. You mus'
|
622 |
+
. 't scan your project for a constant defined as DISAL'
|
623 |
+
. 'LOW_FILE_EDIT, then either delete it or set its val'
|
624 |
+
. 'ue to False. Any plugin/theme can disable the file '
|
625 |
+
. 'editor, so it is impossible to determine the origin'
|
626 |
+
. ' of the constant.'
|
627 |
+
);
|
628 |
} else {
|
629 |
$fileEditorWasDisabled = false;
|
630 |
$content = implode("\n", $newlines);
|
631 |
@file_put_contents($config, $content, LOCK_EX);
|
632 |
SucuriScanEvent::reportErrorEvent('Hardening reverted in the plugin and theme editor');
|
633 |
+
SucuriScanInterface::info('Hardening reverted in the plugin and theme editor');
|
634 |
}
|
635 |
}
|
636 |
}
|
637 |
|
638 |
+
$params['Hardening.Title'] = 'Plugin and Theme Editor';
|
639 |
+
$params['Hardening.Description'] = 'Disables the theme and plugin edit'
|
640 |
+
. 'ors to prevent unwanted modifications to the code. If you are havin'
|
641 |
+
. 'g problems reverting this please open the wp-config.php file and de'
|
642 |
+
. 'lete the line with the constant DISALLOW_FILE_EDIT.';
|
643 |
|
644 |
if ($fileEditorWasDisabled) {
|
645 |
$params['Hardening.Status'] = 1;
|
646 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
647 |
+
$params['Hardening.FieldText'] = 'Revert Hardening';
|
648 |
} else {
|
649 |
$params['Hardening.Status'] = 0;
|
650 |
$params['Hardening.FieldName'] = __FUNCTION__;
|
651 |
+
$params['Hardening.FieldText'] = 'Apply Hardening';
|
652 |
}
|
653 |
|
654 |
return self::drawSection($params);
|
662 |
* contained in such directory, 3rd-party plugins and themes that makes use
|
663 |
* of these direct requests will stop working. The admins will want to allow
|
664 |
* direct access to certain PHP files.
|
665 |
+
*
|
666 |
+
* @return HTML with the information about this hardening option.
|
667 |
*/
|
668 |
public static function whitelistPHPFiles()
|
669 |
{
|
679 |
|
680 |
if (SucuriScanInterface::checkNonce()) {
|
681 |
// Add a new file to the hardening whitelist.
|
682 |
+
$fwhite = SucuriScanRequest::post(':hardening_whitelist');
|
683 |
+
|
684 |
+
if ($fwhite) {
|
685 |
$folder = SucuriScanRequest::post(':hardening_folder');
|
686 |
|
687 |
if (in_array($folder, $allowed_folders)) {
|
688 |
try {
|
689 |
SucuriScanHardening::whitelist($fwhite, $folder);
|
690 |
+
SucuriScanInterface::info('The file has been whitelisted from the hardening');
|
691 |
} catch (Exception $e) {
|
692 |
SucuriScanInterface::error($e->getMessage());
|
693 |
}
|
694 |
} else {
|
695 |
+
SucuriScanInterface::error('Specified folder is not hardened by this plugin');
|
696 |
}
|
697 |
}
|
698 |
|
699 |
// Remove a file from the hardening whitelist.
|
700 |
+
$rmfwhite = SucuriScanRequest::post(':hardening_rmfwhite', '_array');
|
701 |
+
|
702 |
+
if ($rmfwhite) {
|
703 |
foreach ($rmfwhite as $fpath) {
|
704 |
$fpath = str_replace('/.*/', '|', $fpath);
|
705 |
$parts = explode('|', $fpath, 2);
|
706 |
SucuriScanHardening::dewhitelist($parts[1], $parts[0]);
|
707 |
}
|
708 |
|
709 |
+
SucuriScanInterface::info('Selected files have been removed');
|
710 |
}
|
711 |
}
|
712 |
|
713 |
// Read the access control file and retrieve the whitelisted files.
|
714 |
foreach ($allowed_folders as $folder) {
|
715 |
+
$files = SucuriScanHardening::getWhitelisted($folder);
|
716 |
+
|
717 |
+
if (is_array($files) && !empty($files)) {
|
718 |
$params['HardeningWhitelist.NoItemsVisibility'] = 'hidden';
|
719 |
|
720 |
foreach ($files as $file) {
|
721 |
$fregexp = sprintf('%s/.*/%s', $folder, $file);
|
722 |
+
$html = SucuriScanTemplate::getSnippet(
|
723 |
+
'settings-hardening-whitelist-phpfiles',
|
724 |
+
array(
|
725 |
+
'HardeningWhitelist.Regexp' => $fregexp,
|
726 |
+
'HardeningWhitelist.Folder' => $folder,
|
727 |
+
'HardeningWhitelist.File' => $file,
|
728 |
+
)
|
729 |
+
);
|
730 |
$params['HardeningWhitelist.List'] .= $html;
|
731 |
}
|
732 |
}
|
src/settings-integrity.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-integrity.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -24,29 +30,39 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
24 |
* integrity scanner and the optional Unix diff utility. This also includes some
|
25 |
* options to configure the website installation language and the false/positive
|
26 |
* cache file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
*/
|
28 |
class SucuriScanSettingsIntegrity extends SucuriScanSettings
|
29 |
{
|
30 |
/**
|
31 |
* Configures the diffUtility for the integrity scanner.
|
32 |
*
|
33 |
-
* @param
|
34 |
-
* @return string
|
35 |
*/
|
36 |
public static function diffUtility($nonce)
|
37 |
{
|
38 |
$params = array();
|
39 |
|
40 |
$params['DiffUtility.StatusNum'] = 0;
|
41 |
-
$params['DiffUtility.Status'] =
|
42 |
-
$params['DiffUtility.SwitchText'] =
|
43 |
$params['DiffUtility.SwitchValue'] = 'enable';
|
44 |
|
45 |
if ($nonce) {
|
46 |
// Enable or disable the Unix diff utility.
|
47 |
-
|
|
|
|
|
48 |
if (!SucuriScanCommand::exists('diff')) {
|
49 |
-
SucuriScanInterface::error(
|
50 |
} else {
|
51 |
$status = $status . 'd'; /* add past tense */
|
52 |
$message = 'Integrity diff utility has been <code>' . $status . '</code>';
|
@@ -54,60 +70,26 @@ class SucuriScanSettingsIntegrity extends SucuriScanSettings
|
|
54 |
SucuriScanOption::updateOption(':diff_utility', $status);
|
55 |
SucuriScanEvent::reportInfoEvent($message);
|
56 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
57 |
-
SucuriScanInterface::info(
|
58 |
}
|
59 |
}
|
60 |
}
|
61 |
|
62 |
if (SucuriScanOption::isEnabled(':diff_utility')) {
|
63 |
$params['DiffUtility.StatusNum'] = 1;
|
64 |
-
$params['DiffUtility.Status'] =
|
65 |
-
$params['DiffUtility.SwitchText'] =
|
66 |
$params['DiffUtility.SwitchValue'] = 'disable';
|
67 |
}
|
68 |
|
69 |
return SucuriScanTemplate::getSection('settings-scanner-integrity-diff-utility', $params);
|
70 |
}
|
71 |
|
72 |
-
/**
|
73 |
-
* Configures the language for the integrity scanner.
|
74 |
-
*
|
75 |
-
* @param bool $nonce True if the CSRF protection worked, false otherwise.
|
76 |
-
* @return string HTML code to render the configuration panel.
|
77 |
-
*/
|
78 |
-
public static function language($nonce)
|
79 |
-
{
|
80 |
-
$params = array();
|
81 |
-
$languages = SucuriScan::languages();
|
82 |
-
|
83 |
-
if ($nonce) {
|
84 |
-
// Configure the language for the core integrity checks.
|
85 |
-
if ($language = SucuriScanRequest::post(':set_language')) {
|
86 |
-
if (array_key_exists($language, $languages)) {
|
87 |
-
$message = 'Core integrity language set to <code>' . $language . '</code>';
|
88 |
-
|
89 |
-
SucuriScanOption::updateOption(':language', $language);
|
90 |
-
SucuriScanEvent::reportInfoEvent($message);
|
91 |
-
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
92 |
-
SucuriScanInterface::info(__('IntegrityLanguage', SUCURISCAN_TEXTDOMAIN));
|
93 |
-
} else {
|
94 |
-
SucuriScanInterface::error(__('NonSupportedLanguage', SUCURISCAN_TEXTDOMAIN));
|
95 |
-
}
|
96 |
-
}
|
97 |
-
}
|
98 |
-
|
99 |
-
$language = SucuriScanOption::getOption(':language');
|
100 |
-
$params['Integrity.LanguageDropdown'] = SucuriScanTemplate::selectOptions($languages, $language);
|
101 |
-
$params['Integrity.WordPressLocale'] = get_locale();
|
102 |
-
|
103 |
-
return SucuriScanTemplate::getSection('settings-scanner-integrity-language', $params);
|
104 |
-
}
|
105 |
-
|
106 |
/**
|
107 |
* Configures the cache for the integrity scanner.
|
108 |
*
|
109 |
-
* @param
|
110 |
-
* @return string
|
111 |
*/
|
112 |
public static function cache($nonce)
|
113 |
{
|
@@ -126,9 +108,11 @@ class SucuriScanSettingsIntegrity extends SucuriScanSettings
|
|
126 |
}
|
127 |
|
128 |
if (!empty($deletedFiles)) {
|
129 |
-
SucuriScanEvent::reportDebugEvent(
|
130 |
-
|
131 |
-
|
|
|
|
|
132 |
}
|
133 |
}
|
134 |
|
@@ -137,16 +121,21 @@ class SucuriScanSettingsIntegrity extends SucuriScanSettings
|
|
137 |
$params['CacheLifeTime'] = SUCURISCAN_SITECHECK_LIFETIME;
|
138 |
$params['NoFilesVisibility'] = 'visible';
|
139 |
|
140 |
-
|
|
|
|
|
141 |
$params['NoFilesVisibility'] = 'hidden';
|
142 |
|
143 |
foreach ($ignored_files as $hash => $data) {
|
144 |
-
$params['IgnoredFiles'] .= SucuriScanTemplate::getSnippet(
|
145 |
-
'
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
|
|
|
|
|
|
150 |
}
|
151 |
}
|
152 |
|
3 |
/**
|
4 |
* Code related to the settings-integrity.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
30 |
* integrity scanner and the optional Unix diff utility. This also includes some
|
31 |
* options to configure the website installation language and the false/positive
|
32 |
* cache file.
|
33 |
+
*
|
34 |
+
* @category Library
|
35 |
+
* @package Sucuri
|
36 |
+
* @subpackage SucuriScanner
|
37 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
38 |
+
* @copyright 2010-2017 Sucuri Inc.
|
39 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
40 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
41 |
*/
|
42 |
class SucuriScanSettingsIntegrity extends SucuriScanSettings
|
43 |
{
|
44 |
/**
|
45 |
* Configures the diffUtility for the integrity scanner.
|
46 |
*
|
47 |
+
* @param bool $nonce True if the CSRF protection worked, false otherwise.
|
48 |
+
* @return string HTML code to render the configuration panel.
|
49 |
*/
|
50 |
public static function diffUtility($nonce)
|
51 |
{
|
52 |
$params = array();
|
53 |
|
54 |
$params['DiffUtility.StatusNum'] = 0;
|
55 |
+
$params['DiffUtility.Status'] = 'Disabled';
|
56 |
+
$params['DiffUtility.SwitchText'] = 'Enable';
|
57 |
$params['DiffUtility.SwitchValue'] = 'enable';
|
58 |
|
59 |
if ($nonce) {
|
60 |
// Enable or disable the Unix diff utility.
|
61 |
+
$status = SucuriScanRequest::post(':diff_utility', '(en|dis)able');
|
62 |
+
|
63 |
+
if ($status) {
|
64 |
if (!SucuriScanCommand::exists('diff')) {
|
65 |
+
SucuriScanInterface::error('Your hosting provider has blocked the execution of external commands.');
|
66 |
} else {
|
67 |
$status = $status . 'd'; /* add past tense */
|
68 |
$message = 'Integrity diff utility has been <code>' . $status . '</code>';
|
70 |
SucuriScanOption::updateOption(':diff_utility', $status);
|
71 |
SucuriScanEvent::reportInfoEvent($message);
|
72 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
73 |
+
SucuriScanInterface::info('The status of the integrity diff utility has been changed');
|
74 |
}
|
75 |
}
|
76 |
}
|
77 |
|
78 |
if (SucuriScanOption::isEnabled(':diff_utility')) {
|
79 |
$params['DiffUtility.StatusNum'] = 1;
|
80 |
+
$params['DiffUtility.Status'] = 'Enabled';
|
81 |
+
$params['DiffUtility.SwitchText'] = 'Disable';
|
82 |
$params['DiffUtility.SwitchValue'] = 'disable';
|
83 |
}
|
84 |
|
85 |
return SucuriScanTemplate::getSection('settings-scanner-integrity-diff-utility', $params);
|
86 |
}
|
87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
/**
|
89 |
* Configures the cache for the integrity scanner.
|
90 |
*
|
91 |
+
* @param bool $nonce True if the CSRF protection worked, false otherwise.
|
92 |
+
* @return string HTML code to render the configuration panel.
|
93 |
*/
|
94 |
public static function cache($nonce)
|
95 |
{
|
108 |
}
|
109 |
|
110 |
if (!empty($deletedFiles)) {
|
111 |
+
SucuriScanEvent::reportDebugEvent(
|
112 |
+
'Core files that will not be ignored anymore: (mul'
|
113 |
+
. 'tiple entries): ' . implode(',', $deletedFiles)
|
114 |
+
);
|
115 |
+
SucuriScanInterface::info('The selected files have been successfully processed.');
|
116 |
}
|
117 |
}
|
118 |
|
121 |
$params['CacheLifeTime'] = SUCURISCAN_SITECHECK_LIFETIME;
|
122 |
$params['NoFilesVisibility'] = 'visible';
|
123 |
|
124 |
+
$ignored_files = $cache->getAll();
|
125 |
+
|
126 |
+
if (is_array($ignored_files) && !empty($ignored_files)) {
|
127 |
$params['NoFilesVisibility'] = 'hidden';
|
128 |
|
129 |
foreach ($ignored_files as $hash => $data) {
|
130 |
+
$params['IgnoredFiles'] .= SucuriScanTemplate::getSnippet(
|
131 |
+
'settings-scanner-integrity-cache',
|
132 |
+
array(
|
133 |
+
'UniqueId' => substr($hash, 0, 8),
|
134 |
+
'FilePath' => $data->file_path,
|
135 |
+
'StatusType' => $data->file_status,
|
136 |
+
'IgnoredAt' => SucuriScan::datetime($data->ignored_at),
|
137 |
+
)
|
138 |
+
);
|
139 |
}
|
140 |
}
|
141 |
|
src/settings-posthack.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-posthack.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -22,6 +28,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
22 |
* The plugin allows to execute some tools that will clear up the site after a
|
23 |
* suspicious activity. This includes the ability to reset the secret security
|
24 |
* keys, the password for each user account, and the installed plugins.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
*/
|
26 |
class SucuriScanSettingsPosthack extends SucuriScanSettings
|
27 |
{
|
@@ -41,15 +55,15 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
41 |
// Update all WordPress secret keys.
|
42 |
if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':update_wpconfig')) {
|
43 |
if (SucuriScanRequest::post(':process_form') != 1) {
|
44 |
-
SucuriScanInterface::error(
|
45 |
} else {
|
46 |
$wpconfig_process = SucuriScanEvent::setNewConfigKeys();
|
47 |
|
48 |
if (!$wpconfig_process) {
|
49 |
-
SucuriScanInterface::error(
|
50 |
} elseif ($wpconfig_process['updated']) {
|
51 |
SucuriScanEvent::reportNoticeEvent('Generate new security keys (success)');
|
52 |
-
SucuriScanInterface::info(
|
53 |
|
54 |
$params['WPConfigUpdate.Visibility'] = 'visible';
|
55 |
$params['WPConfigUpdate.NewConfig'] .= "/* Old Security Keys */\n";
|
@@ -59,7 +73,7 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
59 |
$params['WPConfigUpdate.NewConfig'] .= $wpconfig_process['new_keys_string'];
|
60 |
} else {
|
61 |
SucuriScanEvent::reportNoticeEvent('Generate new security keys (failure)');
|
62 |
-
SucuriScanInterface::error(
|
63 |
|
64 |
$params['WPConfigUpdate.Visibility'] = 'visible';
|
65 |
$params['WPConfigUpdate.NewConfig'] = $wpconfig_process['new_wpconfig'];
|
@@ -74,26 +88,28 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
74 |
foreach ($key_list as $key_name => $key_value) {
|
75 |
switch ($key_status) {
|
76 |
case 'good':
|
77 |
-
$key_status_text =
|
78 |
break;
|
79 |
|
80 |
case 'bad':
|
81 |
-
$key_status_text =
|
82 |
break;
|
83 |
|
84 |
case 'missing':
|
85 |
$key_value = '';
|
86 |
-
$key_status_text =
|
87 |
break;
|
88 |
}
|
89 |
|
90 |
if (isset($key_status_text)) {
|
91 |
-
$params['SecurityKeys.List'] .=
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
97 |
}
|
98 |
}
|
99 |
}
|
@@ -120,12 +136,14 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
120 |
$user_list = array();
|
121 |
$page_number = SucuriScanTemplate::pageNumber();
|
122 |
$max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
123 |
-
$dbquery = new WP_User_Query(
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
|
|
|
|
129 |
|
130 |
// Retrieve the results and build the pagination links.
|
131 |
if ($dbquery) {
|
@@ -149,15 +167,17 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
149 |
$user->user_registered_formatted = SucuriScan::datetime($user->user_registered_timestamp);
|
150 |
$disabled = ($user->user_login == $session->user_login) ? 'disabled' : '';
|
151 |
|
152 |
-
$params['ResetPassword.UserList'] .=
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
|
|
161 |
}
|
162 |
}
|
163 |
|
@@ -166,6 +186,8 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
166 |
|
167 |
/**
|
168 |
* Sets a new password for the specified user account.
|
|
|
|
|
169 |
*/
|
170 |
public static function resetPasswordAjax()
|
171 |
{
|
@@ -173,11 +195,11 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
173 |
return;
|
174 |
}
|
175 |
|
176 |
-
$response =
|
177 |
$user_id = intval(SucuriScanRequest::post('user_id'));
|
178 |
|
179 |
if (SucuriScanEvent::setNewPassword($user_id)) {
|
180 |
-
$response =
|
181 |
SucuriScanEvent::reportNoticeEvent('Password changed for user #' . $user_id);
|
182 |
}
|
183 |
|
@@ -186,12 +208,14 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
186 |
|
187 |
/**
|
188 |
* Reset all the FREE plugins, even if they are not activated.
|
|
|
|
|
189 |
*/
|
190 |
public static function resetPlugins()
|
191 |
{
|
192 |
$params = array(
|
193 |
'ResetPlugin.PluginList' => '',
|
194 |
-
'ResetPlugin.CacheLifeTime' =>
|
195 |
);
|
196 |
|
197 |
if (defined('SUCURISCAN_GET_PLUGINS_LIFETIME')) {
|
@@ -203,6 +227,8 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
203 |
|
204 |
/**
|
205 |
* Find and list available updates for plugins and themes.
|
|
|
|
|
206 |
*/
|
207 |
public static function availableUpdates()
|
208 |
{
|
@@ -213,6 +239,8 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
213 |
|
214 |
/**
|
215 |
* Process the Ajax request to retrieve the plugins metadata.
|
|
|
|
|
216 |
*/
|
217 |
public static function getPluginsAjax()
|
218 |
{
|
@@ -227,22 +255,23 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
227 |
$plugin_type_class = ( $plugin_data['PluginType'] == 'free' ) ? 'primary' : 'warning';
|
228 |
$input_disabled = ( $plugin_data['PluginType'] == 'free' ) ? '' : 'disabled="disabled"';
|
229 |
$plugin_status_class = $plugin_data['IsPluginActive'] ? 'success' : 'default';
|
230 |
-
$plugin_status = $plugin_data['IsPluginActive']
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
|
|
246 |
}
|
247 |
|
248 |
wp_send_json($response, true);
|
@@ -250,6 +279,8 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
250 |
|
251 |
/**
|
252 |
* Process the Ajax request to reset one free plugin.
|
|
|
|
|
253 |
*/
|
254 |
public static function resetPluginAjax()
|
255 |
{
|
@@ -264,20 +295,20 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
264 |
/* Check if the plugin actually exists */
|
265 |
if (!array_key_exists($plugin, $allPlugins)) {
|
266 |
$response = '<span class="sucuriscan-label-default">'
|
267 |
-
.
|
268 |
} elseif ($allPlugins[$plugin]['IsFreePlugin'] !== true) {
|
269 |
// Ignore plugins not listed in the WordPress repository.
|
270 |
// This usually applies to premium plugins. They cannot be downloaded from
|
271 |
// a reliable source because we can't check the checksum of the files nor
|
272 |
// we can verify if the installation of the new code will work or not.
|
273 |
$response = '<span class="sucuriscan-label-danger">'
|
274 |
-
.
|
275 |
} elseif (!is_writable($allPlugins[$plugin]['InstallationPath'])) {
|
276 |
$response = '<span class="sucuriscan-label-danger">'
|
277 |
-
.
|
278 |
} elseif (!class_exists('SucuriScanPluginInstallerSkin')) {
|
279 |
$response = '<span class="sucuriscan-label-danger">'
|
280 |
-
.
|
281 |
} else {
|
282 |
// Get data associated to the plugin.
|
283 |
$data = $allPlugins[$plugin];
|
@@ -287,10 +318,10 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
287 |
|
288 |
if (!$info) {
|
289 |
$response = '<span class="sucuriscan-label-danger">'
|
290 |
-
.
|
291 |
} elseif (!rename($data['InstallationPath'], $newpath)) {
|
292 |
$response = '<span class="sucuriscan-label-danger">'
|
293 |
-
.
|
294 |
} else {
|
295 |
ob_start();
|
296 |
$upgrader_skin = new SucuriScanPluginInstallerSkin();
|
@@ -303,7 +334,7 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
303 |
/* Revert backup to its original location */
|
304 |
@rename($newpath, $data['InstallationPath']);
|
305 |
$response = '<span class="sucuriscan-label-danger">'
|
306 |
-
.
|
307 |
} else {
|
308 |
/* Destroy the backup of the plugin */
|
309 |
$fifo = new SucuriScanFileInfo();
|
@@ -312,10 +343,7 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
312 |
$fifo->skip_directories = false;
|
313 |
$fifo->removeDirectoryTree($newpath);
|
314 |
|
315 |
-
$installed = SucuriScan::escape(
|
316 |
-
__('VersionInstalled', SUCURISCAN_TEXTDOMAIN),
|
317 |
-
$info['version'] /* mixed version number */
|
318 |
-
));
|
319 |
$response = '<span class="sucuriscan-label-success">' . $installed . '</span>';
|
320 |
}
|
321 |
}
|
@@ -327,8 +355,8 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
327 |
/**
|
328 |
* Retrieve the information for the available updates.
|
329 |
*
|
330 |
-
* @param
|
331 |
-
* @return string|bool
|
332 |
*/
|
333 |
public static function availableUpdatesContent($send_email = false)
|
334 |
{
|
@@ -350,10 +378,10 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
350 |
'Update.IconType' => 'plugins',
|
351 |
'Update.Extension' => SucuriScan::excerpt($data->Name, 35),
|
352 |
'Update.Version' => $data->Version,
|
353 |
-
'Update.NewVersion' =>
|
354 |
-
'Update.TestedWith' =>
|
355 |
-
'Update.ArchiveUrl' =>
|
356 |
-
'Update.MarketUrl' =>
|
357 |
);
|
358 |
|
359 |
if (property_exists($data->update, 'new_version')) {
|
@@ -382,15 +410,18 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
382 |
|
383 |
if (is_array($updates) && !empty($updates)) {
|
384 |
foreach ($updates as $data) {
|
385 |
-
$response .= SucuriScanTemplate::getSnippet(
|
386 |
-
'
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
|
|
|
|
|
|
394 |
}
|
395 |
}
|
396 |
|
@@ -412,6 +443,8 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
412 |
|
413 |
/**
|
414 |
* Process the Ajax request to retrieve the available updates.
|
|
|
|
|
415 |
*/
|
416 |
public static function availableUpdatesAjax()
|
417 |
{
|
@@ -422,7 +455,7 @@ class SucuriScanSettingsPosthack extends SucuriScanSettings
|
|
422 |
$response = SucuriScanSettingsPosthack::availableUpdatesContent();
|
423 |
|
424 |
if (!$response) {
|
425 |
-
$response = '<tr><td colspan="5">' .
|
426 |
}
|
427 |
|
428 |
wp_send_json($response, 200);
|
3 |
/**
|
4 |
* Code related to the settings-posthack.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
28 |
* The plugin allows to execute some tools that will clear up the site after a
|
29 |
* suspicious activity. This includes the ability to reset the secret security
|
30 |
* keys, the password for each user account, and the installed plugins.
|
31 |
+
*
|
32 |
+
* @category Library
|
33 |
+
* @package Sucuri
|
34 |
+
* @subpackage SucuriScanner
|
35 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
36 |
+
* @copyright 2010-2017 Sucuri Inc.
|
37 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
38 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
39 |
*/
|
40 |
class SucuriScanSettingsPosthack extends SucuriScanSettings
|
41 |
{
|
55 |
// Update all WordPress secret keys.
|
56 |
if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':update_wpconfig')) {
|
57 |
if (SucuriScanRequest::post(':process_form') != 1) {
|
58 |
+
SucuriScanInterface::error('You need to confirm that you understand the risk of this operation.');
|
59 |
} else {
|
60 |
$wpconfig_process = SucuriScanEvent::setNewConfigKeys();
|
61 |
|
62 |
if (!$wpconfig_process) {
|
63 |
+
SucuriScanInterface::error('WordPress configuration file was not found.');
|
64 |
} elseif ($wpconfig_process['updated']) {
|
65 |
SucuriScanEvent::reportNoticeEvent('Generate new security keys (success)');
|
66 |
+
SucuriScanInterface::info('Secret keys updated successfully (summary of the operation bellow).');
|
67 |
|
68 |
$params['WPConfigUpdate.Visibility'] = 'visible';
|
69 |
$params['WPConfigUpdate.NewConfig'] .= "/* Old Security Keys */\n";
|
73 |
$params['WPConfigUpdate.NewConfig'] .= $wpconfig_process['new_keys_string'];
|
74 |
} else {
|
75 |
SucuriScanEvent::reportNoticeEvent('Generate new security keys (failure)');
|
76 |
+
SucuriScanInterface::error('WordPress configuration file is not writable.');
|
77 |
|
78 |
$params['WPConfigUpdate.Visibility'] = 'visible';
|
79 |
$params['WPConfigUpdate.NewConfig'] = $wpconfig_process['new_wpconfig'];
|
88 |
foreach ($key_list as $key_name => $key_value) {
|
89 |
switch ($key_status) {
|
90 |
case 'good':
|
91 |
+
$key_status_text = 'good';
|
92 |
break;
|
93 |
|
94 |
case 'bad':
|
95 |
+
$key_status_text = 'not randomized';
|
96 |
break;
|
97 |
|
98 |
case 'missing':
|
99 |
$key_value = '';
|
100 |
+
$key_status_text = '(not set)';
|
101 |
break;
|
102 |
}
|
103 |
|
104 |
if (isset($key_status_text)) {
|
105 |
+
$params['SecurityKeys.List'] .= SucuriScanTemplate::getSnippet(
|
106 |
+
'settings-posthack-security-keys',
|
107 |
+
array(
|
108 |
+
'SecurityKey.KeyName' => $key_name,
|
109 |
+
'SecurityKey.KeyValue' => $key_value,
|
110 |
+
'SecurityKey.KeyStatusText' => $key_status_text,
|
111 |
+
)
|
112 |
+
);
|
113 |
}
|
114 |
}
|
115 |
}
|
136 |
$user_list = array();
|
137 |
$page_number = SucuriScanTemplate::pageNumber();
|
138 |
$max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
139 |
+
$dbquery = new WP_User_Query(
|
140 |
+
array(
|
141 |
+
'number' => $max_per_page,
|
142 |
+
'offset' => ($page_number - 1) * $max_per_page,
|
143 |
+
'fields' => 'all_with_meta',
|
144 |
+
'orderby' => 'ID',
|
145 |
+
)
|
146 |
+
);
|
147 |
|
148 |
// Retrieve the results and build the pagination links.
|
149 |
if ($dbquery) {
|
167 |
$user->user_registered_formatted = SucuriScan::datetime($user->user_registered_timestamp);
|
168 |
$disabled = ($user->user_login == $session->user_login) ? 'disabled' : '';
|
169 |
|
170 |
+
$params['ResetPassword.UserList'] .= SucuriScanTemplate::getSnippet(
|
171 |
+
'settings-posthack-reset-password',
|
172 |
+
array(
|
173 |
+
'ResetPassword.UserID' => $user->ID,
|
174 |
+
'ResetPassword.Username' => $user->user_login,
|
175 |
+
'ResetPassword.Email' => $user->user_email,
|
176 |
+
'ResetPassword.Registered' => $user->user_registered_formatted,
|
177 |
+
'ResetPassword.Roles' => @implode(', ', $user->roles),
|
178 |
+
'ResetPassword.Disabled' => $disabled,
|
179 |
+
)
|
180 |
+
);
|
181 |
}
|
182 |
}
|
183 |
|
186 |
|
187 |
/**
|
188 |
* Sets a new password for the specified user account.
|
189 |
+
*
|
190 |
+
* @return void
|
191 |
*/
|
192 |
public static function resetPasswordAjax()
|
193 |
{
|
195 |
return;
|
196 |
}
|
197 |
|
198 |
+
$response = 'Error';
|
199 |
$user_id = intval(SucuriScanRequest::post('user_id'));
|
200 |
|
201 |
if (SucuriScanEvent::setNewPassword($user_id)) {
|
202 |
+
$response = 'Done';
|
203 |
SucuriScanEvent::reportNoticeEvent('Password changed for user #' . $user_id);
|
204 |
}
|
205 |
|
208 |
|
209 |
/**
|
210 |
* Reset all the FREE plugins, even if they are not activated.
|
211 |
+
*
|
212 |
+
* @return void
|
213 |
*/
|
214 |
public static function resetPlugins()
|
215 |
{
|
216 |
$params = array(
|
217 |
'ResetPlugin.PluginList' => '',
|
218 |
+
'ResetPlugin.CacheLifeTime' => 'unknown',
|
219 |
);
|
220 |
|
221 |
if (defined('SUCURISCAN_GET_PLUGINS_LIFETIME')) {
|
227 |
|
228 |
/**
|
229 |
* Find and list available updates for plugins and themes.
|
230 |
+
*
|
231 |
+
* @return void
|
232 |
*/
|
233 |
public static function availableUpdates()
|
234 |
{
|
239 |
|
240 |
/**
|
241 |
* Process the Ajax request to retrieve the plugins metadata.
|
242 |
+
*
|
243 |
+
* @return void
|
244 |
*/
|
245 |
public static function getPluginsAjax()
|
246 |
{
|
255 |
$plugin_type_class = ( $plugin_data['PluginType'] == 'free' ) ? 'primary' : 'warning';
|
256 |
$input_disabled = ( $plugin_data['PluginType'] == 'free' ) ? '' : 'disabled="disabled"';
|
257 |
$plugin_status_class = $plugin_data['IsPluginActive'] ? 'success' : 'default';
|
258 |
+
$plugin_status = $plugin_data['IsPluginActive'] ? 'active' : 'not active';
|
259 |
+
|
260 |
+
$response .= SucuriScanTemplate::getSnippet(
|
261 |
+
'settings-posthack-reset-plugins',
|
262 |
+
array(
|
263 |
+
'ResetPlugin.Disabled' => $input_disabled,
|
264 |
+
'ResetPlugin.Path' => $plugin_path,
|
265 |
+
'ResetPlugin.Unique' => crc32($plugin_path),
|
266 |
+
'ResetPlugin.Repository' => $plugin_data['Repository'],
|
267 |
+
'ResetPlugin.Plugin' => SucuriScan::excerpt($plugin_data['Name'], 60),
|
268 |
+
'ResetPlugin.Version' => $plugin_data['Version'],
|
269 |
+
'ResetPlugin.Type' => $plugin_data['PluginType'],
|
270 |
+
'ResetPlugin.TypeClass' => $plugin_type_class,
|
271 |
+
'ResetPlugin.Status' => $plugin_status,
|
272 |
+
'ResetPlugin.StatusClass' => $plugin_status_class,
|
273 |
+
)
|
274 |
+
);
|
275 |
}
|
276 |
|
277 |
wp_send_json($response, true);
|
279 |
|
280 |
/**
|
281 |
* Process the Ajax request to reset one free plugin.
|
282 |
+
*
|
283 |
+
* @return void
|
284 |
*/
|
285 |
public static function resetPluginAjax()
|
286 |
{
|
295 |
/* Check if the plugin actually exists */
|
296 |
if (!array_key_exists($plugin, $allPlugins)) {
|
297 |
$response = '<span class="sucuriscan-label-default">'
|
298 |
+
. 'not installed' . '</span>';
|
299 |
} elseif ($allPlugins[$plugin]['IsFreePlugin'] !== true) {
|
300 |
// Ignore plugins not listed in the WordPress repository.
|
301 |
// This usually applies to premium plugins. They cannot be downloaded from
|
302 |
// a reliable source because we can't check the checksum of the files nor
|
303 |
// we can verify if the installation of the new code will work or not.
|
304 |
$response = '<span class="sucuriscan-label-danger">'
|
305 |
+
. 'Plugin is Premium' . '</span>';
|
306 |
} elseif (!is_writable($allPlugins[$plugin]['InstallationPath'])) {
|
307 |
$response = '<span class="sucuriscan-label-danger">'
|
308 |
+
. 'Not Writable' . '</span>';
|
309 |
} elseif (!class_exists('SucuriScanPluginInstallerSkin')) {
|
310 |
$response = '<span class="sucuriscan-label-danger">'
|
311 |
+
. 'Missing Library' . '</span>';
|
312 |
} else {
|
313 |
// Get data associated to the plugin.
|
314 |
$data = $allPlugins[$plugin];
|
318 |
|
319 |
if (!$info) {
|
320 |
$response = '<span class="sucuriscan-label-danger">'
|
321 |
+
. 'Cannot Download' . '</span>';
|
322 |
} elseif (!rename($data['InstallationPath'], $newpath)) {
|
323 |
$response = '<span class="sucuriscan-label-danger">'
|
324 |
+
. 'Cannot Backup' . '</span>';
|
325 |
} else {
|
326 |
ob_start();
|
327 |
$upgrader_skin = new SucuriScanPluginInstallerSkin();
|
334 |
/* Revert backup to its original location */
|
335 |
@rename($newpath, $data['InstallationPath']);
|
336 |
$response = '<span class="sucuriscan-label-danger">'
|
337 |
+
. 'Cannot Install' . '</span>';
|
338 |
} else {
|
339 |
/* Destroy the backup of the plugin */
|
340 |
$fifo = new SucuriScanFileInfo();
|
343 |
$fifo->skip_directories = false;
|
344 |
$fifo->removeDirectoryTree($newpath);
|
345 |
|
346 |
+
$installed = 'Installed v' . SucuriScan::escape($info['version']);
|
|
|
|
|
|
|
347 |
$response = '<span class="sucuriscan-label-success">' . $installed . '</span>';
|
348 |
}
|
349 |
}
|
355 |
/**
|
356 |
* Retrieve the information for the available updates.
|
357 |
*
|
358 |
+
* @param bool $send_email Sends the available updates via email.
|
359 |
+
* @return string|bool HTML code for a table with the updates information.
|
360 |
*/
|
361 |
public static function availableUpdatesContent($send_email = false)
|
362 |
{
|
378 |
'Update.IconType' => 'plugins',
|
379 |
'Update.Extension' => SucuriScan::excerpt($data->Name, 35),
|
380 |
'Update.Version' => $data->Version,
|
381 |
+
'Update.NewVersion' => 'unknown',
|
382 |
+
'Update.TestedWith' => 'unknown',
|
383 |
+
'Update.ArchiveUrl' => 'unknown',
|
384 |
+
'Update.MarketUrl' => 'unknown',
|
385 |
);
|
386 |
|
387 |
if (property_exists($data->update, 'new_version')) {
|
410 |
|
411 |
if (is_array($updates) && !empty($updates)) {
|
412 |
foreach ($updates as $data) {
|
413 |
+
$response .= SucuriScanTemplate::getSnippet(
|
414 |
+
'settings-posthack-available-updates',
|
415 |
+
array(
|
416 |
+
'Update.IconType' => 'appearance',
|
417 |
+
'Update.Extension' => SucuriScan::excerpt($data->Name, 35),
|
418 |
+
'Update.Version' => $data->Version,
|
419 |
+
'Update.NewVersion' => $data->update['new_version'],
|
420 |
+
'Update.TestedWith' => 'Newest WordPress',
|
421 |
+
'Update.ArchiveUrl' => $data->update['package'],
|
422 |
+
'Update.MarketUrl' => $data->update['url'],
|
423 |
+
)
|
424 |
+
);
|
425 |
}
|
426 |
}
|
427 |
|
443 |
|
444 |
/**
|
445 |
* Process the Ajax request to retrieve the available updates.
|
446 |
+
*
|
447 |
+
* @return void
|
448 |
*/
|
449 |
public static function availableUpdatesAjax()
|
450 |
{
|
455 |
$response = SucuriScanSettingsPosthack::availableUpdatesContent();
|
456 |
|
457 |
if (!$response) {
|
458 |
+
$response = '<tr><td colspan="5">' . 'There are no updates available.' . '</td></tr>';
|
459 |
}
|
460 |
|
461 |
wp_send_json($response, 200);
|
src/settings-scanner.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-scanner.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,14 +24,22 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
/**
|
20 |
* Returns the HTML to configure the scanner.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
*/
|
22 |
class SucuriScanSettingsScanner extends SucuriScanSettings
|
23 |
{
|
24 |
/**
|
25 |
* Renders a page with information about the cronjobs feature.
|
26 |
*
|
27 |
-
* @param
|
28 |
-
* @return string
|
29 |
*/
|
30 |
public static function cronjobs($nonce)
|
31 |
{
|
@@ -41,8 +55,9 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
41 |
$allowed_actions[] = 'runnow'; /* execute in the next 10 seconds */
|
42 |
$allowed_actions[] = 'remove'; /* can be reinstalled automatically */
|
43 |
$allowed_actions = sprintf('(%s)', implode('|', $allowed_actions));
|
|
|
44 |
|
45 |
-
if ($cronjob_action
|
46 |
$cronjobs = SucuriScanRequest::post(':cronjobs', '_array');
|
47 |
|
48 |
if (!empty($cronjobs)) {
|
@@ -50,43 +65,55 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
50 |
|
51 |
if ($cronjob_action == 'runnow') {
|
52 |
/* Force execution of the selected scheduled tasks. */
|
53 |
-
SucuriScanInterface::info(
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
61 |
|
62 |
foreach ($cronjobs as $task_name) {
|
63 |
wp_schedule_single_event(time() + 10, $task_name);
|
64 |
}
|
65 |
} elseif ($cronjob_action == 'remove' || $cronjob_action == '_oneoff') {
|
66 |
/* Force deletion of the selected scheduled tasks. */
|
67 |
-
SucuriScanInterface::info(
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
75 |
|
76 |
foreach ($cronjobs as $task_name) {
|
77 |
wp_clear_scheduled_hook($task_name);
|
78 |
}
|
79 |
} else {
|
80 |
-
SucuriScanInterface::info(
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
90 |
|
91 |
foreach ($cronjobs as $task_name) {
|
92 |
$next_due = wp_next_scheduled($task_name);
|
@@ -94,7 +121,7 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
94 |
}
|
95 |
}
|
96 |
} else {
|
97 |
-
SucuriScanInterface::error(
|
98 |
}
|
99 |
}
|
100 |
}
|
@@ -104,7 +131,7 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
104 |
|
105 |
/* Hardcode the first one to allow the immediate execution of the cronjob(s) */
|
106 |
$params['Cronjob.Schedules'] .= '<option value="runnow">'
|
107 |
-
.
|
108 |
|
109 |
foreach ($available as $freq => $name) {
|
110 |
$params['Cronjob.Schedules'] .= sprintf('<option value="%s">%s</option>', $freq, $name);
|
@@ -118,14 +145,16 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
118 |
}
|
119 |
|
120 |
$params['Cronjobs.Total'] += 1;
|
121 |
-
$params['Cronjobs.List'] .=
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
|
|
|
|
129 |
}
|
130 |
}
|
131 |
}
|
@@ -136,49 +165,6 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
136 |
return SucuriScanTemplate::getSection('settings-scanner-cronjobs', $params);
|
137 |
}
|
138 |
|
139 |
-
/**
|
140 |
-
* Returns a list of directories in the website.
|
141 |
-
*/
|
142 |
-
public static function ignoreFoldersAjax()
|
143 |
-
{
|
144 |
-
if (SucuriScanRequest::post('form_action') !== 'get_ignored_files') {
|
145 |
-
return;
|
146 |
-
}
|
147 |
-
|
148 |
-
$response = ''; /* request response */
|
149 |
-
$ignored_dirs = SucuriScanFSScanner::getIgnoredDirectoriesLive();
|
150 |
-
|
151 |
-
foreach ($ignored_dirs as $group => $dir_list) {
|
152 |
-
foreach ($dir_list as $dir_data) {
|
153 |
-
$valid_entry = false;
|
154 |
-
$snippet = array(
|
155 |
-
'IgnoreScan.Directory' => '',
|
156 |
-
'IgnoreScan.DirectoryPath' => '',
|
157 |
-
'IgnoreScan.IgnoredAt' => '',
|
158 |
-
'IgnoreScan.IgnoredAtText' => __('Okay', SUCURISCAN_TEXTDOMAIN),
|
159 |
-
);
|
160 |
-
|
161 |
-
if ($group == 'is_ignored') {
|
162 |
-
$valid_entry = true;
|
163 |
-
$snippet['IgnoreScan.Directory'] = urlencode($dir_data['directory_path']);
|
164 |
-
$snippet['IgnoreScan.DirectoryPath'] = $dir_data['directory_path'];
|
165 |
-
$snippet['IgnoreScan.IgnoredAt'] = SucuriScan::datetime($dir_data['ignored_at']);
|
166 |
-
$snippet['IgnoreScan.IgnoredAtText'] = __('Ignored', SUCURISCAN_TEXTDOMAIN);
|
167 |
-
} elseif ($group == 'is_not_ignored') {
|
168 |
-
$valid_entry = true;
|
169 |
-
$snippet['IgnoreScan.Directory'] = urlencode($dir_data);
|
170 |
-
$snippet['IgnoreScan.DirectoryPath'] = $dir_data;
|
171 |
-
}
|
172 |
-
|
173 |
-
if ($valid_entry) {
|
174 |
-
$response .= SucuriScanTemplate::getSnippet('settings-scanner-ignore-folders', $snippet);
|
175 |
-
}
|
176 |
-
}
|
177 |
-
}
|
178 |
-
|
179 |
-
wp_send_json($response, true);
|
180 |
-
}
|
181 |
-
|
182 |
/**
|
183 |
* Returns the HTML for the folder scanner skipper.
|
184 |
*
|
@@ -187,63 +173,55 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
187 |
* directories with media files like images, audio, videos, etc and directories
|
188 |
* used to store cache data.
|
189 |
*
|
190 |
-
* @param
|
191 |
-
* @return string
|
192 |
*/
|
193 |
public static function ignoreFolders($nonce)
|
194 |
{
|
195 |
$params = array();
|
196 |
|
197 |
-
|
198 |
-
// Ignore a new directory path for the file system scans.
|
199 |
-
if ($action = SucuriScanRequest::post(':ignorescanning_action', '(ignore|unignore)')) {
|
200 |
-
$ign_dirs = SucuriScanRequest::post(':ignorescanning_dirs', '_array');
|
201 |
-
$ign_file = SucuriScanRequest::post(':ignorescanning_file');
|
202 |
-
|
203 |
-
if ($action == 'ignore') {
|
204 |
-
// Target a single file path to be ignored.
|
205 |
-
if ($ign_file !== false) {
|
206 |
-
$ign_dirs = array($ign_file);
|
207 |
-
unset($_POST['sucuriscan_ignorescanning_file']);
|
208 |
-
}
|
209 |
-
|
210 |
-
// Target a list of directories to be ignored.
|
211 |
-
if (is_array($ign_dirs) && !empty($ign_dirs)) {
|
212 |
-
$were_ignored = array();
|
213 |
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
) {
|
218 |
-
$were_ignored[] = $resource_path;
|
219 |
-
}
|
220 |
-
}
|
221 |
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
@implode(',', $ign_dirs)
|
227 |
-
));
|
228 |
-
}
|
229 |
-
}
|
230 |
-
} elseif ($action == 'unignore'
|
231 |
-
&& is_array($ign_dirs)
|
232 |
-
&& !empty($ign_dirs)
|
233 |
-
) {
|
234 |
-
foreach ($ign_dirs as $directory_path) {
|
235 |
-
SucuriScanFSScanner::unignoreDirectory($directory_path);
|
236 |
-
}
|
237 |
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
@implode(',', $ign_dirs)
|
242 |
-
));
|
243 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
}
|
245 |
}
|
246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
return SucuriScanTemplate::getSection('settings-scanner-ignore-folders', $params);
|
248 |
}
|
249 |
}
|
3 |
/**
|
4 |
* Code related to the settings-scanner.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
/**
|
26 |
* Returns the HTML to configure the scanner.
|
27 |
+
*
|
28 |
+
* @category Library
|
29 |
+
* @package Sucuri
|
30 |
+
* @subpackage SucuriScanner
|
31 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
32 |
+
* @copyright 2010-2017 Sucuri Inc.
|
33 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
34 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
35 |
*/
|
36 |
class SucuriScanSettingsScanner extends SucuriScanSettings
|
37 |
{
|
38 |
/**
|
39 |
* Renders a page with information about the cronjobs feature.
|
40 |
*
|
41 |
+
* @param bool $nonce True if the CSRF protection worked.
|
42 |
+
* @return string Page with information about the cronjobs.
|
43 |
*/
|
44 |
public static function cronjobs($nonce)
|
45 |
{
|
55 |
$allowed_actions[] = 'runnow'; /* execute in the next 10 seconds */
|
56 |
$allowed_actions[] = 'remove'; /* can be reinstalled automatically */
|
57 |
$allowed_actions = sprintf('(%s)', implode('|', $allowed_actions));
|
58 |
+
$cronjob_action = SucuriScanRequest::post(':cronjob_action', $allowed_actions);
|
59 |
|
60 |
+
if ($cronjob_action) {
|
61 |
$cronjobs = SucuriScanRequest::post(':cronjobs', '_array');
|
62 |
|
63 |
if (!empty($cronjobs)) {
|
65 |
|
66 |
if ($cronjob_action == 'runnow') {
|
67 |
/* Force execution of the selected scheduled tasks. */
|
68 |
+
SucuriScanInterface::info(
|
69 |
+
sprintf(
|
70 |
+
'%d tasks has been scheduled to run in the next ten seconds.',
|
71 |
+
$total_tasks /* some cronjobs will be ignored */
|
72 |
+
)
|
73 |
+
);
|
74 |
+
SucuriScanEvent::reportNoticeEvent(
|
75 |
+
sprintf(
|
76 |
+
'Force execution of scheduled tasks: (multiple entries): %s',
|
77 |
+
@implode(',', $cronjobs)
|
78 |
+
)
|
79 |
+
);
|
80 |
|
81 |
foreach ($cronjobs as $task_name) {
|
82 |
wp_schedule_single_event(time() + 10, $task_name);
|
83 |
}
|
84 |
} elseif ($cronjob_action == 'remove' || $cronjob_action == '_oneoff') {
|
85 |
/* Force deletion of the selected scheduled tasks. */
|
86 |
+
SucuriScanInterface::info(
|
87 |
+
sprintf(
|
88 |
+
'%d scheduled tasks have been removed.',
|
89 |
+
$total_tasks /* some cronjobs will be ignored */
|
90 |
+
)
|
91 |
+
);
|
92 |
+
SucuriScanEvent::reportNoticeEvent(
|
93 |
+
sprintf(
|
94 |
+
'Delete scheduled tasks: (multiple entries): %s',
|
95 |
+
@implode(',', $cronjobs)
|
96 |
+
)
|
97 |
+
);
|
98 |
|
99 |
foreach ($cronjobs as $task_name) {
|
100 |
wp_clear_scheduled_hook($task_name);
|
101 |
}
|
102 |
} else {
|
103 |
+
SucuriScanInterface::info(
|
104 |
+
sprintf(
|
105 |
+
'%d tasks has been re-scheduled to run <code>%s</code>.',
|
106 |
+
$total_tasks, /* some cronjobs will be ignored */
|
107 |
+
$cronjob_action /* frequency to run cronjob */
|
108 |
+
)
|
109 |
+
);
|
110 |
+
SucuriScanEvent::reportNoticeEvent(
|
111 |
+
sprintf(
|
112 |
+
'Re-configure scheduled tasks %s: (multiple entries): %s',
|
113 |
+
$cronjob_action,
|
114 |
+
@implode(',', $cronjobs)
|
115 |
+
)
|
116 |
+
);
|
117 |
|
118 |
foreach ($cronjobs as $task_name) {
|
119 |
$next_due = wp_next_scheduled($task_name);
|
121 |
}
|
122 |
}
|
123 |
} else {
|
124 |
+
SucuriScanInterface::error('No scheduled tasks were selected from the list.');
|
125 |
}
|
126 |
}
|
127 |
}
|
131 |
|
132 |
/* Hardcode the first one to allow the immediate execution of the cronjob(s) */
|
133 |
$params['Cronjob.Schedules'] .= '<option value="runnow">'
|
134 |
+
. 'Execute Now (in +10 seconds)' . '</option>';
|
135 |
|
136 |
foreach ($available as $freq => $name) {
|
137 |
$params['Cronjob.Schedules'] .= sprintf('<option value="%s">%s</option>', $freq, $name);
|
145 |
}
|
146 |
|
147 |
$params['Cronjobs.Total'] += 1;
|
148 |
+
$params['Cronjobs.List'] .= SucuriScanTemplate::getSnippet(
|
149 |
+
'settings-scanner-cronjobs',
|
150 |
+
array(
|
151 |
+
'Cronjob.Hook' => $hook,
|
152 |
+
'Cronjob.Schedule' => $event['schedule'],
|
153 |
+
'Cronjob.NextTime' => SucuriScan::datetime($timestamp),
|
154 |
+
'Cronjob.NextTimeHuman' => SucuriScan::humanTime($timestamp),
|
155 |
+
'Cronjob.Arguments' => SucuriScan::implode(', ', $event['args']),
|
156 |
+
)
|
157 |
+
);
|
158 |
}
|
159 |
}
|
160 |
}
|
165 |
return SucuriScanTemplate::getSection('settings-scanner-cronjobs', $params);
|
166 |
}
|
167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
/**
|
169 |
* Returns the HTML for the folder scanner skipper.
|
170 |
*
|
173 |
* directories with media files like images, audio, videos, etc and directories
|
174 |
* used to store cache data.
|
175 |
*
|
176 |
+
* @param bool $nonce True if the CSRF protection worked, false otherwise.
|
177 |
+
* @return string HTML for the folder scanner skipper.
|
178 |
*/
|
179 |
public static function ignoreFolders($nonce)
|
180 |
{
|
181 |
$params = array();
|
182 |
|
183 |
+
$params['IgnoreScan.List'] = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
|
185 |
+
if ($nonce) {
|
186 |
+
$ign_ress = SucuriScanRequest::post(':ignorefolder');
|
187 |
+
$ign_dirs = SucuriScanRequest::post(':unignorefolders', '_array');
|
|
|
|
|
|
|
|
|
188 |
|
189 |
+
if ($ign_ress !== false && SucuriScanFSScanner::ignoreDirectory($ign_ress)) {
|
190 |
+
SucuriScanInterface::info('Selected files have been successfully processed.');
|
191 |
+
SucuriScanEvent::reportWarningEvent('This directory will not be scanned: ' . $ign_ress);
|
192 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
|
194 |
+
if ($ign_dirs !== false && is_array($ign_dirs) && !empty($ign_dirs)) {
|
195 |
+
foreach ($ign_dirs as $dir) {
|
196 |
+
SucuriScanFSScanner::unignoreDirectory($dir);
|
|
|
|
|
197 |
}
|
198 |
+
|
199 |
+
SucuriScanInterface::info('Selected files have been successfully processed.');
|
200 |
+
SucuriScanEvent::reportNoticeEvent(
|
201 |
+
'Directories will be scanned: (multiple entries): '
|
202 |
+
. @implode(',', $ign_dirs) /* all directories */
|
203 |
+
);
|
204 |
}
|
205 |
}
|
206 |
|
207 |
+
$ignored_dirs = SucuriScanFSScanner::getIgnoredDirectories();
|
208 |
+
|
209 |
+
foreach ($ignored_dirs['directories'] as $index => $folder) {
|
210 |
+
$ts = $ignored_dirs['ignored_at_list'][$index];
|
211 |
+
|
212 |
+
$params['IgnoreScan.List'] .= SucuriScanTemplate::getSnippet(
|
213 |
+
'settings-scanner-ignore-folders',
|
214 |
+
array(
|
215 |
+
'IgnoreScan.Directory' => $folder,
|
216 |
+
'IgnoreScan.IgnoredAt' => SucuriScan::datetime($ts),
|
217 |
+
)
|
218 |
+
);
|
219 |
+
}
|
220 |
+
|
221 |
+
if (empty($ignored_dirs['directories'])) {
|
222 |
+
$params['IgnoreScan.List'] .= '<tr><td colspan="3">no data available</td></tr>';
|
223 |
+
}
|
224 |
+
|
225 |
return SucuriScanTemplate::getSection('settings-scanner-ignore-folders', $params);
|
226 |
}
|
227 |
}
|
src/settings-webinfo.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings-webinfo.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -23,25 +29,19 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
23 |
*/
|
24 |
function sucuriscan_settings_webinfo_details()
|
25 |
{
|
26 |
-
|
27 |
-
|
28 |
-
$params = array(
|
29 |
-
'ServerInfo.Variables' => '',
|
30 |
-
);
|
31 |
-
|
32 |
$info_vars = array(
|
33 |
'Plugin_version' => SUCURISCAN_VERSION,
|
34 |
'Last_filesystem_scan' => SucuriScanFSScanner::getFilesystemRuntime(true),
|
35 |
'Datetime_and_Timezone' => '',
|
36 |
'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE * 8),
|
37 |
-
'Server' =>
|
38 |
-
'WordPress_debug' =>
|
39 |
-
'Memory_usage' =>
|
40 |
-
'MySQL_version' => '0.0',
|
41 |
-
'SQL_mode' => __('NotSet', SUCURISCAN_TEXTDOMAIN),
|
42 |
'PHP_version' => PHP_VERSION,
|
43 |
);
|
44 |
|
|
|
45 |
$info_vars['Datetime_and_Timezone'] = sprintf(
|
46 |
'%s (%s)',
|
47 |
SucuriScan::datetime(),
|
@@ -49,7 +49,7 @@ function sucuriscan_settings_webinfo_details()
|
|
49 |
);
|
50 |
|
51 |
if (defined('WP_DEBUG') && WP_DEBUG) {
|
52 |
-
$info_vars['WordPress_debug'] =
|
53 |
}
|
54 |
|
55 |
if (function_exists('memory_get_usage')) {
|
@@ -60,15 +60,6 @@ function sucuriscan_settings_webinfo_details()
|
|
60 |
$info_vars['Server'] = $_SERVER['SERVER_SOFTWARE'];
|
61 |
}
|
62 |
|
63 |
-
if ($wpdb) {
|
64 |
-
$info_vars['MySQL_version'] = $wpdb->get_var('SELECT VERSION() AS version');
|
65 |
-
|
66 |
-
$mysql_info = $wpdb->get_results('SHOW VARIABLES LIKE "sql_mode"');
|
67 |
-
if (is_array($mysql_info) && !empty($mysql_info[0]->Value)) {
|
68 |
-
$info_vars['SQL_mode'] = $mysql_info[0]->Value;
|
69 |
-
}
|
70 |
-
}
|
71 |
-
|
72 |
/* PHP INI Settings */
|
73 |
$field_names = array(
|
74 |
'safe_mode',
|
@@ -106,11 +97,13 @@ function sucuriscan_settings_webinfo_details()
|
|
106 |
foreach ($info_vars as $var_name => $var_value) {
|
107 |
$var_name = str_replace('_', "\x20", $var_name);
|
108 |
|
109 |
-
$params['ServerInfo.Variables'] .=
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
|
|
|
|
114 |
}
|
115 |
|
116 |
return SucuriScanTemplate::getSection('settings-webinfo-details', $params);
|
@@ -131,7 +124,7 @@ function sucuriscan_settings_webinfo_htaccess()
|
|
131 |
'HTAccess.StandardVisible' => 'hidden',
|
132 |
'HTAccess.NotFoundVisible' => 'hidden',
|
133 |
'HTAccess.FoundVisible' => 'hidden',
|
134 |
-
'HTAccess.Fpath' =>
|
135 |
);
|
136 |
|
137 |
if ($htaccess) {
|
@@ -165,7 +158,9 @@ function sucuriscan_settings_webinfo_htaccess()
|
|
165 |
function sucuriscan_htaccess_is_standard($rules = '')
|
166 |
{
|
167 |
if (!$rules) {
|
168 |
-
|
|
|
|
|
169 |
$rules = SucuriScanFileInfo::fileContent($htaccess);
|
170 |
}
|
171 |
}
|
3 |
/**
|
4 |
* Code related to the settings-webinfo.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
29 |
*/
|
30 |
function sucuriscan_settings_webinfo_details()
|
31 |
{
|
32 |
+
$params = array();
|
|
|
|
|
|
|
|
|
|
|
33 |
$info_vars = array(
|
34 |
'Plugin_version' => SUCURISCAN_VERSION,
|
35 |
'Last_filesystem_scan' => SucuriScanFSScanner::getFilesystemRuntime(true),
|
36 |
'Datetime_and_Timezone' => '',
|
37 |
'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE * 8),
|
38 |
+
'Server' => 'unknown',
|
39 |
+
'WordPress_debug' => 'not active',
|
40 |
+
'Memory_usage' => 'unknown',
|
|
|
|
|
41 |
'PHP_version' => PHP_VERSION,
|
42 |
);
|
43 |
|
44 |
+
$params['ServerInfo.Variables'] = '';
|
45 |
$info_vars['Datetime_and_Timezone'] = sprintf(
|
46 |
'%s (%s)',
|
47 |
SucuriScan::datetime(),
|
49 |
);
|
50 |
|
51 |
if (defined('WP_DEBUG') && WP_DEBUG) {
|
52 |
+
$info_vars['WordPress_debug'] = 'active';
|
53 |
}
|
54 |
|
55 |
if (function_exists('memory_get_usage')) {
|
60 |
$info_vars['Server'] = $_SERVER['SERVER_SOFTWARE'];
|
61 |
}
|
62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
/* PHP INI Settings */
|
64 |
$field_names = array(
|
65 |
'safe_mode',
|
97 |
foreach ($info_vars as $var_name => $var_value) {
|
98 |
$var_name = str_replace('_', "\x20", $var_name);
|
99 |
|
100 |
+
$params['ServerInfo.Variables'] .= SucuriScanTemplate::getSnippet(
|
101 |
+
'settings-webinfo-details',
|
102 |
+
array(
|
103 |
+
'ServerInfo.Title' => $var_name,
|
104 |
+
'ServerInfo.Value' => $var_value,
|
105 |
+
)
|
106 |
+
);
|
107 |
}
|
108 |
|
109 |
return SucuriScanTemplate::getSection('settings-webinfo-details', $params);
|
124 |
'HTAccess.StandardVisible' => 'hidden',
|
125 |
'HTAccess.NotFoundVisible' => 'hidden',
|
126 |
'HTAccess.FoundVisible' => 'hidden',
|
127 |
+
'HTAccess.Fpath' => 'unknown',
|
128 |
);
|
129 |
|
130 |
if ($htaccess) {
|
158 |
function sucuriscan_htaccess_is_standard($rules = '')
|
159 |
{
|
160 |
if (!$rules) {
|
161 |
+
$htaccess = SucuriScan::getHtaccessPath();
|
162 |
+
|
163 |
+
if ($htaccess) {
|
164 |
$rules = SucuriScanFileInfo::fileContent($htaccess);
|
165 |
}
|
166 |
}
|
src/settings.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the settings.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -18,6 +24,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
18 |
|
19 |
/**
|
20 |
* Abstract class for the settings page.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
*/
|
22 |
class SucuriScanSettings extends SucuriScanOption
|
23 |
{
|
3 |
/**
|
4 |
* Code related to the settings.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
24 |
|
25 |
/**
|
26 |
* Abstract class for the settings page.
|
27 |
+
*
|
28 |
+
* @category Library
|
29 |
+
* @package Sucuri
|
30 |
+
* @subpackage SucuriScanner
|
31 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
32 |
+
* @copyright 2010-2017 Sucuri Inc.
|
33 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
34 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
35 |
*/
|
36 |
class SucuriScanSettings extends SucuriScanOption
|
37 |
{
|
src/sitecheck.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the sitecheck.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -28,7 +34,14 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
28 |
* operation to finish, otherwise the scanner will return innacurate
|
29 |
* information.
|
30 |
*
|
31 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
*/
|
33 |
class SucuriScanSiteCheck extends SucuriScanAPI
|
34 |
{
|
@@ -39,14 +52,14 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
39 |
*/
|
40 |
private static function targetURL()
|
41 |
{
|
42 |
-
$url = SucuriScan::getDomain();
|
43 |
-
|
44 |
/* allow to set a custom URL for the scans */
|
45 |
-
|
|
|
|
|
46 |
return $custom;
|
47 |
}
|
48 |
|
49 |
-
return
|
50 |
}
|
51 |
|
52 |
/**
|
@@ -54,8 +67,8 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
54 |
*
|
55 |
* @see https://sitecheck.sucuri.net/
|
56 |
*
|
57 |
-
* @param
|
58 |
-
* @return array|bool
|
59 |
*/
|
60 |
public static function runMalwareScan($clear = false)
|
61 |
{
|
@@ -208,11 +221,13 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
208 |
continue;
|
209 |
}
|
210 |
|
211 |
-
$params['SiteCheck.Metadata'] .=
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
|
|
|
|
216 |
}
|
217 |
}
|
218 |
|
@@ -231,26 +246,30 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
231 |
|
232 |
$params['Malware.Content'] = '';
|
233 |
$params['Malware.Color'] = 'green';
|
234 |
-
$params['Malware.Title'] =
|
235 |
$params['Malware.CleanVisibility'] = 'visible';
|
236 |
$params['Malware.InfectedVisibility'] = 'hidden';
|
237 |
|
238 |
if (isset($data['MALWARE']['WARN']) && !empty($data['MALWARE']['WARN'])) {
|
239 |
$params['Malware.Color'] = 'red';
|
240 |
-
$params['Malware.Title'] =
|
241 |
$params['Malware.CleanVisibility'] = 'hidden';
|
242 |
$params['Malware.InfectedVisibility'] = 'visible';
|
243 |
|
244 |
foreach ($data['MALWARE']['WARN'] as $mal) {
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
'
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
|
|
|
|
|
|
|
|
254 |
}
|
255 |
}
|
256 |
}
|
@@ -272,7 +291,7 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
272 |
return ''; /* there is not enough information to render */
|
273 |
}
|
274 |
|
275 |
-
$params['Blacklist.Title'] =
|
276 |
$params['Blacklist.Color'] = 'green';
|
277 |
$params['Blacklist.Content'] = '';
|
278 |
|
@@ -285,17 +304,19 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
285 |
substr($info[0], 0, strrpos($info[0], ':'))
|
286 |
);
|
287 |
|
288 |
-
$params['Blacklist.Content'] .=
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
|
|
|
|
294 |
}
|
295 |
}
|
296 |
|
297 |
if (isset($data['BLACKLIST']['WARN'])) {
|
298 |
-
$params['Blacklist.Title'] =
|
299 |
$params['Blacklist.Color'] = 'red';
|
300 |
}
|
301 |
|
@@ -322,12 +343,14 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
322 |
}
|
323 |
|
324 |
$params['Recommendations.Visibility'] = 'visible';
|
325 |
-
$params['Recommendations.Content'] .=
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
|
|
|
|
331 |
}
|
332 |
}
|
333 |
|
@@ -343,10 +366,7 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
343 |
{
|
344 |
$data = self::scanAndCollectData();
|
345 |
|
346 |
-
return sprintf(
|
347 |
-
__('iFramesNum', SUCURISCAN_TEXTDOMAIN),
|
348 |
-
@count($data['LINKS']['IFRAME'])
|
349 |
-
);
|
350 |
}
|
351 |
|
352 |
/**
|
@@ -358,10 +378,7 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
358 |
{
|
359 |
$data = self::scanAndCollectData();
|
360 |
|
361 |
-
return sprintf(
|
362 |
-
__('LinksNum', SUCURISCAN_TEXTDOMAIN),
|
363 |
-
@count($data['LINKS']['URL'])
|
364 |
-
);
|
365 |
}
|
366 |
|
367 |
/**
|
@@ -382,10 +399,7 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
382 |
$total += count($data['LINKS']['JSEXTERNAL']);
|
383 |
}
|
384 |
|
385 |
-
return sprintf(
|
386 |
-
__('ScriptsNum', SUCURISCAN_TEXTDOMAIN),
|
387 |
-
$total
|
388 |
-
);
|
389 |
}
|
390 |
|
391 |
/**
|
@@ -434,8 +448,8 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
434 |
/**
|
435 |
* Extract detailed information from a SiteCheck malware payload.
|
436 |
*
|
437 |
-
* @param
|
438 |
-
* @return array
|
439 |
*/
|
440 |
public static function malwareDetails($malware = array())
|
441 |
{
|
@@ -467,7 +481,7 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
467 |
if (strpos($malware_parts[0], $pattern) !== false) {
|
468 |
$offset = strpos($malware_parts[0], $pattern);
|
469 |
$data['malware_type'] = substr($malware_parts[0], 0, $offset);
|
470 |
-
$data['malware_docs'] = substr($malware_parts[0], $offset+11);
|
471 |
}
|
472 |
|
473 |
$data['malware_payload'] = trim($malware_parts[1]);
|
@@ -484,6 +498,8 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
484 |
* output it means that XDebug cannot cover the next line, leaving a report
|
485 |
* with a missing line in the coverage. Since the test case takes care of
|
486 |
* the functionality of this code we will assume that it is fully covered.
|
|
|
|
|
487 |
*/
|
488 |
public static function ajaxMalwareScan()
|
489 |
{
|
3 |
/**
|
4 |
* Code related to the sitecheck.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
34 |
* operation to finish, otherwise the scanner will return innacurate
|
35 |
* information.
|
36 |
*
|
37 |
+
* @category Library
|
38 |
+
* @package Sucuri
|
39 |
+
* @subpackage SucuriScanner
|
40 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
41 |
+
* @copyright 2010-2017 Sucuri Inc.
|
42 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
43 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
44 |
+
* @see https://sitecheck.sucuri.net/
|
45 |
*/
|
46 |
class SucuriScanSiteCheck extends SucuriScanAPI
|
47 |
{
|
52 |
*/
|
53 |
private static function targetURL()
|
54 |
{
|
|
|
|
|
55 |
/* allow to set a custom URL for the scans */
|
56 |
+
$custom = SucuriScanOption::getOption(':sitecheck_target');
|
57 |
+
|
58 |
+
if ($custom) {
|
59 |
return $custom;
|
60 |
}
|
61 |
|
62 |
+
return SucuriScan::getDomain();
|
63 |
}
|
64 |
|
65 |
/**
|
67 |
*
|
68 |
* @see https://sitecheck.sucuri.net/
|
69 |
*
|
70 |
+
* @param bool $clear Request the results from a fresh scan or not.
|
71 |
+
* @return array|bool JSON encoded website scan results.
|
72 |
*/
|
73 |
public static function runMalwareScan($clear = false)
|
74 |
{
|
221 |
continue;
|
222 |
}
|
223 |
|
224 |
+
$params['SiteCheck.Metadata'] .= SucuriScanTemplate::getSnippet(
|
225 |
+
'sitecheck-details',
|
226 |
+
array(
|
227 |
+
'SiteCheck.Title' => trim($parts[0]),
|
228 |
+
'SiteCheck.Value' => trim($parts[1]),
|
229 |
+
)
|
230 |
+
);
|
231 |
}
|
232 |
}
|
233 |
|
246 |
|
247 |
$params['Malware.Content'] = '';
|
248 |
$params['Malware.Color'] = 'green';
|
249 |
+
$params['Malware.Title'] = 'Site is Clean';
|
250 |
$params['Malware.CleanVisibility'] = 'visible';
|
251 |
$params['Malware.InfectedVisibility'] = 'hidden';
|
252 |
|
253 |
if (isset($data['MALWARE']['WARN']) && !empty($data['MALWARE']['WARN'])) {
|
254 |
$params['Malware.Color'] = 'red';
|
255 |
+
$params['Malware.Title'] = 'Site is not Clean';
|
256 |
$params['Malware.CleanVisibility'] = 'hidden';
|
257 |
$params['Malware.InfectedVisibility'] = 'visible';
|
258 |
|
259 |
foreach ($data['MALWARE']['WARN'] as $mal) {
|
260 |
+
$info = self::malwareDetails($mal);
|
261 |
+
|
262 |
+
if ($info) {
|
263 |
+
$params['Malware.Content'] .= SucuriScanTemplate::getSnippet(
|
264 |
+
'sitecheck-malware',
|
265 |
+
array(
|
266 |
+
'Malware.InfectedURL' => $info['infected_url'],
|
267 |
+
'Malware.MalwareType' => $info['malware_type'],
|
268 |
+
'Malware.MalwareDocs' => $info['malware_docs'],
|
269 |
+
'Malware.AlertMessage' => $info['alert_message'],
|
270 |
+
'Malware.MalwarePayload' => $info['malware_payload'],
|
271 |
+
)
|
272 |
+
);
|
273 |
}
|
274 |
}
|
275 |
}
|
291 |
return ''; /* there is not enough information to render */
|
292 |
}
|
293 |
|
294 |
+
$params['Blacklist.Title'] = 'Not Blacklisted';
|
295 |
$params['Blacklist.Color'] = 'green';
|
296 |
$params['Blacklist.Content'] = '';
|
297 |
|
304 |
substr($info[0], 0, strrpos($info[0], ':'))
|
305 |
);
|
306 |
|
307 |
+
$params['Blacklist.Content'] .= SucuriScanTemplate::getSnippet(
|
308 |
+
'sitecheck-blacklist',
|
309 |
+
array(
|
310 |
+
'Blacklist.URL' => $url,
|
311 |
+
'Blacklist.Status' => $type,
|
312 |
+
'Blacklist.Service' => $title,
|
313 |
+
)
|
314 |
+
);
|
315 |
}
|
316 |
}
|
317 |
|
318 |
if (isset($data['BLACKLIST']['WARN'])) {
|
319 |
+
$params['Blacklist.Title'] = 'Blacklisted';
|
320 |
$params['Blacklist.Color'] = 'red';
|
321 |
}
|
322 |
|
343 |
}
|
344 |
|
345 |
$params['Recommendations.Visibility'] = 'visible';
|
346 |
+
$params['Recommendations.Content'] .= SucuriScanTemplate::getSnippet(
|
347 |
+
'sitecheck-recommendations',
|
348 |
+
array(
|
349 |
+
'Recommendations.Title' => $recommendation[0],
|
350 |
+
'Recommendations.Value' => $recommendation[1],
|
351 |
+
'Recommendations.URL' => $recommendation[2],
|
352 |
+
)
|
353 |
+
);
|
354 |
}
|
355 |
}
|
356 |
|
366 |
{
|
367 |
$data = self::scanAndCollectData();
|
368 |
|
369 |
+
return sprintf('iFrames: %d', @count($data['LINKS']['IFRAME']));
|
|
|
|
|
|
|
370 |
}
|
371 |
|
372 |
/**
|
378 |
{
|
379 |
$data = self::scanAndCollectData();
|
380 |
|
381 |
+
return sprintf('Links: %d', @count($data['LINKS']['URL']));
|
|
|
|
|
|
|
382 |
}
|
383 |
|
384 |
/**
|
399 |
$total += count($data['LINKS']['JSEXTERNAL']);
|
400 |
}
|
401 |
|
402 |
+
return sprintf('Scripts: %d', $total);
|
|
|
|
|
|
|
403 |
}
|
404 |
|
405 |
/**
|
448 |
/**
|
449 |
* Extract detailed information from a SiteCheck malware payload.
|
450 |
*
|
451 |
+
* @param array $malware Array with two entries with basic malware information.
|
452 |
+
* @return array Detailed information of the malware found by SiteCheck.
|
453 |
*/
|
454 |
public static function malwareDetails($malware = array())
|
455 |
{
|
481 |
if (strpos($malware_parts[0], $pattern) !== false) {
|
482 |
$offset = strpos($malware_parts[0], $pattern);
|
483 |
$data['malware_type'] = substr($malware_parts[0], 0, $offset);
|
484 |
+
$data['malware_docs'] = substr($malware_parts[0], $offset + 11);
|
485 |
}
|
486 |
|
487 |
$data['malware_payload'] = trim($malware_parts[1]);
|
498 |
* output it means that XDebug cannot cover the next line, leaving a report
|
499 |
* with a missing line in the coverage. Since the test case takes care of
|
500 |
* the functionality of this code we will assume that it is fully covered.
|
501 |
+
*
|
502 |
+
* @return void
|
503 |
*/
|
504 |
public static function ajaxMalwareScan()
|
505 |
{
|
src/sucuriscan.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the sucuriscan.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -19,18 +25,28 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
19 |
/**
|
20 |
* Miscellaneous library.
|
21 |
*
|
22 |
-
* Multiple and generic methods that will be used through out the code of
|
23 |
-
*
|
24 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
*/
|
26 |
class SucuriScan
|
27 |
{
|
28 |
/**
|
29 |
* Throw generic exception instead of silent failure for unit-tests.
|
30 |
*
|
31 |
-
* @param string $message Error or information message.
|
32 |
-
* @param string $type Either info or error.
|
33 |
* @throws Exception
|
|
|
|
|
|
|
|
|
34 |
*/
|
35 |
public static function throwException($message, $type = 'error')
|
36 |
{
|
@@ -56,32 +72,31 @@ class SucuriScan
|
|
56 |
* Return name of a variable with the plugin's prefix (if needed).
|
57 |
*
|
58 |
* To facilitate the development, you can prefix the name of the key in the
|
59 |
-
* request (when accessing it) with a single colon, this method will
|
60 |
-
*
|
61 |
-
* plugin.
|
62 |
*
|
63 |
-
* @param
|
64 |
-
* @return string
|
65 |
*/
|
66 |
-
public static function varPrefix($
|
67 |
{
|
68 |
-
if (!empty($
|
69 |
-
|
70 |
'%s_%s',
|
71 |
SUCURISCAN,
|
72 |
-
substr($
|
73 |
);
|
74 |
}
|
75 |
|
76 |
-
return $
|
77 |
}
|
78 |
|
79 |
/**
|
80 |
* Gets the value of a configuration option.
|
81 |
*
|
82 |
-
* @param
|
83 |
-
* @param
|
84 |
-
* @return string
|
85 |
*/
|
86 |
public static function iniGet($property = '', $raw = false)
|
87 |
{
|
@@ -93,7 +108,7 @@ class SucuriScan
|
|
93 |
|
94 |
$default = array(
|
95 |
'error_log' => 'error_log',
|
96 |
-
'safe_mode' =>
|
97 |
'memory_limit' => '128M',
|
98 |
'upload_max_filesize' => '2M',
|
99 |
'post_max_size' => '8M',
|
@@ -102,12 +117,12 @@ class SucuriScan
|
|
102 |
);
|
103 |
|
104 |
if ($ini_value === false) {
|
105 |
-
$ini_value =
|
106 |
} elseif (empty($ini_value) || $ini_value === null) {
|
107 |
if (array_key_exists($property, $default)) {
|
108 |
$ini_value = $default[$property];
|
109 |
} else {
|
110 |
-
$ini_value =
|
111 |
}
|
112 |
}
|
113 |
|
@@ -123,8 +138,9 @@ class SucuriScan
|
|
123 |
* quote characters, will never double encode entities.
|
124 |
*
|
125 |
* @see https://developer.wordpress.org/reference/functions/esc_attr/
|
126 |
-
*
|
127 |
-
* @
|
|
|
128 |
*/
|
129 |
public static function escape($text = '')
|
130 |
{
|
@@ -135,19 +151,20 @@ class SucuriScan
|
|
135 |
* Translate a given number in bytes to a human readable file size using the
|
136 |
* a approximate value in Kylo, Mega, Giga, etc.
|
137 |
*
|
138 |
-
* @
|
139 |
-
*
|
140 |
-
* @param
|
141 |
-
* @
|
|
|
142 |
*/
|
143 |
public static function humanFileSize($bytes = 0, $decimals = 2)
|
144 |
{
|
145 |
$sz = 'BKMGTP';
|
146 |
-
$factor = floor((strlen((string) $bytes) - 1) / 3);
|
147 |
$number = $bytes / pow(1024, $factor);
|
148 |
$result = sprintf("%.{$decimals}f", $number) . @$sz[$factor];
|
149 |
$zeroes = '.' . str_repeat('0', $decimals);
|
150 |
-
$result = str_replace($zeroes, '', $result);
|
151 |
|
152 |
return $result;
|
153 |
}
|
@@ -161,8 +178,8 @@ class SucuriScan
|
|
161 |
* in the form of "in X time". If the timestamp is the same as the current
|
162 |
* time it will return "right now".
|
163 |
*
|
164 |
-
* @param
|
165 |
-
* @return string
|
166 |
*/
|
167 |
public static function humanTime($time = 0)
|
168 |
{
|
@@ -237,30 +254,28 @@ class SucuriScan
|
|
237 |
* differs from what other file systems use. To keep consistency during the
|
238 |
* unit-tests we have decided to replace any non forward slash with it.
|
239 |
*
|
240 |
-
* @param
|
241 |
-
* @return string
|
242 |
*/
|
243 |
public static function fixPath($path = '')
|
244 |
{
|
245 |
-
|
246 |
-
$path = str_replace(DIRECTORY_SEPARATOR, $delimiter, $path);
|
247 |
-
$path = rtrim($path, $delimiter);
|
248 |
-
|
249 |
-
return $path;
|
250 |
}
|
251 |
|
252 |
/**
|
253 |
-
* Returns the
|
254 |
-
* site. This is a multisite capable function.
|
255 |
*
|
256 |
-
* @param
|
257 |
-
* @return string
|
258 |
*/
|
259 |
public static function dataStorePath($path = '')
|
260 |
{
|
261 |
-
|
262 |
-
|
263 |
-
|
|
|
|
|
|
|
264 |
$folder = $content_dir . '/uploads/sucuri';
|
265 |
|
266 |
/* custom path no matter its existence */
|
@@ -288,8 +303,8 @@ class SucuriScan
|
|
288 |
/**
|
289 |
* Returns an URL from the admin dashboard.
|
290 |
*
|
291 |
-
* @param
|
292 |
-
* @return string
|
293 |
*/
|
294 |
public static function adminURL($url = '')
|
295 |
{
|
@@ -309,22 +324,23 @@ class SucuriScan
|
|
309 |
*/
|
310 |
public static function siteVersion()
|
311 |
{
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
|
|
328 |
}
|
329 |
}
|
330 |
|
@@ -336,7 +352,7 @@ class SucuriScan
|
|
336 |
*
|
337 |
* @return string|bool Absolute path of the WordPress configuration file.
|
338 |
*/
|
339 |
-
public static function
|
340 |
{
|
341 |
$filename = ABSPATH . '/wp-config.php';
|
342 |
|
@@ -386,6 +402,8 @@ class SucuriScan
|
|
386 |
|
387 |
/**
|
388 |
* Execute the plugin' scheduled tasks.
|
|
|
|
|
389 |
*/
|
390 |
public static function runScheduledTask()
|
391 |
{
|
@@ -407,8 +425,8 @@ class SucuriScan
|
|
407 |
* specify the main HTTP header. This is a list of the allowed headers that the
|
408 |
* user can choose.
|
409 |
*
|
410 |
-
* @param
|
411 |
-
* @return array
|
412 |
*/
|
413 |
public static function allowedHttpHeaders($with_keys = false)
|
414 |
{
|
@@ -447,10 +465,10 @@ class SucuriScan
|
|
447 |
/**
|
448 |
* List HTTP headers ordered.
|
449 |
*
|
450 |
-
* The list of HTTP headers is ordered per relevancy, and having the main
|
451 |
-
* header as the first entry, this guarantees that the IP address of
|
452 |
-
* visitors will be retrieved from the HTTP header chosen by the user
|
453 |
-
* fallback to the other alternatives if available.
|
454 |
*
|
455 |
* @return array Ordered allowed HTTP headers.
|
456 |
*/
|
@@ -473,13 +491,13 @@ class SucuriScan
|
|
473 |
/**
|
474 |
* Retrieve the real ip address of the user in the current request.
|
475 |
*
|
476 |
-
* @param
|
477 |
-
* @return string
|
478 |
*/
|
479 |
public static function getRemoteAddr($with_header = false)
|
480 |
{
|
481 |
$remote_addr = false;
|
482 |
-
$header_used =
|
483 |
$headers = self::orderedHttpHeaders();
|
484 |
|
485 |
foreach ($headers as $header) {
|
@@ -531,8 +549,9 @@ class SucuriScan
|
|
531 |
* Get the clean version of the current domain.
|
532 |
*
|
533 |
* @see https://developer.wordpress.org/reference/functions/get_site_url/
|
534 |
-
*
|
535 |
-
* @
|
|
|
536 |
*/
|
537 |
public static function getDomain($return_tld = false)
|
538 |
{
|
@@ -565,71 +584,52 @@ class SucuriScan
|
|
565 |
}
|
566 |
|
567 |
/**
|
568 |
-
*
|
569 |
*
|
570 |
-
*
|
571 |
-
*
|
572 |
-
*
|
573 |
-
* to disable this option, otherwise the load time of your site may be affected.
|
574 |
*
|
575 |
-
* @return
|
576 |
*/
|
577 |
-
|
578 |
{
|
579 |
-
if ((
|
580 |
-
|| SucuriScanOption::isDisabled(':dns_lookups')
|
581 |
-
) {
|
582 |
return false;
|
583 |
}
|
584 |
|
585 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
586 |
}
|
587 |
|
588 |
/**
|
589 |
* Check whether the site is behind the firewall network.
|
590 |
*
|
591 |
-
* @param
|
592 |
-
* @return array|bool
|
593 |
*/
|
594 |
public static function isBehindFirewall($verbose = false)
|
595 |
{
|
596 |
-
|
597 |
-
|
598 |
-
$host_by_name = 'localhost';
|
599 |
-
$http_host = self::getTopLevelDomain();
|
600 |
-
|
601 |
-
/**
|
602 |
-
* Consider firewall protected if the API key is set.
|
603 |
-
*
|
604 |
-
* Assume that the Sucuri Firewall is protecting this website if there
|
605 |
-
* is a valid API key set in the Firewall page, otherwise execute the
|
606 |
-
* DNS lookup to try to find the name of the server which will help us
|
607 |
-
* determine if the website is behind the Sucuri Firewall or not.
|
608 |
-
*
|
609 |
-
* Notice that this DNS lookup may slow down a website that is hosted in
|
610 |
-
* a hosting pointing to a slow DNS server, the latency in the queries
|
611 |
-
* will be noticeable. Webmasters can disable this behavior by setting
|
612 |
-
* the ":dns_lookups" option as "disabled" or adding this constant to
|
613 |
-
* the WordPress configuration file: (NOT_USING_CLOUDPROXY, true)
|
614 |
-
*/
|
615 |
-
if (SucuriScanFirewall::getKey()) {
|
616 |
-
$status = true;
|
617 |
-
} elseif (self::executeDNSLookups()) {
|
618 |
-
$host_by_addr = @gethostbyname($http_host);
|
619 |
-
$host_by_name = @gethostbyaddr($host_by_addr);
|
620 |
-
$status = (bool) preg_match('/^cloudproxy[0-9]+\.sucuri\.net$/', $host_by_name);
|
621 |
}
|
622 |
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
'host_name' => $host_by_name,
|
627 |
-
'host_addr' => $host_by_addr,
|
628 |
-
'status' => $status,
|
629 |
-
);
|
630 |
-
}
|
631 |
|
632 |
-
return
|
|
|
|
|
|
|
|
|
|
|
633 |
}
|
634 |
|
635 |
/**
|
@@ -654,8 +654,9 @@ class SucuriScan
|
|
654 |
* Get user data by field and data.
|
655 |
*
|
656 |
* @see https://developer.wordpress.org/reference/functions/get_user_by/
|
657 |
-
*
|
658 |
-
* @
|
|
|
659 |
*/
|
660 |
public static function getUserByID($identifier = 0)
|
661 |
{
|
@@ -666,6 +667,7 @@ class SucuriScan
|
|
666 |
* Retrieve a list of all admin user accounts.
|
667 |
*
|
668 |
* @see https://developer.wordpress.org/reference/functions/get_users/
|
|
|
669 |
* @return array|bool List of admin users, false otherwise.
|
670 |
*/
|
671 |
public static function getAdminUsers()
|
@@ -710,9 +712,9 @@ class SucuriScan
|
|
710 |
* take over the format for the date. If it isn't, then the date format string
|
711 |
* will be used instead.
|
712 |
*
|
713 |
-
* @param
|
714 |
-
* @param
|
715 |
-
* @return string
|
716 |
*/
|
717 |
public static function datetime($timestamp = null, $format = null)
|
718 |
{
|
@@ -751,8 +753,8 @@ class SucuriScan
|
|
751 |
/**
|
752 |
* Check whether an IP address has a valid format or not.
|
753 |
*
|
754 |
-
* @param
|
755 |
-
* @return bool
|
756 |
*/
|
757 |
public static function isValidIP($remote_addr = '')
|
758 |
{
|
@@ -763,8 +765,8 @@ class SucuriScan
|
|
763 |
/**
|
764 |
* Check whether an IP address is formatted as CIDR or not.
|
765 |
*
|
766 |
-
* @param
|
767 |
-
* @return bool
|
768 |
*/
|
769 |
public static function isValidCIDR($remote_addr = '')
|
770 |
{
|
@@ -782,8 +784,8 @@ class SucuriScan
|
|
782 |
/**
|
783 |
* Separate the parts of an IP address.
|
784 |
*
|
785 |
-
* @param
|
786 |
-
* @return array|bool
|
787 |
*/
|
788 |
public static function getIPInfo($remote_addr = '')
|
789 |
{
|
@@ -813,8 +815,8 @@ class SucuriScan
|
|
813 |
*
|
814 |
* @see https://www.php.net/manual/en/function.filter-var.php
|
815 |
*
|
816 |
-
* @param
|
817 |
-
* @return bool
|
818 |
*/
|
819 |
public static function isValidEmail($email = '')
|
820 |
{
|
@@ -824,9 +826,9 @@ class SucuriScan
|
|
824 |
/**
|
825 |
* Cut a long text to the length specified, and append suspensive points at the end.
|
826 |
*
|
827 |
-
* @param
|
828 |
-
* @param
|
829 |
-
* @return string
|
830 |
*/
|
831 |
public static function excerpt($text = '', $length = 10)
|
832 |
{
|
@@ -842,8 +844,8 @@ class SucuriScan
|
|
842 |
/**
|
843 |
* Check whether an list is a multidimensional array or not.
|
844 |
*
|
845 |
-
* @param
|
846 |
-
* @return bool
|
847 |
*/
|
848 |
public static function isMultiList($list = array())
|
849 |
{
|
@@ -866,9 +868,9 @@ class SucuriScan
|
|
866 |
/**
|
867 |
* Join array elements with a string no matter if it is multidimensional.
|
868 |
*
|
869 |
-
* @param
|
870 |
-
* @param
|
871 |
-
* @return string
|
872 |
*/
|
873 |
public static function implode($separator = '', $list = array())
|
874 |
{
|
@@ -904,167 +906,4 @@ class SucuriScan
|
|
904 |
{
|
905 |
return (bool) (stripos(@$_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false);
|
906 |
}
|
907 |
-
|
908 |
-
/**
|
909 |
-
* Returns list of supported languages.
|
910 |
-
*
|
911 |
-
* @return array Supported languages abbreviated.
|
912 |
-
*/
|
913 |
-
public static function languages()
|
914 |
-
{
|
915 |
-
return array(
|
916 |
-
'af' => 'af',
|
917 |
-
'ak' => 'ak',
|
918 |
-
'sq' => 'sq',
|
919 |
-
'arq' => 'arq',
|
920 |
-
'am' => 'am',
|
921 |
-
'ar' => 'ar',
|
922 |
-
'hy' => 'hy',
|
923 |
-
'rup_MK' => 'rup_MK',
|
924 |
-
'frp' => 'frp',
|
925 |
-
'as' => 'as',
|
926 |
-
'az' => 'az',
|
927 |
-
'az_TR' => 'az_TR',
|
928 |
-
'bcc' => 'bcc',
|
929 |
-
'ba' => 'ba',
|
930 |
-
'eu' => 'eu',
|
931 |
-
'bel' => 'bel',
|
932 |
-
'bn_BD' => 'bn_BD',
|
933 |
-
'bs_BA' => 'bs_BA',
|
934 |
-
'bre' => 'bre',
|
935 |
-
'bg_BG' => 'bg_BG',
|
936 |
-
'ca' => 'ca',
|
937 |
-
'bal' => 'bal',
|
938 |
-
'zh_CN' => 'zh_CN',
|
939 |
-
'zh_HK' => 'zh_HK',
|
940 |
-
'zh_TW' => 'zh_TW',
|
941 |
-
'co' => 'co',
|
942 |
-
'hr' => 'hr',
|
943 |
-
'cs_CZ' => 'cs_CZ',
|
944 |
-
'da_DK' => 'da_DK',
|
945 |
-
'dv' => 'dv',
|
946 |
-
'nl_NL' => 'nl_NL',
|
947 |
-
'nl_BE' => 'nl_BE',
|
948 |
-
'dzo' => 'dzo',
|
949 |
-
'en_US' => 'en_US',
|
950 |
-
'en_AU' => 'en_AU',
|
951 |
-
'en_CA' => 'en_CA',
|
952 |
-
'en_ZA' => 'en_ZA',
|
953 |
-
'en_GB' => 'en_GB',
|
954 |
-
'eo' => 'eo',
|
955 |
-
'et' => 'et',
|
956 |
-
'fo' => 'fo',
|
957 |
-
'fi' => 'fi',
|
958 |
-
'fr_BE' => 'fr_BE',
|
959 |
-
'fr_CA' => 'fr_CA',
|
960 |
-
'fr_FR' => 'fr_FR',
|
961 |
-
'fy' => 'fy',
|
962 |
-
'fuc' => 'fuc',
|
963 |
-
'gl_ES' => 'gl_ES',
|
964 |
-
'ka_GE' => 'ka_GE',
|
965 |
-
'de_DE' => 'de_DE',
|
966 |
-
'de_CH' => 'de_CH',
|
967 |
-
'el' => 'el',
|
968 |
-
'gn' => 'gn',
|
969 |
-
'gu' => 'gu',
|
970 |
-
'haw_US' => 'haw_US',
|
971 |
-
'haz' => 'haz',
|
972 |
-
'he_IL' => 'he_IL',
|
973 |
-
'hi_IN' => 'hi_IN',
|
974 |
-
'hu_HU' => 'hu_HU',
|
975 |
-
'is_IS' => 'is_IS',
|
976 |
-
'ido' => 'ido',
|
977 |
-
'id_ID' => 'id_ID',
|
978 |
-
'ga' => 'ga',
|
979 |
-
'it_IT' => 'it_IT',
|
980 |
-
'ja' => 'ja',
|
981 |
-
'jv_ID' => 'jv_ID',
|
982 |
-
'kab' => 'kab',
|
983 |
-
'kn' => 'kn',
|
984 |
-
'kk' => 'kk',
|
985 |
-
'km' => 'km',
|
986 |
-
'kin' => 'kin',
|
987 |
-
'ky_KY' => 'ky_KY',
|
988 |
-
'ko_KR' => 'ko_KR',
|
989 |
-
'ckb' => 'ckb',
|
990 |
-
'lo' => 'lo',
|
991 |
-
'lv' => 'lv',
|
992 |
-
'li' => 'li',
|
993 |
-
'lin' => 'lin',
|
994 |
-
'lt_LT' => 'lt_LT',
|
995 |
-
'lb_LU' => 'lb_LU',
|
996 |
-
'mk_MK' => 'mk_MK',
|
997 |
-
'mg_MG' => 'mg_MG',
|
998 |
-
'ms_MY' => 'ms_MY',
|
999 |
-
'ml_IN' => 'ml_IN',
|
1000 |
-
'mri' => 'mri',
|
1001 |
-
'mr' => 'mr',
|
1002 |
-
'xmf' => 'xmf',
|
1003 |
-
'mn' => 'mn',
|
1004 |
-
'me_ME' => 'me_ME',
|
1005 |
-
'my_MM' => 'my_MM',
|
1006 |
-
'ne_NP' => 'ne_NP',
|
1007 |
-
'nb_NO' => 'nb_NO',
|
1008 |
-
'nn_NO' => 'nn_NO',
|
1009 |
-
'oci' => 'oci',
|
1010 |
-
'ory' => 'ory',
|
1011 |
-
'os' => 'os',
|
1012 |
-
'ps' => 'ps',
|
1013 |
-
'fa_IR' => 'fa_IR',
|
1014 |
-
'fa_AF' => 'fa_AF',
|
1015 |
-
'pl_PL' => 'pl_PL',
|
1016 |
-
'pt_BR' => 'pt_BR',
|
1017 |
-
'pt_PT' => 'pt_PT',
|
1018 |
-
'pa_IN' => 'pa_IN',
|
1019 |
-
'rhg' => 'rhg',
|
1020 |
-
'ro_RO' => 'ro_RO',
|
1021 |
-
'roh' => 'roh',
|
1022 |
-
'ru_RU' => 'ru_RU',
|
1023 |
-
'ru_UA' => 'ru_UA',
|
1024 |
-
'rue' => 'rue',
|
1025 |
-
'sah' => 'sah',
|
1026 |
-
'sa_IN' => 'sa_IN',
|
1027 |
-
'srd' => 'srd',
|
1028 |
-
'gd' => 'gd',
|
1029 |
-
'sr_RS' => 'sr_RS',
|
1030 |
-
'szl' => 'szl',
|
1031 |
-
'sd_PK' => 'sd_PK',
|
1032 |
-
'si_LK' => 'si_LK',
|
1033 |
-
'sk_SK' => 'sk_SK',
|
1034 |
-
'sl_SI' => 'sl_SI',
|
1035 |
-
'so_SO' => 'so_SO',
|
1036 |
-
'azb' => 'azb',
|
1037 |
-
'es_AR' => 'es_AR',
|
1038 |
-
'es_CL' => 'es_CL',
|
1039 |
-
'es_CO' => 'es_CO',
|
1040 |
-
'es_MX' => 'es_MX',
|
1041 |
-
'es_PE' => 'es_PE',
|
1042 |
-
'es_PR' => 'es_PR',
|
1043 |
-
'es_ES' => 'es_ES',
|
1044 |
-
'es_VE' => 'es_VE',
|
1045 |
-
'su_ID' => 'su_ID',
|
1046 |
-
'sw' => 'sw',
|
1047 |
-
'sv_SE' => 'sv_SE',
|
1048 |
-
'gsw' => 'gsw',
|
1049 |
-
'tl' => 'tl',
|
1050 |
-
'tg' => 'tg',
|
1051 |
-
'tzm' => 'tzm',
|
1052 |
-
'ta_IN' => 'ta_IN',
|
1053 |
-
'ta_LK' => 'ta_LK',
|
1054 |
-
'tt_RU' => 'tt_RU',
|
1055 |
-
'te' => 'te',
|
1056 |
-
'th' => 'th',
|
1057 |
-
'bo' => 'bo',
|
1058 |
-
'tir' => 'tir',
|
1059 |
-
'tr_TR' => 'tr_TR',
|
1060 |
-
'tuk' => 'tuk',
|
1061 |
-
'ug_CN' => 'ug_CN',
|
1062 |
-
'uk' => 'uk',
|
1063 |
-
'ur' => 'ur',
|
1064 |
-
'uz_UZ' => 'uz_UZ',
|
1065 |
-
'vi' => 'vi',
|
1066 |
-
'wa' => 'wa',
|
1067 |
-
'cy' => 'cy',
|
1068 |
-
);
|
1069 |
-
}
|
1070 |
}
|
3 |
/**
|
4 |
* Code related to the sucuriscan.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
25 |
/**
|
26 |
* Miscellaneous library.
|
27 |
*
|
28 |
+
* Multiple and generic methods that will be used through out the code of other
|
29 |
+
* libraries extending from this and methods defined in other files, be aware of
|
30 |
+
* the hierarchy and check the other libraries for duplicated methods.
|
31 |
+
*
|
32 |
+
* @category Library
|
33 |
+
* @package Sucuri
|
34 |
+
* @subpackage SucuriScanner
|
35 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
36 |
+
* @copyright 2010-2017 Sucuri Inc.
|
37 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
38 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
39 |
*/
|
40 |
class SucuriScan
|
41 |
{
|
42 |
/**
|
43 |
* Throw generic exception instead of silent failure for unit-tests.
|
44 |
*
|
|
|
|
|
45 |
* @throws Exception
|
46 |
+
*
|
47 |
+
* @param string $message Error or information message.
|
48 |
+
* @param string $type Either info or error.
|
49 |
+
* @return bool False all the time.
|
50 |
*/
|
51 |
public static function throwException($message, $type = 'error')
|
52 |
{
|
72 |
* Return name of a variable with the plugin's prefix (if needed).
|
73 |
*
|
74 |
* To facilitate the development, you can prefix the name of the key in the
|
75 |
+
* request (when accessing it) with a single colon, this method will auto-
|
76 |
+
* matically replace that character with the unique plugin ID.
|
|
|
77 |
*
|
78 |
+
* @param string $name Text with optional colon prefix.
|
79 |
+
* @return string Real variable name.
|
80 |
*/
|
81 |
+
public static function varPrefix($name = '')
|
82 |
{
|
83 |
+
if (!empty($name) && $name[0] === ':') {
|
84 |
+
return sprintf(
|
85 |
'%s_%s',
|
86 |
SUCURISCAN,
|
87 |
+
substr($name, 1)
|
88 |
);
|
89 |
}
|
90 |
|
91 |
+
return $name;
|
92 |
}
|
93 |
|
94 |
/**
|
95 |
* Gets the value of a configuration option.
|
96 |
*
|
97 |
+
* @param string $property The configuration option name.
|
98 |
+
* @param bool $raw Return the original value from the php.ini file.
|
99 |
+
* @return string Value of the option as a string on success.
|
100 |
*/
|
101 |
public static function iniGet($property = '', $raw = false)
|
102 |
{
|
108 |
|
109 |
$default = array(
|
110 |
'error_log' => 'error_log',
|
111 |
+
'safe_mode' => 'not active',
|
112 |
'memory_limit' => '128M',
|
113 |
'upload_max_filesize' => '2M',
|
114 |
'post_max_size' => '8M',
|
117 |
);
|
118 |
|
119 |
if ($ini_value === false) {
|
120 |
+
$ini_value = 'unknown';
|
121 |
} elseif (empty($ini_value) || $ini_value === null) {
|
122 |
if (array_key_exists($property, $default)) {
|
123 |
$ini_value = $default[$property];
|
124 |
} else {
|
125 |
+
$ini_value = 'not active';
|
126 |
}
|
127 |
}
|
128 |
|
138 |
* quote characters, will never double encode entities.
|
139 |
*
|
140 |
* @see https://developer.wordpress.org/reference/functions/esc_attr/
|
141 |
+
*
|
142 |
+
* @param string $text The text which is to be encoded.
|
143 |
+
* @return string The encoded text with HTML entities.
|
144 |
*/
|
145 |
public static function escape($text = '')
|
146 |
{
|
151 |
* Translate a given number in bytes to a human readable file size using the
|
152 |
* a approximate value in Kylo, Mega, Giga, etc.
|
153 |
*
|
154 |
+
* @see https://www.php.net/manual/en/function.filesize.php#106569
|
155 |
+
*
|
156 |
+
* @param int $bytes Integer representing a file size in bytes.
|
157 |
+
* @param int $decimals How many decimals should be returned.
|
158 |
+
* @return string Human readable representation of the given number.
|
159 |
*/
|
160 |
public static function humanFileSize($bytes = 0, $decimals = 2)
|
161 |
{
|
162 |
$sz = 'BKMGTP';
|
163 |
+
$factor = (int) floor((strlen((string) $bytes) - 1) / 3);
|
164 |
$number = $bytes / pow(1024, $factor);
|
165 |
$result = sprintf("%.{$decimals}f", $number) . @$sz[$factor];
|
166 |
$zeroes = '.' . str_repeat('0', $decimals);
|
167 |
+
$result = str_replace($zeroes, '', $result);
|
168 |
|
169 |
return $result;
|
170 |
}
|
178 |
* in the form of "in X time". If the timestamp is the same as the current
|
179 |
* time it will return "right now".
|
180 |
*
|
181 |
+
* @param int $time Unix timestamp.
|
182 |
+
* @return string Different between timestamp and current time.
|
183 |
*/
|
184 |
public static function humanTime($time = 0)
|
185 |
{
|
254 |
* differs from what other file systems use. To keep consistency during the
|
255 |
* unit-tests we have decided to replace any non forward slash with it.
|
256 |
*
|
257 |
+
* @param string $path Directory path to fix.
|
258 |
+
* @return string Fixed file path.
|
259 |
*/
|
260 |
public static function fixPath($path = '')
|
261 |
{
|
262 |
+
return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/');
|
|
|
|
|
|
|
|
|
263 |
}
|
264 |
|
265 |
/**
|
266 |
+
* Returns the full path to a specific directory or file.
|
|
|
267 |
*
|
268 |
+
* @param string $path Path that needs to be completed.
|
269 |
+
* @return string Full path including the base directory.
|
270 |
*/
|
271 |
public static function dataStorePath($path = '')
|
272 |
{
|
273 |
+
if (defined('WP_CONTENT_DIR')) {
|
274 |
+
$content_dir = rtrim(WP_CONTENT_DIR, '/');
|
275 |
+
} else {
|
276 |
+
$content_dir = ABSPATH . '/wp-content';
|
277 |
+
}
|
278 |
+
|
279 |
$folder = $content_dir . '/uploads/sucuri';
|
280 |
|
281 |
/* custom path no matter its existence */
|
303 |
/**
|
304 |
* Returns an URL from the admin dashboard.
|
305 |
*
|
306 |
+
* @param string $url Optional trailing of the URL.
|
307 |
+
* @return string Full valid URL from the admin dashboard.
|
308 |
*/
|
309 |
public static function adminURL($url = '')
|
310 |
{
|
324 |
*/
|
325 |
public static function siteVersion()
|
326 |
{
|
327 |
+
if (isset($GLOBALS['wp_version'])) {
|
328 |
+
return self::escape($GLOBALS['wp_version']);
|
329 |
+
}
|
330 |
+
|
331 |
+
$wp_version = '';
|
332 |
+
$filename = ABSPATH . '/' . WPINC . '/version.php';
|
333 |
+
$lines = SucuriScanFileInfo::fileLines($filename);
|
334 |
+
|
335 |
+
foreach ($lines as $line) {
|
336 |
+
if (strpos($line, '$wp_version') === 0) {
|
337 |
+
$version = str_replace("\x20", '', $line);
|
338 |
+
$index = strpos($version, "'");
|
339 |
+
$version = substr($version, $index + 1);
|
340 |
+
$index = strpos($version, "'");
|
341 |
+
$version = substr($version, 0, $index);
|
342 |
+
$wp_version = $version;
|
343 |
+
break;
|
344 |
}
|
345 |
}
|
346 |
|
352 |
*
|
353 |
* @return string|bool Absolute path of the WordPress configuration file.
|
354 |
*/
|
355 |
+
public static function getConfigPath()
|
356 |
{
|
357 |
$filename = ABSPATH . '/wp-config.php';
|
358 |
|
402 |
|
403 |
/**
|
404 |
* Execute the plugin' scheduled tasks.
|
405 |
+
*
|
406 |
+
* @return void
|
407 |
*/
|
408 |
public static function runScheduledTask()
|
409 |
{
|
425 |
* specify the main HTTP header. This is a list of the allowed headers that the
|
426 |
* user can choose.
|
427 |
*
|
428 |
+
* @param bool $with_keys Return the array with its values are keys.
|
429 |
+
* @return array Allowed HTTP headers to retrieve real IP.
|
430 |
*/
|
431 |
public static function allowedHttpHeaders($with_keys = false)
|
432 |
{
|
465 |
/**
|
466 |
* List HTTP headers ordered.
|
467 |
*
|
468 |
+
* The list of HTTP headers is ordered per relevancy, and having the main
|
469 |
+
* HTTP header as the first entry, this guarantees that the IP address of
|
470 |
+
* the visitors will be retrieved from the HTTP header chosen by the user
|
471 |
+
* first and fallback to the other alternatives if available.
|
472 |
*
|
473 |
* @return array Ordered allowed HTTP headers.
|
474 |
*/
|
491 |
/**
|
492 |
* Retrieve the real ip address of the user in the current request.
|
493 |
*
|
494 |
+
* @param bool $with_header Return HTTP header where the IP address was found.
|
495 |
+
* @return string Real IP address of the user in the current request.
|
496 |
*/
|
497 |
public static function getRemoteAddr($with_header = false)
|
498 |
{
|
499 |
$remote_addr = false;
|
500 |
+
$header_used = 'unknown';
|
501 |
$headers = self::orderedHttpHeaders();
|
502 |
|
503 |
foreach ($headers as $header) {
|
549 |
* Get the clean version of the current domain.
|
550 |
*
|
551 |
* @see https://developer.wordpress.org/reference/functions/get_site_url/
|
552 |
+
*
|
553 |
+
* @param bool $return_tld Returns the top-level domain instead.
|
554 |
+
* @return string The domain of the current site.
|
555 |
*/
|
556 |
public static function getDomain($return_tld = false)
|
557 |
{
|
584 |
}
|
585 |
|
586 |
/**
|
587 |
+
* Checks if the server IP is part of the Firewall network.
|
588 |
*
|
589 |
+
* Assumming that the website is being protected by the Sucuri Firewall, we
|
590 |
+
* will check if the client IP address is part of the range of addresses
|
591 |
+
* that we know are ours.
|
|
|
592 |
*
|
593 |
+
* @return boolean True if the website is using one of our IP addresses.
|
594 |
*/
|
595 |
+
private static function isFirewallAddr()
|
596 |
{
|
597 |
+
if (!array_key_exists('HTTP_X_SUCURI_CLIENTIP', $_SERVER)) {
|
|
|
|
|
598 |
return false;
|
599 |
}
|
600 |
|
601 |
+
if (SucuriScanFirewall::getKey()
|
602 |
+
|| preg_match('/^192\.88\.13[45]/', $_SERVER['REMOTE_ADDR'])
|
603 |
+
|| preg_match('/^185\.93\.(228|229|230|231)/', $_SERVER['REMOTE_ADDR'])
|
604 |
+
) {
|
605 |
+
return true;
|
606 |
+
}
|
607 |
+
|
608 |
+
return false;
|
609 |
}
|
610 |
|
611 |
/**
|
612 |
* Check whether the site is behind the firewall network.
|
613 |
*
|
614 |
+
* @param bool $verbose Return array with HTTP and HOST information.
|
615 |
+
* @return array|bool True if the firewall is in use, false otherwise.
|
616 |
*/
|
617 |
public static function isBehindFirewall($verbose = false)
|
618 |
{
|
619 |
+
if (!$verbose) {
|
620 |
+
return (bool) self::isFirewallAddr();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
621 |
}
|
622 |
|
623 |
+
$http_host = self::getTopLevelDomain();
|
624 |
+
$host_by_addr = @gethostbyname($http_host);
|
625 |
+
$host_by_name = @gethostbyaddr($host_by_addr);
|
|
|
|
|
|
|
|
|
|
|
626 |
|
627 |
+
return array(
|
628 |
+
'status' => self::isFirewallAddr(),
|
629 |
+
'http_host' => self::getTopLevelDomain(),
|
630 |
+
'host_name' => $host_by_name,
|
631 |
+
'host_addr' => $host_by_addr,
|
632 |
+
);
|
633 |
}
|
634 |
|
635 |
/**
|
654 |
* Get user data by field and data.
|
655 |
*
|
656 |
* @see https://developer.wordpress.org/reference/functions/get_user_by/
|
657 |
+
*
|
658 |
+
* @param int $identifier User account identifier.
|
659 |
+
* @return array WordPress user object with data.
|
660 |
*/
|
661 |
public static function getUserByID($identifier = 0)
|
662 |
{
|
667 |
* Retrieve a list of all admin user accounts.
|
668 |
*
|
669 |
* @see https://developer.wordpress.org/reference/functions/get_users/
|
670 |
+
*
|
671 |
* @return array|bool List of admin users, false otherwise.
|
672 |
*/
|
673 |
public static function getAdminUsers()
|
712 |
* take over the format for the date. If it isn't, then the date format string
|
713 |
* will be used instead.
|
714 |
*
|
715 |
+
* @param null|string|int $timestamp Unix timestamp.
|
716 |
+
* @param string $format Optional format for the date and time.
|
717 |
+
* @return string The date, translated if locale specifies it.
|
718 |
*/
|
719 |
public static function datetime($timestamp = null, $format = null)
|
720 |
{
|
753 |
/**
|
754 |
* Check whether an IP address has a valid format or not.
|
755 |
*
|
756 |
+
* @param string $remote_addr The host IP address.
|
757 |
+
* @return bool Whether the IP address specified is valid or not.
|
758 |
*/
|
759 |
public static function isValidIP($remote_addr = '')
|
760 |
{
|
765 |
/**
|
766 |
* Check whether an IP address is formatted as CIDR or not.
|
767 |
*
|
768 |
+
* @param string $remote_addr The supposed ip address that will be checked.
|
769 |
+
* @return bool Either TRUE or FALSE if the ip address specified is valid or not.
|
770 |
*/
|
771 |
public static function isValidCIDR($remote_addr = '')
|
772 |
{
|
784 |
/**
|
785 |
* Separate the parts of an IP address.
|
786 |
*
|
787 |
+
* @param string $remote_addr The supposed ip address that will be formatted.
|
788 |
+
* @return array|bool Clean address, CIDR range, and CIDR format; FALSE otherwise.
|
789 |
*/
|
790 |
public static function getIPInfo($remote_addr = '')
|
791 |
{
|
815 |
*
|
816 |
* @see https://www.php.net/manual/en/function.filter-var.php
|
817 |
*
|
818 |
+
* @param string $email The string that will be validated as an email address.
|
819 |
+
* @return bool TRUE if the email address passed to the method is valid, FALSE if not.
|
820 |
*/
|
821 |
public static function isValidEmail($email = '')
|
822 |
{
|
826 |
/**
|
827 |
* Cut a long text to the length specified, and append suspensive points at the end.
|
828 |
*
|
829 |
+
* @param string $text String of characters that will be cut.
|
830 |
+
* @param int $length Maximum length of the returned string, default is 10.
|
831 |
+
* @return string Short version of the text specified.
|
832 |
*/
|
833 |
public static function excerpt($text = '', $length = 10)
|
834 |
{
|
844 |
/**
|
845 |
* Check whether an list is a multidimensional array or not.
|
846 |
*
|
847 |
+
* @param array $list An array or multidimensional array of different values.
|
848 |
+
* @return bool TRUE if the list is multidimensional, FALSE otherwise.
|
849 |
*/
|
850 |
public static function isMultiList($list = array())
|
851 |
{
|
868 |
/**
|
869 |
* Join array elements with a string no matter if it is multidimensional.
|
870 |
*
|
871 |
+
* @param string $separator Character that will act as a separator, default to an empty string.
|
872 |
+
* @param array $list The array of strings to implode.
|
873 |
+
* @return string String of all the items in the list, with the separator between them.
|
874 |
*/
|
875 |
public static function implode($separator = '', $list = array())
|
876 |
{
|
906 |
{
|
907 |
return (bool) (stripos(@$_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false);
|
908 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
909 |
}
|
src/template.lib.php
CHANGED
@@ -3,9 +3,15 @@
|
|
3 |
/**
|
4 |
* Code related to the template.lib.php interface.
|
5 |
*
|
6 |
-
*
|
7 |
-
*
|
8 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
*/
|
10 |
|
11 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
@@ -28,53 +34,30 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
28 |
* Web templates can be used like the template of a form letter to either
|
29 |
* generate a large number of "static" (unchanging) web pages in advance, or to
|
30 |
* produce "dynamic" web pages on demand.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
*/
|
32 |
class SucuriScanTemplate extends SucuriScanRequest
|
33 |
{
|
34 |
-
/**
|
35 |
-
* Translates text using l10n and gettext.
|
36 |
-
*
|
37 |
-
* A translatable text can be inserted into any template file following this
|
38 |
-
* format @@SUCURI.TextID@@ where "TextID" corresponds to the msgid in the
|
39 |
-
* POT files. You can embed pseudo-variables into the translations like so:
|
40 |
-
*
|
41 |
-
* msgid "Copyright"
|
42 |
-
* msgstr "Copyright %%SUCURI.Year%% Sucuri Inc"
|
43 |
-
*
|
44 |
-
* @see https://www.gnu.org/software/gettext/
|
45 |
-
* @see https://codex.wordpress.org/I18n_for_WordPress_Developers
|
46 |
-
* @see https://developer.wordpress.org/themes/functionality/internationalization/
|
47 |
-
*
|
48 |
-
* @param string $content Content of the template to be translated.
|
49 |
-
* @return string New template content with the translated text.
|
50 |
-
*/
|
51 |
-
private static function translateContent($content = '')
|
52 |
-
{
|
53 |
-
if (@preg_match_all('/@@SUCURI\.([0-9a-zA-Z\.\_]+)@@/', $content, $matches)) {
|
54 |
-
foreach ($matches[0] as $key => $placeholder) {
|
55 |
-
$translation = __($matches[1][$key], SUCURISCAN_TEXTDOMAIN);
|
56 |
-
$content = str_replace($placeholder, $translation, $content);
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
return $content;
|
61 |
-
}
|
62 |
-
|
63 |
/**
|
64 |
* Replace all pseudo-variables from a string of characters.
|
65 |
*
|
66 |
* @see http://php.net/manual/en/function.gettype.php
|
67 |
*
|
68 |
-
* @param
|
69 |
-
* @param
|
70 |
-
* @return string
|
71 |
*/
|
72 |
private static function replacePseudoVars($content = '', $params = array())
|
73 |
{
|
74 |
$params = is_array($params) ? $params : array();
|
75 |
|
76 |
-
$content = self::translateContent($content);
|
77 |
-
|
78 |
foreach ($params as $keyname => $kvalue) {
|
79 |
$tplkey = 'SUCURI.' . $keyname;
|
80 |
$with_escape = '%%' . $tplkey . '%%';
|
@@ -104,9 +87,9 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
104 |
/**
|
105 |
* Gather and generate the information required globally by all the template files.
|
106 |
*
|
107 |
-
* @param
|
108 |
-
* @param
|
109 |
-
* @return array
|
110 |
*/
|
111 |
private static function sharedParams($target = null, $params = array())
|
112 |
{
|
@@ -135,11 +118,14 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
135 |
$params['GenerateAPIKey.Visibility'] = 'visible';
|
136 |
$params['GenerateAPIKey.Modal'] = /* register-site */
|
137 |
|
138 |
-
SucuriScanTemplate::getModal(
|
139 |
-
'
|
140 |
-
|
141 |
-
|
142 |
-
|
|
|
|
|
|
|
143 |
}
|
144 |
|
145 |
// Get a list of admin users for the API key generation.
|
@@ -154,8 +140,8 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
154 |
/**
|
155 |
* Return a string indicating the visibility of a HTML component.
|
156 |
*
|
157 |
-
* @param
|
158 |
-
* @return string
|
159 |
*/
|
160 |
public static function visibility($visible = false)
|
161 |
{
|
@@ -166,9 +152,9 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
166 |
* Generate an URL pointing to the page indicated in the method and that must
|
167 |
* be loaded through the administrator panel.
|
168 |
*
|
169 |
-
* @param
|
170 |
-
* @param
|
171 |
-
* @return string
|
172 |
*/
|
173 |
public static function getUrl($page = '', $ajax = false)
|
174 |
{
|
@@ -193,8 +179,8 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
193 |
* Generate an URL pointing to the page indicated in the method and that must
|
194 |
* be loaded through the Ajax handler of the administrator panel.
|
195 |
*
|
196 |
-
* @param
|
197 |
-
* @return string
|
198 |
*/
|
199 |
public static function getAjaxUrl($page = '')
|
200 |
{
|
@@ -206,12 +192,12 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
206 |
* template files, this will also generate the navigation bar and detect which
|
207 |
* items in it are selected by the current page.
|
208 |
*
|
209 |
-
* @param
|
210 |
-
* @return array
|
211 |
*/
|
212 |
private static function linksAndNavbar($params = array())
|
213 |
{
|
214 |
-
$pages =
|
215 |
$params = is_array($params) ? $params : array();
|
216 |
$sub_pages = is_array($pages) ? $pages : array();
|
217 |
|
@@ -241,9 +227,9 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
241 |
* by the dynamic variables provided by the developer through one of the parameters
|
242 |
* of the function.
|
243 |
*
|
244 |
-
* @param
|
245 |
-
* @param
|
246 |
-
* @return string
|
247 |
*/
|
248 |
public static function getBaseTemplate($html = '', $params = array())
|
249 |
{
|
@@ -260,10 +246,10 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
260 |
* by the dynamic variables provided by the developer through one of the parameters
|
261 |
* of the function.
|
262 |
*
|
263 |
-
* @param
|
264 |
-
* @param
|
265 |
-
* @param
|
266 |
-
* @return string
|
267 |
*/
|
268 |
public static function getTemplate($template = '', $params = array(), $type = 'page')
|
269 |
{
|
@@ -311,9 +297,9 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
311 |
* by the dynamic variables provided by the developer through one of the parameters
|
312 |
* of the function.
|
313 |
*
|
314 |
-
* @param
|
315 |
-
* @param
|
316 |
-
* @return string
|
317 |
*/
|
318 |
public static function getSection($template = '', $params = array())
|
319 |
{
|
@@ -327,9 +313,9 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
327 |
* by the dynamic variables provided by the developer through one of the parameters
|
328 |
* of the function.
|
329 |
*
|
330 |
-
* @param
|
331 |
-
* @param
|
332 |
-
* @return string
|
333 |
*/
|
334 |
public static function getModal($template = '', $params = array())
|
335 |
{
|
@@ -338,14 +324,14 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
338 |
'Visibility' => 'visible',
|
339 |
'Identifier' => 'foobar',
|
340 |
'CssClass' => '',
|
341 |
-
'Content' => '<p>Lorem ipsum dolor sit amet, consectetur
|
342 |
-
. '
|
343 |
-
. '
|
344 |
-
. '
|
345 |
-
. ' irure dolor in reprehenderit in voluptate velit esse
|
346 |
-
. '
|
347 |
-
. 'non proident, sunt in culpa qui officia deserunt mollit
|
348 |
-
. 'est laborum.</p>',
|
349 |
);
|
350 |
|
351 |
if (!empty($template) && $template !== 'none') {
|
@@ -370,9 +356,9 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
370 |
* by the dynamic variables provided by the developer through one of the parameters
|
371 |
* of the function.
|
372 |
*
|
373 |
-
* @param
|
374 |
-
* @param
|
375 |
-
* @return string
|
376 |
*/
|
377 |
public static function getSnippet($template = '', $params = array())
|
378 |
{
|
@@ -384,25 +370,25 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
384 |
/**
|
385 |
* Generate the HTML code necessary to render a list of options in a form.
|
386 |
*
|
387 |
-
* @param
|
388 |
-
* @param
|
389 |
-
* @return string
|
390 |
*/
|
391 |
-
public static function selectOptions($
|
392 |
{
|
393 |
$options = '';
|
394 |
|
395 |
-
foreach ((array) $
|
396 |
-
$
|
397 |
|
398 |
-
if ($option_name === $
|
399 |
-
$
|
400 |
}
|
401 |
|
402 |
$options .= sprintf(
|
403 |
"<option value=\"%s\"%s>%s</option>\n",
|
404 |
SucuriScan::escape($option_name),
|
405 |
-
$
|
406 |
SucuriScan::escape($option_label)
|
407 |
);
|
408 |
}
|
@@ -425,10 +411,10 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
425 |
/**
|
426 |
* Generate the HTML code to display a pagination.
|
427 |
*
|
428 |
-
* @param
|
429 |
-
* @param
|
430 |
-
* @param
|
431 |
-
* @return string
|
432 |
*/
|
433 |
public static function pagination($base_url = '', $total_items = 0, $max_per_page = 1)
|
434 |
{
|
@@ -441,7 +427,9 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
441 |
$extra_url = '';
|
442 |
|
443 |
/* fix for inline anchor URLs */
|
444 |
-
|
|
|
|
|
445 |
$clean_url = substr($base_url, 0, $offset);
|
446 |
$extra_url = substr($base_url, $offset);
|
447 |
$base_url = $clean_url;
|
3 |
/**
|
4 |
* Code related to the template.lib.php interface.
|
5 |
*
|
6 |
+
* PHP version 5
|
7 |
+
*
|
8 |
+
* @category Library
|
9 |
+
* @package Sucuri
|
10 |
+
* @subpackage SucuriScanner
|
11 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
12 |
+
* @copyright 2010-2017 Sucuri Inc.
|
13 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
14 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
15 |
*/
|
16 |
|
17 |
if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
34 |
* Web templates can be used like the template of a form letter to either
|
35 |
* generate a large number of "static" (unchanging) web pages in advance, or to
|
36 |
* produce "dynamic" web pages on demand.
|
37 |
+
*
|
38 |
+
* @category Library
|
39 |
+
* @package Sucuri
|
40 |
+
* @subpackage SucuriScanner
|
41 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
42 |
+
* @copyright 2010-2017 Sucuri Inc.
|
43 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
44 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
45 |
*/
|
46 |
class SucuriScanTemplate extends SucuriScanRequest
|
47 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
/**
|
49 |
* Replace all pseudo-variables from a string of characters.
|
50 |
*
|
51 |
* @see http://php.net/manual/en/function.gettype.php
|
52 |
*
|
53 |
+
* @param string $content The content of a template file which contains pseudo-variables.
|
54 |
+
* @param array $params List of pseudo-variables that will be replaced in the template.
|
55 |
+
* @return string The content of the template with the pseudo-variables replated.
|
56 |
*/
|
57 |
private static function replacePseudoVars($content = '', $params = array())
|
58 |
{
|
59 |
$params = is_array($params) ? $params : array();
|
60 |
|
|
|
|
|
61 |
foreach ($params as $keyname => $kvalue) {
|
62 |
$tplkey = 'SUCURI.' . $keyname;
|
63 |
$with_escape = '%%' . $tplkey . '%%';
|
87 |
/**
|
88 |
* Gather and generate the information required globally by all the template files.
|
89 |
*
|
90 |
+
* @param string $target Scenario where the params are going to be replaced.
|
91 |
+
* @param array $params Key-value array with variables shared with the template.
|
92 |
+
* @return array Additional list of variables for the template files.
|
93 |
*/
|
94 |
private static function sharedParams($target = null, $params = array())
|
95 |
{
|
118 |
$params['GenerateAPIKey.Visibility'] = 'visible';
|
119 |
$params['GenerateAPIKey.Modal'] = /* register-site */
|
120 |
|
121 |
+
SucuriScanTemplate::getModal(
|
122 |
+
'register-site',
|
123 |
+
array(
|
124 |
+
'Title' => 'Generate API Key',
|
125 |
+
'Identifier' => 'register-site',
|
126 |
+
'Visibility' => 'hidden',
|
127 |
+
)
|
128 |
+
);
|
129 |
}
|
130 |
|
131 |
// Get a list of admin users for the API key generation.
|
140 |
/**
|
141 |
* Return a string indicating the visibility of a HTML component.
|
142 |
*
|
143 |
+
* @param bool $visible Whether the condition executed returned a positive value or not.
|
144 |
+
* @return string A string indicating the visibility of a HTML component.
|
145 |
*/
|
146 |
public static function visibility($visible = false)
|
147 |
{
|
152 |
* Generate an URL pointing to the page indicated in the method and that must
|
153 |
* be loaded through the administrator panel.
|
154 |
*
|
155 |
+
* @param string $page Short name of the page that will be generated.
|
156 |
+
* @param bool $ajax True if the URL should point to the Ajax handler.
|
157 |
+
* @return string Full string containing the link of the page.
|
158 |
*/
|
159 |
public static function getUrl($page = '', $ajax = false)
|
160 |
{
|
179 |
* Generate an URL pointing to the page indicated in the method and that must
|
180 |
* be loaded through the Ajax handler of the administrator panel.
|
181 |
*
|
182 |
+
* @param string $page Short name of the page that will be generated.
|
183 |
+
* @return string Full string containing the link of the page.
|
184 |
*/
|
185 |
public static function getAjaxUrl($page = '')
|
186 |
{
|
192 |
* template files, this will also generate the navigation bar and detect which
|
193 |
* items in it are selected by the current page.
|
194 |
*
|
195 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
196 |
+
* @return array A complementary list of pseudo-variables for the template files.
|
197 |
*/
|
198 |
private static function linksAndNavbar($params = array())
|
199 |
{
|
200 |
+
$pages = sucuriscanMainPages();
|
201 |
$params = is_array($params) ? $params : array();
|
202 |
$sub_pages = is_array($pages) ? $pages : array();
|
203 |
|
227 |
* by the dynamic variables provided by the developer through one of the parameters
|
228 |
* of the function.
|
229 |
*
|
230 |
+
* @param string $html The HTML content of a template file with its pseudo-variables parsed.
|
231 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
232 |
+
* @return string The formatted HTML content of the base template.
|
233 |
*/
|
234 |
public static function getBaseTemplate($html = '', $params = array())
|
235 |
{
|
246 |
* by the dynamic variables provided by the developer through one of the parameters
|
247 |
* of the function.
|
248 |
*
|
249 |
+
* @param string $template Filename of the template that will be used to generate the page.
|
250 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
251 |
+
* @param string $type Template type; either page, section or snippet.
|
252 |
+
* @return string Formatted HTML code after pseudo-variables replacement.
|
253 |
*/
|
254 |
public static function getTemplate($template = '', $params = array(), $type = 'page')
|
255 |
{
|
297 |
* by the dynamic variables provided by the developer through one of the parameters
|
298 |
* of the function.
|
299 |
*
|
300 |
+
* @param string $template Filename of the template that will be used to generate the page.
|
301 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
302 |
+
* @return string The formatted HTML page after replace all the pseudo-variables.
|
303 |
*/
|
304 |
public static function getSection($template = '', $params = array())
|
305 |
{
|
313 |
* by the dynamic variables provided by the developer through one of the parameters
|
314 |
* of the function.
|
315 |
*
|
316 |
+
* @param string $template Filename of the template that will be used to generate the page.
|
317 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
318 |
+
* @return string The formatted HTML page after replace all the pseudo-variables.
|
319 |
*/
|
320 |
public static function getModal($template = '', $params = array())
|
321 |
{
|
324 |
'Visibility' => 'visible',
|
325 |
'Identifier' => 'foobar',
|
326 |
'CssClass' => '',
|
327 |
+
'Content' => '<p>Lorem ipsum dolor sit amet, consectetur adipisici'
|
328 |
+
. 'ng elit, sed do eiusmod tempor incididunt ut labore et dolore m'
|
329 |
+
. 'agna aliqua. Ut enim ad minim veniam, quis nostrud exercitation'
|
330 |
+
. ' ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis '
|
331 |
+
. 'aute irure dolor in reprehenderit in voluptate velit esse cillu'
|
332 |
+
. 'm dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupi'
|
333 |
+
. 'datat non proident, sunt in culpa qui officia deserunt mollit a'
|
334 |
+
. 'nim id est laborum.</p>',
|
335 |
);
|
336 |
|
337 |
if (!empty($template) && $template !== 'none') {
|
356 |
* by the dynamic variables provided by the developer through one of the parameters
|
357 |
* of the function.
|
358 |
*
|
359 |
+
* @param string $template Filename of the template that will be used to generate the page.
|
360 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
361 |
+
* @return string The formatted HTML page after replace all the pseudo-variables.
|
362 |
*/
|
363 |
public static function getSnippet($template = '', $params = array())
|
364 |
{
|
370 |
/**
|
371 |
* Generate the HTML code necessary to render a list of options in a form.
|
372 |
*
|
373 |
+
* @param array $allowed Key-value array with allowed options.
|
374 |
+
* @param string|int $selected Optional selected value from the list.
|
375 |
+
* @return string HTML code for the select box.
|
376 |
*/
|
377 |
+
public static function selectOptions($allowed = array(), $selected = '')
|
378 |
{
|
379 |
$options = '';
|
380 |
|
381 |
+
foreach ((array) $allowed as $option_name => $option_label) {
|
382 |
+
$selectedAttr = '';
|
383 |
|
384 |
+
if ($option_name === $selected) {
|
385 |
+
$selectedAttr = "\x20selected=\"selected\"";
|
386 |
}
|
387 |
|
388 |
$options .= sprintf(
|
389 |
"<option value=\"%s\"%s>%s</option>\n",
|
390 |
SucuriScan::escape($option_name),
|
391 |
+
$selectedAttr, /* do not escape HTML */
|
392 |
SucuriScan::escape($option_label)
|
393 |
);
|
394 |
}
|
411 |
/**
|
412 |
* Generate the HTML code to display a pagination.
|
413 |
*
|
414 |
+
* @param string $base_url Base URL for the links before the page number.
|
415 |
+
* @param int $total_items Total quantity of items retrieved from a query.
|
416 |
+
* @param int $max_per_page Maximum number of items that will be shown per page.
|
417 |
+
* @return string HTML code for a pagination generated using the provided data.
|
418 |
*/
|
419 |
public static function pagination($base_url = '', $total_items = 0, $max_per_page = 1)
|
420 |
{
|
427 |
$extra_url = '';
|
428 |
|
429 |
/* fix for inline anchor URLs */
|
430 |
+
$offset = strpos($base_url, '#');
|
431 |
+
|
432 |
+
if ($offset !== false) {
|
433 |
$clean_url = substr($base_url, 0, $offset);
|
434 |
$extra_url = substr($base_url, $offset);
|
435 |
$base_url = $clean_url;
|
sucuri.php
CHANGED
@@ -5,12 +5,20 @@
|
|
5 |
* Description: The <a href="https://sucuri.net/" target="_blank">Sucuri</a> plugin provides the website owner the best Activity Auditing, SiteCheck Remote Malware Scanning, Effective Security Hardening and Post-Hack features. SiteCheck will check for malware, spam, blacklisting and other security issues like .htaccess redirects, hidden eval code, etc. The best thing about it is it's completely free.
|
6 |
* Plugin URI: https://wordpress.sucuri.net/
|
7 |
* Author URI: https://sucuri.net/
|
8 |
-
* Text Domain: sucuri-scanner
|
9 |
* Author: Sucuri Inc.
|
10 |
* Version: 1.8.8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
*/
|
12 |
|
13 |
-
|
14 |
/**
|
15 |
* Main file to control the plugin.
|
16 |
*
|
@@ -19,14 +27,6 @@
|
|
19 |
* during the direct access of any of the extra PHP files the interpreter will
|
20 |
* return a 403/Forbidden response and immediately exit the execution, this will
|
21 |
* prevent unwanted access to code with unmet dependencies.
|
22 |
-
*
|
23 |
-
* @package Sucuri Security
|
24 |
-
* @author Daniel Cid <dcid@sucuri.net>
|
25 |
-
* @license Released under the GPL.
|
26 |
-
* @copyright Since 2010 Sucuri Inc.
|
27 |
-
* @since File available since Release 0.1
|
28 |
-
* @link https://wordpress.org/plugins/sucuri-scanner/
|
29 |
-
* @link https://wordpress.sucuri.net/
|
30 |
*/
|
31 |
define('SUCURISCAN_INIT', true);
|
32 |
|
@@ -85,11 +85,6 @@ define('SUCURISCAN', 'sucuriscan');
|
|
85 |
*/
|
86 |
define('SUCURISCAN_VERSION', '1.8.8');
|
87 |
|
88 |
-
/**
|
89 |
-
* Unique name of the plugin text domain.
|
90 |
-
*/
|
91 |
-
define('SUCURISCAN_TEXTDOMAIN', 'sucuri-scanner');
|
92 |
-
|
93 |
/**
|
94 |
* The name of the folder where the plugin's files will be located.
|
95 |
*
|
@@ -109,7 +104,7 @@ define('SUCURISCAN_PLUGIN_PATH', WP_PLUGIN_DIR . '/' . SUCURISCAN_PLUGIN_FOLDER)
|
|
109 |
/**
|
110 |
* The local URL where the plugin's files and assets are served.
|
111 |
*/
|
112 |
-
define('SUCURISCAN_URL', plugin_dir_url(__FILE__));
|
113 |
|
114 |
/**
|
115 |
* Remote URL where the public Sucuri API service is running.
|
@@ -166,7 +161,7 @@ define('SUCURISCAN_SCANNER_FREQUENCY', 10800);
|
|
166 |
/**
|
167 |
* The life time of the cache for the results of the SiteCheck scans.
|
168 |
*/
|
169 |
-
define('SUCURISCAN_SITECHECK_LIFETIME',
|
170 |
|
171 |
/**
|
172 |
* The life time of the cache for the results of the get_plugins function.
|
@@ -194,48 +189,48 @@ if (!array_key_exists('SERVER_NAME', $_SERVER)) {
|
|
194 |
}
|
195 |
|
196 |
/* Load all classes before anything else. */
|
197 |
-
require_once
|
198 |
-
require_once
|
199 |
-
require_once
|
200 |
-
require_once
|
201 |
-
require_once
|
202 |
-
require_once
|
203 |
-
require_once
|
204 |
-
require_once
|
205 |
-
require_once
|
206 |
-
require_once
|
207 |
-
require_once
|
208 |
-
require_once
|
209 |
-
require_once
|
210 |
-
require_once
|
211 |
-
require_once
|
212 |
-
require_once
|
213 |
-
require_once
|
214 |
-
require_once
|
215 |
-
require_once
|
216 |
|
217 |
/* Load page and ajax handlers */
|
218 |
-
require_once
|
219 |
|
220 |
/* Load handlers for main pages (lastlogins). */
|
221 |
-
require_once
|
222 |
-
require_once
|
223 |
-
require_once
|
224 |
-
require_once
|
225 |
|
226 |
/* Load handlers for main pages (settings). */
|
227 |
-
require_once
|
228 |
-
require_once
|
229 |
-
require_once
|
230 |
-
require_once
|
231 |
-
require_once
|
232 |
-
require_once
|
233 |
-
require_once
|
234 |
-
require_once
|
235 |
-
require_once
|
236 |
|
237 |
/* Load global variables and triggers */
|
238 |
-
require_once
|
239 |
|
240 |
/**
|
241 |
* Uninstalls the plugin, its settings and reverts the hardening.
|
@@ -246,15 +241,18 @@ require_once('src/globals.php');
|
|
246 |
* inserted into the sub-database associated to a multi-site installation, will
|
247 |
* revert the hardening applied to the core directories, and will delete all the
|
248 |
* security logs, cache and additional data stored in the storage directory.
|
|
|
|
|
249 |
*/
|
250 |
-
function
|
251 |
{
|
252 |
-
|
|
|
|
|
|
|
|
|
|
|
253 |
|
254 |
-
if ($wpdb) {
|
255 |
-
/* Delete all the possible plugin related options from the database */
|
256 |
-
$sql = "SELECT * FROM {$wpdb->options} WHERE option_name LIKE 'sucuriscan%'";
|
257 |
-
$options = $wpdb->get_results($sql);
|
258 |
foreach ($options as $option) {
|
259 |
delete_site_option($option->option_name);
|
260 |
delete_option($option->option_name);
|
@@ -288,4 +286,4 @@ function sucuriscan_deactivate()
|
|
288 |
$fifo->removeDirectoryTree($directory);
|
289 |
}
|
290 |
|
291 |
-
register_deactivation_hook(__FILE__, '
|
5 |
* Description: The <a href="https://sucuri.net/" target="_blank">Sucuri</a> plugin provides the website owner the best Activity Auditing, SiteCheck Remote Malware Scanning, Effective Security Hardening and Post-Hack features. SiteCheck will check for malware, spam, blacklisting and other security issues like .htaccess redirects, hidden eval code, etc. The best thing about it is it's completely free.
|
6 |
* Plugin URI: https://wordpress.sucuri.net/
|
7 |
* Author URI: https://sucuri.net/
|
|
|
8 |
* Author: Sucuri Inc.
|
9 |
* Version: 1.8.8
|
10 |
+
*
|
11 |
+
* PHP version 5
|
12 |
+
*
|
13 |
+
* @category Library
|
14 |
+
* @package Sucuri
|
15 |
+
* @subpackage SucuriScanner
|
16 |
+
* @author Daniel Cid <dcid@sucuri.net>
|
17 |
+
* @copyright 2010-2017 Sucuri Inc.
|
18 |
+
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2
|
19 |
+
* @link https://wordpress.org/plugins/sucuri-scanner
|
20 |
*/
|
21 |
|
|
|
22 |
/**
|
23 |
* Main file to control the plugin.
|
24 |
*
|
27 |
* during the direct access of any of the extra PHP files the interpreter will
|
28 |
* return a 403/Forbidden response and immediately exit the execution, this will
|
29 |
* prevent unwanted access to code with unmet dependencies.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
*/
|
31 |
define('SUCURISCAN_INIT', true);
|
32 |
|
85 |
*/
|
86 |
define('SUCURISCAN_VERSION', '1.8.8');
|
87 |
|
|
|
|
|
|
|
|
|
|
|
88 |
/**
|
89 |
* The name of the folder where the plugin's files will be located.
|
90 |
*
|
104 |
/**
|
105 |
* The local URL where the plugin's files and assets are served.
|
106 |
*/
|
107 |
+
define('SUCURISCAN_URL', rtrim(plugin_dir_url(__FILE__), '/'));
|
108 |
|
109 |
/**
|
110 |
* Remote URL where the public Sucuri API service is running.
|
161 |
/**
|
162 |
* The life time of the cache for the results of the SiteCheck scans.
|
163 |
*/
|
164 |
+
define('SUCURISCAN_SITECHECK_LIFETIME', 21600);
|
165 |
|
166 |
/**
|
167 |
* The life time of the cache for the results of the get_plugins function.
|
189 |
}
|
190 |
|
191 |
/* Load all classes before anything else. */
|
192 |
+
require_once 'src/sucuriscan.lib.php';
|
193 |
+
require_once 'src/request.lib.php';
|
194 |
+
require_once 'src/fileinfo.lib.php';
|
195 |
+
require_once 'src/cache.lib.php';
|
196 |
+
require_once 'src/option.lib.php';
|
197 |
+
require_once 'src/event.lib.php';
|
198 |
+
require_once 'src/hook.lib.php';
|
199 |
+
require_once 'src/api.lib.php';
|
200 |
+
require_once 'src/mail.lib.php';
|
201 |
+
require_once 'src/command.lib.php';
|
202 |
+
require_once 'src/template.lib.php';
|
203 |
+
require_once 'src/fsscanner.lib.php';
|
204 |
+
require_once 'src/hardening.lib.php';
|
205 |
+
require_once 'src/interface.lib.php';
|
206 |
+
require_once 'src/auditlogs.lib.php';
|
207 |
+
require_once 'src/sitecheck.lib.php';
|
208 |
+
require_once 'src/integrity.lib.php';
|
209 |
+
require_once 'src/firewall.lib.php';
|
210 |
+
require_once 'src/installer-skin.lib.php';
|
211 |
|
212 |
/* Load page and ajax handlers */
|
213 |
+
require_once 'src/pagehandler.php';
|
214 |
|
215 |
/* Load handlers for main pages (lastlogins). */
|
216 |
+
require_once 'src/lastlogins.php';
|
217 |
+
require_once 'src/lastlogins-loggedin.php';
|
218 |
+
require_once 'src/lastlogins-failed.php';
|
219 |
+
require_once 'src/lastlogins-blocked.php';
|
220 |
|
221 |
/* Load handlers for main pages (settings). */
|
222 |
+
require_once 'src/settings.php';
|
223 |
+
require_once 'src/settings-general.php';
|
224 |
+
require_once 'src/settings-scanner.php';
|
225 |
+
require_once 'src/settings-integrity.php';
|
226 |
+
require_once 'src/settings-hardening.php';
|
227 |
+
require_once 'src/settings-posthack.php';
|
228 |
+
require_once 'src/settings-alerts.php';
|
229 |
+
require_once 'src/settings-apiservice.php';
|
230 |
+
require_once 'src/settings-webinfo.php';
|
231 |
|
232 |
/* Load global variables and triggers */
|
233 |
+
require_once 'src/globals.php';
|
234 |
|
235 |
/**
|
236 |
* Uninstalls the plugin, its settings and reverts the hardening.
|
241 |
* inserted into the sub-database associated to a multi-site installation, will
|
242 |
* revert the hardening applied to the core directories, and will delete all the
|
243 |
* security logs, cache and additional data stored in the storage directory.
|
244 |
+
*
|
245 |
+
* @return void
|
246 |
*/
|
247 |
+
function sucuriscanResetAndDeactivate()
|
248 |
{
|
249 |
+
if (array_key_exists('wpdb', $GLOBALS)) {
|
250 |
+
/* Delete all plugin related options from the database */
|
251 |
+
$options = $GLOBALS['wpdb']->get_results(
|
252 |
+
'SELECT option_id, option_name FROM ' . $GLOBALS['wpdb']->options
|
253 |
+
. ' WHERE option_name LIKE "' . SUCURISCAN . '%"'
|
254 |
+
);
|
255 |
|
|
|
|
|
|
|
|
|
256 |
foreach ($options as $option) {
|
257 |
delete_site_option($option->option_name);
|
258 |
delete_option($option->option_name);
|
286 |
$fifo->removeDirectoryTree($directory);
|
287 |
}
|
288 |
|
289 |
+
register_deactivation_hook(__FILE__, 'sucuriscanResetAndDeactivate');
|