Version Description
- Fixed fatal error when PHPMailer failed
- Fixed incorrect selected value in settings
- Fixed kb links and content.
- Added SiteCheck for arbitrary domain
- Various code cleanup
Download this release
Release Info
Developer | dd@sucuri.net |
Plugin | Sucuri Security – Auditing, Malware Scanner and Security Hardening |
Version | 1.8.3 |
Comparing to | |
See all releases |
Code changes from version 1.8.1 to 1.8.3
- inc/tpl/bsidebar.html.tpl +2 -2
- inc/tpl/malwarescan.html.tpl +1 -1
- inc/tpl/settings-datastorage-files.snippet.tpl +11 -0
- inc/tpl/settings-general-datastorage.html.tpl +39 -33
- readme.txt +33 -25
- sucuri.php +226 -168
inc/tpl/bsidebar.html.tpl
CHANGED
@@ -12,7 +12,7 @@
|
|
12 |
</div>
|
13 |
</div>
|
14 |
|
15 |
-
<a href="https://
|
16 |
|
17 |
<div class="sucuriscan-ad-footer">
|
18 |
<ul>
|
@@ -32,7 +32,7 @@
|
|
32 |
<h4>Blacklisted by Google?</h4>
|
33 |
</div>
|
34 |
|
35 |
-
<a href="https://
|
36 |
|
37 |
<div class="sucuriscan-ad-footer sucuriscan-clearfix">
|
38 |
<div class="sucuriscan-pull-left">
|
12 |
</div>
|
13 |
</div>
|
14 |
|
15 |
+
<a href="https://sucuri.net/lp/plugin/wp-pn-protect-wordpress" target="_blank" class="sucuriscan-ad-btn">Protect Your Website Today</a>
|
16 |
|
17 |
<div class="sucuriscan-ad-footer">
|
18 |
<ul>
|
32 |
<h4>Blacklisted by Google?</h4>
|
33 |
</div>
|
34 |
|
35 |
+
<a href="https://sucuri.net/lp/plugin/wp-pn-clean-wordpress-hack" target="_blank" class="sucuriscan-ad-btn">Get Clean Today</a>
|
36 |
|
37 |
<div class="sucuriscan-ad-footer sucuriscan-clearfix">
|
38 |
<div class="sucuriscan-pull-left">
|
inc/tpl/malwarescan.html.tpl
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<div class="sucuriscan-loading">
|
3 |
<h3 class="title">Website Security Scans by Sucuri Sitecheck</h3>
|
4 |
|
5 |
-
<p class="description">Visit our <a href="https://sucuri.net/signup?fromloader" target="_blank">coverage & pricing</a> page for details on how
|
6 |
|
7 |
<form action="%%SUCURI.URL.Scanner%%" method="post" class="sucuriscan-sitecheck-form">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
2 |
<div class="sucuriscan-loading">
|
3 |
<h3 class="title">Website Security Scans by Sucuri Sitecheck</h3>
|
4 |
|
5 |
+
<p class="description">Visit our <a href="https://sucuri.net/signup?fromloader" target="_blank">coverage & pricing</a> page for details on how Sucuri can help you.</p>
|
6 |
|
7 |
<form action="%%SUCURI.URL.Scanner%%" method="post" class="sucuriscan-sitecheck-form">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
inc/tpl/settings-datastorage-files.snippet.tpl
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<tr class="%%SUCURI.DataStorage.CssClass%%">
|
3 |
+
<td class="check-column">
|
4 |
+
<input type="checkbox" name="sucuriscan_fnames[]"
|
5 |
+
%%SUCURI.DataStorage.DisabledInput%%
|
6 |
+
value="%%SUCURI.DataStorage.Fname%%" />
|
7 |
+
</td>
|
8 |
+
<td><span class="sucuriscan-monospace">%%SUCURI.DataStorage.Fpath%%</span></td>
|
9 |
+
<td><span class="sucuriscan-monospace">%%SUCURI.DataStorage.Exists%%</span></td>
|
10 |
+
<td><span class="sucuriscan-monospace">%%SUCURI.DataStorage.IsWritable%%</span></td>
|
11 |
+
</tr>
|
inc/tpl/settings-general-datastorage.html.tpl
CHANGED
@@ -14,49 +14,55 @@
|
|
14 |
|
15 |
<div class="sucuriscan-inline-alert-warning">
|
16 |
<p>
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
21 |
</p>
|
22 |
</div>
|
23 |
|
24 |
-
<div class="sucuriscan-
|
25 |
-
<
|
26 |
-
There are some entries in the options table that will be moved to a plain text
|
27 |
-
file during the development of the next version of the plugin, this is part of
|
28 |
-
a plan to include a way to import and export the settings of this extension to
|
29 |
-
other sites in an easy way. This is necessary as importing data into a database
|
30 |
-
may open security holes <em>(depending on how the code is written)</em> to reduce
|
31 |
-
the risk we will use plain text files which makes things a bit safer.
|
32 |
-
</p>
|
33 |
</div>
|
34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
<div class="sucuriscan-inline-alert-info">
|
36 |
<p>
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
|
|
40 |
</p>
|
41 |
</div>
|
42 |
|
43 |
-
<
|
44 |
-
<
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
<input type="text" name="sucuriscan_datastore_path" class="input-text" />
|
58 |
-
</span>
|
59 |
-
<button type="submit" class="button-primary">Proceed</button>
|
60 |
-
</form>
|
61 |
</div>
|
62 |
</div>
|
14 |
|
15 |
<div class="sucuriscan-inline-alert-warning">
|
16 |
<p>
|
17 |
+
The plugin requires write permissions in this directory as well
|
18 |
+
as the files contained in it. If you prefer to keep these files
|
19 |
+
in a non-public directory <em>(one level up the document root)
|
20 |
+
</em> please define a constant in the <em>"wp-config.php"</em>
|
21 |
+
file named <em>"SUCURI_DATA_STORAGE"</em> with the absolute path
|
22 |
+
to the new directory.
|
23 |
</p>
|
24 |
</div>
|
25 |
|
26 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
27 |
+
<span class="sucuriscan-monospace">%%SUCURI.DatastorePath%%</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
</div>
|
29 |
|
30 |
+
<p>
|
31 |
+
As of version 1.7.18 the plugin started using a plain text file named
|
32 |
+
<em>"sucuri-settings.php"</em> to store its settings instead of the
|
33 |
+
database, this was both a security measure and a mechanism to simplify
|
34 |
+
the management of the settings for multisite installations. Options
|
35 |
+
created in the database by previous versions of the plugin will be
|
36 |
+
migrated to the settings file if it is writable, otherwise they will
|
37 |
+
remain in the database until the user grants write permissions.
|
38 |
+
</p>
|
39 |
+
|
40 |
<div class="sucuriscan-inline-alert-info">
|
41 |
<p>
|
42 |
+
Add this <code>define('SUCURI_SETTINGS_IN', 'database');</code>
|
43 |
+
in the configuration file if you want to keep using the database.
|
44 |
+
However, we encourage you to keep using the plain text files as
|
45 |
+
this guarantees that the automated tests will cover all the code
|
46 |
+
that powers the plugin.
|
47 |
</p>
|
48 |
</div>
|
49 |
|
50 |
+
<table class="wp-list-table widefat sucuriscan-table">
|
51 |
+
<thead>
|
52 |
+
<tr>
|
53 |
+
<th class="manage-column column-cb check-column">
|
54 |
+
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
55 |
+
<input id="cb-select-all-1" type="checkbox">
|
56 |
+
</th>
|
57 |
+
<th class="manage-column">File</th>
|
58 |
+
<th width="70" class="manage-column">Exists?</th>
|
59 |
+
<th width="90" class="manage-column">Writable?</th>
|
60 |
+
</tr>
|
61 |
+
</thead>
|
62 |
|
63 |
+
<tbody>
|
64 |
+
%%%SUCURI.DataStorage.Files%%%
|
65 |
+
</tbody>
|
66 |
+
</table>
|
|
|
|
|
|
|
|
|
67 |
</div>
|
68 |
</div>
|
readme.txt
CHANGED
@@ -1,41 +1,39 @@
|
|
1 |
=== Sucuri Security - Auditing, Malware Scanner and Security Hardening ===
|
2 |
Contributors: dd@sucuri.net
|
3 |
Donate Link: https://sucuri.net/
|
4 |
-
Tags:
|
5 |
Requires at least:3.2
|
6 |
-
Stable tag: 1.8.
|
7 |
-
Tested up to: 4.
|
8 |
|
9 |
-
The Sucuri WordPress Security plugin is a
|
10 |
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
|
15 |
-
Sucuri
|
16 |
website security, with specialization in WordPress Security.
|
17 |
|
18 |
The Sucuri Security WordPress Security plugin is free to all WordPress users.
|
19 |
-
It is a security suite meant to complement your existing security posture
|
20 |
-
|
21 |
-
to have a positive affect on their security posture:
|
22 |
|
23 |
<ol>
|
24 |
-
<li>Security Activity
|
25 |
<li>File Integrity Monitoring</li>
|
26 |
<li>Remote Malware Scanning</li>
|
27 |
<li>Blacklist Monitoring</li>
|
28 |
<li>Effective Security Hardening</li>
|
29 |
<li>Post-Hack Security Actions</li>
|
30 |
<li>Security Notifications</li>
|
31 |
-
<li>Website Firewall (add on)</li>
|
32 |
</ol>
|
33 |
|
34 |
|
35 |
-
= Security Activity
|
36 |
|
37 |
This is perhaps the most underutilized security function. It’s the act of
|
38 |
-
monitoring all security related events within your WordPress
|
39 |
challenge is, what makes up a security event. In the eyes of Sucuri, any
|
40 |
change that occurs within the application could be categorized as a security
|
41 |
event, as such we try to record it.
|
@@ -44,10 +42,6 @@ This is important because it allows you, the website owner, the ability keep a
|
|
44 |
good eye on the various changes occurring within your environment. Who is
|
45 |
logging in? What changes are being made?
|
46 |
|
47 |
-
Here is a video of the Security Activity Monitoring feature:
|
48 |
-
|
49 |
-
[youtube https://www.youtube.com/watch?v=RwEwJgL2-m8]
|
50 |
-
|
51 |
This feature is logging all activity to the Sucuri cloud, for safe keeping.
|
52 |
This ensures that an attacker is not able to wipe your forensic data and
|
53 |
prevent further security analysis after a compromise. If an attacker is able
|
@@ -76,7 +70,7 @@ Here is a video of the Security File Integrity Monitoring feature:
|
|
76 |
[youtube https://www.youtube.com/watch?v=JGbHq7OFs3Q]
|
77 |
|
78 |
|
79 |
-
= Remote
|
80 |
|
81 |
This feature is powered by our very powerful scanning engine, found on our
|
82 |
free security scanner - <a href="https://sitecheck.sucuri.net">SiteCheck</a>. It’s
|
@@ -179,13 +173,10 @@ This is coupled with a number of features like:
|
|
179 |
|
180 |
This is <strong>not included as a free</strong> option to the plugin, but is
|
181 |
integrated so that if purchased you are able to activate. If you prefer to
|
182 |
-
leverage the Sucuri
|
183 |
you have the option to operate the <a href="https://wordpress.org/plugins/sucuri-cloudproxy-waf/">
|
184 |
Website Firewall WordPress Security</a> plugin in standalone mode.
|
185 |
|
186 |
-
Here is a video of the Sucuri Security Website Firewall (Add On Security Service) feature:
|
187 |
-
|
188 |
-
[youtube https://www.youtube.com/watch?v=fN-3DLObLF0]
|
189 |
|
190 |
The Sucuri Security WordPress Security plugin is built by the team that is
|
191 |
known for their proactive approach to security. It is built using intelligence
|
@@ -195,18 +186,18 @@ unique domain scans and 10’s of millions of website security attack blocks.
|
|
195 |
|
196 |
== Installation ==
|
197 |
|
198 |
-
The installation of the Sucuri
|
199 |
simple and straight forward. <a
|
200 |
href="https://sucuri.net/wordpress-security-plugin-installation">A detailed
|
201 |
breakdown of the process is available, including images,</a> below however we
|
202 |
outline the bare minimum steps.
|
203 |
|
204 |
-
Here is a quick video walking you through the installation and configuration of the Sucuri
|
205 |
|
206 |
[youtube https://www.youtube.com/watch?v=KC3UC_Y27G0]
|
207 |
|
208 |
|
209 |
-
To install Sucuri
|
210 |
|
211 |
|
212 |
1. You will want to log into your WordPress administration panel - (e.g.,
|
@@ -270,7 +261,7 @@ end-user. We've narrowed the key features we felt were most pertinent to any
|
|
270 |
website owner and integrated them into this plugin.
|
271 |
|
272 |
|
273 |
-
= If I install the Sucuri
|
274 |
|
275 |
No, this is a free plugin that we offer at no charge. It does not mean you get a free account.
|
276 |
|
@@ -354,6 +345,23 @@ service from the WordPress dashboard.
|
|
354 |
|
355 |
== Changelog ==
|
356 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
= 1.8.1 =
|
358 |
* Modified default setting for the core integrity alerts
|
359 |
* Added more files to the core integrity ignore list
|
1 |
=== Sucuri Security - Auditing, Malware Scanner and Security Hardening ===
|
2 |
Contributors: dd@sucuri.net
|
3 |
Donate Link: https://sucuri.net/
|
4 |
+
Tags: security, malware, firewall, scan, spam, virus, sucuri, protection, backdoors, protection, prevention, monitoring, integrity, auditlog
|
5 |
Requires at least:3.2
|
6 |
+
Stable tag: 1.8.3
|
7 |
+
Tested up to: 4.6.1
|
8 |
|
9 |
+
The Sucuri WordPress Security plugin is a toolset for security integrity monitoring, malware detection, audit logging and security hardening.
|
10 |
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
|
15 |
+
Sucuri is a globally recognized authority in all matters related to
|
16 |
website security, with specialization in WordPress Security.
|
17 |
|
18 |
The Sucuri Security WordPress Security plugin is free to all WordPress users.
|
19 |
+
It is a security suite meant to complement your existing security posture with
|
20 |
+
seven key security features:
|
|
|
21 |
|
22 |
<ol>
|
23 |
+
<li>Security Activity Audit Logging</li>
|
24 |
<li>File Integrity Monitoring</li>
|
25 |
<li>Remote Malware Scanning</li>
|
26 |
<li>Blacklist Monitoring</li>
|
27 |
<li>Effective Security Hardening</li>
|
28 |
<li>Post-Hack Security Actions</li>
|
29 |
<li>Security Notifications</li>
|
|
|
30 |
</ol>
|
31 |
|
32 |
|
33 |
+
= Security Activity Audit Logging =
|
34 |
|
35 |
This is perhaps the most underutilized security function. It’s the act of
|
36 |
+
monitoring all security related events within your WordPress site. The
|
37 |
challenge is, what makes up a security event. In the eyes of Sucuri, any
|
38 |
change that occurs within the application could be categorized as a security
|
39 |
event, as such we try to record it.
|
42 |
good eye on the various changes occurring within your environment. Who is
|
43 |
logging in? What changes are being made?
|
44 |
|
|
|
|
|
|
|
|
|
45 |
This feature is logging all activity to the Sucuri cloud, for safe keeping.
|
46 |
This ensures that an attacker is not able to wipe your forensic data and
|
47 |
prevent further security analysis after a compromise. If an attacker is able
|
70 |
[youtube https://www.youtube.com/watch?v=JGbHq7OFs3Q]
|
71 |
|
72 |
|
73 |
+
= Remote Malware Scanning =
|
74 |
|
75 |
This feature is powered by our very powerful scanning engine, found on our
|
76 |
free security scanner - <a href="https://sitecheck.sucuri.net">SiteCheck</a>. It’s
|
173 |
|
174 |
This is <strong>not included as a free</strong> option to the plugin, but is
|
175 |
integrated so that if purchased you are able to activate. If you prefer to
|
176 |
+
leverage the Sucuri Firewall (CloudProxy) product by itself,
|
177 |
you have the option to operate the <a href="https://wordpress.org/plugins/sucuri-cloudproxy-waf/">
|
178 |
Website Firewall WordPress Security</a> plugin in standalone mode.
|
179 |
|
|
|
|
|
|
|
180 |
|
181 |
The Sucuri Security WordPress Security plugin is built by the team that is
|
182 |
known for their proactive approach to security. It is built using intelligence
|
186 |
|
187 |
== Installation ==
|
188 |
|
189 |
+
The installation of the Sucuri WordPress Security plugin is very
|
190 |
simple and straight forward. <a
|
191 |
href="https://sucuri.net/wordpress-security-plugin-installation">A detailed
|
192 |
breakdown of the process is available, including images,</a> below however we
|
193 |
outline the bare minimum steps.
|
194 |
|
195 |
+
Here is a quick video walking you through the installation and configuration of the Sucuri WordPress Security plugin:
|
196 |
|
197 |
[youtube https://www.youtube.com/watch?v=KC3UC_Y27G0]
|
198 |
|
199 |
|
200 |
+
To install Sucuri and complement your Security posture:
|
201 |
|
202 |
|
203 |
1. You will want to log into your WordPress administration panel - (e.g.,
|
261 |
website owner and integrated them into this plugin.
|
262 |
|
263 |
|
264 |
+
= If I install the Sucuri plugin do I get a Sucuri account? =
|
265 |
|
266 |
No, this is a free plugin that we offer at no charge. It does not mean you get a free account.
|
267 |
|
345 |
|
346 |
== Changelog ==
|
347 |
|
348 |
+
= 1.8.3 =
|
349 |
+
* Fixed fatal error when PHPMailer failed
|
350 |
+
* Fixed incorrect selected value in settings
|
351 |
+
* Fixed kb links and content.
|
352 |
+
* Added SiteCheck for arbitrary domain
|
353 |
+
* Various code cleanup
|
354 |
+
|
355 |
+
= 1.8.2 =
|
356 |
+
* Modified logic of the settings in database checker
|
357 |
+
* Modified default value for the available updates alerts
|
358 |
+
* Fixed undefined array and object keys in audit logs
|
359 |
+
* Fixed incompatibilities with foreign API service responses
|
360 |
+
* Added development option to keep using the database
|
361 |
+
* Added panel with information about the plugin settings
|
362 |
+
* Added conditional to prevent redeclaration of class
|
363 |
+
* Fixed cache flush function used to delete datastore
|
364 |
+
|
365 |
= 1.8.1 =
|
366 |
* Modified default setting for the core integrity alerts
|
367 |
* Added more files to the core integrity ignore list
|
sucuri.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Sucuri Security - Auditing, Malware Scanner and Hardening
|
4 |
-
Plugin URI: https://
|
5 |
-
Description: The <a href="https://sucuri.net/" target="_blank">Sucuri</a> plugin provides the website owner the best
|
6 |
-
Author: Sucuri,
|
7 |
-
Version: 1.8.
|
8 |
Author URI: https://sucuri.net
|
9 |
*/
|
10 |
|
@@ -14,9 +14,9 @@ Author URI: https://sucuri.net
|
|
14 |
*
|
15 |
* @package Sucuri Security
|
16 |
* @author Daniel Cid <dcid@sucuri.net>
|
17 |
-
* @copyright Since 2010-
|
18 |
* @license Released under the GPL - see LICENSE file for details.
|
19 |
-
* @link https://
|
20 |
* @since File available since Release 0.1
|
21 |
*/
|
22 |
|
@@ -65,7 +65,7 @@ define('SUCURISCAN', 'sucuriscan');
|
|
65 |
/**
|
66 |
* Current version of the plugin's code.
|
67 |
*/
|
68 |
-
define('SUCURISCAN_VERSION', '1.8.
|
69 |
|
70 |
/**
|
71 |
* The name of the Sucuri plugin main file.
|
@@ -438,6 +438,31 @@ class SucuriScan
|
|
438 |
{
|
439 |
}
|
440 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
441 |
/**
|
442 |
* Return name of a variable with the plugin's prefix (if needed).
|
443 |
*
|
@@ -606,49 +631,9 @@ class SucuriScan
|
|
606 |
*/
|
607 |
public static function datastore_folder_path($path = '')
|
608 |
{
|
609 |
-
$
|
610 |
-
$abspath = self::fixPath(ABSPATH);
|
611 |
-
|
612 |
-
if (defined('SUCURI_DATA_STORAGE')
|
613 |
-
&& file_exists(SUCURI_DATA_STORAGE)
|
614 |
-
&& is_dir(SUCURI_DATA_STORAGE)
|
615 |
-
) {
|
616 |
-
$datastore = SUCURI_DATA_STORAGE;
|
617 |
-
} else {
|
618 |
-
$datastore = SucuriScanOption::get_option(':datastore_path');
|
619 |
-
}
|
620 |
-
|
621 |
-
// Use the uploads folder by default.
|
622 |
-
if (empty($datastore)) {
|
623 |
-
$uploads_path = false;
|
624 |
|
625 |
-
|
626 |
-
if (function_exists('wp_upload_dir')) {
|
627 |
-
$upload_dir = wp_upload_dir();
|
628 |
-
|
629 |
-
if (isset($upload_dir['basedir'])) {
|
630 |
-
$uploads_path = rtrim($upload_dir['basedir'], DIRECTORY_SEPARATOR);
|
631 |
-
}
|
632 |
-
}
|
633 |
-
|
634 |
-
if ($uploads_path === false) {
|
635 |
-
if (defined('WP_CONTENT_DIR')) {
|
636 |
-
$uploads_path = implode(DIRECTORY_SEPARATOR, array(WP_CONTENT_DIR, 'uploads'));
|
637 |
-
} else {
|
638 |
-
$uploads_path = implode(DIRECTORY_SEPARATOR, array($abspath, 'wp-content', 'uploads'));
|
639 |
-
}
|
640 |
-
}
|
641 |
-
|
642 |
-
$datastore = $uploads_path . DIRECTORY_SEPARATOR . $default_dir;
|
643 |
-
$datastore = self::fixPath($datastore);
|
644 |
-
SucuriScanOption::update_option(':datastore_path', $datastore);
|
645 |
-
}
|
646 |
-
|
647 |
-
// Keep consistency with the directory separator.
|
648 |
-
$final = $datastore . DIRECTORY_SEPARATOR . $path;
|
649 |
-
$final = self::fixPath($final);
|
650 |
-
|
651 |
-
return $final;
|
652 |
}
|
653 |
|
654 |
/**
|
@@ -691,9 +676,7 @@ class SucuriScan
|
|
691 |
}
|
692 |
}
|
693 |
|
694 |
-
|
695 |
-
|
696 |
-
return $wp_version;
|
697 |
}
|
698 |
|
699 |
/**
|
@@ -766,6 +749,7 @@ class SucuriScan
|
|
766 |
public static function run_scheduled_task()
|
767 |
{
|
768 |
SucuriScanEvent::filesystem_scan();
|
|
|
769 |
sucuriscan_core_files_data(true);
|
770 |
sucuriscan_posthack_updates_content(true);
|
771 |
}
|
@@ -911,7 +895,7 @@ class SucuriScan
|
|
911 |
if (function_exists('get_site_url')) {
|
912 |
$site_url = get_site_url();
|
913 |
$pattern = '/([fhtps]+:\/\/)?([^:\/]+)(:[0-9:]+)?(\/.*)?/';
|
914 |
-
$replacement = (
|
915 |
$domain_name = @preg_replace($pattern, $replacement, $site_url);
|
916 |
|
917 |
return $domain_name;
|
@@ -987,9 +971,7 @@ class SucuriScan
|
|
987 |
* the site as protected by a firewall. A fake key can be used to bypass the DNS
|
988 |
* checking, but that is not something that will affect us, only the client.
|
989 |
*/
|
990 |
-
if (
|
991 |
-
&& SucuriScanAPI::getCloudproxyKey()
|
992 |
-
) {
|
993 |
$status = true;
|
994 |
}
|
995 |
|
@@ -1050,9 +1032,7 @@ class SucuriScan
|
|
1050 |
public static function get_admin_users()
|
1051 |
{
|
1052 |
if (function_exists('get_users')) {
|
1053 |
-
|
1054 |
-
|
1055 |
-
return get_users($args);
|
1056 |
}
|
1057 |
|
1058 |
return false;
|
@@ -1076,7 +1056,7 @@ class SucuriScan
|
|
1076 |
if ($users !== false) {
|
1077 |
foreach ($users as $user) {
|
1078 |
if ($user->user_status === '0') {
|
1079 |
-
$valid_users[
|
1080 |
'%s - %s',
|
1081 |
$user->user_login,
|
1082 |
$user->user_email
|
@@ -2687,6 +2667,8 @@ class SucuriScanCache extends SucuriScan
|
|
2687 |
$finfo = $this->getDatastoreContent();
|
2688 |
|
2689 |
if (!empty($finfo['info'])) {
|
|
|
|
|
2690 |
return $finfo['info'];
|
2691 |
}
|
2692 |
|
@@ -2869,6 +2851,10 @@ class SucuriScanCache extends SucuriScan
|
|
2869 |
{
|
2870 |
$finfo = $this->getDatastoreContent();
|
2871 |
|
|
|
|
|
|
|
|
|
2872 |
return $this->saveNewEntries($finfo);
|
2873 |
}
|
2874 |
}
|
@@ -2917,7 +2903,7 @@ class SucuriScanOption extends SucuriScanRequest
|
|
2917 |
'sucuriscan_cloudproxy_apikey' => '',
|
2918 |
'sucuriscan_collect_wrong_passwords' => 'disabled',
|
2919 |
'sucuriscan_comment_monitor' => 'disabled',
|
2920 |
-
'sucuriscan_datastore_path' =>
|
2921 |
'sucuriscan_dismiss_setup' => 'disabled',
|
2922 |
'sucuriscan_dns_lookups' => 'enabled',
|
2923 |
'sucuriscan_email_subject' => 'Sucuri Alert, :domain, :event',
|
@@ -2936,7 +2922,7 @@ class SucuriScanOption extends SucuriScanRequest
|
|
2936 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
2937 |
'sucuriscan_logs4report' => 500,
|
2938 |
'sucuriscan_maximum_failed_logins' => 30,
|
2939 |
-
'sucuriscan_notify_available_updates' => '
|
2940 |
'sucuriscan_notify_bruteforce_attack' => 'disabled',
|
2941 |
'sucuriscan_notify_failed_login' => 'enabled',
|
2942 |
'sucuriscan_notify_plugin_activated' => 'disabled',
|
@@ -2979,9 +2965,6 @@ class SucuriScanOption extends SucuriScanRequest
|
|
2979 |
'sucuriscan_xhr_monitor' => 'disabled',
|
2980 |
);
|
2981 |
|
2982 |
-
$fpath = self::optionsFilePath();
|
2983 |
-
$defaults['sucuriscan_datastore_path'] = dirname($fpath);
|
2984 |
-
|
2985 |
return $defaults;
|
2986 |
}
|
2987 |
|
@@ -3048,6 +3031,41 @@ class SucuriScanOption extends SucuriScanRequest
|
|
3048 |
return false;
|
3049 |
}
|
3050 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3051 |
/**
|
3052 |
* Returns path of the options storage.
|
3053 |
*
|
@@ -3061,7 +3079,10 @@ class SucuriScanOption extends SucuriScanRequest
|
|
3061 |
*/
|
3062 |
public static function optionsFilePath()
|
3063 |
{
|
3064 |
-
$
|
|
|
|
|
|
|
3065 |
|
3066 |
if (defined('SUCURI_DATA_STORAGE')
|
3067 |
&& file_exists(SUCURI_DATA_STORAGE)
|
@@ -3070,7 +3091,7 @@ class SucuriScanOption extends SucuriScanRequest
|
|
3070 |
$folder = SUCURI_DATA_STORAGE;
|
3071 |
}
|
3072 |
|
3073 |
-
return $folder . '/sucuri-settings.php';
|
3074 |
}
|
3075 |
|
3076 |
/**
|
@@ -3209,7 +3230,10 @@ class SucuriScanOption extends SucuriScanRequest
|
|
3209 |
$option = self::variable_prefix($option);
|
3210 |
$options[$option] = $value;
|
3211 |
|
3212 |
-
|
|
|
|
|
|
|
3213 |
}
|
3214 |
|
3215 |
if (function_exists('update_option')) {
|
@@ -5355,16 +5379,19 @@ class SucuriScanAPI extends SucuriScanOption
|
|
5355 |
}
|
5356 |
|
5357 |
$output = curl_exec($curl);
|
5358 |
-
$
|
|
|
5359 |
|
5360 |
curl_close($curl);
|
5361 |
|
5362 |
-
if (array_key_exists('http_code', $
|
5363 |
-
&& $
|
5364 |
&& !empty($output)
|
5365 |
) {
|
5366 |
return $output;
|
5367 |
}
|
|
|
|
|
5368 |
}
|
5369 |
|
5370 |
return false;
|
@@ -6578,7 +6605,6 @@ class SucuriScanAPI extends SucuriScanOption
|
|
6578 |
*/
|
6579 |
class SucuriScanMail extends SucuriScanOption
|
6580 |
{
|
6581 |
-
|
6582 |
/**
|
6583 |
* Check whether the email notifications will be sent in HTML or Plain/Text.
|
6584 |
*
|
@@ -6654,7 +6680,12 @@ class SucuriScanMail extends SucuriScanOption
|
|
6654 |
* @var boolean
|
6655 |
*/
|
6656 |
if (SucuriScanOption::is_enabled(':use_wpmail')) {
|
6657 |
-
|
|
|
|
|
|
|
|
|
|
|
6658 |
} else {
|
6659 |
$headers = implode("\r\n", $headers);
|
6660 |
$mail_sent = @mail($email, $subject, $message, $headers);
|
@@ -6662,6 +6693,7 @@ class SucuriScanMail extends SucuriScanOption
|
|
6662 |
|
6663 |
if ($mail_sent) {
|
6664 |
$emails_sent_num = (int) self::get_option(':emails_sent');
|
|
|
6665 |
self::update_option(':emails_sent', $emails_sent_num + 1);
|
6666 |
self::update_option(':last_email_at', time());
|
6667 |
|
@@ -7196,7 +7228,7 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
7196 |
foreach ($allowed_values as $option_name => $option_label) {
|
7197 |
$options .= sprintf(
|
7198 |
"<option %s value='%s'>%s</option>\n",
|
7199 |
-
($option_name === $selected_val ? 'selected="selected"' : ''),
|
7200 |
SucuriScan::escape($option_name),
|
7201 |
SucuriScan::escape($option_label)
|
7202 |
);
|
@@ -7823,19 +7855,14 @@ class SucuriScanInterface
|
|
7823 |
@mkdir($directory, 0755, true);
|
7824 |
}
|
7825 |
|
7826 |
-
if (
|
7827 |
-
SucuriScanOption::delete_option(':datastore_path');
|
7828 |
-
SucuriScanInterface::error('Uploads directory must not be used as the data store path.');
|
7829 |
-
} elseif (file_exists($directory)) {
|
7830 |
// Create last-logins datastore file.
|
7831 |
sucuriscan_lastlogins_datastore_exists();
|
7832 |
|
7833 |
// Create a htaccess file to deny access from all.
|
7834 |
-
|
7835 |
-
$directory
|
7836 |
-
|
7837 |
-
LOCK_EX
|
7838 |
-
);
|
7839 |
|
7840 |
// Create an index.html to avoid directory listing.
|
7841 |
@file_put_contents(
|
@@ -7843,16 +7870,6 @@ class SucuriScanInterface
|
|
7843 |
'<!-- Prevent the directory listing. -->',
|
7844 |
LOCK_EX
|
7845 |
);
|
7846 |
-
} else {
|
7847 |
-
SucuriScanOption::delete_option(':datastore_path');
|
7848 |
-
SucuriScanInterface::error(
|
7849 |
-
'Data folder does not exists and could not be created. Try to <a href="' .
|
7850 |
-
SucuriScanTemplate::getUrl('settings') . '">click this link</a> to see
|
7851 |
-
if the plugin is able to fix this error automatically, if this message
|
7852 |
-
reappears you will need to either change the location of the directory from
|
7853 |
-
the plugin general settings page or create this directory manually and give
|
7854 |
-
it write permissions: <code>' . $directory . '</code>'
|
7855 |
-
);
|
7856 |
}
|
7857 |
}
|
7858 |
|
@@ -7962,19 +7979,7 @@ class SucuriScanInterface
|
|
7962 |
|
7963 |
// Display the HTML notice to the current user.
|
7964 |
if ($display_notice === true && !empty($message)) {
|
7965 |
-
|
7966 |
-
&& SUCURISCAN_THROW_EXCEPTIONS === true
|
7967 |
-
) {
|
7968 |
-
$number = (string) crc32($type);
|
7969 |
-
$code = (int) substr($number, 0, 3);
|
7970 |
-
$message = str_replace(
|
7971 |
-
'<b>Sucuri:</b>',
|
7972 |
-
($type === 'error' ? 'Error:' : 'Info:'),
|
7973 |
-
$message
|
7974 |
-
);
|
7975 |
-
|
7976 |
-
throw new Exception($message, $code);
|
7977 |
-
}
|
7978 |
|
7979 |
echo SucuriScanTemplate::getSection(
|
7980 |
'notification-admin',
|
@@ -8035,7 +8040,10 @@ class SucuriScanInterface
|
|
8035 |
'/wp-admin/plugins.php',
|
8036 |
);
|
8037 |
|
8038 |
-
if ($page
|
|
|
|
|
|
|
8039 |
return true;
|
8040 |
}
|
8041 |
|
@@ -8209,11 +8217,30 @@ function sucuriscan_scanner_page()
|
|
8209 |
$cache = new SucuriScanCache('sitecheck');
|
8210 |
$scan_results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array');
|
8211 |
$report_results = (bool) ($scan_results && !empty($scan_results));
|
|
|
8212 |
|
8213 |
-
if
|
8214 |
-
|
8215 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8216 |
$report_results = true;
|
|
|
|
|
|
|
8217 |
}
|
8218 |
|
8219 |
if ($report_results === true) {
|
@@ -8254,9 +8281,14 @@ function sucuriscan_scanner_ajax()
|
|
8254 |
*/
|
8255 |
function sucuriscan_sitecheck_info($scan_results = array())
|
8256 |
{
|
8257 |
-
$
|
|
|
|
|
|
|
|
|
|
|
8258 |
$params = array(
|
8259 |
-
'ScannedDomainName' => $
|
8260 |
'ScannerResults.CssClass' => '',
|
8261 |
'ScannerResults.Content' => '',
|
8262 |
'WebsiteDetails.CssClass' => '',
|
@@ -8272,13 +8304,13 @@ function sucuriscan_sitecheck_info($scan_results = array())
|
|
8272 |
|
8273 |
// If the results are not cached, then request a new scan and store in cache.
|
8274 |
if ($scan_results === false) {
|
8275 |
-
$scan_results = SucuriScanAPI::getSitecheckResults($
|
8276 |
|
8277 |
// Check for error messages in the request's response.
|
8278 |
if (is_string($scan_results)) {
|
8279 |
if (@preg_match('/^ERROR:(.*)/', $scan_results, $error_m)) {
|
8280 |
SucuriScanInterface::error(
|
8281 |
-
'The site <code>' . SucuriScan::escape($
|
8282 |
. ' was not scanned: ' . SucuriScan::escape($error_m[1])
|
8283 |
);
|
8284 |
} else {
|
@@ -8432,6 +8464,7 @@ function sucuriscan_sitecheck_website_details($scan_results = false, $params = a
|
|
8432 |
function sucuriscan_sitecheck_general_information($scan_results = false, $secvars = array())
|
8433 |
{
|
8434 |
$possible_keys = array(
|
|
|
8435 |
'DOMAIN' => 'Domain Scanned',
|
8436 |
'IP' => 'Site IP Address',
|
8437 |
'HOSTING' => 'Hosting Company',
|
@@ -9241,8 +9274,9 @@ class SucuriScanHardening extends SucuriScan
|
|
9241 |
$rules_str = implode("\n", $deny_rules);
|
9242 |
$content = str_replace($rules_str, '', $content);
|
9243 |
$written = @file_put_contents($fpath, $content);
|
|
|
9244 |
|
9245 |
-
if (filesize($fpath)
|
9246 |
@unlink($fpath);
|
9247 |
}
|
9248 |
|
@@ -9337,7 +9371,7 @@ class SucuriScanHardening extends SucuriScan
|
|
9337 |
|
9338 |
if (file_exists($htaccess)) {
|
9339 |
if (is_writable($htaccess)) {
|
9340 |
-
$rules = self::whitelist_rule($file);
|
9341 |
@file_put_contents($htaccess, $rules, FILE_APPEND);
|
9342 |
} else {
|
9343 |
throw new Exception('Access control file is not writable');
|
@@ -9358,6 +9392,8 @@ class SucuriScanHardening extends SucuriScan
|
|
9358 |
$content = file_get_contents($htaccess);
|
9359 |
$rules = self::whitelist_rule($file);
|
9360 |
$content = str_replace($rules, '', $content);
|
|
|
|
|
9361 |
@file_put_contents($htaccess, $content);
|
9362 |
}
|
9363 |
}
|
@@ -9366,9 +9402,7 @@ class SucuriScanHardening extends SucuriScan
|
|
9366 |
{
|
9367 |
$htaccess = self::htaccess($folder);
|
9368 |
|
9369 |
-
if (file_exists($htaccess)
|
9370 |
-
&& is_readable($htaccess)
|
9371 |
-
) {
|
9372 |
$content = file_get_contents($htaccess);
|
9373 |
|
9374 |
if (@preg_match_all('/<Files (\S+)>/', $content, $matches)) {
|
@@ -10267,6 +10301,7 @@ function sucuriscan_audit_logs_ajax()
|
|
10267 |
if (SucuriScanRequest::post('form_action') == 'get_audit_logs') {
|
10268 |
$response = array();
|
10269 |
$response['count'] = 0;
|
|
|
10270 |
$response['enable_report'] = false;
|
10271 |
|
10272 |
// Initialize the values for the pagination.
|
@@ -10339,7 +10374,7 @@ function sucuriscan_audit_logs_ajax()
|
|
10339 |
$response['count'] = $counter_i;
|
10340 |
|
10341 |
if ($total_items > 1) {
|
10342 |
-
$max_pages = ceil($audit_logs
|
10343 |
|
10344 |
if ($max_pages > SUCURISCAN_MAX_PAGINATION_BUTTONS) {
|
10345 |
$max_pages = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
@@ -11299,19 +11334,34 @@ function sucuriscan_posthack_updates_content($send_email = false)
|
|
11299 |
|
11300 |
foreach ($updates as $data) {
|
11301 |
$css_class = ($counter % 2 == 0) ? '' : 'alternate';
|
11302 |
-
$
|
11303 |
-
'
|
11304 |
-
|
11305 |
-
|
11306 |
-
|
11307 |
-
|
11308 |
-
|
11309 |
-
|
11310 |
-
|
11311 |
-
'Update.ArchiveUrl' => $data->update->package,
|
11312 |
-
'Update.MarketUrl' => $data->update->url,
|
11313 |
-
)
|
11314 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11315 |
$counter++;
|
11316 |
}
|
11317 |
}
|
@@ -12934,7 +12984,7 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
12934 |
$display_manual_key_form = (bool) (SucuriScanRequest::post(':recover_key') !== false);
|
12935 |
|
12936 |
if ($nonce) {
|
12937 |
-
if (!empty($_POST)) {
|
12938 |
$fpath = SucuriScanOption::optionsFilePath();
|
12939 |
|
12940 |
if (!is_writable($fpath)) {
|
@@ -13022,48 +13072,54 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
13022 |
function sucuriscan_settings_general_datastorage($nonce)
|
13023 |
{
|
13024 |
$params = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13025 |
|
13026 |
-
|
13027 |
-
|
13028 |
-
|
13029 |
-
|
13030 |
-
if ($directory) {
|
13031 |
-
$current = SucuriScanOption::datastore_folder_path();
|
13032 |
-
|
13033 |
-
// Try to create the new directory (if possible).
|
13034 |
-
if (!file_exists($directory)) {
|
13035 |
-
@mkdir($directory, 0755, true);
|
13036 |
-
}
|
13037 |
|
13038 |
-
|
13039 |
-
|
13040 |
-
|
13041 |
-
|
|
|
|
|
|
|
|
|
13042 |
|
13043 |
-
|
13044 |
-
|
13045 |
-
|
13046 |
-
SucuriScanInterface::info($message);
|
13047 |
|
13048 |
-
|
13049 |
-
|
13050 |
|
13051 |
-
|
13052 |
-
|
13053 |
-
|
13054 |
-
|
13055 |
-
|
13056 |
-
|
13057 |
-
|
13058 |
-
|
13059 |
-
|
13060 |
-
|
13061 |
-
|
13062 |
-
}
|
13063 |
}
|
13064 |
|
13065 |
-
$params['DatastorePath'] = SucuriScanOption::get_option(':datastore_path');
|
13066 |
-
|
13067 |
return SucuriScanTemplate::getSection('settings-general-datastorage', $params);
|
13068 |
}
|
13069 |
|
@@ -13551,6 +13607,7 @@ function sucuriscan_settings_corefiles_cache($nonce)
|
|
13551 |
return SucuriScanTemplate::getSection('settings-corefiles-cache', $params);
|
13552 |
}
|
13553 |
|
|
|
13554 |
class SucuriScanSiteCheck extends SucuriScanSettings
|
13555 |
{
|
13556 |
public static function isEnabled()
|
@@ -13643,6 +13700,7 @@ class SucuriScanSiteCheck extends SucuriScanSettings
|
|
13643 |
return SucuriScanTemplate::getSection('settings-sitecheck-timeout', $params);
|
13644 |
}
|
13645 |
}
|
|
|
13646 |
|
13647 |
/**
|
13648 |
* Read and parse the content of the SiteCheck settings template.
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Sucuri Security - Auditing, Malware Scanner and Hardening
|
4 |
+
Plugin URI: https://sucuri.net/
|
5 |
+
Description: The <a href="https://sucuri.net/" target="_blank">Sucuri</a> plugin provides the website owner the best Audit logging, 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 |
+
Author: Sucuri, Inc
|
7 |
+
Version: 1.8.3
|
8 |
Author URI: https://sucuri.net
|
9 |
*/
|
10 |
|
14 |
*
|
15 |
* @package Sucuri Security
|
16 |
* @author Daniel Cid <dcid@sucuri.net>
|
17 |
+
* @copyright Since 2010-2016 Sucuri Inc.
|
18 |
* @license Released under the GPL - see LICENSE file for details.
|
19 |
+
* @link https://sucuri.net/
|
20 |
* @since File available since Release 0.1
|
21 |
*/
|
22 |
|
65 |
/**
|
66 |
* Current version of the plugin's code.
|
67 |
*/
|
68 |
+
define('SUCURISCAN_VERSION', '1.8.3');
|
69 |
|
70 |
/**
|
71 |
* The name of the Sucuri plugin main file.
|
438 |
{
|
439 |
}
|
440 |
|
441 |
+
/**
|
442 |
+
* Throw generic exception instead of silent failure for unit-tests.
|
443 |
+
*
|
444 |
+
* @param string $message Error or information message.
|
445 |
+
* @param string $type Either info or error.
|
446 |
+
* @return void
|
447 |
+
*/
|
448 |
+
public static function throwException($message, $type = 'error')
|
449 |
+
{
|
450 |
+
if (defined('SUCURISCAN_THROW_EXCEPTIONS')
|
451 |
+
&& SUCURISCAN_THROW_EXCEPTIONS === true
|
452 |
+
&& is_string($message)
|
453 |
+
&& !empty($message)
|
454 |
+
) {
|
455 |
+
$code = ($type === 'error' ? 157 : 333);
|
456 |
+
$message = str_replace(
|
457 |
+
'<b>Sucuri:</b>',
|
458 |
+
($type === 'error' ? 'Error:' : 'Info:'),
|
459 |
+
$message
|
460 |
+
);
|
461 |
+
|
462 |
+
throw new Exception($message, $code);
|
463 |
+
}
|
464 |
+
}
|
465 |
+
|
466 |
/**
|
467 |
* Return name of a variable with the plugin's prefix (if needed).
|
468 |
*
|
631 |
*/
|
632 |
public static function datastore_folder_path($path = '')
|
633 |
{
|
634 |
+
$datastore = SucuriScanOption::get_option(':datastore_path');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
635 |
|
636 |
+
return self::fixPath($datastore . '/' . $path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
637 |
}
|
638 |
|
639 |
/**
|
676 |
}
|
677 |
}
|
678 |
|
679 |
+
return self::escape($wp_version);
|
|
|
|
|
680 |
}
|
681 |
|
682 |
/**
|
749 |
public static function run_scheduled_task()
|
750 |
{
|
751 |
SucuriScanEvent::filesystem_scan();
|
752 |
+
|
753 |
sucuriscan_core_files_data(true);
|
754 |
sucuriscan_posthack_updates_content(true);
|
755 |
}
|
895 |
if (function_exists('get_site_url')) {
|
896 |
$site_url = get_site_url();
|
897 |
$pattern = '/([fhtps]+:\/\/)?([^:\/]+)(:[0-9:]+)?(\/.*)?/';
|
898 |
+
$replacement = ($return_tld === true) ? '$2' : '$2$3$4';
|
899 |
$domain_name = @preg_replace($pattern, $replacement, $site_url);
|
900 |
|
901 |
return $domain_name;
|
971 |
* the site as protected by a firewall. A fake key can be used to bypass the DNS
|
972 |
* checking, but that is not something that will affect us, only the client.
|
973 |
*/
|
974 |
+
if (!$status && SucuriScanAPI::getCloudproxyKey()) {
|
|
|
|
|
975 |
$status = true;
|
976 |
}
|
977 |
|
1032 |
public static function get_admin_users()
|
1033 |
{
|
1034 |
if (function_exists('get_users')) {
|
1035 |
+
return get_users(array('role' => 'administrator'));
|
|
|
|
|
1036 |
}
|
1037 |
|
1038 |
return false;
|
1056 |
if ($users !== false) {
|
1057 |
foreach ($users as $user) {
|
1058 |
if ($user->user_status === '0') {
|
1059 |
+
$valid_users[$user->ID] = sprintf(
|
1060 |
'%s - %s',
|
1061 |
$user->user_login,
|
1062 |
$user->user_email
|
2667 |
$finfo = $this->getDatastoreContent();
|
2668 |
|
2669 |
if (!empty($finfo['info'])) {
|
2670 |
+
$finfo['info']['fpath'] = $this->datastore_path;
|
2671 |
+
|
2672 |
return $finfo['info'];
|
2673 |
}
|
2674 |
|
2851 |
{
|
2852 |
$finfo = $this->getDatastoreContent();
|
2853 |
|
2854 |
+
if (array_key_exists('entries', $finfo)) {
|
2855 |
+
$finfo['entries'] = array();
|
2856 |
+
}
|
2857 |
+
|
2858 |
return $this->saveNewEntries($finfo);
|
2859 |
}
|
2860 |
}
|
2903 |
'sucuriscan_cloudproxy_apikey' => '',
|
2904 |
'sucuriscan_collect_wrong_passwords' => 'disabled',
|
2905 |
'sucuriscan_comment_monitor' => 'disabled',
|
2906 |
+
'sucuriscan_datastore_path' => dirname(self::optionsFilePath()),
|
2907 |
'sucuriscan_dismiss_setup' => 'disabled',
|
2908 |
'sucuriscan_dns_lookups' => 'enabled',
|
2909 |
'sucuriscan_email_subject' => 'Sucuri Alert, :domain, :event',
|
2922 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
2923 |
'sucuriscan_logs4report' => 500,
|
2924 |
'sucuriscan_maximum_failed_logins' => 30,
|
2925 |
+
'sucuriscan_notify_available_updates' => 'disabled',
|
2926 |
'sucuriscan_notify_bruteforce_attack' => 'disabled',
|
2927 |
'sucuriscan_notify_failed_login' => 'enabled',
|
2928 |
'sucuriscan_notify_plugin_activated' => 'disabled',
|
2965 |
'sucuriscan_xhr_monitor' => 'disabled',
|
2966 |
);
|
2967 |
|
|
|
|
|
|
|
2968 |
return $defaults;
|
2969 |
}
|
2970 |
|
3031 |
return false;
|
3032 |
}
|
3033 |
|
3034 |
+
/**
|
3035 |
+
* Check if the settings will be stored in the database.
|
3036 |
+
*
|
3037 |
+
* Since version 1.7.18 the plugin started using plain text files to store
|
3038 |
+
* its settings as a security measure to reduce the scope of the attacks
|
3039 |
+
* against the database and to simplify the management of the settings for
|
3040 |
+
* multisite installations. Some users complained about this and suggested
|
3041 |
+
* to create an option to allow them to keep using the database instead of
|
3042 |
+
* plain text files.
|
3043 |
+
*
|
3044 |
+
* We will not add an explicit option in the settings page, but users can go
|
3045 |
+
* around this defining a constant in the configuration file named
|
3046 |
+
* "SUCURI_SETTINGS_IN" with value "database" to force the plugin to store
|
3047 |
+
* its settings in the database instead of the plain text files.
|
3048 |
+
*
|
3049 |
+
* @return boolean True if the settings will be stored in the database.
|
3050 |
+
*/
|
3051 |
+
public static function settingsInDatabase()
|
3052 |
+
{
|
3053 |
+
return (bool) (
|
3054 |
+
defined('SUCURI_SETTINGS_IN')
|
3055 |
+
&& SUCURI_SETTINGS_IN === 'database'
|
3056 |
+
);
|
3057 |
+
}
|
3058 |
+
|
3059 |
+
/**
|
3060 |
+
* Check if the settings will be stored in a plain text file.
|
3061 |
+
*
|
3062 |
+
* @return boolean True if the settings will be stored in a file.
|
3063 |
+
*/
|
3064 |
+
public static function settingsInTextFile()
|
3065 |
+
{
|
3066 |
+
return (bool) (self::settingsInDatabase() === false);
|
3067 |
+
}
|
3068 |
+
|
3069 |
/**
|
3070 |
* Returns path of the options storage.
|
3071 |
*
|
3079 |
*/
|
3080 |
public static function optionsFilePath()
|
3081 |
{
|
3082 |
+
$content_dir = defined('WP_CONTENT_DIR')
|
3083 |
+
? rtrim(WP_CONTENT_DIR, '/')
|
3084 |
+
: ABSPATH . '/wp-content';
|
3085 |
+
$folder = $content_dir . '/uploads/sucuri';
|
3086 |
|
3087 |
if (defined('SUCURI_DATA_STORAGE')
|
3088 |
&& file_exists(SUCURI_DATA_STORAGE)
|
3091 |
$folder = SUCURI_DATA_STORAGE;
|
3092 |
}
|
3093 |
|
3094 |
+
return self::fixPath($folder . '/sucuri-settings.php');
|
3095 |
}
|
3096 |
|
3097 |
/**
|
3230 |
$option = self::variable_prefix($option);
|
3231 |
$options[$option] = $value;
|
3232 |
|
3233 |
+
// Skip if user wants to use the database.
|
3234 |
+
if (self::settingsInTextFile() && self::writeNewOptions($options)) {
|
3235 |
+
return true;
|
3236 |
+
}
|
3237 |
}
|
3238 |
|
3239 |
if (function_exists('update_option')) {
|
5379 |
}
|
5380 |
|
5381 |
$output = curl_exec($curl);
|
5382 |
+
$header = curl_getinfo($curl);
|
5383 |
+
$errors = curl_error($curl);
|
5384 |
|
5385 |
curl_close($curl);
|
5386 |
|
5387 |
+
if (array_key_exists('http_code', $header)
|
5388 |
+
&& $header['http_code'] === 200
|
5389 |
&& !empty($output)
|
5390 |
) {
|
5391 |
return $output;
|
5392 |
}
|
5393 |
+
|
5394 |
+
SucuriScan::throwException($errors);
|
5395 |
}
|
5396 |
|
5397 |
return false;
|
6605 |
*/
|
6606 |
class SucuriScanMail extends SucuriScanOption
|
6607 |
{
|
|
|
6608 |
/**
|
6609 |
* Check whether the email notifications will be sent in HTML or Plain/Text.
|
6610 |
*
|
6680 |
* @var boolean
|
6681 |
*/
|
6682 |
if (SucuriScanOption::is_enabled(':use_wpmail')) {
|
6683 |
+
try {
|
6684 |
+
$mail_sent = wp_mail($email, $subject, $message, $headers);
|
6685 |
+
}
|
6686 |
+
catch (Exception $e) {
|
6687 |
+
$mail_sent = false;
|
6688 |
+
}
|
6689 |
} else {
|
6690 |
$headers = implode("\r\n", $headers);
|
6691 |
$mail_sent = @mail($email, $subject, $message, $headers);
|
6693 |
|
6694 |
if ($mail_sent) {
|
6695 |
$emails_sent_num = (int) self::get_option(':emails_sent');
|
6696 |
+
|
6697 |
self::update_option(':emails_sent', $emails_sent_num + 1);
|
6698 |
self::update_option(':last_email_at', time());
|
6699 |
|
7228 |
foreach ($allowed_values as $option_name => $option_label) {
|
7229 |
$options .= sprintf(
|
7230 |
"<option %s value='%s'>%s</option>\n",
|
7231 |
+
("$option_name" === "$selected_val" ? 'selected="selected"' : ''),
|
7232 |
SucuriScan::escape($option_name),
|
7233 |
SucuriScan::escape($option_label)
|
7234 |
);
|
7855 |
@mkdir($directory, 0755, true);
|
7856 |
}
|
7857 |
|
7858 |
+
if (file_exists($directory)) {
|
|
|
|
|
|
|
7859 |
// Create last-logins datastore file.
|
7860 |
sucuriscan_lastlogins_datastore_exists();
|
7861 |
|
7862 |
// Create a htaccess file to deny access from all.
|
7863 |
+
if (!SucuriScanHardening::is_hardened($directory)) {
|
7864 |
+
SucuriScanHardening::harden_directory($directory);
|
7865 |
+
}
|
|
|
|
|
7866 |
|
7867 |
// Create an index.html to avoid directory listing.
|
7868 |
@file_put_contents(
|
7870 |
'<!-- Prevent the directory listing. -->',
|
7871 |
LOCK_EX
|
7872 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7873 |
}
|
7874 |
}
|
7875 |
|
7979 |
|
7980 |
// Display the HTML notice to the current user.
|
7981 |
if ($display_notice === true && !empty($message)) {
|
7982 |
+
SucuriScan::throwException($message, $type);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7983 |
|
7984 |
echo SucuriScanTemplate::getSection(
|
7985 |
'notification-admin',
|
8040 |
'/wp-admin/plugins.php',
|
8041 |
);
|
8042 |
|
8043 |
+
if ($page
|
8044 |
+
&& is_array($sucuriscan_pages)
|
8045 |
+
&& array_key_exists($page, $sucuriscan_pages)
|
8046 |
+
) {
|
8047 |
return true;
|
8048 |
}
|
8049 |
|
8217 |
$cache = new SucuriScanCache('sitecheck');
|
8218 |
$scan_results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array');
|
8219 |
$report_results = (bool) ($scan_results && !empty($scan_results));
|
8220 |
+
$nonce = SucuriScanInterface::check_nonce();
|
8221 |
|
8222 |
+
// Retrieve SiteCheck scan results if user submits the form.
|
8223 |
+
if ($nonce && SucuriScanRequest::post(':malware_scan')) {
|
8224 |
+
$report_results = true;
|
8225 |
+
}
|
8226 |
+
|
8227 |
+
/**
|
8228 |
+
* Retrieve SiteCheck results from custom domain.
|
8229 |
+
*
|
8230 |
+
* To facilitate the debugging of the code we will allow the existence of a
|
8231 |
+
* GET parameter that will force the plugin to scan a specific website
|
8232 |
+
* instead of the website where the plugin is running. Since this will be a
|
8233 |
+
* semi-hidden feature we can bypass some actions like the recycling of the
|
8234 |
+
* data returned by a previous scan.
|
8235 |
+
*
|
8236 |
+
* Usage: Add "&s=TLD" where TLD is a WordPress or non-WordPress website.
|
8237 |
+
*/
|
8238 |
+
if ($nonce && SucuriScanRequest::get('s')) {
|
8239 |
+
$info = $cache->getDatastoreInfo();
|
8240 |
$report_results = true;
|
8241 |
+
$scan_results = false;
|
8242 |
+
|
8243 |
+
@unlink($info['fpath']);
|
8244 |
}
|
8245 |
|
8246 |
if ($report_results === true) {
|
8281 |
*/
|
8282 |
function sucuriscan_sitecheck_info($scan_results = array())
|
8283 |
{
|
8284 |
+
$tld = SucuriScan::get_domain();
|
8285 |
+
|
8286 |
+
if ($custom = SucuriScanRequest::get('s')) {
|
8287 |
+
$tld = SucuriScan::escape($custom);
|
8288 |
+
}
|
8289 |
+
|
8290 |
$params = array(
|
8291 |
+
'ScannedDomainName' => $tld,
|
8292 |
'ScannerResults.CssClass' => '',
|
8293 |
'ScannerResults.Content' => '',
|
8294 |
'WebsiteDetails.CssClass' => '',
|
8304 |
|
8305 |
// If the results are not cached, then request a new scan and store in cache.
|
8306 |
if ($scan_results === false) {
|
8307 |
+
$scan_results = SucuriScanAPI::getSitecheckResults($tld);
|
8308 |
|
8309 |
// Check for error messages in the request's response.
|
8310 |
if (is_string($scan_results)) {
|
8311 |
if (@preg_match('/^ERROR:(.*)/', $scan_results, $error_m)) {
|
8312 |
SucuriScanInterface::error(
|
8313 |
+
'The site <code>' . SucuriScan::escape($tld) . '</code>'
|
8314 |
. ' was not scanned: ' . SucuriScan::escape($error_m[1])
|
8315 |
);
|
8316 |
} else {
|
8464 |
function sucuriscan_sitecheck_general_information($scan_results = false, $secvars = array())
|
8465 |
{
|
8466 |
$possible_keys = array(
|
8467 |
+
'SITE' => 'Website',
|
8468 |
'DOMAIN' => 'Domain Scanned',
|
8469 |
'IP' => 'Site IP Address',
|
8470 |
'HOSTING' => 'Hosting Company',
|
9274 |
$rules_str = implode("\n", $deny_rules);
|
9275 |
$content = str_replace($rules_str, '', $content);
|
9276 |
$written = @file_put_contents($fpath, $content);
|
9277 |
+
$trimmed = trim($content);
|
9278 |
|
9279 |
+
if (!filesize($fpath) || empty($trimmed)) {
|
9280 |
@unlink($fpath);
|
9281 |
}
|
9282 |
|
9371 |
|
9372 |
if (file_exists($htaccess)) {
|
9373 |
if (is_writable($htaccess)) {
|
9374 |
+
$rules = "\n" . self::whitelist_rule($file);
|
9375 |
@file_put_contents($htaccess, $rules, FILE_APPEND);
|
9376 |
} else {
|
9377 |
throw new Exception('Access control file is not writable');
|
9392 |
$content = file_get_contents($htaccess);
|
9393 |
$rules = self::whitelist_rule($file);
|
9394 |
$content = str_replace($rules, '', $content);
|
9395 |
+
$content = rtrim($content) . "\n";
|
9396 |
+
|
9397 |
@file_put_contents($htaccess, $content);
|
9398 |
}
|
9399 |
}
|
9402 |
{
|
9403 |
$htaccess = self::htaccess($folder);
|
9404 |
|
9405 |
+
if (file_exists($htaccess) && is_readable($htaccess)) {
|
|
|
|
|
9406 |
$content = file_get_contents($htaccess);
|
9407 |
|
9408 |
if (@preg_match_all('/<Files (\S+)>/', $content, $matches)) {
|
10301 |
if (SucuriScanRequest::post('form_action') == 'get_audit_logs') {
|
10302 |
$response = array();
|
10303 |
$response['count'] = 0;
|
10304 |
+
$response['content'] = '';
|
10305 |
$response['enable_report'] = false;
|
10306 |
|
10307 |
// Initialize the values for the pagination.
|
10374 |
$response['count'] = $counter_i;
|
10375 |
|
10376 |
if ($total_items > 1) {
|
10377 |
+
$max_pages = ceil($audit_logs['total_entries'] / $max_per_page);
|
10378 |
|
10379 |
if ($max_pages > SUCURISCAN_MAX_PAGINATION_BUTTONS) {
|
10380 |
$max_pages = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
11334 |
|
11335 |
foreach ($updates as $data) {
|
11336 |
$css_class = ($counter % 2 == 0) ? '' : 'alternate';
|
11337 |
+
$params = array(
|
11338 |
+
'Update.CssClass' => $css_class,
|
11339 |
+
'Update.IconType' => 'plugins',
|
11340 |
+
'Update.Extension' => SucuriScan::excerpt($data->Name, 35),
|
11341 |
+
'Update.Version' => $data->Version,
|
11342 |
+
'Update.NewVersion' => 'Unknown',
|
11343 |
+
'Update.TestedWith' => 'Unknown',
|
11344 |
+
'Update.ArchiveUrl' => 'Unknown',
|
11345 |
+
'Update.MarketUrl' => 'Unknown',
|
|
|
|
|
|
|
11346 |
);
|
11347 |
+
|
11348 |
+
if (property_exists($data->update, 'new_version')) {
|
11349 |
+
$params['Update.NewVersion'] = $data->update->new_version;
|
11350 |
+
}
|
11351 |
+
|
11352 |
+
if (property_exists($data->update, 'tested')) {
|
11353 |
+
$params['Update.TestedWith'] = "WordPress\x20" . $data->update->tested;
|
11354 |
+
}
|
11355 |
+
|
11356 |
+
if (property_exists($data->update, 'package')) {
|
11357 |
+
$params['Update.ArchiveUrl'] = $data->update->package;
|
11358 |
+
}
|
11359 |
+
|
11360 |
+
if (property_exists($data->update, 'url')) {
|
11361 |
+
$params['Update.MarketUrl'] = $data->update->url;
|
11362 |
+
}
|
11363 |
+
|
11364 |
+
$response .= SucuriScanTemplate::getSnippet('posthack-updates', $params);
|
11365 |
$counter++;
|
11366 |
}
|
11367 |
}
|
12984 |
$display_manual_key_form = (bool) (SucuriScanRequest::post(':recover_key') !== false);
|
12985 |
|
12986 |
if ($nonce) {
|
12987 |
+
if (!empty($_POST) && SucuriScanOption::settingsInTextFile()) {
|
12988 |
$fpath = SucuriScanOption::optionsFilePath();
|
12989 |
|
12990 |
if (!is_writable($fpath)) {
|
13072 |
function sucuriscan_settings_general_datastorage($nonce)
|
13073 |
{
|
13074 |
$params = array();
|
13075 |
+
$files = array(
|
13076 |
+
'', /* <root> */
|
13077 |
+
'auditqueue',
|
13078 |
+
'blockedusers',
|
13079 |
+
'failedlogins',
|
13080 |
+
'ignorescanning',
|
13081 |
+
'integrity',
|
13082 |
+
'lastlogins',
|
13083 |
+
'oldfailedlogins',
|
13084 |
+
'plugindata',
|
13085 |
+
'settings',
|
13086 |
+
'sitecheck',
|
13087 |
+
'trustip',
|
13088 |
+
);
|
13089 |
|
13090 |
+
$counter = 0;
|
13091 |
+
$params['DataStorage.Files'] = '';
|
13092 |
+
$params['DatastorePath'] = SucuriScanOption::get_option(':datastore_path');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13093 |
|
13094 |
+
foreach ($files as $name) {
|
13095 |
+
$counter++;
|
13096 |
+
$fname = ($name ? sprintf('sucuri-%s.php', $name) : '');
|
13097 |
+
$fpath = SucuriScan::datastore_folder_path($fname);
|
13098 |
+
$exists = (file_exists($fpath) ? 'Yes' : 'No');
|
13099 |
+
$iswritable = (is_writable($fpath) ? 'Yes' : 'No');
|
13100 |
+
$css_class = ($counter % 2 === 0) ? 'alternate' : '';
|
13101 |
+
$disabled = 'disabled="disabled"';
|
13102 |
|
13103 |
+
if ($exists === 'Yes' && $iswritable === 'Yes') {
|
13104 |
+
$disabled = ''; /* Allow file deletion */
|
13105 |
+
}
|
|
|
13106 |
|
13107 |
+
// Remove unnecessary parts from the file path.
|
13108 |
+
$fpath = str_replace(ABSPATH, '/', $fpath);
|
13109 |
|
13110 |
+
$params['DataStorage.Files'] .= SucuriScanTemplate::getSnippet(
|
13111 |
+
'settings-datastorage-files',
|
13112 |
+
array(
|
13113 |
+
'DataStorage.CssClass' => $css_class,
|
13114 |
+
'DataStorage.Fname' => $fname,
|
13115 |
+
'DataStorage.Fpath' => $fpath,
|
13116 |
+
'DataStorage.Exists' => $exists,
|
13117 |
+
'DataStorage.IsWritable' => $iswritable,
|
13118 |
+
'DataStorage.DisabledInput' => $disabled,
|
13119 |
+
)
|
13120 |
+
);
|
|
|
13121 |
}
|
13122 |
|
|
|
|
|
13123 |
return SucuriScanTemplate::getSection('settings-general-datastorage', $params);
|
13124 |
}
|
13125 |
|
13607 |
return SucuriScanTemplate::getSection('settings-corefiles-cache', $params);
|
13608 |
}
|
13609 |
|
13610 |
+
if (!class_exists('SucuriScanSiteCheck')) {
|
13611 |
class SucuriScanSiteCheck extends SucuriScanSettings
|
13612 |
{
|
13613 |
public static function isEnabled()
|
13700 |
return SucuriScanTemplate::getSection('settings-sitecheck-timeout', $params);
|
13701 |
}
|
13702 |
}
|
13703 |
+
}
|
13704 |
|
13705 |
/**
|
13706 |
* Read and parse the content of the SiteCheck settings template.
|