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

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 Icon 128x128 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 CHANGED
@@ -12,7 +12,7 @@
12
</div>
13
</div>
14
15
- <a href="https://goo.gl/9sD2sh" target="_blank" class="sucuriscan-ad-btn">Protect Your Website Today</a>
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://goo.gl/vEwZq6" 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">
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 &amp; 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%%" />
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 &amp; 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
- Note that the virtual protection added by the plugin to these files is not bullet
18
- proof, it may be bypassed and depending on the configuration of the server it may
19
- leak information, but this is better than to store the data in the database and
20
- wait for a SQL injection to be used to attack the rest of the site.
21
</p>
22
</div>
23
24
- <div class="sucuriscan-inline-alert-info">
25
- <p>
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
- An alternative to this setting you can opt to set the directory path from the
38
- WordPress configuration file using a constant named <em>"SUCURI_DATA_STORAGE"</em>
39
- it must contain a valid and existing absolute directory path.
40
</p>
41
</div>
42
43
- <div class="sucuriscan-hstatus sucuriscan-hstatus-2">
44
- <span class="sucuriscan-monospace">%%SUCURI.DatastorePath%%</span>
45
- </div>
46
-
47
- <p>
48
- Some people may prefer to use a folder that is not in the document root of the
49
- website to add another layer of protection to the data, feel free to change this
50
- path if you want, make sure to use absolute paths.
51
- </p>
52
53
- <form action="%%SUCURI.URL.Settings%%" method="post">
54
- <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
55
- <span class="sucuriscan-input-group">
56
- <label>Data Storage Path:</label>
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: malware, security, firewall, scan, spam, virus, sucuri, protection,WordPress Security, Login Security,Security Auditing,File Integrity,htaccess,phishing,backdoors,SQL Injection, RFI, LFI, XSS, CSRF, website firewall, Website Security, Performance Optimization, Zero Day, Software Vulnerability, Exploits, Hacks, Attackers, Bad Actors, Reverse Proxy, Two Factor Security, Two Factor Authentication, Security Logs, HeatBleed Vulnerability, Website Protection, Bash Vulnerability, RevSlider Vulnerability, MailPoet Vulnerability, Malware Prevention, Website Firewall, Website AntiVirus, Security Response, Security Detection, Security Prevention
5
Requires at least:3.2
6
- Stable tag: 1.8.1
7
- Tested up to: 4.5.3
8
9
- The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
10
11
12
== Description ==
13
14
15
- Sucuri Inc 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. It
20
- offers it’s users four key security features for their website, each designed
21
- to have a positive affect on their security posture:
22
23
<ol>
24
- <li>Security Activity Auditing</li>
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 Monitoring =
36
37
This is perhaps the most underutilized security function. It’s the act of
38
- monitoring all security related events within your WordPress install. The
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 Security Malware Scanning =
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 Security Website Firewall (CloudProxy) product by itself,
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 Security WordPress Security plugin is very
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 Security WordPress Security plugin:
205
206
[youtube https://www.youtube.com/watch?v=KC3UC_Y27G0]
207
208
209
- To install Sucuri Security and complement your Security posture:
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 Security plugin do I get a Sucuri account? =
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://wordpress.sucuri.net/
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
- Author: Sucuri, INC
7
- Version: 1.8.1
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-2015 Sucuri Inc.
18
* @license Released under the GPL - see LICENSE file for details.
19
- * @link https://wordpress.sucuri.net/
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.1');
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
- $default_dir = 'sucuri';
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
- // Multisite installations may have different paths.
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
- $wp_version = self::escape($wp_version);
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 = ( $return_tld === true ) ? '$2' : '$2$3$4';
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 ($status === false
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
- $args = array( 'role' => 'administrator' );
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[ $user->ID ] = sprintf(
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' => 'enabled',
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
- $folder = WP_CONTENT_DIR . '/uploads/sucuri';
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
- return self::writeNewOptions($options);
3213
}
3214
3215
if (function_exists('update_option')) {
@@ -5355,16 +5379,19 @@ class SucuriScanAPI extends SucuriScanOption
5355
}
5356
5357
$output = curl_exec($curl);
5358
- $headers = curl_getinfo($curl);
5359
5360
curl_close($curl);
5361
5362
- if (array_key_exists('http_code', $headers)
5363
- && $headers['http_code'] === 200
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
- $mail_sent = wp_mail($email, $subject, $message, $headers);
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 (@preg_match(';/uploads/$;', $directory)) {
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
- @file_put_contents(
7835
- $directory . '/.htaccess',
7836
- "Order Deny,Allow\nDeny from all\n",
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
- if (defined('SUCURISCAN_THROW_EXCEPTIONS')
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 && array_key_exists($page, $sucuriscan_pages)) {
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 (SucuriScanInterface::check_nonce()
8214
- && SucuriScanRequest::post(':malware_scan', '1')
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
- $clean_domain = SucuriScan::get_domain();
8258
$params = array(
8259
- 'ScannedDomainName' => $clean_domain,
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($clean_domain);
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($clean_domain) . '</code>'
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) === 0) {
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->total_entries / $max_per_page);
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
- $response .= SucuriScanTemplate::getSnippet(
11303
- 'posthack-updates',
11304
- array(
11305
- 'Update.CssClass' => $css_class,
11306
- 'Update.IconType' => 'plugins',
11307
- 'Update.Extension' => SucuriScan::excerpt($data->Name, 35),
11308
- 'Update.Version' => $data->Version,
11309
- 'Update.NewVersion' => $data->update->new_version,
11310
- 'Update.TestedWith' => "WordPress\x20" . $data->update->tested,
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
- // Update the datastore path (if the new directory exists).
13027
- if ($nonce) {
13028
- $directory = SucuriScanRequest::post(':datastore_path');
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
- // Check if the directory is writable and move all the logs.
13039
- if (file_exists($directory)) {
13040
- if (is_writable($directory)) {
13041
- $message = 'Datastore path set to <code>' . $directory . '</code>';
13042
13043
- SucuriScanOption::update_option(':datastore_path', $directory);
13044
- SucuriScanEvent::report_info_event($message);
13045
- SucuriScanEvent::notify_event('plugin_change', $message);
13046
- SucuriScanInterface::info($message);
13047
13048
- if (file_exists($current)) {
13049
- $newpath = SucuriScanOption::datastore_folder_path();
13050
13051
- // Some file systems do not work correctly with trailing separators.
13052
- $current = rtrim($current, '/');
13053
- $newpath = rtrim($newpath, '/');
13054
- @rename($current, $newpath);
13055
- }
13056
- } else {
13057
- SucuriScanInterface::error('The new directory path is not writable.');
13058
- }
13059
- } else {
13060
- SucuriScanInterface::error('The directory path specified does not exists.');
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.