Version Description
- Added better checks for SSL issues
- Fix for audit log timezones
- Various bugfixes and improvements
Download this release
Release Info
Developer | akresic |
Plugin | Sucuri Security – Auditing, Malware Scanner and Security Hardening |
Version | 1.7.10 |
Comparing to | |
See all releases |
Code changes from version 1.7.9 to 1.7.10
- inc/css/sucuriscan-default-css.css +8 -0
- inc/images/main-logo.png +0 -0
- inc/tpl/lastlogins-all.html.tpl +1 -1
- inc/tpl/lastlogins-failedlogins.html.tpl +16 -6
- inc/tpl/malwarescan.html.tpl +11 -1
- inc/tpl/notification-pretty.html.tpl +1 -1
- inc/tpl/notification-resetpwd.html.tpl +10 -0
- inc/tpl/posthack-resetplugins.html.tpl +26 -2
- inc/tpl/settings-general.html.tpl +16 -9
- readme.txt +6 -1
- sucuri.php +439 -147
inc/css/sucuriscan-default-css.css
CHANGED
@@ -269,6 +269,14 @@ td.sucuriscan-corefiles-warning > div{background:#f2dede;color:#a94442;border-co
|
|
269 |
.sucuriscan-admins-lastlogins .sucuriscan-ellipsis{width:170px}
|
270 |
.sucuriscan-admins-lastlogins td{padding:4px 8px}
|
271 |
.sucuriscan-lastlogins-failed{}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
/* About Page */
|
273 |
.sucuriscan-about ul{margin-left:20px}
|
274 |
.sucuriscan-about ul li{list-style:initial}
|
269 |
.sucuriscan-admins-lastlogins .sucuriscan-ellipsis{width:170px}
|
270 |
.sucuriscan-admins-lastlogins td{padding:4px 8px}
|
271 |
.sucuriscan-lastlogins-failed{}
|
272 |
+
/* Pattern Search Styles */
|
273 |
+
.sucuriscan-pattern-search {}
|
274 |
+
.sucuriscan-pattern-search-inputbox {margin-top:12px}
|
275 |
+
.sucuriscan-pattern-search-inputbox .input-text {width:84.7777%;line-height:30px;margin:0;margin-right:6px}
|
276 |
+
.sucuriscan-pattern-search-inputbox .input-button {width:14%;height:initial;line-height:35px}
|
277 |
+
.sucuriscan-pattern-search .sucuriscan-cleanup-btn {margin-top:12px}
|
278 |
+
.sucuriscan-pattern-search table label {color:#999}
|
279 |
+
.sucuriscan-pattern-search .sucuriscan-grep-text em{color:#ea3838}
|
280 |
/* About Page */
|
281 |
.sucuriscan-about ul{margin-left:20px}
|
282 |
.sucuriscan-about ul li{list-style:initial}
|
inc/images/main-logo.png
ADDED
Binary file
|
inc/tpl/lastlogins-all.html.tpl
CHANGED
@@ -13,7 +13,7 @@
|
|
13 |
</th>
|
14 |
</tr>
|
15 |
<tr>
|
16 |
-
<th class="manage-column"
|
17 |
<th class="manage-column">User</th>
|
18 |
<th class="manage-column">IP Address</th>
|
19 |
<th class="manage-column">Hostname</th>
|
13 |
</th>
|
14 |
</tr>
|
15 |
<tr>
|
16 |
+
<th class="manage-column"> </th>
|
17 |
<th class="manage-column">User</th>
|
18 |
<th class="manage-column">IP Address</th>
|
19 |
<th class="manage-column">Hostname</th>
|
inc/tpl/lastlogins-failedlogins.html.tpl
CHANGED
@@ -44,16 +44,17 @@
|
|
44 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-lastlogins-failed sucuriscan-%%SUCURI.IgnoreRules.TableVisibility%%">
|
45 |
<thead>
|
46 |
<tr>
|
47 |
-
<th
|
48 |
-
<th>User</th>
|
49 |
-
<th>Password</th>
|
50 |
-
<th>IP Address</th>
|
51 |
-
<th>Date/Time</th>
|
52 |
-
<th width="300">User-Agent</th>
|
53 |
</tr>
|
54 |
</thead>
|
55 |
|
56 |
<tbody>
|
|
|
57 |
%%SUCURI.FailedLogins.List%%
|
58 |
|
59 |
<tr class="sucuriscan-%%SUCURI.FailedLogins.NoItemsVisibility%%">
|
@@ -61,5 +62,14 @@
|
|
61 |
<em>No logs so far.</em>
|
62 |
</td>
|
63 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
</tbody>
|
65 |
</table>
|
44 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-lastlogins-failed sucuriscan-%%SUCURI.IgnoreRules.TableVisibility%%">
|
45 |
<thead>
|
46 |
<tr>
|
47 |
+
<th class="manage-column"> </th>
|
48 |
+
<th class="manage-column">User</th>
|
49 |
+
<th class="manage-column">Password</th>
|
50 |
+
<th class="manage-column">IP Address</th>
|
51 |
+
<th class="manage-column">Date/Time</th>
|
52 |
+
<th class="manage-column" width="300">User-Agent</th>
|
53 |
</tr>
|
54 |
</thead>
|
55 |
|
56 |
<tbody>
|
57 |
+
|
58 |
%%SUCURI.FailedLogins.List%%
|
59 |
|
60 |
<tr class="sucuriscan-%%SUCURI.FailedLogins.NoItemsVisibility%%">
|
62 |
<em>No logs so far.</em>
|
63 |
</td>
|
64 |
</tr>
|
65 |
+
|
66 |
+
<tr class="sucuriscan-%%SUCURI.FailedLogins.PaginationVisibility%%">
|
67 |
+
<td colspan="6">
|
68 |
+
<ul class="sucuriscan-pagination">
|
69 |
+
%%SUCURI.FailedLogins.PaginationLinks%%
|
70 |
+
</ul>
|
71 |
+
</td>
|
72 |
+
</tr>
|
73 |
+
|
74 |
</tbody>
|
75 |
</table>
|
inc/tpl/malwarescan.html.tpl
CHANGED
@@ -7,9 +7,19 @@
|
|
7 |
<form action="%%SUCURI.URL.Scanner%%" method="post" class="sucuriscan-sitecheck-form">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
9 |
<input type="hidden" name="sucuriscan_malware_scan" value="1" />
|
10 |
-
<
|
11 |
</form>
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
<div class="sucuriscan-sitelogo"> </div>
|
14 |
|
15 |
<div class="sucuriscan-sitecheck-disclaimer">
|
7 |
<form action="%%SUCURI.URL.Scanner%%" method="post" class="sucuriscan-sitecheck-form">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
9 |
<input type="hidden" name="sucuriscan_malware_scan" value="1" />
|
10 |
+
<input type="submit" value="Scan Website" class="button button-hero button-primary input-button" />
|
11 |
</form>
|
12 |
|
13 |
+
<script type="text/javascript">
|
14 |
+
jQuery(function($){
|
15 |
+
$('.sucuriscan-sitecheck-form .input-button').click(function(){
|
16 |
+
$('.sucuriscan-sitecheck-form .input-button')
|
17 |
+
.val('Scanning Website...')
|
18 |
+
.addClass('disabled');
|
19 |
+
});
|
20 |
+
});
|
21 |
+
</script>
|
22 |
+
|
23 |
<div class="sucuriscan-sitelogo"> </div>
|
24 |
|
25 |
<div class="sucuriscan-sitecheck-disclaimer">
|
inc/tpl/notification-pretty.html.tpl
CHANGED
@@ -4,7 +4,7 @@
|
|
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="
|
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>
|
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="%%SUCURI.SucuriURL%%/inc/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>
|
inc/tpl/notification-resetpwd.html.tpl
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
Your password for <strong>%%SUCURI.ResetPassword.UserName%%</strong>
|
3 |
+
<em>(%%SUCURI.ResetPassword.DisplayName%%)</em> at <a target="_blank"
|
4 |
+
href="http://%%SUCURI.ResetPassword.Website%%">%%SUCURI.ResetPassword.Website%%</a>
|
5 |
+
has been reset for security reasons.<br>
|
6 |
+
You can use this temporary password to log in:
|
7 |
+
<span style="display:inline-block;background:#f5f5f5;padding:2px 6px;
|
8 |
+
font-family:Menlo, Monaco, monospace, serif;border:1px solid #ddd">
|
9 |
+
%%SUCURI.ResetPassword.Password%%</span><br>
|
10 |
+
Please change your password after you log in.
|
inc/tpl/posthack-resetplugins.html.tpl
CHANGED
@@ -1,8 +1,12 @@
|
|
1 |
|
2 |
<div id="poststuff" class="sucuriscan-reset-plugins">
|
|
|
3 |
<div class="postbox">
|
|
|
4 |
<div class="inside">
|
|
|
5 |
<form action="%%SUCURI.URL.Posthack%%#reset-plugins" method="post">
|
|
|
6 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
7 |
<input type="hidden" name="sucuriscan_reset_plugins" value="1" />
|
8 |
|
@@ -24,7 +28,7 @@
|
|
24 |
</p>
|
25 |
</div>
|
26 |
|
27 |
-
<table class="wp-list-table widefat sucuriscan-table">
|
28 |
<thead>
|
29 |
<tr>
|
30 |
<th class="manage-column column-cb check-column">
|
@@ -39,7 +43,11 @@
|
|
39 |
</thead>
|
40 |
|
41 |
<tbody>
|
42 |
-
|
|
|
|
|
|
|
|
|
43 |
</tbody>
|
44 |
</table>
|
45 |
|
@@ -52,7 +60,23 @@
|
|
52 |
</p>
|
53 |
|
54 |
<input type="submit" value="Process selected items" class="button button-primary" />
|
|
|
55 |
</form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
</div>
|
|
|
57 |
</div>
|
|
|
58 |
</div>
|
1 |
|
2 |
<div id="poststuff" class="sucuriscan-reset-plugins">
|
3 |
+
|
4 |
<div class="postbox">
|
5 |
+
|
6 |
<div class="inside">
|
7 |
+
|
8 |
<form action="%%SUCURI.URL.Posthack%%#reset-plugins" method="post">
|
9 |
+
|
10 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
11 |
<input type="hidden" name="sucuriscan_reset_plugins" value="1" />
|
12 |
|
28 |
</p>
|
29 |
</div>
|
30 |
|
31 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-reset-plugins-table">
|
32 |
<thead>
|
33 |
<tr>
|
34 |
<th class="manage-column column-cb check-column">
|
43 |
</thead>
|
44 |
|
45 |
<tbody>
|
46 |
+
<tr>
|
47 |
+
<td colspan="5">
|
48 |
+
<span>Loading <em>(may take several seconds)</em>...</span>
|
49 |
+
</td>
|
50 |
+
</tr>
|
51 |
</tbody>
|
52 |
</table>
|
53 |
|
60 |
</p>
|
61 |
|
62 |
<input type="submit" value="Process selected items" class="button button-primary" />
|
63 |
+
|
64 |
</form>
|
65 |
+
|
66 |
+
<script type="text/javascript">
|
67 |
+
jQuery(function($){
|
68 |
+
$.post( '%%SUCURI.AjaxURL.Posthack%%', {
|
69 |
+
action: 'sucuriscan_posthack_ajax',
|
70 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
71 |
+
form_action: 'get_plugins_data',
|
72 |
+
}, function(data){
|
73 |
+
$('.sucuriscan-reset-plugins-table tbody').html( data );
|
74 |
+
});
|
75 |
+
});
|
76 |
+
</script>
|
77 |
+
|
78 |
</div>
|
79 |
+
|
80 |
</div>
|
81 |
+
|
82 |
</div>
|
inc/tpl/settings-general.html.tpl
CHANGED
@@ -152,27 +152,34 @@
|
|
152 |
</tr>
|
153 |
|
154 |
<tr>
|
155 |
-
<td>API proxy host:port</td>
|
156 |
<td><span class="sucuriscan-monospace">%%SUCURI.APIProxy.Host%%:%%SUCURI.APIProxy.Port%%</span></td>
|
157 |
<td> </td>
|
158 |
</tr>
|
159 |
|
160 |
<tr class="alternate">
|
161 |
-
<td>API proxy
|
162 |
-
<td><span class="sucuriscan-monospace">%%SUCURI.APIProxy.Username%%</span></td>
|
163 |
-
<td> </td>
|
164 |
-
</tr>
|
165 |
-
|
166 |
-
<tr>
|
167 |
-
<td>API proxy password</td>
|
168 |
<td>
|
|
|
169 |
<span class="sucuriscan-label-%%SUCURI.APIProxy.PasswordType%%">
|
170 |
-
%%SUCURI.APIProxy.PasswordText
|
171 |
</span>
|
172 |
</td>
|
173 |
<td> </td>
|
174 |
</tr>
|
175 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
<tr class="alternate">
|
177 |
<td>Support reverse proxy</td>
|
178 |
<td>%%SUCURI.ReverseProxyStatus%%</td>
|
152 |
</tr>
|
153 |
|
154 |
<tr>
|
155 |
+
<td>API proxy <em>(host:port)</em></td>
|
156 |
<td><span class="sucuriscan-monospace">%%SUCURI.APIProxy.Host%%:%%SUCURI.APIProxy.Port%%</span></td>
|
157 |
<td> </td>
|
158 |
</tr>
|
159 |
|
160 |
<tr class="alternate">
|
161 |
+
<td>API proxy <em>(auth)</em></td>
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
<td>
|
163 |
+
<span class="sucuriscan-monospace">%%SUCURI.APIProxy.Username%%</span>
|
164 |
<span class="sucuriscan-label-%%SUCURI.APIProxy.PasswordType%%">
|
165 |
+
<em>password is %%SUCURI.APIProxy.PasswordText%%</em>
|
166 |
</span>
|
167 |
</td>
|
168 |
<td> </td>
|
169 |
</tr>
|
170 |
|
171 |
+
<tr>
|
172 |
+
<td>API test request</td>
|
173 |
+
<td><em>(Test ability to send HTTP requests)</em></td>
|
174 |
+
<td class="td-with-button">
|
175 |
+
<form action="%%SUCURI.URL.Settings%%" method="post">
|
176 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
177 |
+
<input type="hidden" name="sucuriscan_debug_request" value="1" />
|
178 |
+
<button type="submit" class="button-primary">Proceed</button>
|
179 |
+
</form>
|
180 |
+
</td>
|
181 |
+
</tr>
|
182 |
+
|
183 |
<tr class="alternate">
|
184 |
<td>Support reverse proxy</td>
|
185 |
<td>%%SUCURI.ReverseProxyStatus%%</td>
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: dd@sucuri.net
|
|
3 |
Donate Link: http://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.7.
|
7 |
Tested up to: 4.2.2
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
@@ -352,6 +352,11 @@ service from the WordPress dashboard.
|
|
352 |
|
353 |
== Changelog ==
|
354 |
|
|
|
|
|
|
|
|
|
|
|
355 |
= 1.7.9 =
|
356 |
* Improved reinstallation process
|
357 |
* Updated sidebar banners
|
3 |
Donate Link: http://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.7.10
|
7 |
Tested up to: 4.2.2
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
352 |
|
353 |
== Changelog ==
|
354 |
|
355 |
+
= 1.7.10 =
|
356 |
+
* Added better checks for SSL issues
|
357 |
+
* Fix for audit log timezones
|
358 |
+
* Various bugfixes and improvements
|
359 |
+
|
360 |
= 1.7.9 =
|
361 |
* Improved reinstallation process
|
362 |
* Updated sidebar banners
|
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.7.
|
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.7.
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
@@ -197,17 +197,17 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
197 |
'sucuriscan_notify_website_updated' => 'Receive email alerts when the WordPress version is updated',
|
198 |
'sucuriscan_notify_settings_updated' => 'Receive email alerts when your website settings are updated',
|
199 |
'sucuriscan_notify_theme_editor' => 'Receive email alerts when a file is modified with theme/plugin editor',
|
200 |
-
'sucuriscan_notify_plugin_installed' => 'plugin:Receive email alerts when a plugin is installed',
|
201 |
-
'sucuriscan_notify_plugin_activated' => 'plugin:Receive email alerts when a plugin is activated',
|
202 |
-
'sucuriscan_notify_plugin_deactivated' => 'plugin:Receive email alerts when a plugin is deactivated',
|
203 |
-
'sucuriscan_notify_plugin_updated' => 'plugin:Receive email alerts when a plugin is updated',
|
204 |
-
'sucuriscan_notify_plugin_deleted' => 'plugin:Receive email alerts when a plugin is deleted',
|
205 |
-
'sucuriscan_notify_widget_added' => 'widget:Receive email alerts when a widget is added to a sidebar',
|
206 |
-
'sucuriscan_notify_widget_deleted' => 'widget:Receive email alerts when a widget is deleted from a sidebar',
|
207 |
-
'sucuriscan_notify_theme_installed' => 'theme:Receive email alerts when a theme is installed',
|
208 |
-
'sucuriscan_notify_theme_activated' => 'theme:Receive email alerts when a theme is activated',
|
209 |
-
'sucuriscan_notify_theme_updated' => 'theme:Receive email alerts when a theme is updated',
|
210 |
-
'sucuriscan_notify_theme_deleted' => 'theme:Receive email alerts when a theme is deleted',
|
211 |
);
|
212 |
|
213 |
$sucuriscan_schedule_allowed = array(
|
@@ -282,6 +282,17 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
282 |
add_action( 'admin_enqueue_scripts', 'SucuriScanInterface::enqueue_scripts', 1 );
|
283 |
add_action( 'admin_menu', 'SucuriScanInterface::add_interface_menu' );
|
284 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
285 |
/**
|
286 |
* Function call interceptors.
|
287 |
*
|
@@ -795,11 +806,16 @@ class SucuriScan {
|
|
795 |
*/
|
796 |
public static function datetime( $timestamp = 0 ){
|
797 |
if ( is_numeric( $timestamp ) && $timestamp > 0 ) {
|
|
|
798 |
$date_format = get_option( 'date_format' );
|
799 |
$time_format = get_option( 'time_format' );
|
800 |
-
$
|
801 |
|
802 |
-
|
|
|
|
|
|
|
|
|
803 |
}
|
804 |
|
805 |
return null;
|
@@ -1631,9 +1647,9 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1631 |
/**
|
1632 |
* Skip some specific directories and file paths from the filesystem scan.
|
1633 |
*
|
1634 |
-
* @param string $directory
|
1635 |
-
* @param string $filename
|
1636 |
-
* @return boolean
|
1637 |
*/
|
1638 |
private function ignore_folderpath( $directory = '', $filename = '' ){
|
1639 |
// Ignoring current and parent folders.
|
@@ -1682,6 +1698,15 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1682 |
return true;
|
1683 |
}
|
1684 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1685 |
// Any file maching one of these rules WILL NOT be ignored.
|
1686 |
if (
|
1687 |
( strpos( $filename, '.php' ) !== false) ||
|
@@ -1725,6 +1750,53 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1725 |
return $dirs;
|
1726 |
}
|
1727 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1728 |
/**
|
1729 |
* Remove a directory recursively.
|
1730 |
*
|
@@ -2424,7 +2496,7 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2424 |
'sucuriscan_site_version' => '0.0',
|
2425 |
'sucuriscan_sitecheck_counter' => 0,
|
2426 |
'sucuriscan_sitecheck_scanner' => 'enabled',
|
2427 |
-
'sucuriscan_verify_ssl_cert' => '
|
2428 |
);
|
2429 |
|
2430 |
return $defaults;
|
@@ -2926,9 +2998,9 @@ class SucuriScanEvent extends SucuriScan {
|
|
2926 |
) {
|
2927 |
self::report_site_version();
|
2928 |
|
2929 |
-
$
|
2930 |
-
$
|
2931 |
-
$signatures = $
|
2932 |
|
2933 |
if ( $signatures ) {
|
2934 |
$hashes_sent = SucuriScanAPI::send_hashes( $signatures );
|
@@ -3237,13 +3309,17 @@ class SucuriScanEvent extends SucuriScan {
|
|
3237 |
$user = get_userdata( $user_id );
|
3238 |
|
3239 |
if ( $user instanceof WP_User ) {
|
|
|
|
|
|
|
3240 |
$new_password = wp_generate_password( 15, true, false );
|
3241 |
|
3242 |
-
$message =
|
3243 |
-
.
|
3244 |
-
.
|
3245 |
-
.
|
3246 |
-
.
|
|
|
3247 |
|
3248 |
$data_set = array( 'Force' => true ); // Skip limit for emails per hour.
|
3249 |
SucuriScanMail::send_mail( $user->user_email, 'Password changed', $message, $data_set );
|
@@ -4150,7 +4226,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4150 |
* @param string $method HTTP method that will be used to send the request.
|
4151 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4152 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4153 |
-
* @return array
|
4154 |
*/
|
4155 |
private static function api_call( $url = '', $method = 'GET', $params = array(), $args = array() ){
|
4156 |
if ( ! $url ) {
|
@@ -4192,38 +4268,39 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4192 |
} elseif ( $method == 'POST' ) {
|
4193 |
$req_args['body'] = $params;
|
4194 |
$response = wp_remote_post( $url, $req_args );
|
|
|
|
|
|
|
4195 |
}
|
4196 |
|
4197 |
-
|
4198 |
-
|
4199 |
-
SucuriScanInterface::error(sprintf(
|
4200 |
-
'Something went wrong with an API call (%s action): %s',
|
4201 |
-
( isset($params['a']) ? self::escape( $params['a'] ) : 'unknown' ),
|
4202 |
-
$response->get_error_message()
|
4203 |
-
));
|
4204 |
-
} else {
|
4205 |
-
$response['body_raw'] = $response['body'];
|
4206 |
|
4207 |
-
|
4208 |
-
|
4209 |
-
|
4210 |
-
|
4211 |
-
|
4212 |
-
|
4213 |
-
|
4214 |
-
|
4215 |
-
|
4216 |
-
|
4217 |
-
|
4218 |
-
|
|
|
4219 |
|
4220 |
-
|
4221 |
-
|
4222 |
-
|
4223 |
-
|
|
|
|
|
|
|
|
|
4224 |
}
|
4225 |
|
4226 |
-
return
|
4227 |
}
|
4228 |
|
4229 |
/**
|
@@ -4328,7 +4405,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4328 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4329 |
* @param boolean $send_api_key Whether the API key should be added to the request parameters or not.
|
4330 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4331 |
-
* @return array
|
4332 |
*/
|
4333 |
public static function api_call_wordpress( $method = 'GET', $params = array(), $send_api_key = true, $args = array() ){
|
4334 |
$url = SUCURISCAN_API;
|
@@ -4355,7 +4432,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4355 |
*
|
4356 |
* @param string $method HTTP method that will be used to send the request.
|
4357 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4358 |
-
* @return array
|
4359 |
*/
|
4360 |
public static function api_call_cloudproxy( $method = 'GET', $params = array() ){
|
4361 |
$send_request = false;
|
@@ -4385,12 +4462,90 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4385 |
return false;
|
4386 |
}
|
4387 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4388 |
/**
|
4389 |
* Determine whether an API response was successful or not checking the expected
|
4390 |
* generic variables and types, in case of an error a notification will appears
|
4391 |
* in the administrator panel explaining the result of the operation.
|
4392 |
*
|
4393 |
-
* @param array $response
|
4394 |
* @return boolean Either true or false in case of success or failure of the API response (respectively).
|
4395 |
*/
|
4396 |
private static function handle_response( $response = array() ){
|
@@ -4404,11 +4559,14 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4404 |
|
4405 |
// Check whether the message list is empty or not.
|
4406 |
if ( isset($response['body']->messages[0]) ) {
|
4407 |
-
$action_message = $response['body']->messages[0];
|
4408 |
}
|
4409 |
|
|
|
|
|
|
|
4410 |
// Special response for invalid API keys.
|
4411 |
-
if (
|
4412 |
SucuriScanOption::delete_option( ':api_key' );
|
4413 |
|
4414 |
$action_message .= ' This generally happens when you add an invalid API key, the'
|
@@ -4417,7 +4575,50 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4417 |
. ' key to your email address.';
|
4418 |
}
|
4419 |
|
4420 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4421 |
}
|
4422 |
} else {
|
4423 |
SucuriScanInterface::error( 'Could not determine the status of an API call.' );
|
@@ -4560,8 +4761,8 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4560 |
if ( preg_match( $log_pattern, $log, $log_match ) ) {
|
4561 |
$log_data = array(
|
4562 |
'event' => 'notice',
|
4563 |
-
'date' =>
|
4564 |
-
'time' =>
|
4565 |
'datetime' => '',
|
4566 |
'timestamp' => 0,
|
4567 |
'account' => $log_match[3],
|
@@ -4572,11 +4773,16 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4572 |
'file_list_count' => 0,
|
4573 |
);
|
4574 |
|
4575 |
-
|
4576 |
-
$
|
4577 |
-
$log_data['
|
|
|
|
|
|
|
4578 |
|
4579 |
// Extract more information from the generic audit logs.
|
|
|
|
|
4580 |
if ( preg_match( $generic_pattern, $log_data['message'], $log_extra ) ) {
|
4581 |
$log_data['event'] = strtolower( $log_extra[1] );
|
4582 |
$log_data['message'] = trim( $log_extra[3] );
|
@@ -4615,6 +4821,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4615 |
if ( preg_match( $extra_pattern, $log_data['message'], $log_extra ) ) {
|
4616 |
$log_data['message'] = $log_extra[1];
|
4617 |
$log_extra[2] = str_replace( ', new size', '; new size', $log_extra[2] );
|
|
|
4618 |
$log_data['file_list'] = explode( ',', $log_extra[2] );
|
4619 |
$log_data['file_list_count'] = count( $log_data['file_list'] );
|
4620 |
}
|
@@ -5488,6 +5695,23 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5488 |
return $url_path;
|
5489 |
}
|
5490 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5491 |
/**
|
5492 |
* Complement the list of pseudo-variables that will be used in the base
|
5493 |
* template files, this will also generate the navigation bar and detect which
|
@@ -5529,6 +5753,10 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5529 |
|
5530 |
$params[ $pseudo_var ] = self::get_url( $unique_name );
|
5531 |
|
|
|
|
|
|
|
|
|
5532 |
$navbar_item_css_class = 'nav-tab';
|
5533 |
|
5534 |
if ( $params['CurrentPageFunc'] == $sub_page_func ) {
|
@@ -5939,11 +6167,11 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
5939 |
}
|
5940 |
|
5941 |
// Scan the project and file all directories.
|
5942 |
-
$
|
5943 |
-
$
|
5944 |
-
$
|
5945 |
-
$
|
5946 |
-
$directory_list = $
|
5947 |
|
5948 |
if ( $directory_list ) {
|
5949 |
$response['is_not_ignored'] = $directory_list;
|
@@ -6205,7 +6433,7 @@ class SucuriScanInterface {
|
|
6205 |
* @return void
|
6206 |
*/
|
6207 |
public static function initialize(){
|
6208 |
-
if ( SucuriScan::
|
6209 |
$_SERVER['SUCURIREAL_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
|
6210 |
$_SERVER['REMOTE_ADDR'] = SucuriScan::get_remote_addr();
|
6211 |
}
|
@@ -6248,6 +6476,8 @@ class SucuriScanInterface {
|
|
6248 |
if (
|
6249 |
function_exists( 'add_menu_page' )
|
6250 |
&& $sucuriscan_pages
|
|
|
|
|
6251 |
) {
|
6252 |
// Add main menu link.
|
6253 |
add_menu_page(
|
@@ -6259,9 +6489,7 @@ class SucuriScanInterface {
|
|
6259 |
SUCURISCAN_URL . '/inc/images/menu-icon.png'
|
6260 |
);
|
6261 |
|
6262 |
-
|
6263 |
-
|
6264 |
-
foreach ( $sub_pages as $sub_page_func => $sub_page_title ) {
|
6265 |
if (
|
6266 |
$sub_page_func == 'sucuriscan_scanner'
|
6267 |
&& SucuriScanTemplate::is_sitecheck_disabled()
|
@@ -6293,9 +6521,9 @@ class SucuriScanInterface {
|
|
6293 |
*/
|
6294 |
public static function handle_old_plugins(){
|
6295 |
if ( class_exists( 'SucuriScanFileInfo' ) ) {
|
6296 |
-
$
|
6297 |
-
$
|
6298 |
-
$
|
6299 |
|
6300 |
$plugins = array(
|
6301 |
'sucuri-wp-plugin/sucuri.php',
|
@@ -6310,7 +6538,7 @@ class SucuriScanInterface {
|
|
6310 |
deactivate_plugins( $plugin );
|
6311 |
}
|
6312 |
|
6313 |
-
$plugin_removed = $
|
6314 |
}
|
6315 |
}
|
6316 |
}
|
@@ -8144,10 +8372,10 @@ function sucuriscan_harden_errorlog(){
|
|
8144 |
|
8145 |
// Search error log files in the project.
|
8146 |
if ( $scan_errorlogs != 'disabled' ) {
|
8147 |
-
$
|
8148 |
-
$
|
8149 |
-
$
|
8150 |
-
$error_logs = $
|
8151 |
$total_log_files = count( $error_logs );
|
8152 |
} else {
|
8153 |
$hardened = 2;
|
@@ -8333,12 +8561,12 @@ function sucuriscan_integrity_form_submissions(){
|
|
8333 |
function sucuriscan_get_integrity_tree( $dir = './', $recursive = false ){
|
8334 |
$abs_path = rtrim( ABSPATH, '/' );
|
8335 |
|
8336 |
-
$
|
8337 |
-
$
|
8338 |
-
$
|
8339 |
-
$
|
8340 |
-
$
|
8341 |
-
$integrity_tree = $
|
8342 |
|
8343 |
if ( ! $integrity_tree ) {
|
8344 |
$integrity_tree = array();
|
@@ -8915,6 +9143,21 @@ function sucuriscan_posthack_page(){
|
|
8915 |
echo SucuriScanTemplate::get_template( 'posthack', $template_variables );
|
8916 |
}
|
8917 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8918 |
/**
|
8919 |
* Check whether the "I understand this operation" checkbox was marked or not.
|
8920 |
*
|
@@ -9057,7 +9300,7 @@ function sucuriscan_posthack_users( $process_form = false ){
|
|
9057 |
$max_per_page
|
9058 |
);
|
9059 |
|
9060 |
-
if ( $total_items >
|
9061 |
$template_variables['ResetPassword.PaginationVisibility'] = 'visible';
|
9062 |
}
|
9063 |
}
|
@@ -9142,38 +9385,51 @@ function sucuriscan_posthack_plugins( $process_form = false ){
|
|
9142 |
'ResetPlugin.CacheLifeTime' => 'unknown',
|
9143 |
);
|
9144 |
|
9145 |
-
|
9146 |
if ( defined( 'SUCURISCAN_GET_PLUGINS_LIFETIME' ) ) {
|
9147 |
$template_variables['ResetPlugin.CacheLifeTime'] = SUCURISCAN_GET_PLUGINS_LIFETIME;
|
9148 |
}
|
9149 |
|
9150 |
sucuriscan_posthack_reinstall_plugins( $process_form );
|
9151 |
-
$all_plugins = SucuriScanAPI::get_plugins();
|
9152 |
-
$counter = 0;
|
9153 |
|
9154 |
-
|
9155 |
-
|
9156 |
-
$plugin_type_class = ( $plugin_data['PluginType'] == 'free' ) ? 'primary' : 'warning';
|
9157 |
-
$input_disabled = ( $plugin_data['PluginType'] == 'free' ) ? '' : 'disabled="disabled"';
|
9158 |
-
$plugin_status = $plugin_data['IsPluginActive'] ? 'active' : 'not active';
|
9159 |
-
$plugin_status_class = $plugin_data['IsPluginActive'] ? 'success' : 'default';
|
9160 |
-
|
9161 |
-
$template_variables['ResetPlugin.PluginList'] .= SucuriScanTemplate::get_snippet('posthack-resetplugins', array(
|
9162 |
-
'ResetPlugin.CssClass' => $css_class,
|
9163 |
-
'ResetPlugin.Disabled' => $input_disabled,
|
9164 |
-
'ResetPlugin.PluginPath' => SucuriScan::escape( $plugin_path ),
|
9165 |
-
'ResetPlugin.Plugin' => SucuriScan::excerpt( $plugin_data['Name'], 35 ),
|
9166 |
-
'ResetPlugin.Version' => $plugin_data['Version'],
|
9167 |
-
'ResetPlugin.Type' => $plugin_data['PluginType'],
|
9168 |
-
'ResetPlugin.TypeClass' => $plugin_type_class,
|
9169 |
-
'ResetPlugin.Status' => $plugin_status,
|
9170 |
-
'ResetPlugin.StatusClass' => $plugin_status_class,
|
9171 |
-
));
|
9172 |
|
9173 |
-
|
9174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9175 |
|
9176 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9177 |
}
|
9178 |
|
9179 |
/**
|
@@ -9192,10 +9448,10 @@ function sucuriscan_posthack_reinstall_plugins( $process_form = false ){
|
|
9192 |
|
9193 |
if ( $plugin_list = SucuriScanRequest::post( 'plugin_path', '_array' ) ) {
|
9194 |
// Create an instance of the FileInfo interface.
|
9195 |
-
$
|
9196 |
-
$
|
9197 |
-
$
|
9198 |
-
$
|
9199 |
|
9200 |
// Get (possible) cached information from the installed plugins.
|
9201 |
$all_plugins = SucuriScanAPI::get_plugins();
|
@@ -9213,7 +9469,7 @@ function sucuriscan_posthack_reinstall_plugins( $process_form = false ){
|
|
9213 |
// First, remove all files/sub-folders from the plugin's directory.
|
9214 |
if ( substr_count( $plugin_path, '/' ) >= 1 ) {
|
9215 |
$plugin_directory = dirname( WP_PLUGIN_DIR . '/' . $plugin_path );
|
9216 |
-
$
|
9217 |
}
|
9218 |
|
9219 |
// Install a fresh copy of the plugin's files.
|
@@ -9872,8 +10128,16 @@ function sucuriscan_failed_logins_panel(){
|
|
9872 |
'FailedLogins.NoItemsVisibility' => 'visible',
|
9873 |
'FailedLogins.WarningVisibility' => 'visible',
|
9874 |
'FailedLogins.CollectPasswordsVisibility' => 'visible',
|
|
|
|
|
9875 |
);
|
9876 |
|
|
|
|
|
|
|
|
|
|
|
|
|
9877 |
$max_failed_logins = SucuriScanOption::get_option( ':maximum_failed_logins' );
|
9878 |
$notify_bruteforce_attack = SucuriScanOption::get_option( ':notify_bruteforce_attack' );
|
9879 |
$failed_logins = sucuriscan_get_failed_logins();
|
@@ -9897,37 +10161,50 @@ function sucuriscan_failed_logins_panel(){
|
|
9897 |
if ( $failed_logins ) {
|
9898 |
$counter = 0;
|
9899 |
|
9900 |
-
|
9901 |
-
|
9902 |
-
|
|
|
|
|
9903 |
|
9904 |
-
|
9905 |
-
|
9906 |
-
|
9907 |
-
|
9908 |
-
|
9909 |
-
|
9910 |
-
|
9911 |
-
|
|
|
9912 |
}
|
9913 |
-
}
|
9914 |
|
9915 |
-
|
9916 |
-
|
9917 |
-
|
9918 |
-
|
9919 |
-
|
9920 |
-
|
9921 |
-
|
9922 |
-
|
9923 |
-
|
9924 |
|
9925 |
-
|
|
|
9926 |
}
|
9927 |
|
9928 |
if ( $counter > 0 ) {
|
9929 |
$template_variables['FailedLogins.NoItemsVisibility'] = 'hidden';
|
9930 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9931 |
}
|
9932 |
|
9933 |
$template_variables['FailedLogins.MaxFailedLogins'] = $max_failed_logins;
|
@@ -10025,10 +10302,15 @@ function sucuriscan_get_failed_logins( $get_old_logs = false ){
|
|
10025 |
);
|
10026 |
|
10027 |
// Read and parse all the entries found in the datastore file.
|
10028 |
-
|
10029 |
-
|
10030 |
-
|
|
|
|
|
|
|
|
|
10031 |
$login_data['attempt_date'] = date( 'r', $login_data['attempt_time'] );
|
|
|
10032 |
|
10033 |
if ( ! $login_data['user_agent'] ) {
|
10034 |
$login_data['user_agent'] = 'Unknown';
|
@@ -10794,6 +11076,16 @@ function sucuriscan_settings_form_submissions( $page_nonce = null ){
|
|
10794 |
SucuriScanEvent::report_info_event( $message );
|
10795 |
SucuriScanInterface::info( $message );
|
10796 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10797 |
}
|
10798 |
}
|
10799 |
|
@@ -10906,10 +11198,10 @@ function sucuriscan_settings_general(){
|
|
10906 |
'ReverseProxySwitchValue' => 'disable',
|
10907 |
'ReverseProxySwitchCssClass' => 'button-danger',
|
10908 |
/* API Proxy Settings */
|
10909 |
-
'APIProxy.Host' => '
|
10910 |
-
'APIProxy.Port' => '
|
10911 |
-
'APIProxy.Username' => '
|
10912 |
-
'APIProxy.Password' => '
|
10913 |
'APIProxy.PasswordType' => 'default',
|
10914 |
'APIProxy.PasswordText' => 'empty',
|
10915 |
);
|
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.10
|
8 |
Author URI: http://sucuri.net
|
9 |
*/
|
10 |
|
66 |
/**
|
67 |
* Current version of the plugin's code.
|
68 |
*/
|
69 |
+
define( 'SUCURISCAN_VERSION', '1.7.10' );
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
197 |
'sucuriscan_notify_website_updated' => 'Receive email alerts when the WordPress version is updated',
|
198 |
'sucuriscan_notify_settings_updated' => 'Receive email alerts when your website settings are updated',
|
199 |
'sucuriscan_notify_theme_editor' => 'Receive email alerts when a file is modified with theme/plugin editor',
|
200 |
+
'sucuriscan_notify_plugin_installed' => 'plugin:Receive email alerts when a <strong>plugin is installed</strong>',
|
201 |
+
'sucuriscan_notify_plugin_activated' => 'plugin:Receive email alerts when a <strong>plugin is activated</strong>',
|
202 |
+
'sucuriscan_notify_plugin_deactivated' => 'plugin:Receive email alerts when a <strong>plugin is deactivated</strong>',
|
203 |
+
'sucuriscan_notify_plugin_updated' => 'plugin:Receive email alerts when a <strong>plugin is updated</strong>',
|
204 |
+
'sucuriscan_notify_plugin_deleted' => 'plugin:Receive email alerts when a <strong>plugin is deleted</strong>',
|
205 |
+
'sucuriscan_notify_widget_added' => 'widget:Receive email alerts when a <strong>widget is added</strong> to a sidebar',
|
206 |
+
'sucuriscan_notify_widget_deleted' => 'widget:Receive email alerts when a <strong>widget is deleted</strong> from a sidebar',
|
207 |
+
'sucuriscan_notify_theme_installed' => 'theme:Receive email alerts when a <strong>theme is installed</strong>',
|
208 |
+
'sucuriscan_notify_theme_activated' => 'theme:Receive email alerts when a <strong>theme is activated</strong>',
|
209 |
+
'sucuriscan_notify_theme_updated' => 'theme:Receive email alerts when a <strong>theme is updated</strong>',
|
210 |
+
'sucuriscan_notify_theme_deleted' => 'theme:Receive email alerts when a <strong>theme is deleted</strong>',
|
211 |
);
|
212 |
|
213 |
$sucuriscan_schedule_allowed = array(
|
282 |
add_action( 'admin_enqueue_scripts', 'SucuriScanInterface::enqueue_scripts', 1 );
|
283 |
add_action( 'admin_menu', 'SucuriScanInterface::add_interface_menu' );
|
284 |
|
285 |
+
/**
|
286 |
+
* Attach Ajax requests to a custom page handler.
|
287 |
+
*/
|
288 |
+
foreach ( $sucuriscan_pages as $page_func => $page_title ) {
|
289 |
+
$ajax_func = $page_func . '_ajax';
|
290 |
+
|
291 |
+
if ( function_exists( $ajax_func ) ) {
|
292 |
+
add_action( 'wp_ajax_' . $ajax_func, $ajax_func );
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
/**
|
297 |
* Function call interceptors.
|
298 |
*
|
806 |
*/
|
807 |
public static function datetime( $timestamp = 0 ){
|
808 |
if ( is_numeric( $timestamp ) && $timestamp > 0 ) {
|
809 |
+
$gmt_offset = get_option( 'gmt_offset' );
|
810 |
$date_format = get_option( 'date_format' );
|
811 |
$time_format = get_option( 'time_format' );
|
812 |
+
$tz_format = sprintf( '%s %s', $date_format, $time_format );
|
813 |
|
814 |
+
if ( is_numeric( $gmt_offset ) ) {
|
815 |
+
$timestamp += ( $gmt_offset * 3600 );
|
816 |
+
}
|
817 |
+
|
818 |
+
return date_i18n( $tz_format, $timestamp );
|
819 |
}
|
820 |
|
821 |
return null;
|
1647 |
/**
|
1648 |
* Skip some specific directories and file paths from the filesystem scan.
|
1649 |
*
|
1650 |
+
* @param string $directory Directory where the scanner is located at the moment.
|
1651 |
+
* @param string $filename Name of the folder or file being scanned at the moment.
|
1652 |
+
* @return boolean Either TRUE or FALSE representing that the scan should ignore this folder or not.
|
1653 |
*/
|
1654 |
private function ignore_folderpath( $directory = '', $filename = '' ){
|
1655 |
// Ignoring current and parent folders.
|
1698 |
return true;
|
1699 |
}
|
1700 |
|
1701 |
+
// Ignore files specified by the administrator.
|
1702 |
+
if ( ! empty($this->ignored_directories) ) {
|
1703 |
+
foreach ( $this->ignored_directories['directories'] as $ignored_dir ) {
|
1704 |
+
if ( strpos( $ignored_dir, $filename ) !== false ) {
|
1705 |
+
return true;
|
1706 |
+
}
|
1707 |
+
}
|
1708 |
+
}
|
1709 |
+
|
1710 |
// Any file maching one of these rules WILL NOT be ignored.
|
1711 |
if (
|
1712 |
( strpos( $filename, '.php' ) !== false) ||
|
1750 |
return $dirs;
|
1751 |
}
|
1752 |
|
1753 |
+
/**
|
1754 |
+
* Returns a list of lines matching the specified pattern in all the files found
|
1755 |
+
* in the specified directory, each entry in the list contains the relative path
|
1756 |
+
* of the file and the number of the line where the pattern was found, as well
|
1757 |
+
* as the string around the pattern in that line.
|
1758 |
+
*
|
1759 |
+
* @param string $directory Directory where the scanner is located at the moment.
|
1760 |
+
* @param string $pattern Text that will be searched inside each file.
|
1761 |
+
* @return array Associative list with the file path and line number of the match.
|
1762 |
+
*/
|
1763 |
+
public function grep_pattern( $directory = '', $pattern = '' ){
|
1764 |
+
$dir_tree = $this->get_directory_tree( $directory );
|
1765 |
+
$pattern = '/.*' . str_replace( '/', '\/', $pattern ) . '.*/';
|
1766 |
+
$results = array();
|
1767 |
+
|
1768 |
+
if (
|
1769 |
+
class_exists( 'SplFileObject' )
|
1770 |
+
&& class_exists( 'RegexIterator' )
|
1771 |
+
&& SucuriScan::is_valid_pattern( $pattern )
|
1772 |
+
) {
|
1773 |
+
foreach ( $dir_tree as $file_path ) {
|
1774 |
+
try {
|
1775 |
+
$fobject = new SplFileObject( $file_path );
|
1776 |
+
$fstream = new RegexIterator( $fobject, $pattern, RegexIterator::MATCH );
|
1777 |
+
|
1778 |
+
foreach ( $fstream as $key => $ltext ) {
|
1779 |
+
$lnumber = ( $key + 1 );
|
1780 |
+
$ltext = str_replace( "\n", '', $ltext );
|
1781 |
+
$fpath = str_replace( $directory, '', $file_path );
|
1782 |
+
$loutput = sprintf( '%s:%d:%s', $fpath, $lnumber, $ltext );
|
1783 |
+
$results[] = array(
|
1784 |
+
'file_path' => $file_path,
|
1785 |
+
'relative_path' => $fpath,
|
1786 |
+
'line_number' => $lnumber,
|
1787 |
+
'line_text' => $ltext,
|
1788 |
+
'output' => $loutput,
|
1789 |
+
);
|
1790 |
+
}
|
1791 |
+
} catch ( RuntimeException $exception ) {
|
1792 |
+
SucuriScanEvent::report_exception( $exception );
|
1793 |
+
}
|
1794 |
+
}
|
1795 |
+
}
|
1796 |
+
|
1797 |
+
return $results;
|
1798 |
+
}
|
1799 |
+
|
1800 |
/**
|
1801 |
* Remove a directory recursively.
|
1802 |
*
|
2496 |
'sucuriscan_site_version' => '0.0',
|
2497 |
'sucuriscan_sitecheck_counter' => 0,
|
2498 |
'sucuriscan_sitecheck_scanner' => 'enabled',
|
2499 |
+
'sucuriscan_verify_ssl_cert' => 'false',
|
2500 |
);
|
2501 |
|
2502 |
return $defaults;
|
2998 |
) {
|
2999 |
self::report_site_version();
|
3000 |
|
3001 |
+
$file_info = new SucuriScanFileInfo();
|
3002 |
+
$file_info->scan_interface = SucuriScanOption::get_option( ':scan_interface' );
|
3003 |
+
$signatures = $file_info->get_directory_tree_md5( ABSPATH );
|
3004 |
|
3005 |
if ( $signatures ) {
|
3006 |
$hashes_sent = SucuriScanAPI::send_hashes( $signatures );
|
3309 |
$user = get_userdata( $user_id );
|
3310 |
|
3311 |
if ( $user instanceof WP_User ) {
|
3312 |
+
$website = SucuriScan::get_domain();
|
3313 |
+
$user_login = $user->user_login;
|
3314 |
+
$display_name = $user->display_name;
|
3315 |
$new_password = wp_generate_password( 15, true, false );
|
3316 |
|
3317 |
+
$message = SucuriScanTemplate::get_section( 'notification-resetpwd', array(
|
3318 |
+
'ResetPassword.UserName' => $user_login,
|
3319 |
+
'ResetPassword.DisplayName' => $display_name,
|
3320 |
+
'ResetPassword.Password' => $new_password,
|
3321 |
+
'ResetPassword.Website' => $website,
|
3322 |
+
) );
|
3323 |
|
3324 |
$data_set = array( 'Force' => true ); // Skip limit for emails per hour.
|
3325 |
SucuriScanMail::send_mail( $user->user_email, 'Password changed', $message, $data_set );
|
4226 |
* @param string $method HTTP method that will be used to send the request.
|
4227 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4228 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4229 |
+
* @return array Response object after the HTTP request is executed.
|
4230 |
*/
|
4231 |
private static function api_call( $url = '', $method = 'GET', $params = array(), $args = array() ){
|
4232 |
if ( ! $url ) {
|
4268 |
} elseif ( $method == 'POST' ) {
|
4269 |
$req_args['body'] = $params;
|
4270 |
$response = wp_remote_post( $url, $req_args );
|
4271 |
+
} else {
|
4272 |
+
$response = false;
|
4273 |
+
SucuriScanInterface::error( 'HTTP method not allowed: ' . $method );
|
4274 |
}
|
4275 |
|
4276 |
+
return self::process_response( $response, $params, $args );
|
4277 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4278 |
|
4279 |
+
/**
|
4280 |
+
* Test ability of the site to send HTTP requests.
|
4281 |
+
*
|
4282 |
+
* @return string Response data from the remote service.
|
4283 |
+
*/
|
4284 |
+
public static function test_api_call(){
|
4285 |
+
$params = array();
|
4286 |
+
$params['first'] = microtime();
|
4287 |
+
$params['lorem'] = microtime();
|
4288 |
+
$params['middle'] = microtime();
|
4289 |
+
$params['foobar'] = microtime();
|
4290 |
+
$params['last'] = microtime();
|
4291 |
+
$response_data = '{invalid_data}';
|
4292 |
|
4293 |
+
$response = self::api_call( 'http://httpbin.org/post', 'POST', $params );
|
4294 |
+
|
4295 |
+
if (
|
4296 |
+
is_array( $response )
|
4297 |
+
&& array_key_exists( 'body_raw', $response )
|
4298 |
+
&& is_string( $response['body_raw'] )
|
4299 |
+
) {
|
4300 |
+
$response_data = $response['body_raw'];
|
4301 |
}
|
4302 |
|
4303 |
+
return $response_data;
|
4304 |
}
|
4305 |
|
4306 |
/**
|
4405 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4406 |
* @param boolean $send_api_key Whether the API key should be added to the request parameters or not.
|
4407 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4408 |
+
* @return array Response object after the HTTP request is executed.
|
4409 |
*/
|
4410 |
public static function api_call_wordpress( $method = 'GET', $params = array(), $send_api_key = true, $args = array() ){
|
4411 |
$url = SUCURISCAN_API;
|
4432 |
*
|
4433 |
* @param string $method HTTP method that will be used to send the request.
|
4434 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4435 |
+
* @return array Response object after the HTTP request is executed.
|
4436 |
*/
|
4437 |
public static function api_call_cloudproxy( $method = 'GET', $params = array() ){
|
4438 |
$send_request = false;
|
4462 |
return false;
|
4463 |
}
|
4464 |
|
4465 |
+
/**
|
4466 |
+
* Execute some actions according to the response message.
|
4467 |
+
*
|
4468 |
+
* @param array $response Response object after the HTTP request is executed.
|
4469 |
+
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4470 |
+
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4471 |
+
* @return array Response object with some modifications.
|
4472 |
+
*/
|
4473 |
+
private static function process_response( $response = array(), $params = array(), $args = array() ){
|
4474 |
+
/**
|
4475 |
+
* Convert the error message generated by the code base functions after the HTTP
|
4476 |
+
* request is executed to a valid response object that will allow this code
|
4477 |
+
* process the data according to the specified standards.
|
4478 |
+
*/
|
4479 |
+
if ( is_wp_error( $response ) ) {
|
4480 |
+
// Extract information from the error object.
|
4481 |
+
$error_message = $response->get_error_message();
|
4482 |
+
$request_action = isset( $params['a'] ) ? $params['a'] : 'unknown';
|
4483 |
+
|
4484 |
+
// Build a fake request response with custom data.
|
4485 |
+
$data_set = array(
|
4486 |
+
'status' => 0,
|
4487 |
+
'action' => $request_action,
|
4488 |
+
'messages' => array( $error_message ),
|
4489 |
+
'request_time' => SucuriScan::local_time(),
|
4490 |
+
'output' => new stdClass(),
|
4491 |
+
'verbose' => 0,
|
4492 |
+
);
|
4493 |
+
|
4494 |
+
// Build the response object and encode data.
|
4495 |
+
$response = array();
|
4496 |
+
$response['body'] = json_encode( $data_set );
|
4497 |
+
$response['headers']['date'] = date( 'r' );
|
4498 |
+
$response['headers']['connection'] = 'close';
|
4499 |
+
$response['headers']['content-type'] = 'application/json';
|
4500 |
+
$response['headers']['content-length'] = strlen( $response['body'] );
|
4501 |
+
$response['response']['code'] = 500;
|
4502 |
+
$response['response']['message'] = 'ERROR';
|
4503 |
+
}
|
4504 |
+
|
4505 |
+
/**
|
4506 |
+
* Process the response object.
|
4507 |
+
*
|
4508 |
+
* Some response messages and even errors require extra steps of processing to,
|
4509 |
+
* for example, try to fix automatically issues related with disconnections,
|
4510 |
+
* timeouts, SSL certificate verifications, etc. Some of these actions can not
|
4511 |
+
* be fixed if the server where the website is being hosted has a special
|
4512 |
+
* configuration, which then requires the human interaction of the admin user,
|
4513 |
+
* they will see extra information explaining the response and how to proceed
|
4514 |
+
* with it.
|
4515 |
+
*/
|
4516 |
+
if (
|
4517 |
+
is_array( $response )
|
4518 |
+
&& array_key_exists( 'body', $response )
|
4519 |
+
&& array_key_exists( 'headers', $response )
|
4520 |
+
&& array_key_exists( 'response', $response )
|
4521 |
+
) {
|
4522 |
+
$response['body_raw'] = $response['body'];
|
4523 |
+
|
4524 |
+
// Check if the response data is JSON-encoded, then decode it.
|
4525 |
+
if (
|
4526 |
+
isset($response['headers']['content-type'])
|
4527 |
+
&& $response['headers']['content-type'] == 'application/json'
|
4528 |
+
) {
|
4529 |
+
$assoc = ( isset($args['assoc']) && $args['assoc'] === true ) ? true : false;
|
4530 |
+
$response['body'] = @json_decode( $response['body_raw'], $assoc );
|
4531 |
+
} elseif ( self::is_serialized( $response['body'] ) ) {
|
4532 |
+
// Check if the response data is serialized (which we will consider as insecure).
|
4533 |
+
$response['body_raw'] = null;
|
4534 |
+
$response['body'] = 'ERROR:Serialized data is not supported.';
|
4535 |
+
}
|
4536 |
+
|
4537 |
+
return $response;
|
4538 |
+
}
|
4539 |
+
|
4540 |
+
return false;
|
4541 |
+
}
|
4542 |
+
|
4543 |
/**
|
4544 |
* Determine whether an API response was successful or not checking the expected
|
4545 |
* generic variables and types, in case of an error a notification will appears
|
4546 |
* in the administrator panel explaining the result of the operation.
|
4547 |
*
|
4548 |
+
* @param array $response Response object after the HTTP request is executed.
|
4549 |
* @return boolean Either true or false in case of success or failure of the API response (respectively).
|
4550 |
*/
|
4551 |
private static function handle_response( $response = array() ){
|
4559 |
|
4560 |
// Check whether the message list is empty or not.
|
4561 |
if ( isset($response['body']->messages[0]) ) {
|
4562 |
+
$action_message = $response['body']->messages[0] . '.';
|
4563 |
}
|
4564 |
|
4565 |
+
// Keep a copy of the original API response message.
|
4566 |
+
$raw_message = $action_message;
|
4567 |
+
|
4568 |
// Special response for invalid API keys.
|
4569 |
+
if ( stripos( $raw_message, 'log file not found' ) !== false ) {
|
4570 |
SucuriScanOption::delete_option( ':api_key' );
|
4571 |
|
4572 |
$action_message .= ' This generally happens when you add an invalid API key, the'
|
4575 |
. ' key to your email address.';
|
4576 |
}
|
4577 |
|
4578 |
+
// Special response for invalid CloudProxy API keys.
|
4579 |
+
if ( stripos( $raw_message, 'wrong api key' ) !== false ) {
|
4580 |
+
SucuriScanOption::delete_option( ':cloudproxy_apikey' );
|
4581 |
+
SucuriScanOption::delete_option( ':revproxy' );
|
4582 |
+
|
4583 |
+
$action_message .= ' The CloudProxy API key does not seems to be valid.';
|
4584 |
+
}
|
4585 |
+
|
4586 |
+
// Special response for connection time outs.
|
4587 |
+
if ( stripos( $raw_message, 'timed out' ) !== false ) {
|
4588 |
+
$current_timeout = SucuriScanOption::get_option( ':request_timeout' );
|
4589 |
+
|
4590 |
+
if ( $current_timeout < 300 ) {
|
4591 |
+
SucuriScanOption::update_option( ':request_timeout', 300 );
|
4592 |
+
}
|
4593 |
+
|
4594 |
+
$action_message .= ' This generally happens when the API service fails to respond'
|
4595 |
+
. ' in time, you currently have configured the plugin to discard the network'
|
4596 |
+
. ' connection after ' . $current_timeout . ' seconds. Wait a few minutes until'
|
4597 |
+
. ' the issue is resolved by itself, or change the timeout limit from the general'
|
4598 |
+
. ' settings page of the plugin, the option is named "API request timeout".';
|
4599 |
+
}
|
4600 |
+
|
4601 |
+
// Stop SSL peer verification on connection failures.
|
4602 |
+
if (
|
4603 |
+
stripos( $raw_message, 'no alternative certificate' )
|
4604 |
+
|| stripos( $raw_message, 'error setting certificate' )
|
4605 |
+
) {
|
4606 |
+
SucuriScanOption::update_option( ':verify_ssl_cert', 'false' );
|
4607 |
+
|
4608 |
+
$action_message .= 'There were some issues with the SSL certificate either in this'
|
4609 |
+
. ' server or with the remote API service. The automatic verification of the'
|
4610 |
+
. ' certificates has been deactivated to reduce the noise during the execution'
|
4611 |
+
. ' of the HTTP requests.';
|
4612 |
+
}
|
4613 |
+
|
4614 |
+
SucuriScanInterface::error(
|
4615 |
+
sprintf(
|
4616 |
+
'(%d) %s: %s',
|
4617 |
+
SucuriScan::local_time(),
|
4618 |
+
ucwords( $response['body']->action ),
|
4619 |
+
$action_message
|
4620 |
+
)
|
4621 |
+
);
|
4622 |
}
|
4623 |
} else {
|
4624 |
SucuriScanInterface::error( 'Could not determine the status of an API call.' );
|
4761 |
if ( preg_match( $log_pattern, $log, $log_match ) ) {
|
4762 |
$log_data = array(
|
4763 |
'event' => 'notice',
|
4764 |
+
'date' => '',
|
4765 |
+
'time' => '',
|
4766 |
'datetime' => '',
|
4767 |
'timestamp' => 0,
|
4768 |
'account' => $log_match[3],
|
4773 |
'file_list_count' => 0,
|
4774 |
);
|
4775 |
|
4776 |
+
// Extract and fix the date and time using the Eastern time zone.
|
4777 |
+
$datetime = sprintf( '%s %s EDT', $log_match[1], $log_match[2] );
|
4778 |
+
$log_data['timestamp'] = strtotime( $datetime );
|
4779 |
+
$log_data['datetime'] = date( 'Y-m-d H:i:s', $log_data['timestamp'] );
|
4780 |
+
$log_data['date'] = date( 'Y-m-d', $log_data['timestamp'] );
|
4781 |
+
$log_data['time'] = date( 'H:i:s', $log_data['timestamp'] );
|
4782 |
|
4783 |
// Extract more information from the generic audit logs.
|
4784 |
+
$log_data['message'] = str_replace( '<br>', '; ', $log_data['message'] );
|
4785 |
+
|
4786 |
if ( preg_match( $generic_pattern, $log_data['message'], $log_extra ) ) {
|
4787 |
$log_data['event'] = strtolower( $log_extra[1] );
|
4788 |
$log_data['message'] = trim( $log_extra[3] );
|
4821 |
if ( preg_match( $extra_pattern, $log_data['message'], $log_extra ) ) {
|
4822 |
$log_data['message'] = $log_extra[1];
|
4823 |
$log_extra[2] = str_replace( ', new size', '; new size', $log_extra[2] );
|
4824 |
+
$log_extra[2] = str_replace( ",\x20", ";\x20", $log_extra[2] );
|
4825 |
$log_data['file_list'] = explode( ',', $log_extra[2] );
|
4826 |
$log_data['file_list_count'] = count( $log_data['file_list'] );
|
4827 |
}
|
5695 |
return $url_path;
|
5696 |
}
|
5697 |
|
5698 |
+
/**
|
5699 |
+
* Generate an URL pointing to the page indicated in the function and that must
|
5700 |
+
* be loaded through the Ajax handler of the administrator panel.
|
5701 |
+
*
|
5702 |
+
* @param string $page Short name of the page that will be generated.
|
5703 |
+
* @return string Full string containing the link of the page.
|
5704 |
+
*/
|
5705 |
+
public static function get_ajax_url( $page = '' ){
|
5706 |
+
$url_path = admin_url( 'admin-ajax.php?page=sucuriscan' );
|
5707 |
+
|
5708 |
+
if ( ! empty($page) ) {
|
5709 |
+
$url_path .= '_' . strtolower( $page );
|
5710 |
+
}
|
5711 |
+
|
5712 |
+
return $url_path;
|
5713 |
+
}
|
5714 |
+
|
5715 |
/**
|
5716 |
* Complement the list of pseudo-variables that will be used in the base
|
5717 |
* template files, this will also generate the navigation bar and detect which
|
5753 |
|
5754 |
$params[ $pseudo_var ] = self::get_url( $unique_name );
|
5755 |
|
5756 |
+
// Copy URL variable and create an Ajax handler.
|
5757 |
+
$pseudo_var_ajax = 'Ajax' . $pseudo_var;
|
5758 |
+
$params[ $pseudo_var_ajax ] = self::get_ajax_url( $unique_name );
|
5759 |
+
|
5760 |
$navbar_item_css_class = 'nav-tab';
|
5761 |
|
5762 |
if ( $params['CurrentPageFunc'] == $sub_page_func ) {
|
6167 |
}
|
6168 |
|
6169 |
// Scan the project and file all directories.
|
6170 |
+
$file_info = new SucuriScanFileInfo();
|
6171 |
+
$file_info->ignore_files = true;
|
6172 |
+
$file_info->ignore_directories = true;
|
6173 |
+
$file_info->scan_interface = SucuriScanOption::get_option( ':scan_interface' );
|
6174 |
+
$directory_list = $file_info->get_diretories_only( ABSPATH );
|
6175 |
|
6176 |
if ( $directory_list ) {
|
6177 |
$response['is_not_ignored'] = $directory_list;
|
6433 |
* @return void
|
6434 |
*/
|
6435 |
public static function initialize(){
|
6436 |
+
if ( SucuriScan::support_reverse_proxy() ) {
|
6437 |
$_SERVER['SUCURIREAL_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
|
6438 |
$_SERVER['REMOTE_ADDR'] = SucuriScan::get_remote_addr();
|
6439 |
}
|
6476 |
if (
|
6477 |
function_exists( 'add_menu_page' )
|
6478 |
&& $sucuriscan_pages
|
6479 |
+
&& is_array( $sucuriscan_pages )
|
6480 |
+
&& array_key_exists( 'sucuriscan', $sucuriscan_pages )
|
6481 |
) {
|
6482 |
// Add main menu link.
|
6483 |
add_menu_page(
|
6489 |
SUCURISCAN_URL . '/inc/images/menu-icon.png'
|
6490 |
);
|
6491 |
|
6492 |
+
foreach ( $sucuriscan_pages as $sub_page_func => $sub_page_title ) {
|
|
|
|
|
6493 |
if (
|
6494 |
$sub_page_func == 'sucuriscan_scanner'
|
6495 |
&& SucuriScanTemplate::is_sitecheck_disabled()
|
6521 |
*/
|
6522 |
public static function handle_old_plugins(){
|
6523 |
if ( class_exists( 'SucuriScanFileInfo' ) ) {
|
6524 |
+
$file_info = new SucuriScanFileInfo();
|
6525 |
+
$file_info->ignore_files = false;
|
6526 |
+
$file_info->ignore_directories = false;
|
6527 |
|
6528 |
$plugins = array(
|
6529 |
'sucuri-wp-plugin/sucuri.php',
|
6538 |
deactivate_plugins( $plugin );
|
6539 |
}
|
6540 |
|
6541 |
+
$plugin_removed = $file_info->remove_directory_tree( $plugin_directory );
|
6542 |
}
|
6543 |
}
|
6544 |
}
|
8372 |
|
8373 |
// Search error log files in the project.
|
8374 |
if ( $scan_errorlogs != 'disabled' ) {
|
8375 |
+
$file_info = new SucuriScanFileInfo();
|
8376 |
+
$file_info->ignore_files = false;
|
8377 |
+
$file_info->ignore_directories = false;
|
8378 |
+
$error_logs = $file_info->find_file( $log_filename );
|
8379 |
$total_log_files = count( $error_logs );
|
8380 |
} else {
|
8381 |
$hardened = 2;
|
8561 |
function sucuriscan_get_integrity_tree( $dir = './', $recursive = false ){
|
8562 |
$abs_path = rtrim( ABSPATH, '/' );
|
8563 |
|
8564 |
+
$file_info = new SucuriScanFileInfo();
|
8565 |
+
$file_info->ignore_files = false;
|
8566 |
+
$file_info->ignore_directories = false;
|
8567 |
+
$file_info->run_recursively = $recursive;
|
8568 |
+
$file_info->scan_interface = SucuriScanOption::get_option( ':scan_interface' );
|
8569 |
+
$integrity_tree = $file_info->get_directory_tree_md5( $dir, true );
|
8570 |
|
8571 |
if ( ! $integrity_tree ) {
|
8572 |
$integrity_tree = array();
|
9143 |
echo SucuriScanTemplate::get_template( 'posthack', $template_variables );
|
9144 |
}
|
9145 |
|
9146 |
+
/**
|
9147 |
+
* Handle an Ajax request for this specific page.
|
9148 |
+
*
|
9149 |
+
* @return mixed.
|
9150 |
+
*/
|
9151 |
+
function sucuriscan_posthack_ajax(){
|
9152 |
+
SucuriScanInterface::check_permissions();
|
9153 |
+
|
9154 |
+
if ( SucuriScanInterface::check_nonce() ) {
|
9155 |
+
sucuriscan_posthack_plugins_ajax();
|
9156 |
+
}
|
9157 |
+
|
9158 |
+
wp_die();
|
9159 |
+
}
|
9160 |
+
|
9161 |
/**
|
9162 |
* Check whether the "I understand this operation" checkbox was marked or not.
|
9163 |
*
|
9300 |
$max_per_page
|
9301 |
);
|
9302 |
|
9303 |
+
if ( $total_items > $max_per_page ) {
|
9304 |
$template_variables['ResetPassword.PaginationVisibility'] = 'visible';
|
9305 |
}
|
9306 |
}
|
9385 |
'ResetPlugin.CacheLifeTime' => 'unknown',
|
9386 |
);
|
9387 |
|
|
|
9388 |
if ( defined( 'SUCURISCAN_GET_PLUGINS_LIFETIME' ) ) {
|
9389 |
$template_variables['ResetPlugin.CacheLifeTime'] = SUCURISCAN_GET_PLUGINS_LIFETIME;
|
9390 |
}
|
9391 |
|
9392 |
sucuriscan_posthack_reinstall_plugins( $process_form );
|
|
|
|
|
9393 |
|
9394 |
+
return SucuriScanTemplate::get_section( 'posthack-resetplugins', $template_variables );
|
9395 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9396 |
|
9397 |
+
/**
|
9398 |
+
* Process the Ajax request to retrieve the plugins metadata.
|
9399 |
+
*
|
9400 |
+
* @return string HTML code for a table with the plugins metadata.
|
9401 |
+
*/
|
9402 |
+
function sucuriscan_posthack_plugins_ajax(){
|
9403 |
+
if ( SucuriScanRequest::post( 'form_action' ) == 'get_plugins_data' ) {
|
9404 |
+
$all_plugins = SucuriScanAPI::get_plugins();
|
9405 |
+
$response = '';
|
9406 |
+
$counter = 0;
|
9407 |
|
9408 |
+
foreach ( $all_plugins as $plugin_path => $plugin_data ) {
|
9409 |
+
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
9410 |
+
$plugin_type_class = ( $plugin_data['PluginType'] == 'free' ) ? 'primary' : 'warning';
|
9411 |
+
$input_disabled = ( $plugin_data['PluginType'] == 'free' ) ? '' : 'disabled="disabled"';
|
9412 |
+
$plugin_status = $plugin_data['IsPluginActive'] ? 'active' : 'not active';
|
9413 |
+
$plugin_status_class = $plugin_data['IsPluginActive'] ? 'success' : 'default';
|
9414 |
+
|
9415 |
+
$response .= SucuriScanTemplate::get_snippet('posthack-resetplugins', array(
|
9416 |
+
'ResetPlugin.CssClass' => $css_class,
|
9417 |
+
'ResetPlugin.Disabled' => $input_disabled,
|
9418 |
+
'ResetPlugin.PluginPath' => SucuriScan::escape( $plugin_path ),
|
9419 |
+
'ResetPlugin.Plugin' => SucuriScan::excerpt( $plugin_data['Name'], 35 ),
|
9420 |
+
'ResetPlugin.Version' => $plugin_data['Version'],
|
9421 |
+
'ResetPlugin.Type' => $plugin_data['PluginType'],
|
9422 |
+
'ResetPlugin.TypeClass' => $plugin_type_class,
|
9423 |
+
'ResetPlugin.Status' => $plugin_status,
|
9424 |
+
'ResetPlugin.StatusClass' => $plugin_status_class,
|
9425 |
+
));
|
9426 |
+
|
9427 |
+
$counter += 1;
|
9428 |
+
}
|
9429 |
+
|
9430 |
+
print( $response );
|
9431 |
+
exit(0);
|
9432 |
+
}
|
9433 |
}
|
9434 |
|
9435 |
/**
|
9448 |
|
9449 |
if ( $plugin_list = SucuriScanRequest::post( 'plugin_path', '_array' ) ) {
|
9450 |
// Create an instance of the FileInfo interface.
|
9451 |
+
$file_info = new SucuriScanFileInfo();
|
9452 |
+
$file_info->ignore_files = false;
|
9453 |
+
$file_info->ignore_directories = false;
|
9454 |
+
$file_info->skip_directories = false;
|
9455 |
|
9456 |
// Get (possible) cached information from the installed plugins.
|
9457 |
$all_plugins = SucuriScanAPI::get_plugins();
|
9469 |
// First, remove all files/sub-folders from the plugin's directory.
|
9470 |
if ( substr_count( $plugin_path, '/' ) >= 1 ) {
|
9471 |
$plugin_directory = dirname( WP_PLUGIN_DIR . '/' . $plugin_path );
|
9472 |
+
$file_info->remove_directory_tree( $plugin_directory );
|
9473 |
}
|
9474 |
|
9475 |
// Install a fresh copy of the plugin's files.
|
10128 |
'FailedLogins.NoItemsVisibility' => 'visible',
|
10129 |
'FailedLogins.WarningVisibility' => 'visible',
|
10130 |
'FailedLogins.CollectPasswordsVisibility' => 'visible',
|
10131 |
+
'FailedLogins.PaginationLinks' => '',
|
10132 |
+
'FailedLogins.PaginationVisibility' => 'hidden',
|
10133 |
);
|
10134 |
|
10135 |
+
// Define variables for the pagination.
|
10136 |
+
$page_number = SucuriScanTemplate::get_page_number();
|
10137 |
+
$max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
10138 |
+
$page_offset = ( $page_number - 1 ) * $max_per_page;
|
10139 |
+
$page_limit = ( $page_offset + $max_per_page );
|
10140 |
+
|
10141 |
$max_failed_logins = SucuriScanOption::get_option( ':maximum_failed_logins' );
|
10142 |
$notify_bruteforce_attack = SucuriScanOption::get_option( ':notify_bruteforce_attack' );
|
10143 |
$failed_logins = sucuriscan_get_failed_logins();
|
10161 |
if ( $failed_logins ) {
|
10162 |
$counter = 0;
|
10163 |
|
10164 |
+
for ( $key = $page_offset; $key < $page_limit; $key++ ) {
|
10165 |
+
if ( array_key_exists( $key, $failed_logins['entries'] ) ) {
|
10166 |
+
$login_data = $failed_logins['entries'][ $key ];
|
10167 |
+
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
10168 |
+
$wrong_user_password = '<span class="sucuriscan-label-default">hidden</span>';
|
10169 |
|
10170 |
+
if ( sucuriscan_collect_wrong_passwords() === true ) {
|
10171 |
+
if (
|
10172 |
+
isset($login_data['user_password'])
|
10173 |
+
&& ! empty($login_data['user_password'])
|
10174 |
+
) {
|
10175 |
+
$wrong_user_password = SucuriScan::escape( $login_data['user_password'] );
|
10176 |
+
} else {
|
10177 |
+
$wrong_user_password = '<span class="sucuriscan-label-info">empty</span>';
|
10178 |
+
}
|
10179 |
}
|
|
|
10180 |
|
10181 |
+
$template_variables['FailedLogins.List'] .= SucuriScanTemplate::get_snippet('lastlogins-failedlogins', array(
|
10182 |
+
'FailedLogins.CssClass' => $css_class,
|
10183 |
+
'FailedLogins.Num' => $login_data['attempt_count'],
|
10184 |
+
'FailedLogins.Username' => SucuriScan::escape( $login_data['user_login'] ),
|
10185 |
+
'FailedLogins.Password' => $wrong_user_password,
|
10186 |
+
'FailedLogins.RemoteAddr' => SucuriScan::escape( $login_data['remote_addr'] ),
|
10187 |
+
'FailedLogins.Datetime' => SucuriScan::datetime( $login_data['attempt_time'] ),
|
10188 |
+
'FailedLogins.UserAgent' => SucuriScan::escape( $login_data['user_agent'] ),
|
10189 |
+
));
|
10190 |
|
10191 |
+
$counter += 1;
|
10192 |
+
}
|
10193 |
}
|
10194 |
|
10195 |
if ( $counter > 0 ) {
|
10196 |
$template_variables['FailedLogins.NoItemsVisibility'] = 'hidden';
|
10197 |
}
|
10198 |
+
|
10199 |
+
$template_variables['FailedLogins.PaginationLinks'] = SucuriScanTemplate::get_pagination(
|
10200 |
+
'%%SUCURI.URL.Lastlogins%%#failed-logins',
|
10201 |
+
$failed_logins['count'],
|
10202 |
+
$max_per_page
|
10203 |
+
);
|
10204 |
+
|
10205 |
+
if ( $failed_logins['count'] > $max_per_page ) {
|
10206 |
+
$template_variables['FailedLogins.PaginationVisibility'] = 'visible';
|
10207 |
+
}
|
10208 |
}
|
10209 |
|
10210 |
$template_variables['FailedLogins.MaxFailedLogins'] = $max_failed_logins;
|
10302 |
);
|
10303 |
|
10304 |
// Read and parse all the entries found in the datastore file.
|
10305 |
+
$offset = count( $lines ) - 1;
|
10306 |
+
|
10307 |
+
for ( $key = $offset; $key >= 0; $key-- ) {
|
10308 |
+
$line = trim( $lines[ $key ] );
|
10309 |
+
$login_data = @json_decode( $line, true );
|
10310 |
+
|
10311 |
+
if ( is_array( $login_data ) ) {
|
10312 |
$login_data['attempt_date'] = date( 'r', $login_data['attempt_time'] );
|
10313 |
+
$login_data['attempt_count'] = ( $key + 1 );
|
10314 |
|
10315 |
if ( ! $login_data['user_agent'] ) {
|
10316 |
$login_data['user_agent'] = 'Unknown';
|
11076 |
SucuriScanEvent::report_info_event( $message );
|
11077 |
SucuriScanInterface::info( $message );
|
11078 |
}
|
11079 |
+
|
11080 |
+
// Debug ability of the plugin to send HTTP requests correctly.
|
11081 |
+
if ( $debug_request = SucuriScanRequest::post( ':debug_request' ) ) {
|
11082 |
+
SucuriScanInterface::info(
|
11083 |
+
sprintf(
|
11084 |
+
'<pre>%s</pre>',
|
11085 |
+
SucuriScanAPI::test_api_call()
|
11086 |
+
)
|
11087 |
+
);
|
11088 |
+
}
|
11089 |
}
|
11090 |
}
|
11091 |
|
11198 |
'ReverseProxySwitchValue' => 'disable',
|
11199 |
'ReverseProxySwitchCssClass' => 'button-danger',
|
11200 |
/* API Proxy Settings */
|
11201 |
+
'APIProxy.Host' => 'no_proxy_host',
|
11202 |
+
'APIProxy.Port' => 'no_proxy_port',
|
11203 |
+
'APIProxy.Username' => 'no_proxy_username',
|
11204 |
+
'APIProxy.Password' => 'no_proxy_password',
|
11205 |
'APIProxy.PasswordType' => 'default',
|
11206 |
'APIProxy.PasswordText' => 'empty',
|
11207 |
);
|