Version Description
- Improved hardening options
- Added more logging events
- Various bugfixes and improvements
Download this release
Release Info
Developer | akresic |
Plugin | Sucuri Security – Auditing, Malware Scanner and Security Hardening |
Version | 1.7.12 |
Comparing to | |
See all releases |
Code changes from version 1.7.11 to 1.7.12
- inc/css/sucuriscan-default-css.css +4 -1
- inc/tpl/integrity-corefiles.html.tpl +16 -0
- inc/tpl/notification-corefiles.html.tpl +47 -0
- readme.txt +7 -2
- sucuri.php +409 -190
inc/css/sucuriscan-default-css.css
CHANGED
@@ -230,7 +230,10 @@ td.sucuriscan-corefiles-warning > div{background:#f2dede;color:#a94442;border-co
|
|
230 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning div{padding:10px;border-width:1px;border-style:solid}
|
231 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning code{font-size:12px;padding:0 5px}
|
232 |
.sucuriscan-maincontent .sucuriscan-integrity-message{position:relative}
|
233 |
-
.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-mark
|
|
|
|
|
|
|
234 |
.sucuriscan-maincontent .sucuriscan-ignoredfiles{margin-top:0}
|
235 |
.sucuriscan-ignore-file form{padding:10px;padding-top:0;border-bottom:1px solid #ddd;border-right:1px solid #ddd}
|
236 |
.sucuriscan-ignore-file p{border-bottom:none}
|
230 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning div{padding:10px;border-width:1px;border-style:solid}
|
231 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning code{font-size:12px;padding:0 5px}
|
232 |
.sucuriscan-maincontent .sucuriscan-integrity-message{position:relative}
|
233 |
+
.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-mark,
|
234 |
+
.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-failure{position:absolute;top:1px;right:1px;background:#ddd;font-weight:bold;color:#fff;line-height:35px;padding:0 10px;border-left:1px solid #ddd}
|
235 |
+
.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-mark{background:#7ad03a}
|
236 |
+
.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-failure{background:#dd3d36;border-left:0}
|
237 |
.sucuriscan-maincontent .sucuriscan-ignoredfiles{margin-top:0}
|
238 |
.sucuriscan-ignore-file form{padding:10px;padding-top:0;border-bottom:1px solid #ddd;border-right:1px solid #ddd}
|
239 |
.sucuriscan-ignore-file p{border-bottom:none}
|
inc/tpl/integrity-corefiles.html.tpl
CHANGED
@@ -8,6 +8,22 @@
|
|
8 |
</div>
|
9 |
</div>
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
<form action="%%SUCURI.URL.Home%%" method="post">
|
12 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
13 |
|
8 |
</div>
|
9 |
</div>
|
10 |
|
11 |
+
<div class="postbox sucuriscan-border sucuriscan-border-bad sucuriscan-integrity-message sucuriscan-%%SUCURI.CoreFiles.FailureVisibility%%">
|
12 |
+
<span class="sucuriscan-integrity-failure">FAILURE</span>
|
13 |
+
<h3>Core integrity</h3>
|
14 |
+
|
15 |
+
<div class="inside">
|
16 |
+
<p>
|
17 |
+
Error retrieving the WordPress core hashes. The information used by the plugin
|
18 |
+
to determine the integrity of the core files is retrieved and controlled by
|
19 |
+
WordPress. Any error message related with this tool is likely related with a
|
20 |
+
modification in their API service that is not supported yet. It is also possible
|
21 |
+
that your website is not able to communicate with this server due to a missing
|
22 |
+
HTTP transport tool.
|
23 |
+
</p>
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
|
27 |
<form action="%%SUCURI.URL.Home%%" method="post">
|
28 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
29 |
|
inc/tpl/notification-corefiles.html.tpl
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<p>
|
3 |
+
Changes in the integrity of your core files were detected, you may want to check
|
4 |
+
each file to determine if they were infected with malicious code. The WordPress
|
5 |
+
core directories <code>/<root></code>, <code>/wp-admin</code> and <code>
|
6 |
+
/wp-includes</code> are the only ones being scanned; the content, uploads, and
|
7 |
+
custom directories are not part of the official archives so you have to check
|
8 |
+
them manually.
|
9 |
+
</p>
|
10 |
+
|
11 |
+
<table border="1" cellspacing="1" cellpadding="5">
|
12 |
+
<thead>
|
13 |
+
<tr>
|
14 |
+
<th colspan="5">
|
15 |
+
Core integrity (%%SUCURI.CoreFiles.ListCount%% files)
|
16 |
+
</th>
|
17 |
+
</tr>
|
18 |
+
|
19 |
+
<tr>
|
20 |
+
<th> </th>
|
21 |
+
<th width="80">Status</th>
|
22 |
+
<th width="100">File Size</th>
|
23 |
+
<th width="170">Modified At</th>
|
24 |
+
<th>File Path</th>
|
25 |
+
</tr>
|
26 |
+
</thead>
|
27 |
+
|
28 |
+
<tbody>
|
29 |
+
%%SUCURI.CoreFiles.List%%
|
30 |
+
</tbody>
|
31 |
+
|
32 |
+
<tfoot>
|
33 |
+
<tr>
|
34 |
+
<td colspan="5">
|
35 |
+
<p>
|
36 |
+
<strong>Note.</strong> This is not a malware scanner but an integrity checker
|
37 |
+
which is a completely different thing, if you want to check if your site is
|
38 |
+
generating malicious code then use the <a href="%%SUCURI.URL.Scanner%%">malware
|
39 |
+
scan</a> tool. If you see the text <em>"must be fixed manually"</em> in any of
|
40 |
+
these files that means that they do not have write permissions so you can not
|
41 |
+
fix them using this tool. Access the <a href="%%SUCURI.URL.Home%%">admin area
|
42 |
+
</a> of your website to fix these files.
|
43 |
+
</p>
|
44 |
+
</td>
|
45 |
+
</tr>
|
46 |
+
</tfoot>
|
47 |
+
</table>
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ 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.
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
10 |
|
@@ -352,6 +352,11 @@ service from the WordPress dashboard.
|
|
352 |
|
353 |
== Changelog ==
|
354 |
|
|
|
|
|
|
|
|
|
|
|
355 |
= 1.7.11 =
|
356 |
* Reverted change for CloudProxy detection to protect legacy users
|
357 |
|
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.12
|
7 |
+
Tested up to: 4.2.3
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
10 |
|
352 |
|
353 |
== Changelog ==
|
354 |
|
355 |
+
= 1.7.12 =
|
356 |
+
* Improved hardening options
|
357 |
+
* Added more logging events
|
358 |
+
* Various bugfixes and improvements
|
359 |
+
|
360 |
= 1.7.11 =
|
361 |
* Reverted change for CloudProxy detection to protect legacy users
|
362 |
|
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.
|
@@ -189,6 +189,7 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
189 |
'sucuriscan_notify_plugin_change' => 'Receive email alerts for <strong>Sucuri</strong> plugin changes',
|
190 |
'sucuriscan_prettify_mails' => 'Receive email alerts in HTML <em>(there may be issues with some mail services)</em>',
|
191 |
'sucuriscan_lastlogin_redirection' => 'Allow redirection after login to report the last-login information',
|
|
|
192 |
'sucuriscan_notify_user_registration' => 'user:Receive email alerts for new user registration',
|
193 |
'sucuriscan_notify_success_login' => 'user:Receive email alerts for successful login attempts',
|
194 |
'sucuriscan_notify_failed_login' => 'user:Receive email alerts for failed login attempts',
|
@@ -253,6 +254,8 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
253 |
$sucuriscan_email_subjects = array(
|
254 |
'Sucuri Alert, :domain, :event',
|
255 |
'Sucuri Alert, :domain, :event, :remoteaddr',
|
|
|
|
|
256 |
'Sucuri Alert, :event, :remoteaddr',
|
257 |
'Sucuri Alert, :event',
|
258 |
);
|
@@ -268,7 +271,7 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
268 |
* information to the Sucuri API service where a security and integrity scan
|
269 |
* will be performed against the hashes provided and the official versions.
|
270 |
*/
|
271 |
-
add_action( 'sucuriscan_scheduled_scan', '
|
272 |
|
273 |
/**
|
274 |
* Initialize the execute of the main plugin's functions.
|
@@ -305,29 +308,30 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
305 |
*/
|
306 |
if ( class_exists( 'SucuriScanHook' ) ) {
|
307 |
$sucuriscan_hooks = array(
|
308 |
-
// Passes.
|
309 |
'add_attachment',
|
310 |
'add_link',
|
|
|
311 |
'create_category',
|
312 |
'delete_post',
|
313 |
'delete_user',
|
314 |
'login_form_resetpass',
|
315 |
'private_to_published',
|
316 |
'publish_page',
|
317 |
-
'publish_post',
|
318 |
'publish_phone',
|
319 |
-
'
|
320 |
'retrieve_password',
|
321 |
'switch_theme',
|
322 |
'user_register',
|
|
|
323 |
'wp_login',
|
324 |
'wp_login_failed',
|
325 |
'wp_trash_post',
|
|
|
326 |
);
|
327 |
|
328 |
foreach ( $sucuriscan_hooks as $hook_name ) {
|
329 |
$hook_func = 'SucuriScanHook::hook_' . $hook_name;
|
330 |
-
add_action( $hook_name, $hook_func, 50 );
|
331 |
}
|
332 |
|
333 |
add_action( 'admin_init', 'SucuriScanHook::hook_undefined_actions' );
|
@@ -618,6 +622,16 @@ class SucuriScan {
|
|
618 |
return '/define\(\s*\'([A-Z_]+)\',(\s*)\'(.+)\'\s*\);/';
|
619 |
}
|
620 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
621 |
/**
|
622 |
* Retrieve the real ip address of the user in the current request.
|
623 |
*
|
@@ -729,16 +743,26 @@ class SucuriScan {
|
|
729 |
}
|
730 |
|
731 |
/**
|
732 |
-
* Check whether the site is
|
733 |
*
|
734 |
* @param boolean $verbose Return an array with the hostname, address, and status, or not.
|
735 |
* @return boolean Either TRUE or FALSE if the site is behind CloudProxy.
|
736 |
*/
|
737 |
public static function is_behind_cloudproxy( $verbose = false ){
|
738 |
$http_host = self::get_top_level_domain();
|
739 |
-
|
740 |
-
|
741 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
742 |
|
743 |
/*
|
744 |
* If the DNS reversion failed but the CloudProxy API key is set, then consider
|
@@ -2533,6 +2557,7 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2533 |
'sucuriscan_notify_plugin_installed' => 'disabled',
|
2534 |
'sucuriscan_notify_plugin_updated' => 'disabled',
|
2535 |
'sucuriscan_notify_post_publication' => 'enabled',
|
|
|
2536 |
'sucuriscan_notify_settings_updated' => 'disabled',
|
2537 |
'sucuriscan_notify_success_login' => 'enabled',
|
2538 |
'sucuriscan_notify_theme_activated' => 'disabled',
|
@@ -3087,9 +3112,10 @@ class SucuriScanEvent extends SucuriScan {
|
|
3087 |
* @param integer $severity Importance of the event that will be reported, values from one to five.
|
3088 |
* @param string $location In which part of the system was the event triggered.
|
3089 |
* @param string $message The explanation of the event.
|
|
|
3090 |
* @return boolean TRUE if the event was logged in the monitoring service, FALSE otherwise.
|
3091 |
*/
|
3092 |
-
private static function report_event( $severity = 0, $location = '', $message = '' ){
|
3093 |
$user = wp_get_current_user();
|
3094 |
$username = false;
|
3095 |
$current_time = date( 'Y-m-d H:i:s' );
|
@@ -3122,6 +3148,11 @@ class SucuriScanEvent extends SucuriScan {
|
|
3122 |
default: $severity_name = 'Info'; break;
|
3123 |
}
|
3124 |
|
|
|
|
|
|
|
|
|
|
|
3125 |
// Clear event message.
|
3126 |
$message = strip_tags( $message );
|
3127 |
$message = str_replace( "\r", '', $message );
|
@@ -3142,71 +3173,78 @@ class SucuriScanEvent extends SucuriScan {
|
|
3142 |
/**
|
3143 |
* Reports a debug event on the website.
|
3144 |
*
|
3145 |
-
* @param string $message
|
3146 |
-
* @
|
|
|
3147 |
*/
|
3148 |
-
public static function report_debug_event( $message = '' ){
|
3149 |
-
return self::report_event( 0, 'core', $message );
|
3150 |
}
|
3151 |
|
3152 |
/**
|
3153 |
* Reports a notice event on the website.
|
3154 |
*
|
3155 |
-
* @param string $message
|
3156 |
-
* @
|
|
|
3157 |
*/
|
3158 |
-
public static function report_notice_event( $message = '' ){
|
3159 |
-
return self::report_event( 1, 'core', $message );
|
3160 |
}
|
3161 |
|
3162 |
/**
|
3163 |
* Reports a info event on the website.
|
3164 |
*
|
3165 |
-
* @param string $message
|
3166 |
-
* @
|
|
|
3167 |
*/
|
3168 |
-
public static function report_info_event( $message = '' ){
|
3169 |
-
return self::report_event( 2, 'core', $message );
|
3170 |
}
|
3171 |
|
3172 |
/**
|
3173 |
* Reports a warning event on the website.
|
3174 |
*
|
3175 |
-
* @param string $message
|
3176 |
-
* @
|
|
|
3177 |
*/
|
3178 |
-
public static function report_warning_event( $message = '' ){
|
3179 |
-
return self::report_event( 3, 'core', $message );
|
3180 |
}
|
3181 |
|
3182 |
/**
|
3183 |
* Reports a error event on the website.
|
3184 |
*
|
3185 |
-
* @param string $message
|
3186 |
-
* @
|
|
|
3187 |
*/
|
3188 |
-
public static function report_error_event( $message = '' ){
|
3189 |
-
return self::report_event( 4, 'core', $message );
|
3190 |
}
|
3191 |
|
3192 |
/**
|
3193 |
* Reports a critical event on the website.
|
3194 |
*
|
3195 |
-
* @param string $message
|
3196 |
-
* @
|
|
|
3197 |
*/
|
3198 |
-
public static function report_critical_event( $message = '' ){
|
3199 |
-
return self::report_event( 5, 'core', $message );
|
3200 |
}
|
3201 |
|
3202 |
/**
|
3203 |
* Reports a notice or error event for enable and disable actions.
|
3204 |
*
|
3205 |
-
* @param string $message
|
3206 |
* @param string $action An optional text, hopefully either enabled or disabled.
|
3207 |
-
* @
|
|
|
3208 |
*/
|
3209 |
-
public static function report_auto_event( $message = '', $action = '' ){
|
3210 |
$message = strip_tags( $message );
|
3211 |
|
3212 |
// Auto-detect the action performed, either enabled or disabled.
|
@@ -3216,11 +3254,11 @@ class SucuriScanEvent extends SucuriScan {
|
|
3216 |
|
3217 |
// Report the correct event for the action performed.
|
3218 |
if ( $action == 'enabled' ) {
|
3219 |
-
return self::report_notice_event( $message );
|
3220 |
} elseif ( $action == 'disabled' ) {
|
3221 |
-
return self::report_error_event( $message );
|
3222 |
} else {
|
3223 |
-
return self::report_info_event( $message );
|
3224 |
}
|
3225 |
}
|
3226 |
|
@@ -3295,6 +3333,9 @@ class SucuriScanEvent extends SucuriScan {
|
|
3295 |
} elseif ( $event == 'bruteforce_attack' ) {
|
3296 |
// Send a notification even if the limit of emails per hour was reached.
|
3297 |
$email_params['Force'] = true;
|
|
|
|
|
|
|
3298 |
}
|
3299 |
|
3300 |
$title = str_replace( '_', chr( 32 ), $event );
|
@@ -3823,8 +3864,72 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3823 |
}
|
3824 |
}
|
3825 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3826 |
// TODO: Detect auto updates in core, themes, and plugin files.
|
3827 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3828 |
/**
|
3829 |
* Send a notifications to the administrator of some specific events that are
|
3830 |
* not triggered through an hooked action, but through a simple request in the
|
@@ -4841,7 +4946,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4841 |
$response['body']->output_data = array();
|
4842 |
$log_pattern = '/^([0-9\-]+) ([0-9:]+) (\S+) : (.+)/';
|
4843 |
$extra_pattern = '/(.+ \(multiple entries\):) (.+)/';
|
4844 |
-
$generic_pattern = '
|
4845 |
$auth_pattern = '/^User authentication (succeeded|failed): ([^<;]+)/';
|
4846 |
|
4847 |
foreach ( $response['body']->output as $log ) {
|
@@ -5569,28 +5674,50 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5569 |
* @return string A text with the subject for the email alert.
|
5570 |
*/
|
5571 |
private static function get_email_subject( $event = '' ){
|
5572 |
-
$
|
5573 |
|
5574 |
/**
|
5575 |
* Probably a bad value in the options table. Delete the entry from the database
|
5576 |
* and call this function to try again, it will probably fall in an infinite
|
5577 |
* loop, but this is the easiest way to control this procedure.
|
5578 |
*/
|
5579 |
-
if ( ! $
|
5580 |
self::delete_option( ':email_subject' );
|
5581 |
|
5582 |
return self::get_email_subject( $event );
|
5583 |
}
|
5584 |
|
5585 |
-
$
|
5586 |
-
$
|
5587 |
-
$
|
5588 |
-
|
5589 |
-
|
5590 |
-
|
5591 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5592 |
|
5593 |
-
return $
|
5594 |
}
|
5595 |
|
5596 |
/**
|
@@ -7760,6 +7887,160 @@ function sucuriscan_monitoring_dates( $type = '', $date = '', $in_html = true ){
|
|
7760 |
return $options;
|
7761 |
}
|
7762 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7763 |
/**
|
7764 |
* Sucuri one-click hardening page.
|
7765 |
*
|
@@ -7968,59 +8249,36 @@ function sucuriscan_harden_nginx_phpfpm(){
|
|
7968 |
* @return void
|
7969 |
*/
|
7970 |
function sucuriscan_harden_upload(){
|
7971 |
-
$
|
7972 |
-
$datastore_path = SucuriScan::datastore_folder_path();
|
7973 |
-
$htaccess_upload = dirname( $datastore_path ) . '/.htaccess';
|
7974 |
-
|
7975 |
-
if ( ! is_readable( $htaccess_upload ) ) {
|
7976 |
-
$cp = 0;
|
7977 |
-
} else {
|
7978 |
-
$cp = 0;
|
7979 |
-
$fcontent = SucuriScanFileInfo::file_lines( $htaccess_upload );
|
7980 |
-
|
7981 |
-
foreach ( $fcontent as $fline ) {
|
7982 |
-
if ( stripos( $fline, 'deny from all' ) !== false ) {
|
7983 |
-
$cp = 1;
|
7984 |
-
break;
|
7985 |
-
}
|
7986 |
-
}
|
7987 |
-
}
|
7988 |
|
7989 |
if ( SucuriScanRequest::post( ':run_hardening' ) ) {
|
7990 |
-
if ( SucuriScanRequest::post( ':harden_upload' )
|
7991 |
-
|
7992 |
-
|
7993 |
-
|
7994 |
-
$cp = 1;
|
7995 |
$message = 'Hardening applied to the uploads directory';
|
7996 |
SucuriScanEvent::report_notice_event( $message );
|
7997 |
SucuriScanInterface::info( $message );
|
|
|
|
|
7998 |
}
|
7999 |
} elseif ( SucuriScanRequest::post( ':harden_upload_unharden' ) ) {
|
8000 |
-
$
|
8001 |
-
$htaccess_content = $htaccess_upload_writable ? @file_get_contents( $htaccess_upload ) : '';
|
8002 |
-
|
8003 |
-
if ( $htaccess_upload_writable ) {
|
8004 |
-
$cp = 0;
|
8005 |
-
|
8006 |
-
if ( preg_match( '/<Files \*\.php>\ndeny from all\n<\/Files>/', $htaccess_content, $match ) ) {
|
8007 |
-
$htaccess_content = str_replace( "<Files *.php>\ndeny from all\n</Files>", '', $htaccess_content );
|
8008 |
-
@file_put_contents( $htaccess_upload, $htaccess_content, LOCK_EX );
|
8009 |
-
}
|
8010 |
|
|
|
8011 |
$message = 'Hardening reverted in the uploads directory';
|
8012 |
SucuriScanEvent::report_error_event( $message );
|
8013 |
SucuriScanInterface::info( $message );
|
8014 |
} else {
|
8015 |
-
SucuriScanInterface::
|
8016 |
-
'File <code>/wp-content/uploads/.htaccess</code> does not exists or
|
8017 |
-
is not writable, you will need to remove the following code (manually):
|
8018 |
-
<code><Files *.php>deny from all</Files></code>'
|
8019 |
-
);
|
8020 |
}
|
8021 |
}
|
8022 |
}
|
8023 |
|
|
|
|
|
|
|
|
|
8024 |
$description = 'It checks if the uploads directory of this site allows the direct execution'
|
8025 |
. ' of PHP files. It is recommendable to prevent this because someone may try to exploit'
|
8026 |
. ' a vulnerability of a plugin, theme, and/or other PHP-based code located in this'
|
@@ -8051,71 +8309,40 @@ function sucuriscan_harden_upload(){
|
|
8051 |
* @return void
|
8052 |
*/
|
8053 |
function sucuriscan_harden_wpcontent(){
|
8054 |
-
$cp = 1;
|
8055 |
-
$htaccess_upload = WP_CONTENT_DIR . '/.htaccess';
|
8056 |
-
|
8057 |
-
if ( ! is_readable( $htaccess_upload ) ) {
|
8058 |
-
$cp = 0;
|
8059 |
-
} else {
|
8060 |
-
$cp = 0;
|
8061 |
-
$fcontent = SucuriScanFileInfo::file_lines( $htaccess_upload );
|
8062 |
-
|
8063 |
-
foreach ( $fcontent as $fline ) {
|
8064 |
-
if ( stripos( $fline, 'deny from all' ) !== false ) {
|
8065 |
-
$cp = 1;
|
8066 |
-
break;
|
8067 |
-
}
|
8068 |
-
}
|
8069 |
-
}
|
8070 |
-
|
8071 |
if ( SucuriScanRequest::post( ':run_hardening' ) ) {
|
8072 |
-
if ( SucuriScanRequest::post( ':harden_wpcontent' )
|
8073 |
-
|
8074 |
-
|
8075 |
-
|
8076 |
-
$cp = 1;
|
8077 |
$message = 'Hardening applied to the content directory';
|
8078 |
SucuriScanEvent::report_notice_event( $message );
|
8079 |
SucuriScanInterface::info( $message );
|
|
|
|
|
8080 |
}
|
8081 |
} elseif ( SucuriScanRequest::post( ':harden_wpcontent_unharden' ) ) {
|
8082 |
-
$
|
8083 |
-
$htaccess_content = $htaccess_upload_writable ? @file_get_contents( $htaccess_upload ) : '';
|
8084 |
-
|
8085 |
-
if ( $htaccess_upload_writable ) {
|
8086 |
-
$cp = 0;
|
8087 |
-
|
8088 |
-
if ( preg_match( '/<Files \*\.php>\ndeny from all\n<\/Files>/', $htaccess_content, $match ) ) {
|
8089 |
-
$htaccess_content = str_replace( "<Files *.php>\ndeny from all\n</Files>", '', $htaccess_content );
|
8090 |
-
@file_put_contents( $htaccess_upload, $htaccess_content, LOCK_EX );
|
8091 |
-
}
|
8092 |
|
|
|
8093 |
$message = 'Hardening reverted in the content directory';
|
8094 |
SucuriScanEvent::report_error_event( $message );
|
8095 |
SucuriScanInterface::info( $message );
|
8096 |
} else {
|
8097 |
-
SucuriScanInterface::info(
|
8098 |
-
'File <code>' . WP_CONTENT_DIR . '/.htaccess</code> does not exists or is not
|
8099 |
-
writable, you will need to remove the following code manually from there:
|
8100 |
-
<code><Files *.php>deny from all</Files></code>'
|
8101 |
-
);
|
8102 |
}
|
8103 |
}
|
8104 |
}
|
8105 |
|
|
|
|
|
|
|
|
|
8106 |
$description = 'This option blocks direct access to any PHP file located under the content'
|
8107 |
. ' directory of this site. The note under the <em>"Protect uploads directory"</em>'
|
8108 |
. ' section also applies to this option so you may want to read that part too. If you'
|
8109 |
. ' experience any kind of issues in your site after you apply this hardening go to the'
|
8110 |
. ' content directory using a FTP client or a file manager <em>(generally available in'
|
8111 |
-
. ' your hosting panel)</em> and rename a file named <code>.htaccess</code
|
8112 |
-
. 'Note:</b> Apache/2.4 introduced new directives to configure the access level of'
|
8113 |
-
. ' certain resources in the server, for instance the rules applied to harden these'
|
8114 |
-
. ' directories will not work and will probably cause issues. We will not fix this'
|
8115 |
-
. ' because there is no accurate way to determine the exact version number of Apache'
|
8116 |
-
. ' installed in this server considering some security measures applied to its'
|
8117 |
-
. ' configuration that will prevent the version number to be readable by PHP, proceed'
|
8118 |
-
. ' with caution.';
|
8119 |
|
8120 |
return sucuriscan_harden_status(
|
8121 |
'Restrict wp-content access',
|
@@ -8139,72 +8366,36 @@ function sucuriscan_harden_wpcontent(){
|
|
8139 |
* @return void
|
8140 |
*/
|
8141 |
function sucuriscan_harden_wpincludes(){
|
8142 |
-
$
|
8143 |
-
$htaccess_upload = ABSPATH . '/wp-includes/.htaccess';
|
8144 |
-
|
8145 |
-
if ( ! is_readable( $htaccess_upload ) ) {
|
8146 |
-
$cp = 0;
|
8147 |
-
} else {
|
8148 |
-
$cp = 0;
|
8149 |
-
$fcontent = SucuriScanFileInfo::file_lines( $htaccess_upload );
|
8150 |
-
|
8151 |
-
foreach ( $fcontent as $fline ) {
|
8152 |
-
if ( stripos( $fline, 'deny from all' ) !== false ) {
|
8153 |
-
$cp = 1;
|
8154 |
-
break;
|
8155 |
-
}
|
8156 |
-
}
|
8157 |
-
}
|
8158 |
|
8159 |
if ( SucuriScanRequest::post( ':run_hardening' ) ) {
|
8160 |
-
if ( SucuriScanRequest::post( ':harden_wpincludes' )
|
8161 |
-
$
|
8162 |
-
|
8163 |
-
|
8164 |
-
. "\n<Files wp-tinymce.php>"
|
8165 |
-
. "\nallow from all"
|
8166 |
-
. "\n</Files>"
|
8167 |
-
. "\n<Files ms-files.php>"
|
8168 |
-
. "\nallow from all"
|
8169 |
-
. "\n</Files>"
|
8170 |
-
. "\n";
|
8171 |
-
|
8172 |
-
if ( @file_put_contents( $htaccess_upload, $file_rules ) === false ) {
|
8173 |
-
SucuriScanInterface::error( 'Unable to create <code>.htaccess</code> file, folder destination is not writable.' );
|
8174 |
-
} else {
|
8175 |
-
$cp = 1;
|
8176 |
$message = 'Hardening applied to the library directory';
|
8177 |
SucuriScanEvent::report_notice_event( $message );
|
8178 |
SucuriScanInterface::info( $message );
|
|
|
|
|
8179 |
}
|
8180 |
} elseif ( SucuriScanRequest::post( ':harden_wpincludes_unharden' ) ) {
|
8181 |
-
$
|
8182 |
-
$htaccess_content = $htaccess_upload_writable ? @file_get_contents( $htaccess_upload ) : '';
|
8183 |
-
|
8184 |
-
if ( $htaccess_upload_writable ) {
|
8185 |
-
$cp = 0;
|
8186 |
-
|
8187 |
-
if ( preg_match_all( '/<Files (\*|wp-tinymce|ms-files)\.php>\n(deny|allow) from all\n<\/Files>/', $htaccess_content, $match ) ) {
|
8188 |
-
foreach ( $match[0] as $restriction ) {
|
8189 |
-
$htaccess_content = str_replace( $restriction, '', $htaccess_content );
|
8190 |
-
}
|
8191 |
-
|
8192 |
-
@file_put_contents( $htaccess_upload, $htaccess_content, LOCK_EX );
|
8193 |
-
}
|
8194 |
|
|
|
8195 |
$message = 'Hardening reverted in the library directory';
|
8196 |
SucuriScanEvent::report_error_event( $message );
|
8197 |
SucuriScanInterface::info( $message );
|
8198 |
} else {
|
8199 |
-
SucuriScanInterface::
|
8200 |
-
'File <code>wp-includes/.htaccess</code> does not exists or is not
|
8201 |
-
writable, you will need to remove the following code manually from
|
8202 |
-
there: <code><Files *.php>deny from all</Files></code>'
|
8203 |
-
);
|
8204 |
}
|
8205 |
}
|
8206 |
}
|
8207 |
|
|
|
|
|
|
|
|
|
8208 |
return sucuriscan_harden_status(
|
8209 |
'Restrict wp-includes access',
|
8210 |
$cp,
|
@@ -8913,18 +9104,23 @@ function sucuriscan_wordpress_outdated(){
|
|
8913 |
/**
|
8914 |
* Compare the md5sum of the core files in the current site with the hashes hosted
|
8915 |
* remotely in Sucuri servers. These hashes are updated every time a new version
|
8916 |
-
* of WordPress is released.
|
|
|
|
|
8917 |
*
|
8918 |
-
* @
|
|
|
8919 |
*/
|
8920 |
-
function sucuriscan_core_files(){
|
8921 |
$site_version = SucuriScan::site_version();
|
|
|
8922 |
|
8923 |
$template_variables = array(
|
8924 |
'CoreFiles.List' => '',
|
8925 |
'CoreFiles.ListCount' => 0,
|
8926 |
'CoreFiles.GoodVisibility' => 'visible',
|
8927 |
'CoreFiles.BadVisibility' => 'hidden',
|
|
|
8928 |
);
|
8929 |
|
8930 |
if ( $site_version && SucuriScanOption::get_option( ':scan_checksums' ) == 'enabled' ) {
|
@@ -8984,6 +9180,7 @@ function sucuriscan_core_files(){
|
|
8984 |
'CoreFiles.IsNotFixable' => $is_fixable_text,
|
8985 |
));
|
8986 |
$counter += 1;
|
|
|
8987 |
}
|
8988 |
}
|
8989 |
|
@@ -8993,10 +9190,24 @@ function sucuriscan_core_files(){
|
|
8993 |
$template_variables['CoreFiles.BadVisibility'] = 'visible';
|
8994 |
}
|
8995 |
} else {
|
8996 |
-
|
|
|
|
|
8997 |
}
|
8998 |
}
|
8999 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9000 |
return SucuriScanTemplate::get_section( 'integrity-corefiles', $template_variables );
|
9001 |
}
|
9002 |
|
@@ -9997,7 +10208,11 @@ if ( ! function_exists( 'sucuri_login_redirect' ) ) {
|
|
9997 |
function sucuriscan_login_redirect( $redirect_to = '', $request = null, $user = false ){
|
9998 |
$login_url = ! empty($redirect_to) ? $redirect_to : admin_url();
|
9999 |
|
10000 |
-
if (
|
|
|
|
|
|
|
|
|
10001 |
$login_url = add_query_arg( 'sucuriscan_lastlogin', 1, $login_url );
|
10002 |
}
|
10003 |
|
@@ -10965,6 +11180,10 @@ function sucuriscan_settings_form_submissions( $page_nonce = null ){
|
|
10965 |
if ( SucuriScanRequest::post( ':save_notification_settings' ) !== false ) {
|
10966 |
$options_updated_counter = 0;
|
10967 |
|
|
|
|
|
|
|
|
|
10968 |
foreach ( $sucuriscan_notify_options as $alert_type => $alert_label ) {
|
10969 |
$option_value = SucuriScanRequest::post( $alert_type, '(1|0)' );
|
10970 |
|
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.12
|
8 |
Author URI: http://sucuri.net
|
9 |
*/
|
10 |
|
66 |
/**
|
67 |
* Current version of the plugin's code.
|
68 |
*/
|
69 |
+
define( 'SUCURISCAN_VERSION', '1.7.12' );
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
189 |
'sucuriscan_notify_plugin_change' => 'Receive email alerts for <strong>Sucuri</strong> plugin changes',
|
190 |
'sucuriscan_prettify_mails' => 'Receive email alerts in HTML <em>(there may be issues with some mail services)</em>',
|
191 |
'sucuriscan_lastlogin_redirection' => 'Allow redirection after login to report the last-login information',
|
192 |
+
'sucuriscan_notify_scan_checksums' => 'Receive email alerts for core integrity checks',
|
193 |
'sucuriscan_notify_user_registration' => 'user:Receive email alerts for new user registration',
|
194 |
'sucuriscan_notify_success_login' => 'user:Receive email alerts for successful login attempts',
|
195 |
'sucuriscan_notify_failed_login' => 'user:Receive email alerts for failed login attempts',
|
254 |
$sucuriscan_email_subjects = array(
|
255 |
'Sucuri Alert, :domain, :event',
|
256 |
'Sucuri Alert, :domain, :event, :remoteaddr',
|
257 |
+
'Sucuri Alert, :domain, :event, :username',
|
258 |
+
'Sucuri Alert, :domain, :event, :email',
|
259 |
'Sucuri Alert, :event, :remoteaddr',
|
260 |
'Sucuri Alert, :event',
|
261 |
);
|
271 |
* information to the Sucuri API service where a security and integrity scan
|
272 |
* will be performed against the hashes provided and the official versions.
|
273 |
*/
|
274 |
+
add_action( 'sucuriscan_scheduled_scan', 'SucuriScan::run_scheduled_task' );
|
275 |
|
276 |
/**
|
277 |
* Initialize the execute of the main plugin's functions.
|
308 |
*/
|
309 |
if ( class_exists( 'SucuriScanHook' ) ) {
|
310 |
$sucuriscan_hooks = array(
|
|
|
311 |
'add_attachment',
|
312 |
'add_link',
|
313 |
+
'all',
|
314 |
'create_category',
|
315 |
'delete_post',
|
316 |
'delete_user',
|
317 |
'login_form_resetpass',
|
318 |
'private_to_published',
|
319 |
'publish_page',
|
|
|
320 |
'publish_phone',
|
321 |
+
'publish_post',
|
322 |
'retrieve_password',
|
323 |
'switch_theme',
|
324 |
'user_register',
|
325 |
+
'wp_insert_comment',
|
326 |
'wp_login',
|
327 |
'wp_login_failed',
|
328 |
'wp_trash_post',
|
329 |
+
'xmlrpc_publish_post',
|
330 |
);
|
331 |
|
332 |
foreach ( $sucuriscan_hooks as $hook_name ) {
|
333 |
$hook_func = 'SucuriScanHook::hook_' . $hook_name;
|
334 |
+
add_action( $hook_name, $hook_func, 50, 5 );
|
335 |
}
|
336 |
|
337 |
add_action( 'admin_init', 'SucuriScanHook::hook_undefined_actions' );
|
622 |
return '/define\(\s*\'([A-Z_]+)\',(\s*)\'(.+)\'\s*\);/';
|
623 |
}
|
624 |
|
625 |
+
/**
|
626 |
+
* Execute the plugin' scheduled tasks.
|
627 |
+
*
|
628 |
+
* @return void
|
629 |
+
*/
|
630 |
+
public static function run_scheduled_task(){
|
631 |
+
SucuriScanEvent::filesystem_scan();
|
632 |
+
sucuriscan_core_files( true );
|
633 |
+
}
|
634 |
+
|
635 |
/**
|
636 |
* Retrieve the real ip address of the user in the current request.
|
637 |
*
|
743 |
}
|
744 |
|
745 |
/**
|
746 |
+
* Check whether the site is behind the Sucuri CloudProxy network.
|
747 |
*
|
748 |
* @param boolean $verbose Return an array with the hostname, address, and status, or not.
|
749 |
* @return boolean Either TRUE or FALSE if the site is behind CloudProxy.
|
750 |
*/
|
751 |
public static function is_behind_cloudproxy( $verbose = false ){
|
752 |
$http_host = self::get_top_level_domain();
|
753 |
+
|
754 |
+
if (
|
755 |
+
defined( 'NOT_USING_CLOUDPROXY' )
|
756 |
+
&& NOT_USING_CLOUDPROXY === true
|
757 |
+
) {
|
758 |
+
$status = false;
|
759 |
+
$host_by_addr = '::1';
|
760 |
+
$host_by_name = 'localhost';
|
761 |
+
} else {
|
762 |
+
$host_by_addr = @gethostbyname( $http_host );
|
763 |
+
$host_by_name = @gethostbyaddr( $host_by_addr );
|
764 |
+
$status = (bool) preg_match( '/^cloudproxy[0-9]+\.sucuri\.net$/', $host_by_name );
|
765 |
+
}
|
766 |
|
767 |
/*
|
768 |
* If the DNS reversion failed but the CloudProxy API key is set, then consider
|
2557 |
'sucuriscan_notify_plugin_installed' => 'disabled',
|
2558 |
'sucuriscan_notify_plugin_updated' => 'disabled',
|
2559 |
'sucuriscan_notify_post_publication' => 'enabled',
|
2560 |
+
'sucuriscan_notify_scan_checksums' => 'disabled',
|
2561 |
'sucuriscan_notify_settings_updated' => 'disabled',
|
2562 |
'sucuriscan_notify_success_login' => 'enabled',
|
2563 |
'sucuriscan_notify_theme_activated' => 'disabled',
|
3112 |
* @param integer $severity Importance of the event that will be reported, values from one to five.
|
3113 |
* @param string $location In which part of the system was the event triggered.
|
3114 |
* @param string $message The explanation of the event.
|
3115 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3116 |
* @return boolean TRUE if the event was logged in the monitoring service, FALSE otherwise.
|
3117 |
*/
|
3118 |
+
private static function report_event( $severity = 0, $location = '', $message = '', $internal = false ){
|
3119 |
$user = wp_get_current_user();
|
3120 |
$username = false;
|
3121 |
$current_time = date( 'Y-m-d H:i:s' );
|
3148 |
default: $severity_name = 'Info'; break;
|
3149 |
}
|
3150 |
|
3151 |
+
// Mark the event as internal if necessary.
|
3152 |
+
if ( $internal === true ) {
|
3153 |
+
$severity_name = '@' . $severity_name;
|
3154 |
+
}
|
3155 |
+
|
3156 |
// Clear event message.
|
3157 |
$message = strip_tags( $message );
|
3158 |
$message = str_replace( "\r", '', $message );
|
3173 |
/**
|
3174 |
* Reports a debug event on the website.
|
3175 |
*
|
3176 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3177 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3178 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3179 |
*/
|
3180 |
+
public static function report_debug_event( $message = '', $internal = false ){
|
3181 |
+
return self::report_event( 0, 'core', $message, $internal );
|
3182 |
}
|
3183 |
|
3184 |
/**
|
3185 |
* Reports a notice event on the website.
|
3186 |
*
|
3187 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3188 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3189 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3190 |
*/
|
3191 |
+
public static function report_notice_event( $message = '', $internal = false ){
|
3192 |
+
return self::report_event( 1, 'core', $message, $internal );
|
3193 |
}
|
3194 |
|
3195 |
/**
|
3196 |
* Reports a info event on the website.
|
3197 |
*
|
3198 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3199 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3200 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3201 |
*/
|
3202 |
+
public static function report_info_event( $message = '', $internal = false ){
|
3203 |
+
return self::report_event( 2, 'core', $message, $internal );
|
3204 |
}
|
3205 |
|
3206 |
/**
|
3207 |
* Reports a warning event on the website.
|
3208 |
*
|
3209 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3210 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3211 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3212 |
*/
|
3213 |
+
public static function report_warning_event( $message = '', $internal = false ){
|
3214 |
+
return self::report_event( 3, 'core', $message, $internal );
|
3215 |
}
|
3216 |
|
3217 |
/**
|
3218 |
* Reports a error event on the website.
|
3219 |
*
|
3220 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3221 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3222 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3223 |
*/
|
3224 |
+
public static function report_error_event( $message = '', $internal = false ){
|
3225 |
+
return self::report_event( 4, 'core', $message, $internal );
|
3226 |
}
|
3227 |
|
3228 |
/**
|
3229 |
* Reports a critical event on the website.
|
3230 |
*
|
3231 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3232 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3233 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3234 |
*/
|
3235 |
+
public static function report_critical_event( $message = '', $internal = false ){
|
3236 |
+
return self::report_event( 5, 'core', $message, $internal );
|
3237 |
}
|
3238 |
|
3239 |
/**
|
3240 |
* Reports a notice or error event for enable and disable actions.
|
3241 |
*
|
3242 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3243 |
* @param string $action An optional text, hopefully either enabled or disabled.
|
3244 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3245 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3246 |
*/
|
3247 |
+
public static function report_auto_event( $message = '', $action = '', $internal = false ){
|
3248 |
$message = strip_tags( $message );
|
3249 |
|
3250 |
// Auto-detect the action performed, either enabled or disabled.
|
3254 |
|
3255 |
// Report the correct event for the action performed.
|
3256 |
if ( $action == 'enabled' ) {
|
3257 |
+
return self::report_notice_event( $message, $internal );
|
3258 |
} elseif ( $action == 'disabled' ) {
|
3259 |
+
return self::report_error_event( $message, $internal );
|
3260 |
} else {
|
3261 |
+
return self::report_info_event( $message, $internal );
|
3262 |
}
|
3263 |
}
|
3264 |
|
3333 |
} elseif ( $event == 'bruteforce_attack' ) {
|
3334 |
// Send a notification even if the limit of emails per hour was reached.
|
3335 |
$email_params['Force'] = true;
|
3336 |
+
} elseif ( $event == 'scan_checksums' ) {
|
3337 |
+
$event = 'core_integrity_checks';
|
3338 |
+
$email_params['Force'] = true;
|
3339 |
}
|
3340 |
|
3341 |
$title = str_replace( '_', chr( 32 ), $event );
|
3864 |
}
|
3865 |
}
|
3866 |
|
3867 |
+
/**
|
3868 |
+
* Fires immediately after a comment is inserted into the database.
|
3869 |
+
*
|
3870 |
+
* The action comment-post can also be used to track the insertion of data in
|
3871 |
+
* the comments table, but this only returns the identifier of the new entry in
|
3872 |
+
* the database and the status (approved, not approved, spam). The WP-Insert-
|
3873 |
+
* Comment action returns the same identifier and additionally the full data set
|
3874 |
+
* with the comment information.
|
3875 |
+
*
|
3876 |
+
* @see https://codex.wordpress.org/Plugin_API/Action_Reference/wp_insert_comment
|
3877 |
+
* @see https://codex.wordpress.org/Plugin_API/Action_Reference/comment_post
|
3878 |
+
*
|
3879 |
+
* @param integer $id The comment identifier.
|
3880 |
+
* @param object $comment The comment object.
|
3881 |
+
* @return void
|
3882 |
+
*/
|
3883 |
+
public static function hook_wp_insert_comment( $id = 0, $comment = false ){
|
3884 |
+
if (
|
3885 |
+
$comment instanceof stdClass
|
3886 |
+
&& property_exists( $comment, 'comment_ID' )
|
3887 |
+
&& property_exists( $comment, 'comment_agent' )
|
3888 |
+
&& property_exists( $comment, 'comment_author_IP' )
|
3889 |
+
) {
|
3890 |
+
$data_set = array(
|
3891 |
+
'id' => $comment->comment_ID,
|
3892 |
+
'post_id' => $comment->comment_post_ID,
|
3893 |
+
'user_id' => $comment->user_id,
|
3894 |
+
'parent' => $comment->comment_parent,
|
3895 |
+
'approved' => $comment->comment_approved,
|
3896 |
+
'remote_addr' => $comment->comment_author_IP,
|
3897 |
+
'author_email' => $comment->comment_author_email,
|
3898 |
+
'date' => $comment->comment_date,
|
3899 |
+
'content' => $comment->comment_content,
|
3900 |
+
'user_agent' => $comment->comment_agent,
|
3901 |
+
);
|
3902 |
+
$message = base64_encode( json_encode( $data_set ) );
|
3903 |
+
self::report_notice_event( 'Base64:' . $message, true );
|
3904 |
+
}
|
3905 |
+
}
|
3906 |
+
|
3907 |
+
// TODO: Log when the comment status is modified: wp_set_comment_status
|
3908 |
+
// TODO: Log when the comment data is modified: edit_comment
|
3909 |
+
// TODO: Log when the comment is going to be deleted: delete_comment, trash_comment
|
3910 |
+
// TODO: Log when the comment is finally deleted: deleted_comment, trashed_comment
|
3911 |
+
// TODO: Log when the comment is closed: comment_closed
|
3912 |
// TODO: Detect auto updates in core, themes, and plugin files.
|
3913 |
|
3914 |
+
/**
|
3915 |
+
* Placeholder for arbitrary actions.
|
3916 |
+
*
|
3917 |
+
* @return void
|
3918 |
+
*/
|
3919 |
+
public static function hook_all( $action = null, $data = false ){
|
3920 |
+
global $wp_filter;
|
3921 |
+
|
3922 |
+
if (
|
3923 |
+
is_array( $wp_filter )
|
3924 |
+
&& ! empty( $wp_filter )
|
3925 |
+
&& ! array_key_exists( $action, $wp_filter )
|
3926 |
+
&& preg_match( '/^(admin_post|wp_ajax)_.+/', $action )
|
3927 |
+
) {
|
3928 |
+
$message = sprintf( 'Undefined XHR action %s', $action );
|
3929 |
+
self::report_error_event( $message );
|
3930 |
+
}
|
3931 |
+
}
|
3932 |
+
|
3933 |
/**
|
3934 |
* Send a notifications to the administrator of some specific events that are
|
3935 |
* not triggered through an hooked action, but through a simple request in the
|
4946 |
$response['body']->output_data = array();
|
4947 |
$log_pattern = '/^([0-9\-]+) ([0-9:]+) (\S+) : (.+)/';
|
4948 |
$extra_pattern = '/(.+ \(multiple entries\):) (.+)/';
|
4949 |
+
$generic_pattern = '/^@?([A-Z][a-z]{3,7}): ([^:;]+; )?(.+)/';
|
4950 |
$auth_pattern = '/^User authentication (succeeded|failed): ([^<;]+)/';
|
4951 |
|
4952 |
foreach ( $response['body']->output as $log ) {
|
5674 |
* @return string A text with the subject for the email alert.
|
5675 |
*/
|
5676 |
private static function get_email_subject( $event = '' ){
|
5677 |
+
$subject = self::get_option( ':email_subject' );
|
5678 |
|
5679 |
/**
|
5680 |
* Probably a bad value in the options table. Delete the entry from the database
|
5681 |
* and call this function to try again, it will probably fall in an infinite
|
5682 |
* loop, but this is the easiest way to control this procedure.
|
5683 |
*/
|
5684 |
+
if ( ! $subject ) {
|
5685 |
self::delete_option( ':email_subject' );
|
5686 |
|
5687 |
return self::get_email_subject( $event );
|
5688 |
}
|
5689 |
|
5690 |
+
$subject = strip_tags( $subject );
|
5691 |
+
$subject = str_replace( ':event', $event, $subject );
|
5692 |
+
$subject = str_replace( ':domain', self::get_domain(), $subject );
|
5693 |
+
$subject = str_replace( ':remoteaddr', self::get_remote_addr(), $subject );
|
5694 |
+
|
5695 |
+
/**
|
5696 |
+
* Extract user data from the current session.
|
5697 |
+
*
|
5698 |
+
* Get the data of the user in the current session only if the pseudo-tags for
|
5699 |
+
* the username and/or email address are necessary to build the email subject,
|
5700 |
+
* otherwise this operation may delay the sending of the alerts.
|
5701 |
+
*/
|
5702 |
+
if ( preg_match( '/:(username|email)/', $subject ) ) {
|
5703 |
+
$user = wp_get_current_user();
|
5704 |
+
$username = 'unknown';
|
5705 |
+
$eaddress = 'unknown';
|
5706 |
+
|
5707 |
+
if (
|
5708 |
+
$user instanceof WP_User
|
5709 |
+
&& isset( $user->user_login )
|
5710 |
+
&& isset( $user->user_email )
|
5711 |
+
) {
|
5712 |
+
$username = $user->user_login;
|
5713 |
+
$eaddress = $user->user_email;
|
5714 |
+
}
|
5715 |
+
|
5716 |
+
$subject = str_replace( ':username', $user->user_login, $subject );
|
5717 |
+
$subject = str_replace( ':email', $user->user_email, $subject );
|
5718 |
+
}
|
5719 |
|
5720 |
+
return $subject;
|
5721 |
}
|
5722 |
|
5723 |
/**
|
7887 |
return $options;
|
7888 |
}
|
7889 |
|
7890 |
+
/**
|
7891 |
+
* Project hardening library.
|
7892 |
+
*
|
7893 |
+
* In computing, hardening is usually the process of securing a system by
|
7894 |
+
* reducing its surface of vulnerability. A system has a larger vulnerability
|
7895 |
+
* surface the more functions it fulfills; in principle a single-function system
|
7896 |
+
* is more secure than a multipurpose one. Reducing available vectors of attack
|
7897 |
+
* typically includes the removal of unnecessary software, unnecessary usernames
|
7898 |
+
* or logins and the disabling or removal of unnecessary services.
|
7899 |
+
*
|
7900 |
+
* There are various methods of hardening Unix and Linux systems. This may
|
7901 |
+
* involve, among other measures, applying a patch to the kernel such as Exec
|
7902 |
+
* Shield or PaX; closing open network ports; and setting up intrusion-detection
|
7903 |
+
* systems, firewalls and intrusion-prevention systems. There are also hardening
|
7904 |
+
* scripts and tools like Bastille Linux, JASS for Solaris systems and
|
7905 |
+
* Apache/PHP Hardener that can, for example, deactivate unneeded features in
|
7906 |
+
* configuration files or perform various other protective measures.
|
7907 |
+
*/
|
7908 |
+
class SucuriScanHardening extends SucuriScan {
|
7909 |
+
|
7910 |
+
/**
|
7911 |
+
* Returns a list of access control rules for the Apache web server that can be
|
7912 |
+
* used to deny and allow certain files to be accessed by certain network nodes.
|
7913 |
+
* Currently supports Apache 2.2 and 2.4 and denies access to all PHP files with
|
7914 |
+
* any mixed extension case.
|
7915 |
+
*
|
7916 |
+
* @param string $directory Valid directory path.
|
7917 |
+
* @return array List of access control rules.
|
7918 |
+
*/
|
7919 |
+
private static function get_rules( $directory = '' ){
|
7920 |
+
$directory = basename( $directory );
|
7921 |
+
$rules = array(
|
7922 |
+
'<FilesMatch "\.(?i:php)$">',
|
7923 |
+
' <IfModule !mod_authz_core.c>',
|
7924 |
+
' Order allow,deny',
|
7925 |
+
' Deny from all',
|
7926 |
+
' </IfModule>',
|
7927 |
+
' <IfModule mod_authz_core.c>',
|
7928 |
+
' Require all denied',
|
7929 |
+
' </IfModule>',
|
7930 |
+
'</FilesMatch>',
|
7931 |
+
);
|
7932 |
+
|
7933 |
+
if ( $directory == 'wp-includes' ) {
|
7934 |
+
$rules[] = '<Files wp-tinymce.php>';
|
7935 |
+
$rules[] = ' Allow from all';
|
7936 |
+
$rules[] = '</Files>';
|
7937 |
+
$rules[] = '<Files ms-files.php>';
|
7938 |
+
$rules[] = ' Allow from all';
|
7939 |
+
$rules[] = '</Files>';
|
7940 |
+
}
|
7941 |
+
|
7942 |
+
return $rules;
|
7943 |
+
}
|
7944 |
+
|
7945 |
+
/**
|
7946 |
+
* Adds some rules to an existing access control file (or creates it if does not
|
7947 |
+
* exists) to deny access to all files with certain extension in any mixed case.
|
7948 |
+
* The permissions to modify the file are checked before anything else, this
|
7949 |
+
* function is self-contained.
|
7950 |
+
*
|
7951 |
+
* @param string $directory Valid directory path where to place the access rules.
|
7952 |
+
* @return boolean True if the rules are successfully added, false otherwise.
|
7953 |
+
*/
|
7954 |
+
public static function harden_directory( $directory = '' ){
|
7955 |
+
if (
|
7956 |
+
file_exists( $directory)
|
7957 |
+
&& is_writable( $directory )
|
7958 |
+
&& is_dir( $directory )
|
7959 |
+
) {
|
7960 |
+
$fhandle = false;
|
7961 |
+
$target = $directory . '/.htaccess';
|
7962 |
+
$deny_rules = self::get_rules( $directory );
|
7963 |
+
|
7964 |
+
if ( file_exists( $target ) ) {
|
7965 |
+
$fhandle = @fopen( $target, 'a' );
|
7966 |
+
} else {
|
7967 |
+
$fhandle = @fopen( $target, 'w' );
|
7968 |
+
}
|
7969 |
+
|
7970 |
+
if ( $fhandle ) {
|
7971 |
+
$rules_str = implode( "\n", $deny_rules );
|
7972 |
+
$written = fwrite( $fhandle, $rules_str );
|
7973 |
+
fclose( $fhandle );
|
7974 |
+
|
7975 |
+
return (bool) ( $written !== false );
|
7976 |
+
}
|
7977 |
+
}
|
7978 |
+
|
7979 |
+
return false;
|
7980 |
+
}
|
7981 |
+
|
7982 |
+
/**
|
7983 |
+
* Deletes some rules from an existing access control file to allow access to
|
7984 |
+
* all files with certain extension in any mixed case. The file is truncated if
|
7985 |
+
* after the operation its size is equals to zero.
|
7986 |
+
*
|
7987 |
+
* @param string $directory Valid directory path where to access rules are.
|
7988 |
+
* @return boolean True if the rules are successfully deleted, false otherwise.
|
7989 |
+
*/
|
7990 |
+
public static function unharden_directory( $directory = '' ){
|
7991 |
+
if ( self::is_hardened( $directory ) ) {
|
7992 |
+
$deny_rules = self::get_rules( $directory );
|
7993 |
+
$fpath = $directory . '/.htaccess';
|
7994 |
+
$content = @file_get_contents( $fpath );
|
7995 |
+
|
7996 |
+
if ( $content ) {
|
7997 |
+
$rules_str = implode( "\n", $deny_rules );
|
7998 |
+
$content = str_replace( $rules_str, '', $content );
|
7999 |
+
$written = @file_put_contents( $fpath, $content );
|
8000 |
+
|
8001 |
+
if ( filesize( $fpath ) === 0 ) {
|
8002 |
+
@unlink( $fpath );
|
8003 |
+
}
|
8004 |
+
|
8005 |
+
return (bool) ( $written !== false );
|
8006 |
+
}
|
8007 |
+
}
|
8008 |
+
|
8009 |
+
return false;
|
8010 |
+
}
|
8011 |
+
|
8012 |
+
/**
|
8013 |
+
* Check whether a directory is hardened or not.
|
8014 |
+
*
|
8015 |
+
* @param string $directory Valid directory path.
|
8016 |
+
* @return boolean True if the directory is hardened, false otherwise.
|
8017 |
+
*/
|
8018 |
+
public static function is_hardened( $directory = '' ){
|
8019 |
+
if (
|
8020 |
+
file_exists( $directory )
|
8021 |
+
&& is_dir( $directory )
|
8022 |
+
) {
|
8023 |
+
$fpath = $directory . '/.htaccess';
|
8024 |
+
|
8025 |
+
if (
|
8026 |
+
file_exists( $fpath )
|
8027 |
+
&& is_readable( $fpath )
|
8028 |
+
) {
|
8029 |
+
$rules = self::get_rules( $directory );
|
8030 |
+
$rules_str = implode( "\n", $rules );
|
8031 |
+
$content = @file_get_contents( $fpath );
|
8032 |
+
|
8033 |
+
if ( strpos( $content, $rules_str ) !== false ) {
|
8034 |
+
return true;
|
8035 |
+
}
|
8036 |
+
}
|
8037 |
+
}
|
8038 |
+
|
8039 |
+
return false;
|
8040 |
+
}
|
8041 |
+
|
8042 |
+
}
|
8043 |
+
|
8044 |
/**
|
8045 |
* Sucuri one-click hardening page.
|
8046 |
*
|
8249 |
* @return void
|
8250 |
*/
|
8251 |
function sucuriscan_harden_upload(){
|
8252 |
+
$dpath = WP_CONTENT_DIR . '/uploads';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8253 |
|
8254 |
if ( SucuriScanRequest::post( ':run_hardening' ) ) {
|
8255 |
+
if ( SucuriScanRequest::post( ':harden_upload' ) ) {
|
8256 |
+
$result = SucuriScanHardening::harden_directory( $dpath );
|
8257 |
+
|
8258 |
+
if ( $result === true ) {
|
|
|
8259 |
$message = 'Hardening applied to the uploads directory';
|
8260 |
SucuriScanEvent::report_notice_event( $message );
|
8261 |
SucuriScanInterface::info( $message );
|
8262 |
+
} else {
|
8263 |
+
SucuriScanInterface::error( 'Error hardening directory, check the permissions.' );
|
8264 |
}
|
8265 |
} elseif ( SucuriScanRequest::post( ':harden_upload_unharden' ) ) {
|
8266 |
+
$result = SucuriScanHardening::unharden_directory( $dpath );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8267 |
|
8268 |
+
if ( $result === true ) {
|
8269 |
$message = 'Hardening reverted in the uploads directory';
|
8270 |
SucuriScanEvent::report_error_event( $message );
|
8271 |
SucuriScanInterface::info( $message );
|
8272 |
} else {
|
8273 |
+
SucuriScanInterface::info( 'Access file is not writable, check the permissions.' );
|
|
|
|
|
|
|
|
|
8274 |
}
|
8275 |
}
|
8276 |
}
|
8277 |
|
8278 |
+
// Check whether the directory is already hardened or not.
|
8279 |
+
$is_hardened = SucuriScanHardening::is_hardened( $dpath );
|
8280 |
+
$cp = ( $is_hardened === true ) ? 1 : 0;
|
8281 |
+
|
8282 |
$description = 'It checks if the uploads directory of this site allows the direct execution'
|
8283 |
. ' of PHP files. It is recommendable to prevent this because someone may try to exploit'
|
8284 |
. ' a vulnerability of a plugin, theme, and/or other PHP-based code located in this'
|
8309 |
* @return void
|
8310 |
*/
|
8311 |
function sucuriscan_harden_wpcontent(){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8312 |
if ( SucuriScanRequest::post( ':run_hardening' ) ) {
|
8313 |
+
if ( SucuriScanRequest::post( ':harden_wpcontent' ) ) {
|
8314 |
+
$result = SucuriScanHardening::harden_directory( WP_CONTENT_DIR );
|
8315 |
+
|
8316 |
+
if ( $result === true ) {
|
|
|
8317 |
$message = 'Hardening applied to the content directory';
|
8318 |
SucuriScanEvent::report_notice_event( $message );
|
8319 |
SucuriScanInterface::info( $message );
|
8320 |
+
} else {
|
8321 |
+
SucuriScanInterface::error( 'Error hardening directory, check the permissions.' );
|
8322 |
}
|
8323 |
} elseif ( SucuriScanRequest::post( ':harden_wpcontent_unharden' ) ) {
|
8324 |
+
$result = SucuriScanHardening::unharden_directory( WP_CONTENT_DIR );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8325 |
|
8326 |
+
if ( $result === true ) {
|
8327 |
$message = 'Hardening reverted in the content directory';
|
8328 |
SucuriScanEvent::report_error_event( $message );
|
8329 |
SucuriScanInterface::info( $message );
|
8330 |
} else {
|
8331 |
+
SucuriScanInterface::info( 'Access file is not writable, check the permissions.' );
|
|
|
|
|
|
|
|
|
8332 |
}
|
8333 |
}
|
8334 |
}
|
8335 |
|
8336 |
+
// Check whether the directory is already hardened or not.
|
8337 |
+
$is_hardened = SucuriScanHardening::is_hardened( WP_CONTENT_DIR );
|
8338 |
+
$cp = ( $is_hardened === true ) ? 1 : 0;
|
8339 |
+
|
8340 |
$description = 'This option blocks direct access to any PHP file located under the content'
|
8341 |
. ' directory of this site. The note under the <em>"Protect uploads directory"</em>'
|
8342 |
. ' section also applies to this option so you may want to read that part too. If you'
|
8343 |
. ' experience any kind of issues in your site after you apply this hardening go to the'
|
8344 |
. ' content directory using a FTP client or a file manager <em>(generally available in'
|
8345 |
+
. ' your hosting panel)</em> and rename a file named <code>.htaccess</code>.';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8346 |
|
8347 |
return sucuriscan_harden_status(
|
8348 |
'Restrict wp-content access',
|
8366 |
* @return void
|
8367 |
*/
|
8368 |
function sucuriscan_harden_wpincludes(){
|
8369 |
+
$dpath = ABSPATH . '/wp-includes';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8370 |
|
8371 |
if ( SucuriScanRequest::post( ':run_hardening' ) ) {
|
8372 |
+
if ( SucuriScanRequest::post( ':harden_wpincludes' ) ) {
|
8373 |
+
$result = SucuriScanHardening::harden_directory( $dpath );
|
8374 |
+
|
8375 |
+
if ( $result === true ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8376 |
$message = 'Hardening applied to the library directory';
|
8377 |
SucuriScanEvent::report_notice_event( $message );
|
8378 |
SucuriScanInterface::info( $message );
|
8379 |
+
} else {
|
8380 |
+
SucuriScanInterface::error( 'Error hardening directory, check the permissions.' );
|
8381 |
}
|
8382 |
} elseif ( SucuriScanRequest::post( ':harden_wpincludes_unharden' ) ) {
|
8383 |
+
$result = SucuriScanHardening::unharden_directory( $dpath );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8384 |
|
8385 |
+
if ( $result === true ) {
|
8386 |
$message = 'Hardening reverted in the library directory';
|
8387 |
SucuriScanEvent::report_error_event( $message );
|
8388 |
SucuriScanInterface::info( $message );
|
8389 |
} else {
|
8390 |
+
SucuriScanInterface::info( 'Access file is not writable, check the permissions.' );
|
|
|
|
|
|
|
|
|
8391 |
}
|
8392 |
}
|
8393 |
}
|
8394 |
|
8395 |
+
// Check whether the directory is already hardened or not.
|
8396 |
+
$is_hardened = SucuriScanHardening::is_hardened( $dpath );
|
8397 |
+
$cp = ( $is_hardened === true ) ? 1 : 0;
|
8398 |
+
|
8399 |
return sucuriscan_harden_status(
|
8400 |
'Restrict wp-includes access',
|
8401 |
$cp,
|
9104 |
/**
|
9105 |
* Compare the md5sum of the core files in the current site with the hashes hosted
|
9106 |
* remotely in Sucuri servers. These hashes are updated every time a new version
|
9107 |
+
* of WordPress is released. If the "Send Email" parameter is set the function will
|
9108 |
+
* send a notification to the administrator with a list of files that were added,
|
9109 |
+
* modified and/or deleted so far.
|
9110 |
*
|
9111 |
+
* @param boolean $send_email If the HTML code returned will be sent via email.
|
9112 |
+
* @return string HTML code with a list of files that were affected.
|
9113 |
*/
|
9114 |
+
function sucuriscan_core_files( $send_email = false ){
|
9115 |
$site_version = SucuriScan::site_version();
|
9116 |
+
$affected_files = 0;
|
9117 |
|
9118 |
$template_variables = array(
|
9119 |
'CoreFiles.List' => '',
|
9120 |
'CoreFiles.ListCount' => 0,
|
9121 |
'CoreFiles.GoodVisibility' => 'visible',
|
9122 |
'CoreFiles.BadVisibility' => 'hidden',
|
9123 |
+
'CoreFiles.FailureVisibility' => 'hidden',
|
9124 |
);
|
9125 |
|
9126 |
if ( $site_version && SucuriScanOption::get_option( ':scan_checksums' ) == 'enabled' ) {
|
9180 |
'CoreFiles.IsNotFixable' => $is_fixable_text,
|
9181 |
));
|
9182 |
$counter += 1;
|
9183 |
+
$affected_files += 1;
|
9184 |
}
|
9185 |
}
|
9186 |
|
9190 |
$template_variables['CoreFiles.BadVisibility'] = 'visible';
|
9191 |
}
|
9192 |
} else {
|
9193 |
+
$template_variables['CoreFiles.GoodVisibility'] = 'hidden';
|
9194 |
+
$template_variables['CoreFiles.BadVisibility'] = 'hidden';
|
9195 |
+
$template_variables['CoreFiles.FailureVisibility'] = 'visible';
|
9196 |
}
|
9197 |
}
|
9198 |
|
9199 |
+
// Send an email notification with the affected files.
|
9200 |
+
if ( $send_email === true ) {
|
9201 |
+
if ( $affected_files > 0 ) {
|
9202 |
+
$content = SucuriScanTemplate::get_section( 'notification-corefiles', $template_variables );
|
9203 |
+
$sent = SucuriScanEvent::notify_event( 'scan_checksums', $content );
|
9204 |
+
|
9205 |
+
return $sent;
|
9206 |
+
}
|
9207 |
+
|
9208 |
+
return false;
|
9209 |
+
}
|
9210 |
+
|
9211 |
return SucuriScanTemplate::get_section( 'integrity-corefiles', $template_variables );
|
9212 |
}
|
9213 |
|
10208 |
function sucuriscan_login_redirect( $redirect_to = '', $request = null, $user = false ){
|
10209 |
$login_url = ! empty($redirect_to) ? $redirect_to : admin_url();
|
10210 |
|
10211 |
+
if (
|
10212 |
+
$user instanceof WP_User
|
10213 |
+
&& in_array( 'administrator', $user->roles )
|
10214 |
+
&& SucuriScanOption::get_option( ':lastlogin_redirection' ) === 'enabled'
|
10215 |
+
) {
|
10216 |
$login_url = add_query_arg( 'sucuriscan_lastlogin', 1, $login_url );
|
10217 |
}
|
10218 |
|
11180 |
if ( SucuriScanRequest::post( ':save_notification_settings' ) !== false ) {
|
11181 |
$options_updated_counter = 0;
|
11182 |
|
11183 |
+
if ( SucuriScanRequest::post( ':notify_scan_checksums', '1' ) ) {
|
11184 |
+
$_POST['sucuriscan_prettify_mails'] = '1';
|
11185 |
+
}
|
11186 |
+
|
11187 |
foreach ( $sucuriscan_notify_options as $alert_type => $alert_label ) {
|
11188 |
$option_value = SucuriScanRequest::post( $alert_type, '(1|0)' );
|
11189 |
|