Version Description
- Added Hardening option to remove error log files
- Bug fixes on some new registrations.
- Changed format of the internal logs to json.
Download this release
Release Info
Developer | dd@sucuri.net |
Plugin | Sucuri Security – Auditing, Malware Scanner and Security Hardening |
Version | 1.7.0 |
Comparing to | |
See all releases |
Code changes from version 1.6.9 to 1.7.0
- inc/tpl/notification-pretty.html.tpl +2 -9
- inc/tpl/settings-general.html.tpl +17 -5
- inc/tpl/settings-notifications.html.tpl +28 -1
- readme.txt +208 -43
- sucuri.php +323 -64
inc/tpl/notification-pretty.html.tpl
CHANGED
@@ -1,15 +1,10 @@
|
|
1 |
-
|
2 |
-
<html>
|
3 |
-
<head>
|
4 |
-
<title>%%SUCURI.TemplateTitle%%</title>
|
5 |
-
</head>
|
6 |
-
<body>
|
7 |
<table class="sucuriscan-template" style="width:90%;background:#fff;font-family:Arial,Helvetica,sans-serif;border-spacing:0">
|
8 |
<thead sytle="border-bottom:1px solid #ccc">
|
9 |
<tr style="background-color:#4b4b4b;background-image:-moz-linear-gradient(top, #555555, #3b3b3b);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#3b3b3b));background-image:-webkit-linear-gradient(top, #555555, #3b3b3b);background-image:-o-linear-gradient(top, #555555, #3b3b3b);background-image:linear-gradient(to bottom, #555555, #3b3b3b);background-repeat:repeat-x">
|
10 |
<td sytle="font-size:20px;font-weight:normal;color:#ffffff;padding:10px;border-right:1px solid #2f2f2f;border-left:1px solid #6f6f6f;-webkit-box-shadow:inset 0 1px 0 #888888;-moz-box-shadow:inset 0 1px 0 #888888;box-shadow:inset 0 1px 0 #888888;text-shadow:1px 1px 2px rgba(0, 0, 0, 0.5)">
|
11 |
<a href="http://sucuri.net/" style="text-decoration:none;display:inline-block;margin:8px 0 5px 20px">
|
12 |
-
<img src="http://sucuri.net/wp-content/themes/sucuri-two/images/main-logo.png" style="border:none" />
|
13 |
</a>
|
14 |
<span style="display:inline-block;line-height:46px;margin:0 20px 0 0;float:right;color:#ffffff">%%SUCURI.TemplateTitle%%</span>
|
15 |
</td>
|
@@ -34,5 +29,3 @@
|
|
34 |
</tr>
|
35 |
</tbody>
|
36 |
</table>
|
37 |
-
</body>
|
38 |
-
</html>
|
1 |
+
|
|
|
|
|
|
|
|
|
|
|
2 |
<table class="sucuriscan-template" style="width:90%;background:#fff;font-family:Arial,Helvetica,sans-serif;border-spacing:0">
|
3 |
<thead sytle="border-bottom:1px solid #ccc">
|
4 |
<tr style="background-color:#4b4b4b;background-image:-moz-linear-gradient(top, #555555, #3b3b3b);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#3b3b3b));background-image:-webkit-linear-gradient(top, #555555, #3b3b3b);background-image:-o-linear-gradient(top, #555555, #3b3b3b);background-image:linear-gradient(to bottom, #555555, #3b3b3b);background-repeat:repeat-x">
|
5 |
<td sytle="font-size:20px;font-weight:normal;color:#ffffff;padding:10px;border-right:1px solid #2f2f2f;border-left:1px solid #6f6f6f;-webkit-box-shadow:inset 0 1px 0 #888888;-moz-box-shadow:inset 0 1px 0 #888888;box-shadow:inset 0 1px 0 #888888;text-shadow:1px 1px 2px rgba(0, 0, 0, 0.5)">
|
6 |
<a href="http://sucuri.net/" style="text-decoration:none;display:inline-block;margin:8px 0 5px 20px">
|
7 |
+
<img src="http://sucuri.net/wp-content/themes/sucuri-two/images/main-logo.png" alt="Sucuri, Inc." style="border:none" />
|
8 |
</a>
|
9 |
<span style="display:inline-block;line-height:46px;margin:0 20px 0 0;float:right;color:#ffffff">%%SUCURI.TemplateTitle%%</span>
|
10 |
</td>
|
29 |
</tr>
|
30 |
</tbody>
|
31 |
</table>
|
|
|
|
inc/tpl/settings-general.html.tpl
CHANGED
@@ -38,11 +38,11 @@
|
|
38 |
</tr>
|
39 |
|
40 |
<tr class="alternate">
|
41 |
-
<td>API Key</td>
|
42 |
<td>
|
43 |
<span class="sucuriscan-monospace">%%SUCURI.APIKey%%</span>
|
44 |
</td>
|
45 |
-
<td class="td-with-button">
|
46 |
<form action="%%SUCURI.URL.Settings%%" method="post" class="sucuriscan-%%SUCURI.APIKey.RecoverVisibility%%">
|
47 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
48 |
<button type="submit" name="sucuriscan_recover_key" class="button-primary">Recover</button>
|
@@ -63,7 +63,7 @@
|
|
63 |
|
64 |
<tr>
|
65 |
<td>Notify events to</td>
|
66 |
-
<td
|
67 |
<td class="td-with-button">
|
68 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
69 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -164,6 +164,18 @@
|
|
164 |
</tr>
|
165 |
|
166 |
<tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
<td>Last Scanning</td>
|
168 |
<td><span class="sucuriscan-monospace">%%SUCURI.ScanningRuntimeHuman%%</span></td>
|
169 |
<td class="td-with-button">
|
@@ -174,7 +186,7 @@
|
|
174 |
</td>
|
175 |
</tr>
|
176 |
|
177 |
-
<tr
|
178 |
<td>Scanning frequency</td>
|
179 |
<td>%%SUCURI.ScanningFrequency%%</td>
|
180 |
<td class="td-with-button">
|
@@ -188,7 +200,7 @@
|
|
188 |
</td>
|
189 |
</tr>
|
190 |
|
191 |
-
<tr class="sucuriscan-%%SUCURI.ScanningInterfaceVisibility%%">
|
192 |
<td>Scanning interface</td>
|
193 |
<td>%%SUCURI.ScanningInterface%%</td>
|
194 |
<td class="td-with-button">
|
38 |
</tr>
|
39 |
|
40 |
<tr class="alternate">
|
41 |
+
<td width="200">API Key</td>
|
42 |
<td>
|
43 |
<span class="sucuriscan-monospace">%%SUCURI.APIKey%%</span>
|
44 |
</td>
|
45 |
+
<td width="350" class="td-with-button">
|
46 |
<form action="%%SUCURI.URL.Settings%%" method="post" class="sucuriscan-%%SUCURI.APIKey.RecoverVisibility%%">
|
47 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
48 |
<button type="submit" name="sucuriscan_recover_key" class="button-primary">Recover</button>
|
63 |
|
64 |
<tr>
|
65 |
<td>Notify events to</td>
|
66 |
+
<td>%%SUCURI.NotifyTo%%</td>
|
67 |
<td class="td-with-button">
|
68 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
69 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
164 |
</tr>
|
165 |
|
166 |
<tr>
|
167 |
+
<td>Scan error log files</td>
|
168 |
+
<td>%%SUCURI.ScanErrorlogsStatus%%</td>
|
169 |
+
<td class="td-with-button">
|
170 |
+
<form action="%%SUCURI.URL.Settings%%" method="post">
|
171 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
172 |
+
<input type="hidden" name="sucuriscan_scan_errorlogs" value="%%SUCURI.ScanErrorlogsSwitchValue%%" />
|
173 |
+
<button type="submit" class="button-primary %%SUCURI.ScanErrorlogsSwitchCssClass%%">%%SUCURI.ScanErrorlogsSwitchText%%</button>
|
174 |
+
</form>
|
175 |
+
</td>
|
176 |
+
</tr>
|
177 |
+
|
178 |
+
<tr class="alternate">
|
179 |
<td>Last Scanning</td>
|
180 |
<td><span class="sucuriscan-monospace">%%SUCURI.ScanningRuntimeHuman%%</span></td>
|
181 |
<td class="td-with-button">
|
186 |
</td>
|
187 |
</tr>
|
188 |
|
189 |
+
<tr>
|
190 |
<td>Scanning frequency</td>
|
191 |
<td>%%SUCURI.ScanningFrequency%%</td>
|
192 |
<td class="td-with-button">
|
200 |
</td>
|
201 |
</tr>
|
202 |
|
203 |
+
<tr class="alternate sucuriscan-%%SUCURI.ScanningInterfaceVisibility%%">
|
204 |
<td>Scanning interface</td>
|
205 |
<td>%%SUCURI.ScanningInterface%%</td>
|
206 |
<td class="td-with-button">
|
inc/tpl/settings-notifications.html.tpl
CHANGED
@@ -1,10 +1,37 @@
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
<form action="%%SUCURI.URL.Settings%%#settings-notifications" method="post">
|
3 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-notifications">
|
4 |
<thead>
|
5 |
<tr>
|
6 |
<th colspan="3" class="thead-with-button">
|
7 |
-
<span>
|
8 |
<div class="thead-topright-action">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<button type="submit" name="sucuriscan_save_notification_settings" class="button-primary">Save</button>
|
1 |
|
2 |
+
<div id="poststuff">
|
3 |
+
<div class="postbox sucuriscan-border sucuriscan-table-description">
|
4 |
+
<h3>Notification Settings</h3>
|
5 |
+
|
6 |
+
<div class="inside">
|
7 |
+
<p>
|
8 |
+
Check the boxes bellow to receive alerts via email of the events explained in
|
9 |
+
the table, by the default the notifications will be sent to the address
|
10 |
+
configured during the installation of your site, you can change this in the
|
11 |
+
<em>General Settings</em> panel. You can specify multiple recipients separating
|
12 |
+
each address with a comma.
|
13 |
+
</p>
|
14 |
+
|
15 |
+
<div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.PrettifyMailsWarningVisibility%%">
|
16 |
+
<p>
|
17 |
+
Some emails sent by this plugin will be rejected outright by some popular email
|
18 |
+
services. To fix this you will need to use a third-party email service, or use a
|
19 |
+
plugin to force the site to use SMTP <em>(Simple Mail Transfer Protocol)</em>
|
20 |
+
for sending emails, and then configure your SMTP server to properly handle
|
21 |
+
messages. You can also <strong>disable HTML alerts</strong> to get notifications
|
22 |
+
in <em>text/plain</em> format.
|
23 |
+
</p>
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
|
29 |
<form action="%%SUCURI.URL.Settings%%#settings-notifications" method="post">
|
30 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-notifications">
|
31 |
<thead>
|
32 |
<tr>
|
33 |
<th colspan="3" class="thead-with-button">
|
34 |
+
<span>Notification Settings</span>
|
35 |
<div class="thead-topright-action">
|
36 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
37 |
<button type="submit" name="sucuriscan_save_notification_settings" class="button-primary">Save</button>
|
readme.txt
CHANGED
@@ -1,71 +1,233 @@
|
|
1 |
=== Sucuri Security - Auditing, Malware Scanner and Hardening ===
|
2 |
Contributors: dd@sucuri.net
|
3 |
Donate Link: http://sitecheck.sucuri.net
|
4 |
-
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection
|
5 |
Requires at least:3.2
|
6 |
-
Stable tag:1.
|
7 |
Tested up to: 4.0
|
8 |
|
9 |
-
The Sucuri WordPress Security plugin
|
|
|
10 |
|
11 |
== Description ==
|
12 |
|
13 |
-
The Sucuri Security - Auditing, SiteCheck Malware Scanner and Hardening is a security plugin enables you to scan your WordPress site using Sucuri SiteCheck for security and malware issues, and also verifies the security integrity of your core files right in your dashboard. It includes audit trails and post-hack security ions to help you reset passwords and secret keys in case it has been already hacked, or infected with malware.
|
14 |
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
-
Sucuri SiteCheck detects various types of malware, SPAM injections, website errors, disabled sites, database connection issues and code anomalies that require special attention to include:
|
18 |
|
19 |
-
|
20 |
-
* Cross Site Scripting (XSS)
|
21 |
-
* Website Defacements
|
22 |
-
* Hidden & Malicious iFrames
|
23 |
-
* PHP Mailers
|
24 |
-
* Phishing Attempts
|
25 |
-
* Malicious Redirects
|
26 |
-
* Anomalies
|
27 |
-
* Drive-by-Downloads
|
28 |
-
* IP Cloaking
|
29 |
-
* Social Engineering Attacks
|
30 |
|
|
|
|
|
|
|
31 |
|
32 |
-
There are a number of blacklisting authorities that monitor for malware, SPAM, and phishing attempts. Sucuri SiteCheck leverages the APIs for these authorities to check your website blacklisting status:
|
33 |
|
34 |
-
|
35 |
-
* Google Safe Browsing
|
36 |
-
* Norton
|
37 |
-
* AVG
|
38 |
-
* Phish Tank (Phishing Specifically)
|
39 |
-
* ESET
|
40 |
-
* McAfee SiteAdvisor
|
41 |
-
* Yandex
|
42 |
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
-
* Verify WordPress Version
|
46 |
-
* Protect Uploads Directory
|
47 |
-
* Restrict wp-content Access
|
48 |
-
* Restrict wp-includes Access
|
49 |
-
* Verify PHP Version
|
50 |
-
* Disable the theme and plugin editors
|
51 |
|
52 |
-
|
53 |
-
which can be useful to detect hidden backdoors.
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
the
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
|
60 |
== Installation ==
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
|
67 |
== Changelog ==
|
68 |
|
|
|
|
|
|
|
|
|
|
|
69 |
= 1.6.9 =
|
70 |
* Multiple bug fixes (as reported on the support forums).
|
71 |
* Added heartbeat for the file scans.
|
@@ -129,7 +291,8 @@ the compromise on your site).
|
|
129 |
= 1.5.4 = Bug fixes.
|
130 |
|
131 |
= 1.5.2 =
|
132 |
-
* Adding additional information about .htaccess hacks and the server
|
|
|
133 |
|
134 |
= 1.5.0 =
|
135 |
* Fixing last login and giving better warns on permission errors.
|
@@ -151,7 +314,8 @@ the compromise on your site).
|
|
151 |
* Fixing some issues on the last login and allowing the option to disable it.
|
152 |
|
153 |
= 1.4.4 =
|
154 |
-
* Small bug fixes + forcing a re-scan on every scan attempt (not using the
|
|
|
155 |
|
156 |
= 1.4.3 =
|
157 |
* Fixing a few PHP warnings.
|
@@ -210,6 +374,7 @@ the compromise on your site).
|
|
210 |
= 1.1.1 =
|
211 |
* First public release.
|
212 |
|
|
|
213 |
== Credits ==
|
214 |
|
215 |
* <a href="http://sucuri.net">Sucuri Security</a>
|
1 |
=== Sucuri Security - Auditing, Malware Scanner and Hardening ===
|
2 |
Contributors: dd@sucuri.net
|
3 |
Donate Link: http://sitecheck.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,
|
5 |
Requires at least:3.2
|
6 |
+
Stable tag:1.7.0
|
7 |
Tested up to: 4.0
|
8 |
|
9 |
+
The Sucuri WordPress Security plugin is the best security toolset for security integrity monitoring, activity monitoring and malware detection. It’s a complementary toolset to your existing security posture.
|
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.
|
42 |
+
|
43 |
+
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 |
+
This feature is logging all activity to the Sucuri cloud, for safe keeping.
|
48 |
+
This ensures that an attacker is not able to wipe your forensic data and
|
49 |
+
prevent further security analysis after a compromise. If an attacker is able
|
50 |
+
to bypass your security controls, your security logs will be kept safe within
|
51 |
+
the Sucuri Security Operations Center (SOC).
|
52 |
+
|
53 |
+
This feature is particularly important to website / system administrators and
|
54 |
+
security experts looking to understand what is going on with their website and
|
55 |
+
when it’s happening.
|
56 |
+
|
57 |
+
|
58 |
+
= Security File Integrity Monitoring =
|
59 |
+
|
60 |
+
Security File Integrity Monitoring has been fundamental to the world of
|
61 |
+
security. It’s the act of comparing a known good with the current state. If
|
62 |
+
the current state differs from the known good, you know you have a problem.
|
63 |
+
This is the basis of a lot of host Intrusion detection systems. It’s what we
|
64 |
+
have built into the plugin.
|
65 |
+
|
66 |
+
It will create a <strong>known good</strong> the minute the plugin is
|
67 |
+
installed. This will be of all the directories at the root of the install,
|
68 |
+
this includes plugins, themes and core files.
|
69 |
+
|
70 |
+
|
71 |
+
= Remote Security Malware Scanning =
|
72 |
+
|
73 |
+
This feature is powered by our very powerful scanning engine, found on our
|
74 |
+
free security scanner - <a href="http://sitecheck.sucuri.net">SiteCheck. It’s
|
75 |
+
important to take some time to <a
|
76 |
+
href="http://blog.sucuri.net/2012/10/ask-sucuri-how-does-sitecheck-work.html">understand
|
77 |
+
how this scanner works</a>.
|
78 |
+
|
79 |
+
There are limitations with the way this scanner works, you can find more info
|
80 |
+
on that in the FAQ section.
|
81 |
+
|
82 |
+
|
83 |
+
= Security Blacklist Monitoring =
|
84 |
+
|
85 |
+
Another very interesting feature of the Security Malware Scanner is that it
|
86 |
+
incorporates various blacklist engines. Security blacklist engines include the
|
87 |
+
following:
|
88 |
+
|
89 |
+
<ol>
|
90 |
+
<li>Sucuri Labs</li>
|
91 |
+
<li>Google Safe Browsing</li>
|
92 |
+
<li>Norton</li>
|
93 |
+
<li>AVG</li>
|
94 |
+
<li>Phish Tank</li>
|
95 |
+
<li>ESET</li>
|
96 |
+
<li>McAfee Site Advisor</li>
|
97 |
+
<li>Yandex</li>
|
98 |
+
<li>SpamHaus</li>
|
99 |
+
<li>Bitdefender</li>
|
100 |
+
</ol>
|
101 |
+
|
102 |
+
These are some of the largest blacklisting entities, each having the ability
|
103 |
+
to directly impact your brands online reputation. By synchronize with their
|
104 |
+
environments we’re able to tell you, upon scan, whether any of them are
|
105 |
+
negatively flagging your website with a security related issue.
|
106 |
+
|
107 |
+
If they do, then via our Website AntiVirus product, we’re able to help you get
|
108 |
+
off the their security blacklist.
|
109 |
+
|
110 |
+
|
111 |
+
= Effective Security Hardening =
|
112 |
+
|
113 |
+
It’s easy to get lost in the world of security hardening. At Sucuri we clean
|
114 |
+
100’s of websites a day, many with the various security hardening
|
115 |
+
configurations you find in various WordPress Security presentations. In this
|
116 |
+
section, we add those that we feel to be most effective, and that complement
|
117 |
+
the entire Sucuri suite of products.
|
118 |
|
|
|
119 |
|
120 |
+
= Post-Hack Security Actions =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
+
Regardless of how good your security posture is, sometimes it’s impossible to
|
123 |
+
prevent the inevitable. When this happens, we’ve included a section to help
|
124 |
+
you walk through the three key things you should do after a compromise.
|
125 |
|
|
|
126 |
|
127 |
+
= Security Notifications =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
Having all these security features would be useless unless you were notified
|
130 |
+
of the issues. This is why we have made available security notifications. We
|
131 |
+
have also expanded the various security related events, to provide website
|
132 |
+
owners more flexibility in regards to what they want to know about. As a
|
133 |
+
website owner, you have the option to make these security alerts as quiet or
|
134 |
+
noisy as you would like.
|
135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
|
137 |
+
= Website Firewall (add on) =
|
|
|
138 |
|
139 |
+
This is by far the coolest security feature Sucuri has to offer everyday
|
140 |
+
website owners. It’s an enterprise grade Website Firewall known as CloudProxy.
|
141 |
+
It is designed to give you the best security protection any website can hope
|
142 |
+
for. It protects your website from a variety of website attacks and security
|
143 |
+
events to include:
|
144 |
+
|
145 |
+
<ol>
|
146 |
+
<li>Denial of Service (DOS / DDOS) Attacks</li>
|
147 |
+
<li>Exploitation of Software Vulnerabilities</li>
|
148 |
+
<li>Zero Day Disclosure Patches</li>
|
149 |
+
<li>Brute Force Attacks against your Access Control Mechanisms</li>
|
150 |
+
</ol>
|
151 |
+
|
152 |
+
This is coupled with a number of features like:
|
153 |
+
|
154 |
+
<ol>
|
155 |
+
<li>Performance Optimization</li>
|
156 |
+
<li>Advanced Access Control Features</li>
|
157 |
+
<li>Failover and Redundancy</li>
|
158 |
+
</ol>
|
159 |
+
|
160 |
+
This is not included as a <strong>Free</strong> option to the plugin, but is
|
161 |
+
integrated so that if purchased you are able to activate.
|
162 |
+
|
163 |
+
The Sucuri Security WordPress Security plugin is built by the team that is
|
164 |
+
known for their proactive approach to security. It is built using intelligence
|
165 |
+
gathered from thousands upon thousands of remediation cases, millions of
|
166 |
+
unique domain scans and 10’s of millions of website security attack blocks.
|
167 |
|
168 |
|
169 |
== Installation ==
|
170 |
|
171 |
+
The installation of the Sucuri Security WordPress Security plugin is very
|
172 |
+
simple and straight forward. <a
|
173 |
+
href="https://sucuri.net/wordpress-security-plugin-installation">A detailed
|
174 |
+
breakdown of the process is available, including images,</a> below however we
|
175 |
+
outline the bare minimum steps.
|
176 |
+
|
177 |
+
To install Sucuri Security and complement your Security posture:
|
178 |
+
|
179 |
+
|
180 |
+
1. You will want to log into your WordPress administration panel - (e.g.,
|
181 |
+
http://yourdomain/wp-admin)
|
182 |
+
|
183 |
+
2. Navigate to <strong>Plugins Menu</strong> option in your WordPress
|
184 |
+
administration panel
|
185 |
+
|
186 |
+
3. Select <strong>Add New</strong>
|
187 |
+
|
188 |
+
4. Type <strong>Sucuri</strong> in the <strong>Search</strong> box, and click
|
189 |
+
<strong>Search</strong> plugins.
|
190 |
+
|
191 |
+
5. The first option you get should be for <strong>Sucuri Security - Auditing,
|
192 |
+
Malware Scanner and Hardening</strong>
|
193 |
+
|
194 |
+
6. Select <strong>Install Now</strong>
|
195 |
+
|
196 |
+
7. Now choose to <strong>Activate</strong> the plugin.
|
197 |
+
|
198 |
+
8. Once activated, you will need to create an API key, this is done
|
199 |
+
automatically for you. Simply click on <strong>Generate API Key for
|
200 |
+
XXXXXX</strong>
|
201 |
+
|
202 |
+
9. Once the API key is generated the page will redirect you to your dashboard
|
203 |
+
and the plugin is automatically configured for you.
|
204 |
+
|
205 |
+
|
206 |
+
To configure the Sucuri WordPress Security plugin for your specific Security
|
207 |
+
needs:
|
208 |
+
|
209 |
+
1. Navigate to the <strong>Sucuri Security</strong> menu option (left hand
|
210 |
+
side).
|
211 |
+
|
212 |
+
2. Hover or click on the name.
|
213 |
+
|
214 |
+
3. Click on <strong>Settings</strong>
|
215 |
+
|
216 |
+
The <strong>Settings</strong> page allows you to configure the website to your
|
217 |
+
preferred security needs. Some of it’s features include changing the email
|
218 |
+
notifications, via the <strong>notification settings</strong> tab or disabling
|
219 |
+
integrity checking. We encourage you to visit this section and tune your
|
220 |
+
security needs as you see fit.
|
221 |
+
|
222 |
|
223 |
|
224 |
== Changelog ==
|
225 |
|
226 |
+
= 1.7.0 =
|
227 |
+
* Added Hardening option to remove error log files
|
228 |
+
* Bug fixes on some new registrations.
|
229 |
+
* Changed format of the internal logs to json.
|
230 |
+
|
231 |
= 1.6.9 =
|
232 |
* Multiple bug fixes (as reported on the support forums).
|
233 |
* Added heartbeat for the file scans.
|
291 |
= 1.5.4 = Bug fixes.
|
292 |
|
293 |
= 1.5.2 =
|
294 |
+
* Adding additional information about .htaccess hacks and the server
|
295 |
+
* environment.
|
296 |
|
297 |
= 1.5.0 =
|
298 |
* Fixing last login and giving better warns on permission errors.
|
314 |
* Fixing some issues on the last login and allowing the option to disable it.
|
315 |
|
316 |
= 1.4.4 =
|
317 |
+
* Small bug fixes + forcing a re-scan on every scan attempt (not using the
|
318 |
+
* cache anymore).
|
319 |
|
320 |
= 1.4.3 =
|
321 |
* Fixing a few PHP warnings.
|
374 |
= 1.1.1 =
|
375 |
* First public release.
|
376 |
|
377 |
+
|
378 |
== Credits ==
|
379 |
|
380 |
* <a href="http://sucuri.net">Sucuri Security</a>
|
sucuri.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Sucuri Security - Auditing, Malware Scanner and Hardening
|
|
4 |
Plugin URI: http://wordpress.sucuri.net/
|
5 |
Description: The <a href="http://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 |
Author URI: http://sucuri.net
|
9 |
*/
|
10 |
|
@@ -66,7 +66,7 @@ define('SUCURISCAN', 'sucuriscan');
|
|
66 |
/**
|
67 |
* Current version of the plugin's code.
|
68 |
*/
|
69 |
-
define('SUCURISCAN_VERSION', '1.
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
@@ -182,6 +182,8 @@ if( defined('SUCURISCAN') ){
|
|
182 |
*/
|
183 |
|
184 |
$sucuriscan_notify_options = array(
|
|
|
|
|
185 |
'sucuriscan_notify_user_registration' => 'Enable email alerts for new user registration',
|
186 |
'sucuriscan_notify_success_login' => 'Enable email alerts for successful logins',
|
187 |
'sucuriscan_notify_failed_login' => 'Enable email alerts for failed logins',
|
@@ -200,8 +202,6 @@ if( defined('SUCURISCAN') ){
|
|
200 |
'sucuriscan_notify_plugin_updated' => 'Enable email alerts when a plugin is updated',
|
201 |
'sucuriscan_notify_plugin_installed' => 'Enable email alerts when a plugin is installed',
|
202 |
'sucuriscan_notify_plugin_deleted' => 'Enable email alerts when a plugin is deleted',
|
203 |
-
'sucuriscan_prettify_mails' => 'Enable email alerts in HTML (uncheck to get email in text/plain)',
|
204 |
-
'sucuriscan_lastlogin_redirection' => 'Allow redirection after login to report the last-login information',
|
205 |
);
|
206 |
|
207 |
$sucuriscan_schedule_allowed = array(
|
@@ -371,6 +371,31 @@ class SucuriScan {
|
|
371 |
return $var_name;
|
372 |
}
|
373 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
/**
|
375 |
* Encodes the less-than, greater-than, ampersand, double quote and single quote
|
376 |
* characters, will never double encode entities.
|
@@ -537,8 +562,9 @@ class SucuriScan {
|
|
537 |
*
|
538 |
* @return string The real ip address of the user in the current request.
|
539 |
*/
|
540 |
-
public static function get_remote_addr(){
|
541 |
$remote_addr = '';
|
|
|
542 |
|
543 |
if( self::is_behind_cloudproxy() ){
|
544 |
$alternatives = array(
|
@@ -548,8 +574,9 @@ class SucuriScan {
|
|
548 |
'HTTP_X_FORWARDED',
|
549 |
'HTTP_FORWARDED_FOR',
|
550 |
'HTTP_FORWARDED',
|
551 |
-
'
|
552 |
'SUCURI_RIP',
|
|
|
553 |
);
|
554 |
|
555 |
foreach( $alternatives as $alternative ){
|
@@ -558,6 +585,7 @@ class SucuriScan {
|
|
558 |
&& self::is_valid_ip($_SERVER[$alternative])
|
559 |
){
|
560 |
$remote_addr = $_SERVER[$alternative];
|
|
|
561 |
break;
|
562 |
}
|
563 |
}
|
@@ -565,15 +593,29 @@ class SucuriScan {
|
|
565 |
|
566 |
elseif( isset($_SERVER['REMOTE_ADDR']) ) {
|
567 |
$remote_addr = $_SERVER['REMOTE_ADDR'];
|
|
|
568 |
}
|
569 |
|
570 |
if( $remote_addr == '::1' ){
|
571 |
$remote_addr = '127.0.0.1';
|
572 |
}
|
573 |
|
|
|
|
|
|
|
|
|
574 |
return $remote_addr;
|
575 |
}
|
576 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
577 |
/**
|
578 |
* Retrieve the user-agent from the current request.
|
579 |
*
|
@@ -617,9 +659,9 @@ class SucuriScan {
|
|
617 |
*/
|
618 |
public static function is_behind_cloudproxy( $verbose=FALSE ){
|
619 |
$http_host = self::get_domain();
|
620 |
-
$
|
621 |
-
$
|
622 |
-
$status = (bool) preg_match('/^cloudproxy[0-9]+\.sucuri\.net$/', $
|
623 |
|
624 |
if( $verbose ){
|
625 |
return array(
|
@@ -672,6 +714,17 @@ class SucuriScan {
|
|
672 |
return NULL;
|
673 |
}
|
674 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
675 |
/**
|
676 |
* Return the time passed since the specified timestamp until now.
|
677 |
*
|
@@ -683,7 +736,8 @@ class SucuriScan {
|
|
683 |
$timestamp = strtotime($timestamp);
|
684 |
}
|
685 |
|
686 |
-
$
|
|
|
687 |
|
688 |
if( $diff == 0 ){ return 'just now'; }
|
689 |
|
@@ -724,6 +778,16 @@ class SucuriScan {
|
|
724 |
return $var_name;
|
725 |
}
|
726 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
727 |
/**
|
728 |
* Check whether an IP address has a valid format or not.
|
729 |
*
|
@@ -773,6 +837,43 @@ class SucuriScan {
|
|
773 |
}
|
774 |
}
|
775 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
776 |
/**
|
777 |
* Cut a long text to the length specified, and append suspensive points at the end.
|
778 |
*
|
@@ -856,7 +957,11 @@ class SucuriScanRequest extends SucuriScan {
|
|
856 |
public static function request( $list=array(), $key='', $pattern='' ){
|
857 |
$key = self::variable_prefix($key);
|
858 |
|
859 |
-
if(
|
|
|
|
|
|
|
|
|
860 |
// Select the key from the list and escape its content.
|
861 |
$key_value = $list[$key];
|
862 |
|
@@ -868,7 +973,7 @@ class SucuriScanRequest extends SucuriScan {
|
|
868 |
case '_nonce': $pattern = '/^[a-z0-9]{10}$/'; break;
|
869 |
case '_page': $pattern = '/^[a-z_]+$/'; break;
|
870 |
case '_array': $pattern = '_array'; break;
|
871 |
-
case '_yyyymmdd': $pattern = '/^[0-9]{4}\-[0-9]{2}
|
872 |
default: $pattern = '/^'.$pattern.'$/'; break;
|
873 |
}
|
874 |
}
|
@@ -1056,6 +1161,36 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1056 |
return FALSE;
|
1057 |
}
|
1058 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1059 |
/**
|
1060 |
* Check whether the built-in class SplFileObject is available in the system
|
1061 |
* or not, it is required to have PHP >= 5.1.0. The SplFileObject class offers
|
@@ -1196,7 +1331,7 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1196 |
}
|
1197 |
|
1198 |
/**
|
1199 |
-
* Skip some specific directories and
|
1200 |
*
|
1201 |
* @param string $directory Directory where the scanner is located at the moment.
|
1202 |
* @param string $filename Name of the folder or file being scanned at the moment.
|
@@ -1803,13 +1938,14 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
1803 |
'sucuriscan_scan_interface' => 'spl',
|
1804 |
'sucuriscan_scan_modfiles' => 'enabled',
|
1805 |
'sucuriscan_scan_checksums' => 'enabled',
|
|
|
1806 |
'sucuriscan_runtime' => 0,
|
1807 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
1808 |
'sucuriscan_notify_to' => '',
|
1809 |
'sucuriscan_emails_sent' => 0,
|
1810 |
'sucuriscan_emails_per_hour' => 5,
|
1811 |
'sucuriscan_last_email_at' => time(),
|
1812 |
-
'sucuriscan_prettify_mails' => '
|
1813 |
'sucuriscan_notify_success_login' => 'enabled',
|
1814 |
'sucuriscan_notify_failed_login' => 'enabled',
|
1815 |
'sucuriscan_notify_post_publication' => 'enabled',
|
@@ -2117,7 +2253,23 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2117 |
*/
|
2118 |
public static function get_ignored_events(){
|
2119 |
$post_types = self::get_option(':ignored_events');
|
2120 |
-
$post_types_arr =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2121 |
|
2122 |
if( !is_array($post_types_arr) ){
|
2123 |
$post_types_arr = array();
|
@@ -2143,7 +2295,7 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2143 |
// Check if the event is not ignored already.
|
2144 |
if( !array_key_exists($event_name, $ignored_events) ){
|
2145 |
$ignored_events[$event_name] = time();
|
2146 |
-
$saved = self::update_option( ':ignored_events',
|
2147 |
|
2148 |
return $saved;
|
2149 |
}
|
@@ -2164,7 +2316,7 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2164 |
|
2165 |
if( array_key_exists($event_name, $ignored_events) ){
|
2166 |
unset( $ignored_events[$event_name] );
|
2167 |
-
$saved = self::update_option( ':ignored_events',
|
2168 |
|
2169 |
return $saved;
|
2170 |
}
|
@@ -3060,9 +3212,11 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3060 |
elseif(
|
3061 |
current_user_can('update_themes')
|
3062 |
&& SucuriScanRequest::get('action', '(upgrade-theme|do-theme-upgrade)')
|
3063 |
-
&& SucuriScanRequest::post('checked')
|
3064 |
){
|
3065 |
-
|
|
|
|
|
3066 |
$theme_info = wp_get_theme($theme);
|
3067 |
$theme_name = ucwords($theme);
|
3068 |
$theme_version = '0.0';
|
@@ -3304,9 +3458,10 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
3304 |
$response['body'] = @json_decode($response['body_raw']);
|
3305 |
}
|
3306 |
|
3307 |
-
// Check if the response data is serialized
|
3308 |
-
elseif(
|
3309 |
-
$response['
|
|
|
3310 |
}
|
3311 |
|
3312 |
return $response;
|
@@ -3738,12 +3893,12 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
3738 |
*/
|
3739 |
public static function get_sitecheck_results( $domain='' ){
|
3740 |
if( !empty($domain) ){
|
3741 |
-
$url = 'http://sitecheck.sucuri.net/
|
3742 |
$response = self::api_call( $url, 'GET', array(
|
3743 |
-
'serialized' => 1,
|
3744 |
-
'clear' => 1,
|
3745 |
-
'fromwp' => 2,
|
3746 |
'scan' => $domain,
|
|
|
|
|
|
|
3747 |
));
|
3748 |
|
3749 |
if( $response ){
|
@@ -3989,7 +4144,8 @@ class SucuriScanMail extends SucuriScanOption {
|
|
3989 |
* @return boolean Whether the emails will be in HTML or Plain/Text.
|
3990 |
*/
|
3991 |
public static function prettify_mails(){
|
3992 |
-
return ( self::get_option(':prettify_mails') === 'enabled' );
|
|
|
3993 |
}
|
3994 |
|
3995 |
/**
|
@@ -4028,7 +4184,7 @@ class SucuriScanMail extends SucuriScanOption {
|
|
4028 |
|
4029 |
// Check whether the email notifications will be sent in HTML or Plain/Text.
|
4030 |
if( self::prettify_mails() ){
|
4031 |
-
$headers = array( '
|
4032 |
$data_set['PrettifyType'] = 'pretty';
|
4033 |
} else {
|
4034 |
$message = strip_tags($message);
|
@@ -4040,15 +4196,9 @@ class SucuriScanMail extends SucuriScanOption {
|
|
4040 |
if( $debug ){ die($message); }
|
4041 |
|
4042 |
$subject = sprintf( 'Sucuri Alert, %s, %s', $wp_domain, $subject );
|
|
|
4043 |
|
4044 |
-
$
|
4045 |
-
$email,
|
4046 |
-
$subject,
|
4047 |
-
$message,
|
4048 |
-
$headers
|
4049 |
-
);
|
4050 |
-
|
4051 |
-
if( $email_sent ){
|
4052 |
$emails_sent_num = (int) self::get_option(':emails_sent');
|
4053 |
self::update_option( ':emails_sent', $emails_sent_num + 1 );
|
4054 |
self::update_option( ':last_email_at', time() );
|
@@ -4071,7 +4221,6 @@ class SucuriScanMail extends SucuriScanOption {
|
|
4071 |
private static function prettify_mail( $subject='', $message='', $data_set=array() ){
|
4072 |
$prettify_type = isset($data_set['PrettifyType']) ? $data_set['PrettifyType'] : 'simple';
|
4073 |
$template_name = 'notification-' . $prettify_type;
|
4074 |
-
$remote_addr = self::get_remote_addr();
|
4075 |
$user = wp_get_current_user();
|
4076 |
$display_name = '';
|
4077 |
|
@@ -4087,10 +4236,10 @@ class SucuriScanMail extends SucuriScanOption {
|
|
4087 |
'TemplateTitle' => 'Sucuri Alert',
|
4088 |
'Subject' => $subject,
|
4089 |
'Website' => self::get_option('siteurl'),
|
4090 |
-
'RemoteAddress' =>
|
4091 |
'Message' => $message,
|
4092 |
'User' => $display_name,
|
4093 |
-
'Time' =>
|
4094 |
);
|
4095 |
|
4096 |
foreach( $data_set as $var_key => $var_value ){
|
@@ -4936,8 +5085,12 @@ function sucuriscan_sitecheck_info( $res=array() ){
|
|
4936 |
$res = SucuriScanAPI::get_sitecheck_results($clean_domain);
|
4937 |
|
4938 |
// Check for error messages in the request's response.
|
4939 |
-
if( is_string($res)
|
4940 |
-
|
|
|
|
|
|
|
|
|
4941 |
}
|
4942 |
|
4943 |
else {
|
@@ -5181,14 +5334,16 @@ function sucuriscan_sitecheck_info( $res=array() ){
|
|
5181 |
<?php endforeach; ?>
|
5182 |
<?php endif; ?>
|
5183 |
|
5184 |
-
<?php
|
5185 |
-
<?php
|
5186 |
-
|
5187 |
-
<
|
5188 |
-
<
|
5189 |
-
|
5190 |
-
|
5191 |
-
|
|
|
|
|
5192 |
|
5193 |
<!-- Possible recommendations or outdated software on the site. -->
|
5194 |
<?php if( $outdated_warns_exist || $recommendations_exist ): ?>
|
@@ -5844,6 +5999,7 @@ function sucuriscan_hardening_page(){
|
|
5844 |
sucuriscan_harden_adminuser();
|
5845 |
sucuriscan_harden_fileeditor();
|
5846 |
sucuriscan_harden_dbtables();
|
|
|
5847 |
?>
|
5848 |
</form>
|
5849 |
</div>
|
@@ -6226,11 +6382,7 @@ function sucuriscan_cloudproxy_enabled(){
|
|
6226 |
|
6227 |
$description = 'A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, '
|
6228 |
. 'DDoS, SQL injections, etc) and helping it remain malware and blacklist free. This test checks if your site is '
|
6229 |
-
. 'using <a href="http://cloudproxy.sucuri.net/" target="_blank">Sucuri\'s CloudProxy WAF</a> to protect your site.
|
6230 |
-
. '</p><p>'
|
6231 |
-
. '<b>HTTP Host:</b> <span class="sucuriscan-monospace">' . $proxy_info['http_host'] . '</span><br>'
|
6232 |
-
. '<b>Host Name:</b> <span class="sucuriscan-monospace">' . $proxy_info['host_name'] . '</span><br>'
|
6233 |
-
. '<b>Host Address:</b> <span class="sucuriscan-monospace">' . $proxy_info['host_addr'] . '</span>';
|
6234 |
|
6235 |
if( $proxy_info['status'] === FALSE ){
|
6236 |
$status = 0;
|
@@ -6461,6 +6613,76 @@ function sucuriscan_harden_dbtables(){
|
|
6461 |
);
|
6462 |
}
|
6463 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6464 |
/**
|
6465 |
* WordPress core integrity page.
|
6466 |
*
|
@@ -7508,7 +7730,7 @@ if( !function_exists('sucuri_set_lastlogin') ){
|
|
7508 |
'user_lastlogin' => current_time('mysql')
|
7509 |
);
|
7510 |
|
7511 |
-
@file_put_contents($datastore_filepath,
|
7512 |
}
|
7513 |
}
|
7514 |
add_action('wp_login', 'sucuriscan_set_lastlogin', 50);
|
@@ -7563,8 +7785,14 @@ function sucuriscan_get_logins( $limit=10, $offset=0, $user_id=0 ){
|
|
7563 |
for( $i=$offset; $i<$total_lines; $i++ ){
|
7564 |
$line = $reversed_lines[$i] ? trim($reversed_lines[$i]) : '';
|
7565 |
|
7566 |
-
if
|
7567 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
7568 |
$last_login['user_lastlogin_timestamp'] = strtotime($last_login['user_lastlogin']);
|
7569 |
$last_login['user_registered_timestamp'] = 0;
|
7570 |
|
@@ -8205,6 +8433,14 @@ function sucuriscan_settings_form_submissions( $page_nonce=NULL ){
|
|
8205 |
SucuriScanInterface::info( 'Filesystem scanner for file integrity was <code>' . $action_d . '</code>' );
|
8206 |
}
|
8207 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8208 |
// Modify the schedule of the filesystem scanner.
|
8209 |
if( $frequency = SucuriScanRequest::post(':scan_frequency') ){
|
8210 |
$allowed_frequency = array_keys($sucuriscan_schedule_allowed);
|
@@ -8247,8 +8483,10 @@ function sucuriscan_settings_form_submissions( $page_nonce=NULL ){
|
|
8247 |
|
8248 |
// Update the email where the event notifications will be sent.
|
8249 |
if( $new_email = SucuriScanRequest::post(':notify_to') ){
|
8250 |
-
|
8251 |
-
|
|
|
|
|
8252 |
SucuriScanEvent::notify_event( 'plugin_change', 'Email address to get the event notifications was changed' );
|
8253 |
SucuriScanInterface::info( 'All the event notifications will be sent to the email specified.' );
|
8254 |
} else {
|
@@ -8439,6 +8677,7 @@ function sucuriscan_settings_general(){
|
|
8439 |
$scan_interface = SucuriScanOption::get_option(':scan_interface');
|
8440 |
$scan_modfiles = SucuriScanOption::get_option(':scan_modfiles');
|
8441 |
$scan_checksums = SucuriScanOption::get_option(':scan_checksums');
|
|
|
8442 |
$emails_per_hour = SucuriScanOption::get_option(':emails_per_hour');
|
8443 |
$maximum_failed_logins = SucuriScanOption::get_option(':maximum_failed_logins');
|
8444 |
$verify_ssl_cert = SucuriScanOption::get_option(':verify_ssl_cert');
|
@@ -8479,6 +8718,11 @@ function sucuriscan_settings_general(){
|
|
8479 |
'ScanChecksumsSwitchText' => 'Disable',
|
8480 |
'ScanChecksumsSwitchValue' => 'disable',
|
8481 |
'ScanChecksumsSwitchCssClass' => 'button-danger',
|
|
|
|
|
|
|
|
|
|
|
8482 |
/* Filsystem scanning frequency. */
|
8483 |
'ScanningFrequency' => 'Undefined',
|
8484 |
'ScanningFrequencyOptions' => $scan_freq_options,
|
@@ -8520,6 +8764,13 @@ function sucuriscan_settings_general(){
|
|
8520 |
$template_variables['ScanChecksumsSwitchCssClass'] = 'button-success';
|
8521 |
}
|
8522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8523 |
if( array_key_exists($scan_freq, $sucuriscan_schedule_allowed) ){
|
8524 |
$template_variables['ScanningFrequency'] = $sucuriscan_schedule_allowed[$scan_freq];
|
8525 |
}
|
@@ -8549,6 +8800,7 @@ function sucuriscan_settings_notifications(){
|
|
8549 |
|
8550 |
$template_variables = array(
|
8551 |
'NotificationOptions' => '',
|
|
|
8552 |
);
|
8553 |
|
8554 |
$counter = 0;
|
@@ -9018,7 +9270,12 @@ function sucuriscan_server_info(){
|
|
9018 |
'Plugin_version' => SUCURISCAN_VERSION,
|
9019 |
'Plugin_checksum' => SUCURISCAN_PLUGIN_CHECKSUM,
|
9020 |
'Last_filesystem_scan' => SucuriScanOption::get_filesystem_runtime(TRUE),
|
9021 |
-
'Using_CloudProxy' => '
|
|
|
|
|
|
|
|
|
|
|
9022 |
'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE*8),
|
9023 |
'Server' => 'Unknown',
|
9024 |
'Developer_mode' => 'OFF',
|
@@ -9028,9 +9285,11 @@ function sucuriscan_server_info(){
|
|
9028 |
'PHP_version' => PHP_VERSION,
|
9029 |
);
|
9030 |
|
9031 |
-
|
9032 |
-
|
9033 |
-
|
|
|
|
|
9034 |
|
9035 |
if( defined('WP_DEBUG') && WP_DEBUG ){
|
9036 |
$info_vars['Developer_mode'] = 'ON';
|
@@ -9064,7 +9323,7 @@ function sucuriscan_server_info(){
|
|
9064 |
);
|
9065 |
|
9066 |
foreach( $field_names as $php_flag ){
|
9067 |
-
$php_flag_value = ini_get($php_flag);
|
9068 |
$php_flag_name = 'PHP_' . $php_flag;
|
9069 |
$info_vars[$php_flag_name] = $php_flag_value ? $php_flag_value : 'N/A';
|
9070 |
}
|
4 |
Plugin URI: http://wordpress.sucuri.net/
|
5 |
Description: The <a href="http://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.7.0
|
8 |
Author URI: http://sucuri.net
|
9 |
*/
|
10 |
|
66 |
/**
|
67 |
* Current version of the plugin's code.
|
68 |
*/
|
69 |
+
define('SUCURISCAN_VERSION', '1.7.0');
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
182 |
*/
|
183 |
|
184 |
$sucuriscan_notify_options = array(
|
185 |
+
// 'sucuriscan_prettify_mails' => 'Enable email alerts in HTML (uncheck to get email in text/plain)', // TODO: Investigate HTML mails issues.
|
186 |
+
'sucuriscan_lastlogin_redirection' => 'Allow redirection after login to report the last-login information',
|
187 |
'sucuriscan_notify_user_registration' => 'Enable email alerts for new user registration',
|
188 |
'sucuriscan_notify_success_login' => 'Enable email alerts for successful logins',
|
189 |
'sucuriscan_notify_failed_login' => 'Enable email alerts for failed logins',
|
202 |
'sucuriscan_notify_plugin_updated' => 'Enable email alerts when a plugin is updated',
|
203 |
'sucuriscan_notify_plugin_installed' => 'Enable email alerts when a plugin is installed',
|
204 |
'sucuriscan_notify_plugin_deleted' => 'Enable email alerts when a plugin is deleted',
|
|
|
|
|
205 |
);
|
206 |
|
207 |
$sucuriscan_schedule_allowed = array(
|
371 |
return $var_name;
|
372 |
}
|
373 |
|
374 |
+
/**
|
375 |
+
* Gets the value of a configuration option.
|
376 |
+
*
|
377 |
+
* @param string $property The configuration option name.
|
378 |
+
* @return string Value of the configuration option as a string on success.
|
379 |
+
*/
|
380 |
+
public static function ini_get( $property='' ){
|
381 |
+
$ini_value = ini_get($property);
|
382 |
+
|
383 |
+
if( empty($ini_value) || is_null($ini_value) ){
|
384 |
+
switch( $property ){
|
385 |
+
case 'error_log': $ini_value = 'error_log'; break;
|
386 |
+
case 'safe_mode': $ini_value = 'Off'; break;
|
387 |
+
case 'allow_url_fopen': $ini_value = '1'; break;
|
388 |
+
case 'memory_limit': $ini_value = '128M'; break;
|
389 |
+
case 'upload_max_filesize': $ini_value = '2M'; break;
|
390 |
+
case 'post_max_size': $ini_value = '8M'; break;
|
391 |
+
case 'max_execution_time': $ini_value = '30'; break;
|
392 |
+
case 'max_input_time': $ini_value = '-1'; break;
|
393 |
+
}
|
394 |
+
}
|
395 |
+
|
396 |
+
return $ini_value;
|
397 |
+
}
|
398 |
+
|
399 |
/**
|
400 |
* Encodes the less-than, greater-than, ampersand, double quote and single quote
|
401 |
* characters, will never double encode entities.
|
562 |
*
|
563 |
* @return string The real ip address of the user in the current request.
|
564 |
*/
|
565 |
+
public static function get_remote_addr( $return_header=FALSE ){
|
566 |
$remote_addr = '';
|
567 |
+
$header_used = 'unknown';
|
568 |
|
569 |
if( self::is_behind_cloudproxy() ){
|
570 |
$alternatives = array(
|
574 |
'HTTP_X_FORWARDED',
|
575 |
'HTTP_FORWARDED_FOR',
|
576 |
'HTTP_FORWARDED',
|
577 |
+
'HTTP_X_SUCURI_CLIENTIP',
|
578 |
'SUCURI_RIP',
|
579 |
+
'REMOTE_ADDR',
|
580 |
);
|
581 |
|
582 |
foreach( $alternatives as $alternative ){
|
585 |
&& self::is_valid_ip($_SERVER[$alternative])
|
586 |
){
|
587 |
$remote_addr = $_SERVER[$alternative];
|
588 |
+
$header_used = $alternative;
|
589 |
break;
|
590 |
}
|
591 |
}
|
593 |
|
594 |
elseif( isset($_SERVER['REMOTE_ADDR']) ) {
|
595 |
$remote_addr = $_SERVER['REMOTE_ADDR'];
|
596 |
+
$header_used = 'REMOTE_ADDR';
|
597 |
}
|
598 |
|
599 |
if( $remote_addr == '::1' ){
|
600 |
$remote_addr = '127.0.0.1';
|
601 |
}
|
602 |
|
603 |
+
if( $return_header ){
|
604 |
+
return $header_used;
|
605 |
+
}
|
606 |
+
|
607 |
return $remote_addr;
|
608 |
}
|
609 |
|
610 |
+
/**
|
611 |
+
* Return the HTTP header used to retrieve the remote address.
|
612 |
+
*
|
613 |
+
* @return string The HTTP header used to retrieve the remote address.
|
614 |
+
*/
|
615 |
+
public static function get_remote_addr_header(){
|
616 |
+
return self::get_remote_addr(TRUE);
|
617 |
+
}
|
618 |
+
|
619 |
/**
|
620 |
* Retrieve the user-agent from the current request.
|
621 |
*
|
659 |
*/
|
660 |
public static function is_behind_cloudproxy( $verbose=FALSE ){
|
661 |
$http_host = self::get_domain();
|
662 |
+
$host_by_addr = @gethostbyname($http_host);
|
663 |
+
$host_by_name = @gethostbyaddr($host_by_addr);
|
664 |
+
$status = (bool) preg_match('/^cloudproxy[0-9]+\.sucuri\.net$/', $host_by_name);
|
665 |
|
666 |
if( $verbose ){
|
667 |
return array(
|
714 |
return NULL;
|
715 |
}
|
716 |
|
717 |
+
/**
|
718 |
+
* Retrieve the date in localized format based on the current time.
|
719 |
+
*
|
720 |
+
* @return string The date, translated if locale specifies it.
|
721 |
+
*/
|
722 |
+
public static function current_datetime(){
|
723 |
+
$local_time = current_time('timestamp');
|
724 |
+
|
725 |
+
return self::datetime($local_time);
|
726 |
+
}
|
727 |
+
|
728 |
/**
|
729 |
* Return the time passed since the specified timestamp until now.
|
730 |
*
|
736 |
$timestamp = strtotime($timestamp);
|
737 |
}
|
738 |
|
739 |
+
$local_time = current_time('timestamp');
|
740 |
+
$diff = abs( $local_time - intval($timestamp) );
|
741 |
|
742 |
if( $diff == 0 ){ return 'just now'; }
|
743 |
|
778 |
return $var_name;
|
779 |
}
|
780 |
|
781 |
+
/**
|
782 |
+
* Check whether a variable contains a serialized data or not.
|
783 |
+
*
|
784 |
+
* @param string $data The data that will be checked.
|
785 |
+
* @return boolean TRUE if the data was serialized, FALSE otherwise.
|
786 |
+
*/
|
787 |
+
public static function is_serialized( $data='' ){
|
788 |
+
return ( is_string($data) && preg_match('/^(a|O):[0-9]+:.+/', $data) );
|
789 |
+
}
|
790 |
+
|
791 |
/**
|
792 |
* Check whether an IP address has a valid format or not.
|
793 |
*
|
837 |
}
|
838 |
}
|
839 |
|
840 |
+
/**
|
841 |
+
* Return a string with all the valid email addresses.
|
842 |
+
*
|
843 |
+
* @param string $email The string that will be validated as an email address.
|
844 |
+
* @param boolean $as_array TRUE to return the list of valid email addresses as an array.
|
845 |
+
* @return string All the valid email addresses separated by a comma.
|
846 |
+
*/
|
847 |
+
public static function get_valid_email( $email='', $as_array=FALSE ){
|
848 |
+
$valid_emails = array();
|
849 |
+
|
850 |
+
if( strpos($email, ',') !== FALSE ){
|
851 |
+
$addresses = explode(',', $email);
|
852 |
+
|
853 |
+
foreach( $addresses as $address ){
|
854 |
+
$address = trim($address);
|
855 |
+
|
856 |
+
if( self::is_valid_email($address) ){
|
857 |
+
$valid_emails[] = $address;
|
858 |
+
}
|
859 |
+
}
|
860 |
+
}
|
861 |
+
|
862 |
+
elseif( self::is_valid_email($email) ){
|
863 |
+
$valid_emails[] = $email;
|
864 |
+
}
|
865 |
+
|
866 |
+
if( !empty($valid_emails) ){
|
867 |
+
if( $as_array === TRUE ){
|
868 |
+
return $valid_emails;
|
869 |
+
}
|
870 |
+
|
871 |
+
return self::implode(', ', $valid_emails);
|
872 |
+
}
|
873 |
+
|
874 |
+
return FALSE;
|
875 |
+
}
|
876 |
+
|
877 |
/**
|
878 |
* Cut a long text to the length specified, and append suspensive points at the end.
|
879 |
*
|
957 |
public static function request( $list=array(), $key='', $pattern='' ){
|
958 |
$key = self::variable_prefix($key);
|
959 |
|
960 |
+
if(
|
961 |
+
is_array($list)
|
962 |
+
&& is_string($key)
|
963 |
+
&& isset($list[$key])
|
964 |
+
){
|
965 |
// Select the key from the list and escape its content.
|
966 |
$key_value = $list[$key];
|
967 |
|
973 |
case '_nonce': $pattern = '/^[a-z0-9]{10}$/'; break;
|
974 |
case '_page': $pattern = '/^[a-z_]+$/'; break;
|
975 |
case '_array': $pattern = '_array'; break;
|
976 |
+
case '_yyyymmdd': $pattern = '/^[0-9]{4}(\-[0-9]{2}){2}$/'; break;
|
977 |
default: $pattern = '/^'.$pattern.'$/'; break;
|
978 |
}
|
979 |
}
|
1161 |
return FALSE;
|
1162 |
}
|
1163 |
|
1164 |
+
/**
|
1165 |
+
* Find a file under the directory tree specified.
|
1166 |
+
*
|
1167 |
+
* @param string $filename Name of the folder or file being scanned at the moment.
|
1168 |
+
* @param string $directory Directory where the scanner is located at the moment.
|
1169 |
+
* @return array List of file paths where the file was found.
|
1170 |
+
*/
|
1171 |
+
public function find_file( $filename='', $directory=NULL ){
|
1172 |
+
$file_paths = array();
|
1173 |
+
|
1174 |
+
if(
|
1175 |
+
is_null($directory)
|
1176 |
+
&& defined('ABSPATH')
|
1177 |
+
){
|
1178 |
+
$directory = ABSPATH;
|
1179 |
+
}
|
1180 |
+
|
1181 |
+
if( is_dir($directory) ){
|
1182 |
+
$dir_tree = $this->get_directory_tree( $directory );
|
1183 |
+
|
1184 |
+
foreach( $dir_tree as $filepath ){
|
1185 |
+
if( stripos($filepath, $filename) !== FALSE ){
|
1186 |
+
$file_paths[] = $filepath;
|
1187 |
+
}
|
1188 |
+
}
|
1189 |
+
}
|
1190 |
+
|
1191 |
+
return $file_paths;
|
1192 |
+
}
|
1193 |
+
|
1194 |
/**
|
1195 |
* Check whether the built-in class SplFileObject is available in the system
|
1196 |
* or not, it is required to have PHP >= 5.1.0. The SplFileObject class offers
|
1331 |
}
|
1332 |
|
1333 |
/**
|
1334 |
+
* Skip some specific directories and file paths from the filesystem scan.
|
1335 |
*
|
1336 |
* @param string $directory Directory where the scanner is located at the moment.
|
1337 |
* @param string $filename Name of the folder or file being scanned at the moment.
|
1938 |
'sucuriscan_scan_interface' => 'spl',
|
1939 |
'sucuriscan_scan_modfiles' => 'enabled',
|
1940 |
'sucuriscan_scan_checksums' => 'enabled',
|
1941 |
+
'sucuriscan_scan_errorlogs' => 'enabled',
|
1942 |
'sucuriscan_runtime' => 0,
|
1943 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
1944 |
'sucuriscan_notify_to' => '',
|
1945 |
'sucuriscan_emails_sent' => 0,
|
1946 |
'sucuriscan_emails_per_hour' => 5,
|
1947 |
'sucuriscan_last_email_at' => time(),
|
1948 |
+
'sucuriscan_prettify_mails' => 'disabled',
|
1949 |
'sucuriscan_notify_success_login' => 'enabled',
|
1950 |
'sucuriscan_notify_failed_login' => 'enabled',
|
1951 |
'sucuriscan_notify_post_publication' => 'enabled',
|
2253 |
*/
|
2254 |
public static function get_ignored_events(){
|
2255 |
$post_types = self::get_option(':ignored_events');
|
2256 |
+
$post_types_arr = FALSE;
|
2257 |
+
|
2258 |
+
// Encode (old) serialized data into JSON.
|
2259 |
+
if( self::is_serialized($post_types) ){
|
2260 |
+
var_dump($post_types);
|
2261 |
+
$post_types_arr = @unserialize($post_types);
|
2262 |
+
$post_types_fix = json_encode($post_types_arr);
|
2263 |
+
echo 'fixed';
|
2264 |
+
self::update_option( ':ignored_events', $post_types_fix );
|
2265 |
+
|
2266 |
+
return $post_types_arr;
|
2267 |
+
}
|
2268 |
+
|
2269 |
+
// Decode JSON-encoded data as an array.
|
2270 |
+
elseif( preg_match('/^\{.+\}$/', $post_types) ){
|
2271 |
+
$post_types_arr = @json_decode( $post_types, TRUE );
|
2272 |
+
}
|
2273 |
|
2274 |
if( !is_array($post_types_arr) ){
|
2275 |
$post_types_arr = array();
|
2295 |
// Check if the event is not ignored already.
|
2296 |
if( !array_key_exists($event_name, $ignored_events) ){
|
2297 |
$ignored_events[$event_name] = time();
|
2298 |
+
$saved = self::update_option( ':ignored_events', json_encode($ignored_events) );
|
2299 |
|
2300 |
return $saved;
|
2301 |
}
|
2316 |
|
2317 |
if( array_key_exists($event_name, $ignored_events) ){
|
2318 |
unset( $ignored_events[$event_name] );
|
2319 |
+
$saved = self::update_option( ':ignored_events', json_encode($ignored_events) );
|
2320 |
|
2321 |
return $saved;
|
2322 |
}
|
3212 |
elseif(
|
3213 |
current_user_can('update_themes')
|
3214 |
&& SucuriScanRequest::get('action', '(upgrade-theme|do-theme-upgrade)')
|
3215 |
+
&& SucuriScanRequest::post('checked', '_array')
|
3216 |
){
|
3217 |
+
$themes = SucuriScanRequest::post('checked', '_array');
|
3218 |
+
|
3219 |
+
foreach( $themes as $theme ){
|
3220 |
$theme_info = wp_get_theme($theme);
|
3221 |
$theme_name = ucwords($theme);
|
3222 |
$theme_version = '0.0';
|
3458 |
$response['body'] = @json_decode($response['body_raw']);
|
3459 |
}
|
3460 |
|
3461 |
+
// Check if the response data is serialized (which we will consider as insecure).
|
3462 |
+
elseif( self::is_serialized($response['body']) ){
|
3463 |
+
$response['body_raw'] = NULL;
|
3464 |
+
$response['body'] = 'ERROR:Serialized data is not supported.';
|
3465 |
}
|
3466 |
|
3467 |
return $response;
|
3893 |
*/
|
3894 |
public static function get_sitecheck_results( $domain='' ){
|
3895 |
if( !empty($domain) ){
|
3896 |
+
$url = 'http://sitecheck.sucuri.net/';
|
3897 |
$response = self::api_call( $url, 'GET', array(
|
|
|
|
|
|
|
3898 |
'scan' => $domain,
|
3899 |
+
'fromwp' => 2,
|
3900 |
+
'clear' => 1,
|
3901 |
+
'json' => 1,
|
3902 |
));
|
3903 |
|
3904 |
if( $response ){
|
4144 |
* @return boolean Whether the emails will be in HTML or Plain/Text.
|
4145 |
*/
|
4146 |
public static function prettify_mails(){
|
4147 |
+
// return ( self::get_option(':prettify_mails') === 'enabled' ); // TODO: Investigate HTML mails issues.
|
4148 |
+
return FALSE;
|
4149 |
}
|
4150 |
|
4151 |
/**
|
4184 |
|
4185 |
// Check whether the email notifications will be sent in HTML or Plain/Text.
|
4186 |
if( self::prettify_mails() ){
|
4187 |
+
$headers = array( 'content-type: text/html' );
|
4188 |
$data_set['PrettifyType'] = 'pretty';
|
4189 |
} else {
|
4190 |
$message = strip_tags($message);
|
4196 |
if( $debug ){ die($message); }
|
4197 |
|
4198 |
$subject = sprintf( 'Sucuri Alert, %s, %s', $wp_domain, $subject );
|
4199 |
+
$mail_sent = wp_mail( $email, $subject, $message, $headers );
|
4200 |
|
4201 |
+
if( $mail_sent ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4202 |
$emails_sent_num = (int) self::get_option(':emails_sent');
|
4203 |
self::update_option( ':emails_sent', $emails_sent_num + 1 );
|
4204 |
self::update_option( ':last_email_at', time() );
|
4221 |
private static function prettify_mail( $subject='', $message='', $data_set=array() ){
|
4222 |
$prettify_type = isset($data_set['PrettifyType']) ? $data_set['PrettifyType'] : 'simple';
|
4223 |
$template_name = 'notification-' . $prettify_type;
|
|
|
4224 |
$user = wp_get_current_user();
|
4225 |
$display_name = '';
|
4226 |
|
4236 |
'TemplateTitle' => 'Sucuri Alert',
|
4237 |
'Subject' => $subject,
|
4238 |
'Website' => self::get_option('siteurl'),
|
4239 |
+
'RemoteAddress' => self::get_remote_addr(),
|
4240 |
'Message' => $message,
|
4241 |
'User' => $display_name,
|
4242 |
+
'Time' => SucuriScan::current_datetime(),
|
4243 |
);
|
4244 |
|
4245 |
foreach( $data_set as $var_key => $var_value ){
|
5085 |
$res = SucuriScanAPI::get_sitecheck_results($clean_domain);
|
5086 |
|
5087 |
// Check for error messages in the request's response.
|
5088 |
+
if( is_string($res) ){
|
5089 |
+
if( preg_match('/^ERROR:(.*)/', $res, $error_m) ){
|
5090 |
+
SucuriScanInterface::error( 'The site <code>' . $clean_domain . '</code> was not scanned: ' . $error_m[1] );
|
5091 |
+
} else {
|
5092 |
+
SucuriScanInterface::error( 'The API returned data that can not be processed.' );
|
5093 |
+
}
|
5094 |
}
|
5095 |
|
5096 |
else {
|
5334 |
<?php endforeach; ?>
|
5335 |
<?php endif; ?>
|
5336 |
|
5337 |
+
<?php if( isset($res['SYSTEM']['NOTICE']) ): ?>
|
5338 |
+
<?php foreach( $res['SYSTEM']['NOTICE'] as $j=>$notice ): ?>
|
5339 |
+
<?php if( is_array($notice) ){ $notice = implode(', ', $notice); } ?>
|
5340 |
+
<tr>
|
5341 |
+
<td colspan="2">
|
5342 |
+
<span class="sucuriscan-monospace"><?php _e($notice) ?></span>
|
5343 |
+
</td>
|
5344 |
+
</tr>
|
5345 |
+
<?php endforeach; ?>
|
5346 |
+
<?php endif; ?>
|
5347 |
|
5348 |
<!-- Possible recommendations or outdated software on the site. -->
|
5349 |
<?php if( $outdated_warns_exist || $recommendations_exist ): ?>
|
5999 |
sucuriscan_harden_adminuser();
|
6000 |
sucuriscan_harden_fileeditor();
|
6001 |
sucuriscan_harden_dbtables();
|
6002 |
+
sucuriscan_harden_errorlog();
|
6003 |
?>
|
6004 |
</form>
|
6005 |
</div>
|
6382 |
|
6383 |
$description = 'A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, '
|
6384 |
. 'DDoS, SQL injections, etc) and helping it remain malware and blacklist free. This test checks if your site is '
|
6385 |
+
. 'using <a href="http://cloudproxy.sucuri.net/" target="_blank">Sucuri\'s CloudProxy WAF</a> to protect your site.';
|
|
|
|
|
|
|
|
|
6386 |
|
6387 |
if( $proxy_info['status'] === FALSE ){
|
6388 |
$status = 0;
|
6613 |
);
|
6614 |
}
|
6615 |
|
6616 |
+
/**
|
6617 |
+
* Check whether an error_log file exists in the project.
|
6618 |
+
*
|
6619 |
+
* @return void
|
6620 |
+
*/
|
6621 |
+
function sucuriscan_harden_errorlog(){
|
6622 |
+
$hardened = 1;
|
6623 |
+
$log_filename = SucuriScan::ini_get('error_log');
|
6624 |
+
$scan_errorlogs = SucuriScanOption::get_option(':scan_errorlogs');
|
6625 |
+
|
6626 |
+
$description = 'PHP uses files named as <code>' . $log_filename . '</code> to log errors found in '
|
6627 |
+
. 'the code, these files may leak sensitive information of your project allowing an attacker '
|
6628 |
+
. 'to find vulnerabilities in the code. You must use these files to fix any bug while using '
|
6629 |
+
. 'a development environment, and remove them in production mode.';
|
6630 |
+
|
6631 |
+
// Search error log files in the project.
|
6632 |
+
if( $scan_errorlogs != 'disabled' ){
|
6633 |
+
$sucuri_fileinfo = new SucuriScanFileInfo();
|
6634 |
+
$sucuri_fileinfo->ignore_files = FALSE;
|
6635 |
+
$sucuri_fileinfo->ignore_directories = FALSE;
|
6636 |
+
$error_logs = $sucuri_fileinfo->find_file('error_log');
|
6637 |
+
$total_log_files = count($error_logs);
|
6638 |
+
} else {
|
6639 |
+
$error_logs = array();
|
6640 |
+
$total_log_files = 0;
|
6641 |
+
$description .= '<div class="sucuriscan-inline-alert-error"><p>The filesystem scan for error '
|
6642 |
+
. 'log files is disabled, so even if there are logs in your project they will be not '
|
6643 |
+
. 'shown here. You can enable the scanner again from the plugin <em>Settings</em> '
|
6644 |
+
. 'page.</p></div>';
|
6645 |
+
}
|
6646 |
+
|
6647 |
+
// Remove every error log file found in the filesystem scan.
|
6648 |
+
if( SucuriScanRequest::post(':run_hardening') ){
|
6649 |
+
if( SucuriScanRequest::post(':harden_errorlog') ){
|
6650 |
+
$removed_logs = 0;
|
6651 |
+
|
6652 |
+
foreach( $error_logs as $i => $error_log_path ){
|
6653 |
+
if( unlink($error_log_path) ){
|
6654 |
+
unset($error_logs[$i]);
|
6655 |
+
$removed_logs += 1;
|
6656 |
+
}
|
6657 |
+
}
|
6658 |
+
|
6659 |
+
SucuriScanInterface::info( 'Error log files removed <code>' . $removed_logs . ' out of ' . $total_log_files . '</code>' );
|
6660 |
+
}
|
6661 |
+
}
|
6662 |
+
|
6663 |
+
// List the error log files in a HTML table.
|
6664 |
+
if( !empty($error_logs) ){
|
6665 |
+
$hardened = 0;
|
6666 |
+
$description .= '</p><ul class="sucuriscan-list-as-table">';
|
6667 |
+
|
6668 |
+
foreach( $error_logs as $error_log_path ){
|
6669 |
+
$description .= '<li>' . $error_log_path . '</li>';
|
6670 |
+
}
|
6671 |
+
|
6672 |
+
$description .= '</ul><p>';
|
6673 |
+
}
|
6674 |
+
|
6675 |
+
sucuriscan_harden_status(
|
6676 |
+
'Error logs',
|
6677 |
+
$hardened,
|
6678 |
+
( $hardened == 0 ? 'sucuriscan_harden_errorlog' : NULL ),
|
6679 |
+
'There are no error log files in your project.',
|
6680 |
+
'There are ' . $total_log_files . ' error log files in your project.',
|
6681 |
+
$description,
|
6682 |
+
NULL
|
6683 |
+
);
|
6684 |
+
}
|
6685 |
+
|
6686 |
/**
|
6687 |
* WordPress core integrity page.
|
6688 |
*
|
7730 |
'user_lastlogin' => current_time('mysql')
|
7731 |
);
|
7732 |
|
7733 |
+
@file_put_contents($datastore_filepath, json_encode($login_info)."\n", FILE_APPEND);
|
7734 |
}
|
7735 |
}
|
7736 |
add_action('wp_login', 'sucuriscan_set_lastlogin', 50);
|
7785 |
for( $i=$offset; $i<$total_lines; $i++ ){
|
7786 |
$line = $reversed_lines[$i] ? trim($reversed_lines[$i]) : '';
|
7787 |
|
7788 |
+
// Check if the data is serialized (which we will consider as insecure).
|
7789 |
+
if( SucuriScan::is_serialized($line) ){
|
7790 |
+
$last_login = @unserialize($line); // TODO: Remove after version 1.7.5
|
7791 |
+
} else {
|
7792 |
+
$last_login = @json_decode($line, TRUE);
|
7793 |
+
}
|
7794 |
+
|
7795 |
+
if( $last_login ){
|
7796 |
$last_login['user_lastlogin_timestamp'] = strtotime($last_login['user_lastlogin']);
|
7797 |
$last_login['user_registered_timestamp'] = 0;
|
7798 |
|
8433 |
SucuriScanInterface::info( 'Filesystem scanner for file integrity was <code>' . $action_d . '</code>' );
|
8434 |
}
|
8435 |
|
8436 |
+
// Enable or disable the filesystem scanner for error logs.
|
8437 |
+
if( $scan_errorlogs = SucuriScanRequest::post(':scan_errorlogs', '(en|dis)able') ){
|
8438 |
+
$action_d = $scan_errorlogs . 'd';
|
8439 |
+
SucuriScanOption::update_option(':scan_errorlogs', $action_d);
|
8440 |
+
SucuriScanEvent::notify_event( 'plugin_change', 'Filesystem scanner for error logs was: ' . $action_d );
|
8441 |
+
SucuriScanInterface::info( 'Filesystem scanner for error logs was <code>' . $action_d . '</code>' );
|
8442 |
+
}
|
8443 |
+
|
8444 |
// Modify the schedule of the filesystem scanner.
|
8445 |
if( $frequency = SucuriScanRequest::post(':scan_frequency') ){
|
8446 |
$allowed_frequency = array_keys($sucuriscan_schedule_allowed);
|
8483 |
|
8484 |
// Update the email where the event notifications will be sent.
|
8485 |
if( $new_email = SucuriScanRequest::post(':notify_to') ){
|
8486 |
+
$valid_email = SucuriScan::get_valid_email($new_email);
|
8487 |
+
|
8488 |
+
if( $valid_email ){
|
8489 |
+
SucuriScanOption::update_option( ':notify_to', $valid_email );
|
8490 |
SucuriScanEvent::notify_event( 'plugin_change', 'Email address to get the event notifications was changed' );
|
8491 |
SucuriScanInterface::info( 'All the event notifications will be sent to the email specified.' );
|
8492 |
} else {
|
8677 |
$scan_interface = SucuriScanOption::get_option(':scan_interface');
|
8678 |
$scan_modfiles = SucuriScanOption::get_option(':scan_modfiles');
|
8679 |
$scan_checksums = SucuriScanOption::get_option(':scan_checksums');
|
8680 |
+
$scan_errorlogs = SucuriScanOption::get_option(':scan_errorlogs');
|
8681 |
$emails_per_hour = SucuriScanOption::get_option(':emails_per_hour');
|
8682 |
$maximum_failed_logins = SucuriScanOption::get_option(':maximum_failed_logins');
|
8683 |
$verify_ssl_cert = SucuriScanOption::get_option(':verify_ssl_cert');
|
8718 |
'ScanChecksumsSwitchText' => 'Disable',
|
8719 |
'ScanChecksumsSwitchValue' => 'disable',
|
8720 |
'ScanChecksumsSwitchCssClass' => 'button-danger',
|
8721 |
+
/* Scan error logs. */
|
8722 |
+
'ScanErrorlogsStatus' => 'Enabled',
|
8723 |
+
'ScanErrorlogsSwitchText' => 'Disable',
|
8724 |
+
'ScanErrorlogsSwitchValue' => 'disable',
|
8725 |
+
'ScanErrorlogsSwitchCssClass' => 'button-danger',
|
8726 |
/* Filsystem scanning frequency. */
|
8727 |
'ScanningFrequency' => 'Undefined',
|
8728 |
'ScanningFrequencyOptions' => $scan_freq_options,
|
8764 |
$template_variables['ScanChecksumsSwitchCssClass'] = 'button-success';
|
8765 |
}
|
8766 |
|
8767 |
+
if( $scan_errorlogs == 'disabled' ){
|
8768 |
+
$template_variables['ScanErrorlogsStatus'] = 'Disabled';
|
8769 |
+
$template_variables['ScanErrorlogsSwitchText'] = 'Enable';
|
8770 |
+
$template_variables['ScanErrorlogsSwitchValue'] = 'enable';
|
8771 |
+
$template_variables['ScanErrorlogsSwitchCssClass'] = 'button-success';
|
8772 |
+
}
|
8773 |
+
|
8774 |
if( array_key_exists($scan_freq, $sucuriscan_schedule_allowed) ){
|
8775 |
$template_variables['ScanningFrequency'] = $sucuriscan_schedule_allowed[$scan_freq];
|
8776 |
}
|
8800 |
|
8801 |
$template_variables = array(
|
8802 |
'NotificationOptions' => '',
|
8803 |
+
'PrettifyMailsWarningVisibility' => SucuriScanTemplate::visibility( SucuriScanMail::prettify_mails() ),
|
8804 |
);
|
8805 |
|
8806 |
$counter = 0;
|
9270 |
'Plugin_version' => SUCURISCAN_VERSION,
|
9271 |
'Plugin_checksum' => SUCURISCAN_PLUGIN_CHECKSUM,
|
9272 |
'Last_filesystem_scan' => SucuriScanOption::get_filesystem_runtime(TRUE),
|
9273 |
+
'Using_CloudProxy' => 'Unknown',
|
9274 |
+
'HTTP_Host' => 'Unknown',
|
9275 |
+
'Host_Name' => 'Unknown',
|
9276 |
+
'Host_Address' => 'Unknown',
|
9277 |
+
'Remote_Address' => SucuriScan::get_remote_addr(),
|
9278 |
+
'Remote_Address_Header' => SucuriScan::get_remote_addr_header(),
|
9279 |
'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE*8),
|
9280 |
'Server' => 'Unknown',
|
9281 |
'Developer_mode' => 'OFF',
|
9285 |
'PHP_version' => PHP_VERSION,
|
9286 |
);
|
9287 |
|
9288 |
+
$proxy_info = SucuriScan::is_behind_cloudproxy(TRUE);
|
9289 |
+
$info_vars['HTTP_Host'] = $proxy_info['http_host'];
|
9290 |
+
$info_vars['Host_Name'] = $proxy_info['host_name'];
|
9291 |
+
$info_vars['Host_Address'] = $proxy_info['host_addr'];
|
9292 |
+
$info_vars['Using_CloudProxy'] = $proxy_info['status'] ? 'Yes' : 'No';
|
9293 |
|
9294 |
if( defined('WP_DEBUG') && WP_DEBUG ){
|
9295 |
$info_vars['Developer_mode'] = 'ON';
|
9323 |
);
|
9324 |
|
9325 |
foreach( $field_names as $php_flag ){
|
9326 |
+
$php_flag_value = SucuriScan::ini_get($php_flag);
|
9327 |
$php_flag_name = 'PHP_' . $php_flag;
|
9328 |
$info_vars[$php_flag_name] = $php_flag_value ? $php_flag_value : 'N/A';
|
9329 |
}
|