Sucuri Security – Auditing, Malware Scanner and Security Hardening - Version 1.8.19

Version Description

This version adds an option to refresh the malware scan results on demand, as well as several small bug fixes and improvements.

=

Download this release

Release Info

Developer ycampo
Plugin Icon 128x128 Sucuri Security – Auditing, Malware Scanner and Security Hardening
Version 1.8.19
Comparing to
See all releases

Code changes from version 1.8.18 to 1.8.19

inc/tpl/dashboard.html.tpl CHANGED
@@ -28,6 +28,7 @@ jQuery(document).ready(function ($) {
28
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
29
action: 'sucuriscan_ajax',
30
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
31
form_action: 'malware_scan',
32
}, function (data) {
33
$('#sucuriscan-title-iframes').html(data.iframes.title);
28
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
29
action: 'sucuriscan_ajax',
30
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
31
+ sucuriscan_sitecheck_refresh: '%%SUCURI.SiteCheck.Refresh%%',
32
form_action: 'malware_scan',
33
}, function (data) {
34
$('#sucuriscan-title-iframes').html(data.iframes.title);
inc/tpl/integrity.html.tpl CHANGED
@@ -6,6 +6,7 @@ jQuery(document).ready(function ($) {
6
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
7
action: 'sucuriscan_ajax',
8
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
9
form_action: 'check_wordpress_integrity',
10
}, function (data) {
11
$('#sucuriscan-integrity-response').html(data);
6
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
7
action: 'sucuriscan_ajax',
8
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
9
+ sucuriscan_sitecheck_refresh: '%%SUCURI.SiteCheck.Refresh%%',
10
form_action: 'check_wordpress_integrity',
11
}, function (data) {
12
$('#sucuriscan-integrity-response').html(data);
inc/tpl/sitecheck-details.html.tpl CHANGED
@@ -4,3 +4,10 @@
4
%%%SUCURI.SiteCheck.Metadata%%%
5
</ul>
6
</div>
4
%%%SUCURI.SiteCheck.Metadata%%%
5
</ul>
6
</div>
7
+
8
+ <div class="sucuriscan-cache-expiration">
9
+ <small>
10
+ This information will be updated %%SUCURI.SiteCheck.Lifetime%%
11
+ &mdash; <a href="%%SUCURI.URL.Dashboard%%&sucuriscan_sitecheck_refresh=true">Refresh Malware Scan</a>
12
+ </small>
13
+ </div>
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">Recomendations</h3>
4
5
<ul>
6
%%%SUCURI.Recommendations.Content%%%
1
2
+ <div class="sucuriscan-panel sucuriscan-sitecheck-list sucuriscan-sitecheck-recommendations">
3
+ <h3 class="sucuriscan-tag-title sucuriscan-tag-%%SUCURI.Recommendations.Color%%">Recomendations</h3>
4
5
<ul>
6
%%%SUCURI.Recommendations.Content%%%
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: dd@sucuri.net
3
Donate Link: https://sucuri.net/
4
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection, blacklist, detection, hardening, file integrity
5
Requires at least: 3.6
6
- Tested up to: 4.9.4
7
- Stable tag: 1.8.18
8
9
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
10
@@ -185,11 +185,16 @@ We take your privacy seriously. For free plugin users without an API key, no inf
185
186
== Upgrade Notice ==
187
188
- = 1.8.15 =
189
- 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.
190
191
== Changelog ==
192
193
= 1.8.18 =
194
* Keep settings when the plugin is deactivated, unless the plugin is uninstalled
195
3
Donate Link: https://sucuri.net/
4
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection, blacklist, detection, hardening, file integrity
5
Requires at least: 3.6
6
+ Tested up to: 5.0.3
7
+ Stable tag: 1.8.19
8
9
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
10
185
186
== Upgrade Notice ==
187
188
+ = 1.8.19 =
189
+ This version adds an option to refresh the malware scan results on demand, as well as several small bug fixes and improvements.
190
191
== Changelog ==
192
193
+ = 1.8.19 =
194
+ * Add option to refresh the SiteCheck malware scan results
195
+ * Add support for a CLI command to ignore files in the core integrity check
196
+ * Fix text
197
+
198
= 1.8.18 =
199
* Keep settings when the plugin is deactivated, unless the plugin is uninstalled
200
src/base.lib.php CHANGED
@@ -877,6 +877,10 @@ class SucuriScan
877
*/
878
public static function implode($separator = '', $list = array())
879
{
880
if (self::isMultiList($list)) {
881
$pieces = array();
882
877
*/
878
public static function implode($separator = '', $list = array())
879
{
880
+ if (!is_array($list)) {
881
+ return 'INVALID_ARGS';
882
+ }
883
+
884
if (self::isMultiList($list)) {
885
$pieces = array();
886
src/cache.lib.php CHANGED
@@ -288,9 +288,39 @@ class SucuriScanCache extends SucuriScan
288
289
$finfo['info']['fpath'] = $this->datastore_path;
290
291
return $finfo['info'];
292
}
293
294
/**
295
* Get the total number of unique entries in the datastore file.
296
*
288
289
$finfo['info']['fpath'] = $this->datastore_path;
290
291
+ if (!isset($finfo['info']['created_on'])) {
292
+ $finfo['info']['created_on'] = time();
293
+ }
294
+
295
+ if (!isset($finfo['info']['updated_on'])) {
296
+ $finfo['info']['updated_on'] = time();
297
+ }
298
+
299
return $finfo['info'];
300
}
301
302
+ /**
303
+ * Returns the Unix timestamp when the cache was created.
304
+ *
305
+ * @return int Unix timestamp when the cache was created.
306
+ */
307
+ public function createdAt()
308
+ {
309
+ $info = $this->getDatastoreInfo();
310
+ return (int) $info['created_on'];
311
+ }
312
+
313
+ /**
314
+ * Returns the Unix timestamp when the cache was updated.
315
+ *
316
+ * @return int Unix timestamp when the cache was updated.
317
+ */
318
+ public function updatedAt()
319
+ {
320
+ $info = $this->getDatastoreInfo();
321
+ return (int) $info['updated_on'];
322
+ }
323
+
324
/**
325
* Get the total number of unique entries in the datastore file.
326
*
src/cli.lib.php CHANGED
@@ -88,6 +88,81 @@ class SucuriScanCLI extends WP_CLI_Command
88
89
WP_CLI::success($message);
90
}
91
}
92
93
WP_CLI::add_command('sucuri', 'SucuriScanCLI');
88
89
WP_CLI::success($message);
90
}
91
+
92
+ /**
93
+ * Manage which files are included in Sucuri integrity checks.
94
+ *
95
+ * ## OPTIONS
96
+ *
97
+ * <action>
98
+ * : The action to be taken (ignore or unignore).
99
+ *
100
+ * <file_path>
101
+ * : Relative path to a file.
102
+ *
103
+ * [--reason=<reason>]
104
+ * : Why the file should be ignored from integrity checks.
105
+ * ---
106
+ * default: added
107
+ * options:
108
+ * - added
109
+ * - modified
110
+ * - removed
111
+ * ---
112
+ *
113
+ * ## EXAMPLES
114
+ *
115
+ * # Ignore a file
116
+ * wp sucuri integrity ignore wp-admin/install.php --reason=removed
117
+ * Success: 'wp-admin/install.php' file successfully ignored.
118
+ *
119
+ * # Unignore a file
120
+ * wp sucuri integrity unignore foo.php
121
+ * Success: 'foo.php' file successfully unignored.
122
+ *
123
+ * @param array $args Arguments from the command line interface.
124
+ * @param array $assoc_args Associative arguments from the command line interface.
125
+ * @return void
126
+ */
127
+ public function integrity($args, $assoc_args)
128
+ {
129
+ list($action, $file_path) = $args;
130
+
131
+ $allowed_actions = array('ignore', 'unignore');
132
+
133
+ if (! in_array($action, $allowed_actions, true)) {
134
+ WP_CLI::error("Requested action '{$action}' is not supported.");
135
+ }
136
+
137
+ $allowed_reasons = array('added', 'modified', 'removed');
138
+
139
+ $file_status = WP_CLI\Utils\get_flag_value( $assoc_args, 'reason', $default = 'added' );
140
+
141
+ if (! in_array($file_status, $allowed_reasons, true)) {
142
+ WP_CLI::error("Specified reason '{$file_status}' is not supported.");
143
+ }
144
+
145
+ $cache = new SucuriScanCache('integrity');
146
+
147
+ $cache_key = md5($file_path);
148
+
149
+ if ('ignore' === $action) {
150
+ $cache->add(
151
+ $cache_key,
152
+ array(
153
+ 'file_path' => $file_path,
154
+ 'file_status' => $file_status,
155
+ 'ignored_at' => time(),
156
+ )
157
+ );
158
+ WP_CLI::success("'{$file_path}' file successfully ignored.");
159
+ }
160
+
161
+ if ('unignore' === $action) {
162
+ $cache->delete($cache_key);
163
+ WP_CLI::success("'{$file_path}' file successfully unignored.");
164
+ }
165
+ }
166
}
167
168
WP_CLI::add_command('sucuri', 'SucuriScanCLI');
src/pagehandler.php CHANGED
@@ -40,6 +40,7 @@ function sucuriscan_page()
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';
@@ -50,6 +51,10 @@ function sucuriscan_page()
50
$params['SiteCheck.Blacklist'] = '<div id="sucuriscan-blacklist"></div>';
51
$params['SiteCheck.Recommendations'] = '<div id="sucuriscan-recommendations"></div>';
52
53
echo SucuriScanTemplate::getTemplate('dashboard', $params);
54
}
55
40
$params['AuditLogs'] = SucuriScanAuditLogs::pageAuditLogs();
41
42
/* load data for the SiteCheck section */
43
+ $params['SiteCheck.Refresh'] = 'false';
44
$params['SiteCheck.iFramesTitle'] = 'iFrames';
45
$params['SiteCheck.LinksTitle'] = 'Links';
46
$params['SiteCheck.ScriptsTitle'] = 'Scripts';
51
$params['SiteCheck.Blacklist'] = '<div id="sucuriscan-blacklist"></div>';
52
$params['SiteCheck.Recommendations'] = '<div id="sucuriscan-recommendations"></div>';
53
54
+ if (SucuriScanRequest::get(':sitecheck_refresh') !== false) {
55
+ $params['SiteCheck.Refresh'] = 'true';
56
+ }
57
+
58
echo SucuriScanTemplate::getTemplate('dashboard', $params);
59
}
60
src/settings-hardening.php CHANGED
@@ -144,7 +144,7 @@ class SucuriScanHardeningPage extends SucuriScan
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'
@@ -154,7 +154,7 @@ class SucuriScanHardeningPage extends SucuriScan
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
}
144
145
$params['URL.Settings'] = admin_url('update-core.php');
146
$params['Hardening.Status'] = 0;
147
+ $params['Hardening.FieldText'] = 'Check Updates Now';
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'
154
155
if (isset($updates[0]) && $updates[0] instanceof stdClass) {
156
if ($updates[0]->response == 'latest' || $updates[0]->response == 'development') {
157
+ $params['Hardening.FieldText'] = 'WordPress Update Available';
158
$params['Hardening.FieldAttrs'] = 'disabled';
159
$params['Hardening.Status'] = 1;
160
}
src/sitecheck.lib.php CHANGED
@@ -112,6 +112,12 @@ class SucuriScanSiteCheck extends SucuriScanAPI
112
public static function scanAndCollectData()
113
{
114
$cache = new SucuriScanCache('sitecheck');
115
$results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array');
116
117
/* return cached malware scan results. */
@@ -140,6 +146,21 @@ class SucuriScanSiteCheck extends SucuriScanAPI
140
return $results;
141
}
142
143
/**
144
* Generates the HTML section for the SiteCheck details.
145
*
@@ -152,6 +173,8 @@ class SucuriScanSiteCheck extends SucuriScanAPI
152
$data['details'] = array();
153
154
$params['SiteCheck.Metadata'] = '';
155
$data['details'][] = 'PHP Version: ' . phpversion();
156
$data['details'][] = 'Version: ' . SucuriScan::siteVersion();
157
@@ -332,9 +355,14 @@ class SucuriScanSiteCheck extends SucuriScanAPI
332
{
333
$params = array();
334
$data = self::scanAndCollectData();
335
336
$params['Recommendations.Content'] = '';
337
- $params['Recommendations.Visibility'] = 'hidden';
338
339
if (isset($data['RECOMMENDATIONS'])) {
340
foreach ($data['RECOMMENDATIONS'] as $recommendation) {
@@ -342,7 +370,19 @@ class SucuriScanSiteCheck extends SucuriScanAPI
342
continue;
343
}
344
345
- $params['Recommendations.Visibility'] = 'visible';
346
$params['Recommendations.Content'] .= SucuriScanTemplate::getSnippet(
347
'sitecheck-recommendations',
348
array(
@@ -354,6 +394,12 @@ class SucuriScanSiteCheck extends SucuriScanAPI
354
}
355
}
356
357
return SucuriScanTemplate::getSection('sitecheck-recommendations', $params);
358
}
359
@@ -474,7 +520,7 @@ class SucuriScanSiteCheck extends SucuriScanAPI
474
}
475
476
// Extract the information from the malware message.
477
- $malware_parts = explode("\n", $malware[1]);
478
479
if (isset($malware_parts[1])) {
480
$pattern = ".\x20Details:\x20";
112
public static function scanAndCollectData()
113
{
114
$cache = new SucuriScanCache('sitecheck');
115
+
116
+ if (SucuriScanRequest::post(':sitecheck_refresh') === 'true') {
117
+ /* user requested to reset the sitecheck cache */
118
+ $cache->delete('scan_results');
119
+ }
120
+
121
$results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array');
122
123
/* return cached malware scan results. */
146
return $results;
147
}
148
149
+ /**
150
+ * Returns the amount of time left before the SiteCheck cache expires.
151
+ *
152
+ * @return string Time left before the SiteCheck cache expires.
153
+ */
154
+ private static function cacheLifetime()
155
+ {
156
+ $current = time();
157
+ $cache = new SucuriScanCache('sitecheck');
158
+ $timeDiff = $current - $cache->updatedAt();
159
+ $timeLeft = SUCURISCAN_SITECHECK_LIFETIME - $timeDiff;
160
+
161
+ return self::humanTime($current + $timeLeft);
162
+ }
163
+
164
/**
165
* Generates the HTML section for the SiteCheck details.
166
*
173
$data['details'] = array();
174
175
$params['SiteCheck.Metadata'] = '';
176
+ $params['SiteCheck.Lifetime'] = self::cacheLifetime();
177
+
178
$data['details'][] = 'PHP Version: ' . phpversion();
179
$data['details'][] = 'Version: ' . SucuriScan::siteVersion();
180
355
{
356
$params = array();
357
$data = self::scanAndCollectData();
358
+ $sechead = array(
359
+ 'x-content-type-options' => 'X-Content-Type-Options Header',
360
+ 'x-frame-options' => 'X-Frame-Options Security Header',
361
+ 'x-xss-protection' => 'X-XSS-Protection Security Header',
362
+ );
363
364
$params['Recommendations.Content'] = '';
365
+ $params['Recommendations.Color'] = 'green';
366
367
if (isset($data['RECOMMENDATIONS'])) {
368
foreach ($data['RECOMMENDATIONS'] as $recommendation) {
370
continue;
371
}
372
373
+ if (stripos($recommendation[0], 'x-content-type')) {
374
+ unset($sechead['x-content-type-options']);
375
+ }
376
+
377
+ if (stripos($recommendation[0], 'x-frame-options')) {
378
+ unset($sechead['x-frame-options']);
379
+ }
380
+
381
+ if (stripos($recommendation[0], 'x-xss-protection')) {
382
+ unset($sechead['x-xss-protection']);
383
+ }
384
+
385
+ $params['Recommendations.Color'] = 'blue';
386
$params['Recommendations.Content'] .= SucuriScanTemplate::getSnippet(
387
'sitecheck-recommendations',
388
array(
394
}
395
}
396
397
+ foreach ($sechead as $header => $message) {
398
+ $params['Recommendations.Content'] .=
399
+ '<li class="sucuriscan-sitecheck-list-INFO">'
400
+ . $message . '</li>';
401
+ }
402
+
403
return SucuriScanTemplate::getSection('sitecheck-recommendations', $params);
404
}
405
520
}
521
522
// Extract the information from the malware message.
523
+ $malware_parts = explode("\n", $malware[1], 2);
524
525
if (isset($malware_parts[1])) {
526
$pattern = ".\x20Details:\x20";
sucuri.php CHANGED
@@ -6,7 +6,7 @@
6
* Plugin URI: https://wordpress.sucuri.net/
7
* Author URI: https://sucuri.net/
8
* Author: Sucuri Inc.
9
- * Version: 1.8.18
10
*
11
* PHP version 5
12
*
@@ -83,7 +83,7 @@ define('SUCURISCAN', 'sucuriscan');
83
/**
84
* Current version of the plugin's code.
85
*/
86
- define('SUCURISCAN_VERSION', '1.8.18');
87
88
/**
89
* Defines the human readable name of the plugin.
@@ -252,6 +252,7 @@ function sucuriscanResetAndDeactivate()
252
{
253
/* Delete scheduled task from the system */
254
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
255
}
256
257
/**
@@ -303,6 +304,8 @@ function sucuriscanUninstall()
303
$fifo->run_recursively = false;
304
$directory = SucuriScan::dataStorePath();
305
$fifo->removeDirectoryTree($directory);
306
}
307
308
register_deactivation_hook(__FILE__, 'sucuriscanResetAndDeactivate');
6
* Plugin URI: https://wordpress.sucuri.net/
7
* Author URI: https://sucuri.net/
8
* Author: Sucuri Inc.
9
+ * Version: 1.8.19
10
*
11
* PHP version 5
12
*
83
/**
84
* Current version of the plugin's code.
85
*/
86
+ define('SUCURISCAN_VERSION', '1.8.19');
87
88
/**
89
* Defines the human readable name of the plugin.
252
{
253
/* Delete scheduled task from the system */
254
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
255
+ SucuriScanEvent::reportDebugEvent('Sucuri plugin has been deactivated');
256
}
257
258
/**
304
$fifo->run_recursively = false;
305
$directory = SucuriScan::dataStorePath();
306
$fifo->removeDirectoryTree($directory);
307
+
308
+ SucuriScanEvent::reportDebugEvent('Sucuri plugin has been uninstalled');
309
}
310
311
register_deactivation_hook(__FILE__, 'sucuriscanResetAndDeactivate');